Compare commits

..
43 Commits
Author SHA1 Message Date
toxblh eee33ee645 v0.6 2018-04-12 07:57:18 +01:00
Anton Palgunov 046f0fc1cf Merge pull request #6 from Toxblh/cleanup
Cleanup project
2018-04-12 07:34:59 +01:00
Serg 4b7788fff7 some cleanup 2018-04-12 08:58:24 +07:00
Serg ea5fbf0ee8 action has unified source too 2018-04-12 08:48:24 +07:00
Serg d0cfa45b5d hacky solution to autohide if title is empty 2018-04-11 23:46:05 +07:00
toxblh ed14f34a2d conflict resolved 2018-04-11 17:09:34 +01:00
toxblh 98d5a6eb0e add staticImageButton for buttons with custom image 2018-04-11 17:03:38 +01:00
Serg b492b89d2f unified source for scripts (and image data in future) 2018-04-11 22:37:46 +07:00
Serg ff58329691 displaysleep item 2018-04-11 13:47:09 +07:00
Serg dd3ab9ac6f no codesign for debug, no UI tests 2018-04-11 07:29:28 +07:00
toxblh f08ce7a381 add FlexSpace. A bit refactor structure. Correct loading scripts from preset 2018-04-11 01:07:58 +01:00
Serg 11c8d167c0 custom width 2018-04-11 00:56:14 +07:00
Serg 0ba5984217 shell scripts and sleep implemented 2018-04-10 23:37:20 +07:00
Serg 1584cf979c cleanup extra code 2018-04-10 23:21:38 +07:00
toxblh 753cfd8a31 add buttons: battery and time with format 2018-04-10 14:07:52 +01:00
toxblh 34b51b2dd8 a bit fix json lint 2018-04-10 13:23:12 +01:00
Serg 5bda77d0d5 Merge remote-tracking branch 'upstream/master' into preset
# Conflicts:
#	README.md
2018-04-10 19:02:59 +07:00
Serg 2bc8912add weather – example on bundled scripts 2018-04-10 19:01:41 +07:00
Serg b70c8ca4a3 start to log my dirty code 2018-04-10 18:44:47 +07:00
Serg 2750d00317 media keys implemented 2018-04-10 18:41:25 +07:00
Serg 4fb7cb9b99 cleaner custom actions, potentially able to register from the outside 2018-04-10 18:16:28 +07:00
Serg 651ddbef5c escape button implemented 2018-04-10 17:57:51 +07:00
Serg fe5705627f missing changes :( 2018-04-10 17:51:21 +07:00
Serg c0401ce83d exit touchbar implemented 2018-04-10 17:50:34 +07:00
Serg 1c45ca13a3 generic actions sketched 2018-04-10 17:39:07 +07:00
Serg 970fb99e33 interval for apple script 2018-04-10 16:58:52 +07:00
Serg 46f35f4737 preset working 2018-04-10 16:50:41 +07:00
toxblh 713f4dffc7 added StatusMenu. Del from Dock. 2018-04-10 09:16:05 +01:00
Serg d0efdef8c2 initial json parsing 2018-04-10 14:13:20 +07:00
toxblh 65e3d67c32 a bit upd readme 2018-04-10 00:00:34 +01:00
toxblh e56a05657e add first badge to readme 😅 2018-04-09 23:25:30 +01:00
toxblh 4a84532c56 upd roadmap 2018-04-09 23:00:39 +01:00
toxblh 435439ecd2 Added Haptic feddback on click all buttons 2018-04-09 22:59:02 +01:00
Anton Palgunov bb0c81ea76 Merge pull request #5 from ReDetection/master
Workaround for apple script
2018-04-09 17:29:14 +01:00
Serg c022018ec4 workaround for NSAppleScript not being thread safe :( 2018-04-09 23:23:06 +07:00
Anton Palgunov e10eed17ad Merge pull request #4 from ReDetection/master
Async apple script
2018-04-09 16:10:37 +01:00
Serg 17e2362ebf async apple script; fix for those who have no helper apps 2018-04-09 22:07:15 +07:00
toxblh dd97c706f9 upd Roadmap 2018-04-09 15:39:29 +01:00
toxblh 002af40756 upd roadmap 2018-04-09 15:37:30 +01:00
toxblh 285fb1fb85 added sleep button 2018-04-09 15:26:04 +01:00
toxblh 1e07deedae a bit fix for Icons 2018-04-09 14:25:34 +01:00
toxblh a86d31b0ac Added Icon for DockBar 2018-04-09 14:22:30 +01:00
toxblh 0a0b393fb7 fix brithness keys 2018-04-09 12:38:05 +01:00
47 changed files with 910 additions and 558 deletions
+92 -154
View File
@@ -9,20 +9,30 @@
/* Begin PBXBuildFile section */
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */; };
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */; };
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */; };
36C2ECDD207C723B003CDA33 /* ParseConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */; };
36C2ECDE207C82DE003CDA33 /* ItemsParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */; };
36C2ECE0207CB1B0003CDA33 /* defaultPreset.json in Resources */ = {isa = PBXBuildFile; fileRef = 36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */; };
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
B059D624205E04F3006E6B86 /* TouchBarItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* TouchBarItems.swift */; };
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B252205C7D8000BC04DC /* AppDelegate.swift */; };
B082B255205C7D8000BC04DC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B254205C7D8000BC04DC /* ViewController.swift */; };
B082B257205C7D8000BC04DC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B082B256205C7D8000BC04DC /* Assets.xcassets */; };
B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B082B258205C7D8000BC04DC /* Main.storyboard */; };
B082B266205C7D8000BC04DC /* MTMRTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B265205C7D8000BC04DC /* MTMRTests.swift */; };
B082B271205C7D8000BC04DC /* MTMRUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B270205C7D8000BC04DC /* MTMRUITests.swift */; };
B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */; };
B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B09EB1E5207C0F8E00D5C1E0 /* MultitouchSupport.framework */; };
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */; };
B0A8BF9E207B84160086F74D /* weather.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0A8BF9D207B84160086F74D /* weather.scpt */; };
B0C1CFCA205C97D30021C862 /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C1CFC9205C97D30021C862 /* WindowController.swift */; };
B0B17431207D6B590004B740 /* PlaySmart.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B17427207D6B580004B740 /* PlaySmart.scpt */; };
B0B17432207D6B590004B740 /* Weather.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B17428207D6B580004B740 /* Weather.scpt */; };
B0B17433207D6B590004B740 /* Finder.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B17429207D6B580004B740 /* Finder.scpt */; };
B0B17434207D6B590004B740 /* Battery.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B1742A207D6B580004B740 /* Battery.scpt */; };
B0B17435207D6B590004B740 /* Spotify.next.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B1742B207D6B590004B740 /* Spotify.next.scpt */; };
B0B17436207D6B590004B740 /* iTunes.next.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B1742C207D6B590004B740 /* iTunes.next.scpt */; };
B0B17437207D6B590004B740 /* Spotify.nowPlaying.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B1742D207D6B590004B740 /* Spotify.nowPlaying.scpt */; };
B0B17438207D6B590004B740 /* Vox.next.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B1742E207D6B590004B740 /* Vox.next.scpt */; };
B0B17439207D6B590004B740 /* Vox.nowPlaying.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B1742F207D6B590004B740 /* Vox.nowPlaying.scpt */; };
B0B1743A207D6B590004B740 /* iTunes.nowPlaying.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0B17430207D6B590004B740 /* iTunes.nowPlaying.scpt */; };
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */; };
B0F8771D207AD35400D6E430 /* battery.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B0F8771C207AD35400D6E430 /* battery.scpt */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -33,43 +43,44 @@
remoteGlobalIDString = B082B24E205C7D8000BC04DC;
remoteInfo = MTMR;
};
B082B26D205C7D8000BC04DC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B082B247205C7D8000BC04DC /* Project object */;
proxyType = 1;
remoteGlobalIDString = B082B24E205C7D8000BC04DC;
remoteInfo = MTMR;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
36BDC22F207CDA8600FCFEBE /* TECHNICAL_DEBT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = TECHNICAL_DEBT.md; sourceTree = "<group>"; };
36C2ECD2207B3B1D003CDA33 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeTouchBarItem.swift; sourceTree = "<group>"; };
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleScriptTouchBarItem.swift; sourceTree = "<group>"; };
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsParsing.swift; sourceTree = "<group>"; };
36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseConfigTests.swift; sourceTree = "<group>"; };
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = defaultPreset.json; sourceTree = "<group>"; };
B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = "<group>"; };
B059D623205E04F3006E6B86 /* TouchBarItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarItems.swift; sourceTree = "<group>"; };
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButtonTouchBarItem.swift; sourceTree = "<group>"; };
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = "<group>"; };
B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TouchBarPrivateApi-Bridging.h"; sourceTree = "<group>"; };
B059D62C205F11E8006E6B86 /* DFRFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DFRFoundation.framework; path = ../../../../../System/Library/PrivateFrameworks/DFRFoundation.framework; sourceTree = "<group>"; };
B082B24F205C7D8000BC04DC /* MTMR.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MTMR.app; sourceTree = BUILT_PRODUCTS_DIR; };
B082B252205C7D8000BC04DC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
B082B254205C7D8000BC04DC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
B082B256205C7D8000BC04DC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
B082B259205C7D8000BC04DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
B082B25B205C7D8000BC04DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B082B25C205C7D8000BC04DC /* MTMR.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MTMR.entitlements; sourceTree = "<group>"; };
B082B261205C7D8000BC04DC /* MTMRTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MTMRTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
B082B265205C7D8000BC04DC /* MTMRTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MTMRTests.swift; sourceTree = "<group>"; };
B082B267205C7D8000BC04DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B082B26C205C7D8000BC04DC /* MTMRUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MTMRUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
B082B270205C7D8000BC04DC /* MTMRUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MTMRUITests.swift; sourceTree = "<group>"; };
B082B272205C7D8000BC04DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticFeedback.swift; sourceTree = "<group>"; };
B09EB1E5207C0F8E00D5C1E0 /* MultitouchSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MultitouchSupport.framework; path = ../../../../../System/Library/PrivateFrameworks/MultitouchSupport.framework; sourceTree = "<group>"; };
B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPress.swift; sourceTree = "<group>"; };
B0A8BF9D207B84160086F74D /* weather.scpt */ = {isa = PBXFileReference; lastKnownFileType = text; path = weather.scpt; sourceTree = "<group>"; };
B0C1CFC9205C97D30021C862 /* WindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = "<group>"; };
B0B17427207D6B580004B740 /* PlaySmart.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PlaySmart.scpt; sourceTree = "<group>"; };
B0B17428207D6B580004B740 /* Weather.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Weather.scpt; sourceTree = "<group>"; };
B0B17429207D6B580004B740 /* Finder.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Finder.scpt; sourceTree = "<group>"; };
B0B1742A207D6B580004B740 /* Battery.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Battery.scpt; sourceTree = "<group>"; };
B0B1742B207D6B590004B740 /* Spotify.next.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Spotify.next.scpt; sourceTree = "<group>"; };
B0B1742C207D6B590004B740 /* iTunes.next.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = iTunes.next.scpt; sourceTree = "<group>"; };
B0B1742D207D6B590004B740 /* Spotify.nowPlaying.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Spotify.nowPlaying.scpt; sourceTree = "<group>"; };
B0B1742E207D6B590004B740 /* Vox.next.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Vox.next.scpt; sourceTree = "<group>"; };
B0B1742F207D6B590004B740 /* Vox.nowPlaying.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Vox.nowPlaying.scpt; sourceTree = "<group>"; };
B0B17430207D6B590004B740 /* iTunes.nowPlaying.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = iTunes.nowPlaying.scpt; sourceTree = "<group>"; };
B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TouchBarSupport.m; sourceTree = "<group>"; };
B0F8771B207AC92700D6E430 /* TouchBarSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarSupport.h; sourceTree = "<group>"; };
B0F8771C207AD35400D6E430 /* battery.scpt */ = {isa = PBXFileReference; lastKnownFileType = text; path = battery.scpt; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -78,6 +89,7 @@
buildActionMask = 2147483647;
files = (
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */,
B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -88,19 +100,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B082B269205C7D8000BC04DC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B059D62B205F11E8006E6B86 /* Frameworks */ = {
isa = PBXGroup;
children = (
B09EB1E5207C0F8E00D5C1E0 /* MultitouchSupport.framework */,
B059D62C205F11E8006E6B86 /* DFRFoundation.framework */,
);
name = Frameworks;
@@ -110,9 +116,9 @@
isa = PBXGroup;
children = (
36C2ECD2207B3B1D003CDA33 /* README.md */,
36BDC22F207CDA8600FCFEBE /* TECHNICAL_DEBT.md */,
B082B251205C7D8000BC04DC /* MTMR */,
B082B264205C7D8000BC04DC /* MTMRTests */,
B082B26F205C7D8000BC04DC /* MTMRUITests */,
B082B250205C7D8000BC04DC /* Products */,
B059D62B205F11E8006E6B86 /* Frameworks */,
);
@@ -123,7 +129,6 @@
children = (
B082B24F205C7D8000BC04DC /* MTMR.app */,
B082B261205C7D8000BC04DC /* MTMRTests.xctest */,
B082B26C205C7D8000BC04DC /* MTMRUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -131,24 +136,21 @@
B082B251205C7D8000BC04DC /* MTMR */ = {
isa = PBXGroup;
children = (
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */,
B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */,
B0B1743B207D6ED40004B740 /* CBridge */,
B0B17426207D6AFE0004B740 /* AppleScripts */,
B082B252205C7D8000BC04DC /* AppDelegate.swift */,
B082B254205C7D8000BC04DC /* ViewController.swift */,
B082B256205C7D8000BC04DC /* Assets.xcassets */,
B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */,
B059D623205E04F3006E6B86 /* TouchBarItems.swift */,
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */,
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */,
36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */,
B059D621205E03F5006E6B86 /* TouchBarController.swift */,
B0C1CFC9205C97D30021C862 /* WindowController.swift */,
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */,
B082B258205C7D8000BC04DC /* Main.storyboard */,
B082B25B205C7D8000BC04DC /* Info.plist */,
B082B25C205C7D8000BC04DC /* MTMR.entitlements */,
B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */,
B0F8771B207AC92700D6E430 /* TouchBarSupport.h */,
B0F8771C207AD35400D6E430 /* battery.scpt */,
B0A8BF9D207B84160086F74D /* weather.scpt */,
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */,
);
path = MTMR;
sourceTree = "<group>";
@@ -156,19 +158,38 @@
B082B264205C7D8000BC04DC /* MTMRTests */ = {
isa = PBXGroup;
children = (
B082B265205C7D8000BC04DC /* MTMRTests.swift */,
36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */,
B082B267205C7D8000BC04DC /* Info.plist */,
);
path = MTMRTests;
sourceTree = "<group>";
};
B082B26F205C7D8000BC04DC /* MTMRUITests */ = {
B0B17426207D6AFE0004B740 /* AppleScripts */ = {
isa = PBXGroup;
children = (
B082B270205C7D8000BC04DC /* MTMRUITests.swift */,
B082B272205C7D8000BC04DC /* Info.plist */,
B0B1742A207D6B580004B740 /* Battery.scpt */,
B0B17429207D6B580004B740 /* Finder.scpt */,
B0B1742C207D6B590004B740 /* iTunes.next.scpt */,
B0B17430207D6B590004B740 /* iTunes.nowPlaying.scpt */,
B0B17427207D6B580004B740 /* PlaySmart.scpt */,
B0B1742B207D6B590004B740 /* Spotify.next.scpt */,
B0B1742D207D6B590004B740 /* Spotify.nowPlaying.scpt */,
B0B1742E207D6B590004B740 /* Vox.next.scpt */,
B0B1742F207D6B590004B740 /* Vox.nowPlaying.scpt */,
B0B17428207D6B580004B740 /* Weather.scpt */,
);
path = MTMRUITests;
path = AppleScripts;
sourceTree = "<group>";
};
B0B1743B207D6ED40004B740 /* CBridge */ = {
isa = PBXGroup;
children = (
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */,
B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */,
B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */,
B0F8771B207AC92700D6E430 /* TouchBarSupport.h */,
);
path = CBridge;
sourceTree = "<group>";
};
/* End PBXGroup section */
@@ -209,24 +230,6 @@
productReference = B082B261205C7D8000BC04DC /* MTMRTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
B082B26B205C7D8000BC04DC /* MTMRUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = B082B27B205C7D8000BC04DC /* Build configuration list for PBXNativeTarget "MTMRUITests" */;
buildPhases = (
B082B268205C7D8000BC04DC /* Sources */,
B082B269205C7D8000BC04DC /* Frameworks */,
B082B26A205C7D8000BC04DC /* Resources */,
);
buildRules = (
);
dependencies = (
B082B26E205C7D8000BC04DC /* PBXTargetDependency */,
);
name = MTMRUITests;
productName = MTMRUITests;
productReference = B082B26C205C7D8000BC04DC /* MTMRUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -239,7 +242,7 @@
TargetAttributes = {
B082B24E205C7D8000BC04DC = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 0;
@@ -248,13 +251,6 @@
};
B082B260205C7D8000BC04DC = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
TestTargetID = B082B24E205C7D8000BC04DC;
};
B082B26B205C7D8000BC04DC = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
TestTargetID = B082B24E205C7D8000BC04DC;
};
};
};
@@ -273,7 +269,6 @@
targets = (
B082B24E205C7D8000BC04DC /* MTMR */,
B082B260205C7D8000BC04DC /* MTMRTests */,
B082B26B205C7D8000BC04DC /* MTMRUITests */,
);
};
/* End PBXProject section */
@@ -283,10 +278,19 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B0A8BF9E207B84160086F74D /* weather.scpt in Resources */,
B0B17434207D6B590004B740 /* Battery.scpt in Resources */,
B0B1743A207D6B590004B740 /* iTunes.nowPlaying.scpt in Resources */,
B082B257205C7D8000BC04DC /* Assets.xcassets in Resources */,
B0B17437207D6B590004B740 /* Spotify.nowPlaying.scpt in Resources */,
B0B17436207D6B590004B740 /* iTunes.next.scpt in Resources */,
B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */,
B0F8771D207AD35400D6E430 /* battery.scpt in Resources */,
B0B17435207D6B590004B740 /* Spotify.next.scpt in Resources */,
B0B17433207D6B590004B740 /* Finder.scpt in Resources */,
B0B17439207D6B590004B740 /* Vox.nowPlaying.scpt in Resources */,
B0B17438207D6B590004B740 /* Vox.next.scpt in Resources */,
36C2ECE0207CB1B0003CDA33 /* defaultPreset.json in Resources */,
B0B17432207D6B590004B740 /* Weather.scpt in Resources */,
B0B17431207D6B590004B740 /* PlaySmart.scpt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -297,13 +301,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B082B26A205C7D8000BC04DC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -313,11 +310,11 @@
files = (
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
B082B255205C7D8000BC04DC /* ViewController.swift in Sources */,
B0C1CFCA205C97D30021C862 /* WindowController.swift in Sources */,
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
B059D624205E04F3006E6B86 /* TouchBarItems.swift in Sources */,
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */,
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
);
@@ -327,15 +324,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B082B266205C7D8000BC04DC /* MTMRTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B082B268205C7D8000BC04DC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B082B271205C7D8000BC04DC /* MTMRUITests.swift in Sources */,
36C2ECDD207C723B003CDA33 /* ParseConfigTests.swift in Sources */,
36C2ECDE207C82DE003CDA33 /* ItemsParsing.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -347,11 +337,6 @@
target = B082B24E205C7D8000BC04DC /* MTMR */;
targetProxy = B082B262205C7D8000BC04DC /* PBXContainerItemProxy */;
};
B082B26E205C7D8000BC04DC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = B082B24E205C7D8000BC04DC /* MTMR */;
targetProxy = B082B26D205C7D8000BC04DC /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -397,7 +382,6 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -480,9 +464,8 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = D6D8BR2QNB;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
@@ -491,7 +474,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "MTMR/TouchBarPrivateApi-Bridging.h";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "MTMR/CBridge/TouchBarPrivateApi-Bridging.h";
SWIFT_VERSION = 4.0;
};
name = Debug;
@@ -500,7 +484,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = D6D8BR2QNB;
FRAMEWORK_SEARCH_PATHS = (
@@ -511,7 +495,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "MTMR/TouchBarPrivateApi-Bridging.h";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "MTMR/CBridge/TouchBarPrivateApi-Bridging.h";
SWIFT_VERSION = 4.0;
};
name = Release;
@@ -520,16 +505,12 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = D6D8BR2QNB;
INFOPLIST_FILE = MTMRTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMRTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MTMR.app/Contents/MacOS/MTMR";
};
name = Debug;
};
@@ -537,48 +518,14 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = D6D8BR2QNB;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = MTMRTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMRTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MTMR.app/Contents/MacOS/MTMR";
};
name = Release;
};
B082B27C205C7D8000BC04DC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = D6D8BR2QNB;
INFOPLIST_FILE = MTMRUITests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMRUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
TEST_TARGET_NAME = MTMR;
};
name = Debug;
};
B082B27D205C7D8000BC04DC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = D6D8BR2QNB;
INFOPLIST_FILE = MTMRUITests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMRUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
TEST_TARGET_NAME = MTMR;
};
name = Release;
};
@@ -612,15 +559,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B082B27B205C7D8000BC04DC /* Build configuration list for PBXNativeTarget "MTMRUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B082B27C205C7D8000BC04DC /* Debug */,
B082B27D205C7D8000BC04DC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = B082B247205C7D8000BC04DC /* Project object */;
+21 -3
View File
@@ -10,16 +10,34 @@ import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
func applicationDidFinishLaunching(_ aNotification: Notification) {
TouchBarController.shared.setupControlStripPresence()
// Insert code here to initialize your application
TouchBarController.shared.setupControlStripPresence()
if let button = statusItem.button {
button.image = #imageLiteral(resourceName: "StatusImage")
}
createMenu()
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
@objc func testFn(_ sender: Any?) {
let quoteText = "You click on menu"
print(quoteText)
}
func createMenu() {
let menu = NSMenu()
menu.addItem(withTitle: "Preferences", action: #selector(testFn(_:)), keyEquivalent: ",")
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")
statusItem.menu = menu
}
}
+41 -14
View File
@@ -1,28 +1,47 @@
import Foundation
class AppleScriptTouchBarItem: NSCustomTouchBarItem {
let script: NSAppleScript
private var timer: Timer!
private let button = NSButton(title: "", target: nil, action: nil)
class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
private var script: NSAppleScript!
private let interval: TimeInterval
private var forceHideConstraint: NSLayoutConstraint!
init?(identifier: NSTouchBarItem.Identifier, appleScript: String, interval: TimeInterval) {
guard let script = NSAppleScript(source: appleScript) else {
return nil
init?(identifier: NSTouchBarItem.Identifier, source: Source, interval: TimeInterval, onTap: @escaping ()->()) {
self.interval = interval
super.init(identifier: identifier, title: "compile", onTap: onTap)
self.forceHideConstraint = self.view.widthAnchor.constraint(equalToConstant: 0)
guard let script = source.appleScript else {
button.title = "no script"
return
}
self.script = script
super.init(identifier: identifier)
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
self.view = button
button.bezelColor = .clear
refresh()
DispatchQueue.main.async {
var error: NSDictionary?
guard script.compileAndReturnError(&error) else {
print(error?.description ?? "unknown error")
DispatchQueue.main.async {
self.button.title = "compile error"
}
return
}
self.refreshAndSchedule()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func refresh() {
self.button.title = self.execute()
func refreshAndSchedule() {
print("refresh happened")
let scriptResult = self.execute()
DispatchQueue.main.async {
self.button.title = scriptResult
self.forceHideConstraint.isActive = scriptResult == ""
}
DispatchQueue.main.asyncAfter(deadline: .now() + self.interval) { [weak self] in
self?.refreshAndSchedule()
}
}
func execute() -> String {
@@ -32,6 +51,14 @@ class AppleScriptTouchBarItem: NSCustomTouchBarItem {
print(error)
return "error"
}
return output.stringValue ?? "empty value"
return output.stringValue ?? ""
}
}
extension Source {
var appleScript: NSAppleScript? {
guard let source = self.string else { return nil }
return NSAppleScript(source: source)
}
}
@@ -3,27 +3,27 @@ set percent to word 6 of theList's item 2
set charge to word 7 of theList's item 2
if (charge = "charging") then
set iconC to "⚡️"
set iconC to "⚡️"
else
set iconC to ""
set iconC to ""
end if
set remainingRaw to my split(theList's item 2, " ")
set remainingTime to remainingRaw's item 5
if (remainingTime = "(no") then
set strTime to " (?)"
set strTime to " (?)"
else if (remainingTime = "0:00") then
set strTime to ""
set strTime to ""
else
set strTime to " (" & remainingTime & ")"
set strTime to " (" & remainingTime & ")"
end if
return iconC & percent & "%" & strTime
to split(someText, delimiter)
set AppleScript's text item delimiters to delimiter
set someText to someText's text items
set AppleScript's text item delimiters to {""}
return someText
set AppleScript's text item delimiters to delimiter
set someText to someText's text items
set AppleScript's text item delimiters to {""}
return someText
end split
+5
View File
@@ -0,0 +1,5 @@
tell application "Finder"
make new Finder window
set target of front window to path to home folder as string
activate
end tell
+11
View File
@@ -0,0 +1,11 @@
if application "iTunes" is running then
tell application "iTunes" to playpause
end if
if application "Spotify" is running then
tell application "Spotify" to playpause
end if
if application "VOX" is running then
tell application "VOX" to playpause
end if
+7
View File
@@ -0,0 +1,7 @@
if application "Spotify" is running then
tell application "Spotify"
if player state is playing then
next track
end if
end tell
end if
+10
View File
@@ -0,0 +1,10 @@
if application "Spotify" is running then
tell application "Spotify"
if player state is playing then
return (get artist of current track) & " – " & (get name of current track)
else
return ""
end if
end tell
end if
return ""
+7
View File
@@ -0,0 +1,7 @@
if application "VOX" is running then
tell application "VOX"
if player state is 1 then
next
end if
end tell
end if
+10
View File
@@ -0,0 +1,10 @@
if application "VOX" is running then
tell application "VOX"
if player state is 1 then
return (get artist) & " – " & (get track)
else
return ""
end if
end tell
end if
return ""
+32
View File
@@ -0,0 +1,32 @@
# This script requires two libs. Download them:
# https://itunes.apple.com/ru/app/json-helper-for-applescript/id453114608?l=en&mt=12
# https://itunes.apple.com/ru/app/location-helper-for-applescript/id488536386?mt=12
tell application "Location Helper"
set clocation_coords to get location coordinates
tell application "JSON Helper"
set weather to fetch JSON from "http://api.openweathermap.org/data/2.5/weather?lat=" & item 1 of clocation_coords & "&lon=" & item 2 of clocation_coords & "&units=metric&appid=32c4256d09a4c52b38aecddba7a078f6"
set temp to temp of main of weather as string
set cond_icon to icon of item 1 of weather of weather as string
if cond_icon is in ["01d", "01n"] then
set cond to "☀️"
else if cond_icon is in ["02d", "02n"] then
set cond to "⛅️"
else if cond_icon is in ["03d", "03n", "04d", "04n"] then
set cond to "☁️"
else if cond_icon is in ["09d", "09n"] then
set cond to "🌧"
else if cond_icon is in ["10d", "10n"] then
set cond to "🌦"
else if cond_icon is in ["11d", "11n"] then
set cond to "🌩"
else if cond_icon is in ["13d", "13n"] then
set cond to "❄️"
else if cond_icon is in ["50d", "50n"] then
set cond to "🌫"
else
set cond to ""
end if
set temp_round to round (temp * 1.0)
return cond & " " & temp_round & "°C"
end tell
end tell
+7
View File
@@ -0,0 +1,7 @@
if application "iTunes" is running then
tell application "iTunes"
if player state is playing then
next track
end if
end tell
end if
+10
View File
@@ -0,0 +1,10 @@
if application "iTunes" is running then
tell application "iTunes"
if player state is playing then
return (get artist of current track) & " – " & (get name of current track)
else
return ""
end if
end tell
end if
return ""
@@ -1,53 +1,63 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"idiom" : "mac",
"filename" : "logo-16.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"idiom" : "mac",
"filename" : "logo-32.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"idiom" : "mac",
"filename" : "logo-32.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"idiom" : "mac",
"filename" : "logo-64.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"idiom" : "mac",
"filename" : "logo-128.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"idiom" : "mac",
"filename" : "logo-256.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"idiom" : "mac",
"filename" : "logo-256.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"idiom" : "mac",
"filename" : "logo-512.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"idiom" : "mac",
"filename" : "logo-512.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"idiom" : "mac",
"filename" : "logo-1024.png",
"scale" : "2x"
}
],
Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+24
View File
@@ -0,0 +1,24 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "StatusImage.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+2 -47
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
@@ -680,50 +680,5 @@
</objects>
<point key="canvasLocation" x="75" y="0.0"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" customClass="WindowController" customModule="MTMR" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1028"/>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
<connections>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="250"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModule="MTMR" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="178" height="57"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bso-ZY-Qqn">
<rect key="frame" x="18" y="20" width="142" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="My TouchBar. My rules" id="cmP-Ef-Jrj">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="74" y="613"/>
</scene>
</scenes>
</document>
@@ -0,0 +1,20 @@
//
// TouchBarPrivateApi-Bridging.h
// MTMR
//
// Created by Anton Palgunov on 18/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
#import "TouchBarPrivateApi.h"
#import "TouchBarSupport.h"
NS_ASSUME_NONNULL_BEGIN
CF_EXPORT CFTypeRef MTActuatorCreateFromDeviceID(UInt64 deviceID);
CF_EXPORT IOReturn MTActuatorOpen(CFTypeRef actuatorRef);
CF_EXPORT IOReturn MTActuatorClose(CFTypeRef actuatorRef);
CF_EXPORT IOReturn MTActuatorActuate(CFTypeRef actuatorRef, SInt32 actuationID, UInt32 arg1, Float32 arg2, Float32 arg3);
CF_EXPORT bool MTActuatorIsOpen(CFTypeRef actuatorRef);
NS_ASSUME_NONNULL_END
+37
View File
@@ -0,0 +1,37 @@
//
// TouchBarItems.swift
// MTMR
//
// Created by Anton Palgunov on 18/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import Cocoa
class CustomButtonTouchBarItem: NSCustomTouchBarItem {
let tapClosure: () -> ()
private(set) var button: NSButton!
init(identifier: NSTouchBarItem.Identifier, title: String, onTap callback: @escaping () -> (), image: NSImage? = nil) {
self.tapClosure = callback
super.init(identifier: identifier)
if let image = image {
button = NSButton(title: title, image: image, target: self, action: #selector(didTapped))
button.bezelColor = .clear
} else {
button = NSButton(title: title, target: self, action: #selector(didTapped))
}
self.view = button
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didTapped() {
self.tapClosure()
let hf: HapticFeedback = HapticFeedback()
hf.tap(strong: 6)
}
}
+58
View File
@@ -0,0 +1,58 @@
//
// HapticFeedback.swift
// MTMR
//
// Created by Anton Palgunov on 09/04/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import IOKit
class HapticFeedback {
private var actuatorRef: CFTypeRef?
private var deviceID: UInt64 = 0x200000001000000
private var error: IOReturn = 0
// Don't know how to do strong is enum one of
// 1 like back Click
// 2 like Click
// 3 week
// 4 medium
// 5 week medium
// 6 strong
// 15 nothing
// 16 nothing
// you can get a plist `otool -s __TEXT __tpad_act_plist /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/Current/MultitouchSupport|tail -n +3|awk -F'\t' '{print $2}'|xxd -r -p`
func tap(strong:Int32) -> Void {
let actuatorRef = MTActuatorCreateFromDeviceID(deviceID).takeRetainedValue()
// TODO: Need to fix warning
guard actuatorRef != nil else {
print("guard actuatorRef == nil")
return
}
error = MTActuatorOpen(actuatorRef)
guard error == kIOReturnSuccess else {
print("guard MTActuatorOpen")
return
}
error = MTActuatorActuate(actuatorRef, strong, 0, 0.0, 0.0)
guard error == kIOReturnSuccess else {
print("guard MTActuatorActuate")
return
}
error = MTActuatorClose(actuatorRef)
guard error == kIOReturnSuccess else {
print("guard MTActuatorClose")
return
}
return
}
}
+3 -1
View File
@@ -17,11 +17,13 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>0.6</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 Anton Palgunov. All rights reserved.</string>
<key>NSMainStoryboardFile</key>
+280
View File
@@ -0,0 +1,280 @@
import Foundation
extension Data {
func barItemDefinitions() -> [BarItemDefinition]? {
return try? JSONDecoder().decode([BarItemDefinition].self, from: self)
}
}
struct BarItemDefinition: Decodable {
let type: ItemType
let action: ActionType
let additionalParameters: [GeneralParameter]
private enum CodingKeys: String, CodingKey {
case type
}
init(type: ItemType, action: ActionType, additionalParameters: [GeneralParameter]) {
self.type = type
self.action = action
self.additionalParameters = additionalParameters
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(String.self, forKey: .type)
let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type)
let additionalParameters = try GeneralParameters(from: decoder).parameters
if let result = try? parametersDecoder(decoder),
case let (itemType, action) = result {
self.init(type: itemType, action: action, additionalParameters: additionalParameters)
} else {
self.init(type: .staticButton(title: "unknown"), action: .none, additionalParameters: additionalParameters)
}
}
}
class SupportedTypesHolder {
typealias ParametersDecoder = (Decoder) throws ->(item: ItemType, action: ActionType)
private var supportedTypes: [String: ParametersDecoder] = [
"escape": { _ in return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53)) },
"brightnessUp": { _ in return (item: .staticButton(title: "🔆"), action: .keyPress(keycode: 113)) },
"brightnessDown": { _ in return (item: .staticButton(title: "🔅"), action: .keyPress(keycode: 107)) },
"volumeDown": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarVolumeDownTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN)) },
"volumeUp": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarVolumeUpTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP)) },
"previous": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarRewindTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS)) },
"play": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarPlayPauseTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_PLAY)) },
"next": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarFastForwardTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_NEXT)) },
"weather": { decoder in
enum CodingKeys: String, CodingKey { case refreshInterval }
let container = try decoder.container(keyedBy: CodingKeys.self)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
let scriptPath = Bundle.main.path(forResource: "Weather", ofType: "scpt")!
let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0)
return (item: item, action: .none)
},
"battery": { decoder in
enum CodingKeys: String, CodingKey { case refreshInterval }
let container = try decoder.container(keyedBy: CodingKeys.self)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
let scriptPath = Bundle.main.path(forResource: "Battery", ofType: "scpt")!
let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0)
return (item: item, action: .none)
},
"sleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]) ) },
"displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]) ) },
]
static let sharedInstance = SupportedTypesHolder()
func lookup(by type: String) -> ParametersDecoder {
return supportedTypes[type] ?? { decoder in
return (item: try ItemType(from: decoder), action: try ActionType(from: decoder))
}
}
func register(typename: String, decoder: @escaping ParametersDecoder) {
supportedTypes[typename] = decoder
}
func register(typename: String, item: ItemType, action: ActionType) {
register(typename: typename) { _ in
return (item: item, action: action)
}
}
}
enum ItemType: Decodable {
case staticButton(title: String)
case staticImageButton(title: String, image: NSImage)
case appleScriptTitledButton(source: Source, refreshInterval: Double)
case timeButton(formatTemplate: String)
case flexSpace()
private enum CodingKeys: String, CodingKey {
case type
case title
case source
case refreshInterval
case formatTemplate
case image
}
enum ItemTypeRaw: String, Decodable {
case staticButton
case staticImageButton
case appleScriptTitledButton
case timeButton
case flexSpace
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(ItemTypeRaw.self, forKey: .type)
switch type {
case .appleScriptTitledButton:
let source = try container.decode(Source.self, forKey: .source)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
self = .appleScriptTitledButton(source: source, refreshInterval: interval)
case .staticImageButton:
let title = try container.decode(String.self, forKey: .title)
let imageRaw = try container.decode(String.self, forKey: .image)
if let decodedImageData = Data(base64Encoded: imageRaw, options: .ignoreUnknownCharacters) {
let decImage = NSImage(data: decodedImageData)!
self = .staticImageButton(title: title, image: decImage)
} else {
self = .staticButton(title: title)
}
case .staticButton:
let title = try container.decode(String.self, forKey: .title)
self = .staticButton(title: title)
case .timeButton:
let template = try container.decodeIfPresent(String.self, forKey: .formatTemplate) ?? "HH:mm"
self = .timeButton(formatTemplate: template)
case .flexSpace:
self = .flexSpace()
}
}
}
enum ActionType: Decodable {
case none
case hidKey(keycode: Int)
case keyPress(keycode: Int)
case appleSctipt(source: Source)
case shellScript(executable: String, parameters: [String])
case custom(closure: ()->())
private enum CodingKeys: String, CodingKey {
case action
case keycode
case actionAppleScript
case executablePath
case shellArguments
}
private enum ActionTypeRaw: String, Decodable {
case hidKey
case keyPress
case appleScript
case shellScript
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decodeIfPresent(ActionTypeRaw.self, forKey: .action)
switch type {
case .some(.hidKey):
let keycode = try container.decode(Int.self, forKey: .keycode)
self = .hidKey(keycode: keycode)
case .some(.keyPress):
let keycode = try container.decode(Int.self, forKey: .keycode)
self = .keyPress(keycode: keycode)
case .some(.appleScript):
let source = try container.decode(Source.self, forKey: .actionAppleScript)
self = .appleSctipt(source: source)
case .some(.shellScript):
let executable = try container.decode(String.self, forKey: .executablePath)
let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? []
self = .shellScript(executable: executable, parameters: parameters)
case .none:
self = .none
}
}
}
extension ItemType: Equatable {}
func ==(lhs: ItemType, rhs: ItemType) -> Bool {
switch (lhs, rhs) {
case let (.staticButton(a), .staticButton(b)):
return a == b
case let (.flexSpace(a), .flexSpace(b)):
return a == b
case let (.appleScriptTitledButton(a, b), .appleScriptTitledButton(c, d)):
return a == c && b == d
default:
return false
}
}
extension ActionType: Equatable {}
func ==(lhs: ActionType, rhs: ActionType) -> Bool {
switch (lhs, rhs) {
case (.none, .none):
return true
case let (.hidKey(a), .hidKey(b)),
let (.keyPress(a), .keyPress(b)):
return a == b
case let (.appleSctipt(a), .appleSctipt(b)):
return a == b
case let (.shellScript(a, b), .shellScript(c, d)):
return a == c && b == d
default:
return false
}
}
enum GeneralParameter {
case width(_: CGFloat)
}
struct GeneralParameters: Decodable {
let parameters: [GeneralParameter]
fileprivate enum CodingKeys: String, CodingKey {
case width
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
var result: [GeneralParameter] = []
if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) {
result.append(.width(value))
}
parameters = result
}
}
struct Source: Decodable {
let filePath: String?
let base64: String?
let inline: String?
var data: Data? {
return base64?.base64Data ?? inline?.data(using: .utf8) ?? filePath?.fileData
}
var string: String? {
return inline ?? self.data?.base64Content
}
private init(filePath: String?, base64: String?, inline: String?) {
self.filePath = filePath
self.base64 = base64
self.inline = inline
}
init(filePath: String) {
self.init(filePath: filePath, base64: nil, inline: nil)
}
}
extension Source: Equatable {}
func ==(left: Source, right: Source) -> Bool {
return left.data == right.data
}
extension String {
var base64Data: Data? {
return Data(base64Encoded: self)
}
var fileData: Data? {
return try? Data(contentsOf: URL(fileURLWithPath: self))
}
}
extension Data {
var base64Content: String? {
return String(data: self, encoding: .utf8)
}
}
+4 -13
View File
@@ -13,6 +13,10 @@ protocol KeyPress {
func send()
}
struct GenericKeyPress: KeyPress {
var keyCode: CGKeyCode
}
extension KeyPress {
func send () {
let src = CGEventSource(stateID: .hidSystemState)
@@ -25,19 +29,6 @@ extension KeyPress {
}
}
struct ESCKeyPress: KeyPress {
let keyCode: CGKeyCode = 53
}
struct BrightnessUpPress: KeyPress {
let keyCode: CGKeyCode = 107
}
struct BrightnessDownPress: KeyPress {
let keyCode: CGKeyCode = 113
}
func doKey(_ key: Int, down: Bool) {
let flags = NSEvent.ModifierFlags(rawValue: down ? 0xa00 : 0xb00)
let data1 = (key << 16) | ((down ? 0xa : 0xb) << 8)
+119 -69
View File
@@ -8,38 +8,74 @@
import Cocoa
struct ExactItem {
let identifier: NSTouchBarItem.Identifier
let presetItem: BarItemDefinition
}
extension ItemType {
var identifierBase: String {
switch self {
case .staticButton(title: _):
return "com.toxblh.mtmr.staticButton."
case .staticImageButton(title: _):
return "com.toxblh.mtmr.staticImageButton."
case .appleScriptTitledButton(source: _):
return "com.toxblh.mtmr.appleScriptButton."
case .timeButton(formatTemplate: _):
return "com.toxblh.mtmr.timeButton."
case .flexSpace():
return "NSTouchBarItem.Identifier.flexibleSpace"
}
}
}
extension NSTouchBarItem.Identifier {
static let controlStripItem = NSTouchBarItem.Identifier("com.toxblh.mtmr.controlStrip")
}
class TouchBarController: NSObject, NSTouchBarDelegate {
static let shared = TouchBarController()
let touchBar = NSTouchBar()
var items: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
private override init() {
super.init()
SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in
self?.dismissTouchBar()
}))
loadItems()
touchBar.delegate = self
touchBar.defaultItemIdentifiers = [
.escButton,
.dismissButton,
.brightDown,
.brightUp,
.flexibleSpace,
.prev,
.play,
.next,
.sleep,
.weather,
.volumeDown,
.volumeUp,
.battery,
.time,
]
self.presentTouchBar()
}
func loadItems() {
let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR")
let presetPath = appSupportDirectory.appending("/items.json")
if !FileManager.default.fileExists(atPath: presetPath),
let defaultPreset = Bundle.main.path(forResource: "defaultPreset", ofType: "json") {
try? FileManager.default.createDirectory(atPath: appSupportDirectory, withIntermediateDirectories: true, attributes: nil)
try? FileManager.default.copyItem(atPath: defaultPreset, toPath: presetPath)
}
let jsonData = presetPath.fileData
let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [])]
for item in jsonItems {
let identifierString = item.type.identifierBase.appending(UUID().uuidString)
let identifier = item.type == ItemType.flexSpace()
? NSTouchBarItem.Identifier.flexibleSpace
: NSTouchBarItem.Identifier(identifierString)
items[identifier] = item
touchBar.defaultItemIdentifiers += [identifier]
}
}
func setupControlStripPresence() {
DFRSystemModalShowsCloseBoxWhenFrontMost(false)
@@ -62,59 +98,73 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
}
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
switch identifier {
case .escButton:
return CustomButtonTouchBarItem(identifier: identifier, title: "esc", key: ESCKeyPress())
case .dismissButton:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "exit", target: self, action: #selector(dismissTouchBar))
return item
case .brightUp:
return CustomButtonTouchBarItem(identifier: identifier, title: "🔆", key: BrightnessUpPress())
case .brightDown:
return CustomButtonTouchBarItem(identifier: identifier, title: "🔅", key: BrightnessDownPress())
case .volumeDown:
return CustomButtonTouchBarItem(identifier: identifier, title: "🔉", HIDKeycode: NX_KEYTYPE_SOUND_DOWN)
case .volumeUp:
return CustomButtonTouchBarItem(identifier: identifier, title: "🔊", HIDKeycode: NX_KEYTYPE_SOUND_UP)
case .weather:
let url = Bundle.main.url(forResource: "weather", withExtension: "scpt")!
let script = try! String.init(contentsOf: url)
return AppleScriptTouchBarItem(identifier: identifier, appleScript: script, interval: 600)
case .prev:
return CustomButtonTouchBarItem(identifier: identifier, title: "⏪", HIDKeycode: NX_KEYTYPE_PREVIOUS)
case .play:
return CustomButtonTouchBarItem(identifier: identifier, title: "⏯", HIDKeycode: NX_KEYTYPE_PLAY)
case .next:
return CustomButtonTouchBarItem(identifier: identifier, title: "⏩", HIDKeycode: NX_KEYTYPE_NEXT)
case .battery:
let url = Bundle.main.url(forResource: "battery", withExtension: "scpt")!
let script = try! String.init(contentsOf: url)
return AppleScriptTouchBarItem(identifier: identifier, appleScript: script, interval: 60)
case .time:
return TimeTouchBarItem(identifier: identifier, formatTemplate: "HH:mm")
default:
guard let item = self.items[identifier] else {
return nil
}
let action = self.action(forItem: item)
var barItem: NSTouchBarItem!
switch item.type {
case .staticButton(title: let title):
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action)
case .staticImageButton(title: let title, image: let image):
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action, image: image)
case .appleScriptTitledButton(source: let source, refreshInterval: let interval):
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, onTap: action)
case .timeButton(formatTemplate: let template):
barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template)
case .flexSpace:
barItem = nil
}
for parameter in item.additionalParameters {
if case .width(let value) = parameter, let widthBarItem = barItem as? CanSetWidth {
widthBarItem.setWidth(value: value)
}
}
return barItem
}
func action(forItem item: BarItemDefinition) -> ()->() {
switch item.action {
case .hidKey(keycode: let keycode):
return { HIDPostAuxKey(keycode) }
case .keyPress(keycode: let keycode):
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
case .appleSctipt(source: let source):
guard let appleScript = source.appleScript else {
print("cannot create apple script for item \(item)")
return {}
}
return {
var error: NSDictionary?
appleScript.executeAndReturnError(&error)
if let error = error {
print("error \(error) when handling \(item) ")
}
}
case .shellScript(executable: let executable, parameters: let parameters):
return {
let task = Process()
task.launchPath = executable
task.arguments = parameters
task.launch()
}
case .custom(closure: let closure):
return closure
case .none:
return {}
}
}
}
extension CustomButtonTouchBarItem {
convenience init(identifier: NSTouchBarItem.Identifier, title: String, HIDKeycode: Int) {
self.init(identifier: identifier, title: title) { _ in
HIDPostAuxKey(HIDKeycode)
}
}
convenience init(identifier: NSTouchBarItem.Identifier, title: String, key: KeyPress) {
self.init(identifier: identifier, title: title) { _ in
key.send()
}
protocol CanSetWidth {
func setWidth(value: CGFloat)
}
extension NSCustomTouchBarItem: CanSetWidth {
func setWidth(value: CGFloat) {
self.view.widthAnchor.constraint(equalToConstant: value).isActive = true
}
}
-55
View File
@@ -1,55 +0,0 @@
//
// TouchBarItems.swift
// MTMR
//
// Created by Anton Palgunov on 18/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import Cocoa
extension NSTouchBarItem.Identifier {
static let escButton = NSTouchBarItem.Identifier("com.toxblh.mtmr.escButton")
static let dismissButton = NSTouchBarItem.Identifier("com.toxblh.mtmr.dismissButton")
// Volume
static let volumeUp = NSTouchBarItem.Identifier("com.toxblh.mtmr.volumeUp")
static let volumeDown = NSTouchBarItem.Identifier("com.toxblh.mtmr.volumeDown")
// Brightness
static let brightUp = NSTouchBarItem.Identifier("com.toxblh.mtmr.brightUp")
static let brightDown = NSTouchBarItem.Identifier("com.toxblh.mtmr.brightDown")
// Music
static let prev = NSTouchBarItem.Identifier("com.toxblh.mtmr.prev")
static let next = NSTouchBarItem.Identifier("com.toxblh.mtmr.next")
static let play = NSTouchBarItem.Identifier("com.toxblh.mtmr.play")
// Plugins
static let sleep = NSTouchBarItem.Identifier("com.toxblh.mtmr.sleep")
static let weather = NSTouchBarItem.Identifier("com.toxblh.mtmr.weather")
static let time = NSTouchBarItem.Identifier("com.toxblh.mtmr.time")
static let battery = NSTouchBarItem.Identifier("com.toxblh.mtmr.battery")
static let nowPlaying = NSTouchBarItem.Identifier("com.toxblh.mtmr.nowPlaying")
static let controlStripItem = NSTouchBarItem.Identifier("com.toxblh.mtmr.controlStrip")
}
class CustomButtonTouchBarItem: NSCustomTouchBarItem {
let tapClosure: (NSCustomTouchBarItem) -> ()
init(identifier: NSTouchBarItem.Identifier, title: String, onTap callback: @escaping (NSCustomTouchBarItem) -> ()) {
self.tapClosure = callback
super.init(identifier: identifier)
self.view = NSButton(title: title, target: self, action: #selector(didTapped))
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didTapped() {
self.tapClosure(self)
}
}
-10
View File
@@ -1,10 +0,0 @@
//
// TouchBarPrivateApi-Bridging.h
// MTMR
//
// Created by Anton Palgunov on 18/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
#import "TouchBarPrivateApi.h"
#import "TouchBarSupport.h"
-27
View File
@@ -1,27 +0,0 @@
//
// ViewController.swift
// MTMR
//
// Created by Anton Palgunov on 16/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
-17
View File
@@ -1,17 +0,0 @@
//
// WindowController.swift
// MTMR
//
// Created by Anton Palgunov on 17/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import Cocoa
class WindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
}
}
+22
View File
@@ -0,0 +1,22 @@
[
{ "type": "escape" },
{ "type": "exitTouchbar" },
{ "type": "brightnessDown" },
{
"type": "staticButton",
"title": "🔆",
"action": "keyPress",
"keycode": 113,
"width": 36,
},
{ "type": "flexSpace" },
{ "type": "volumeDown", "width": 44 },
{ "type": "volumeUp", "width": 44 },
{ "type": "previous" },
{ "type": "play" },
{ "type": "next" },
{ "type": "weather", "refreshInterval": 1800 },
{ "type": "sleep" },
{ "type": "battery" },
{ "type": "timeButton" },
]
-32
View File
@@ -1,32 +0,0 @@
# This script requires two libs. Download them:
# https://itunes.apple.com/ru/app/json-helper-for-applescript/id453114608?l=en&mt=12
# https://itunes.apple.com/ru/app/location-helper-for-applescript/id488536386?mt=12
tell application "Location Helper"
set clocation_coords to get location coordinates
tell application "JSON Helper"
set weather to fetch JSON from "http://api.openweathermap.org/data/2.5/weather?lat=" & item 1 of clocation_coords & "&lon=" & item 2 of clocation_coords & "&units=metric&appid=32c4256d09a4c52b38aecddba7a078f6"
set temp to temp of main of weather as string
set cond_icon to icon of item 1 of weather of weather as string
if cond_icon is in ["01d", "01n"] then
set cond to "☀️"
else if cond_icon is in ["02d", "02n"] then
set cond to "⛅️"
else if cond_icon is in ["03d", "03n", "04d", "04n"] then
set cond to "☁️"
else if cond_icon is in ["09d", "09n"] then
set cond to "🌧"
else if cond_icon is in ["10d", "10n"] then
set cond to "🌦"
else if cond_icon is in ["11d", "11n"] then
set cond to "🌩"
else if cond_icon is in ["13d", "13n"] then
set cond to "❄️"
else if cond_icon is in ["50d", "50n"] then
set cond to "🌫"
else
set cond to ""
end if
set temp_round to round (temp * 1.0)
return cond & " " & temp_round & "°C"
end tell
end tell
-36
View File
@@ -1,36 +0,0 @@
//
// MTMRTests.swift
// MTMRTests
//
// Created by Anton Palgunov on 16/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import XCTest
@testable import MTMR
class MTMRTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
+33
View File
@@ -0,0 +1,33 @@
import XCTest
@testable import MTMR
class ParseConfig: XCTestCase {
func testButtonNoAction() {
let buttonNoActionFixture = """
[ { "type": "staticButton", "title": "Pew" } ]
""".data(using: .utf8)!
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
XCTAssertEqual(result?.first?.type, .staticButton(title: "Pew"))
XCTAssertEqual(result?.first?.action, .some(.none))
}
func testButtonKeyCodeAction() {
let buttonKeycodeFixture = """
[ { "type": "staticButton", "title": "Pew", "action": "hidKey", "keycode": 123} ]
""".data(using: .utf8)!
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonKeycodeFixture)
XCTAssertEqual(result?.first?.type, .staticButton(title: "Pew"))
XCTAssertEqual(result?.first?.action, .hidKey(keycode: 123))
}
func testPredefinedItem() {
let buttonKeycodeFixture = """
[ { "type": "brightnessUp" } ]
""".data(using: .utf8)!
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonKeycodeFixture)
XCTAssertEqual(result?.first?.type, .staticButton(title: "🔆"))
XCTAssertEqual(result?.first?.action, .keyPress(keycode: 113))
}
}
-22
View File
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
-36
View File
@@ -1,36 +0,0 @@
//
// MTMRUITests.swift
// MTMRUITests
//
// Created by Anton Palgunov on 16/03/2018.
// Copyright © 2018 Anton Palgunov. All rights reserved.
//
import XCTest
class MTMRUITests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
XCUIApplication().launch()
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// Use recording to get started writing UI tests.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
}
+21 -3
View File
@@ -1,14 +1,16 @@
<p align="center">
<img src="Resources/logo.png" width="120">
</p>
# My TouchBar. My rules
[![GitHub release](https://img.shields.io/github/release/toxblh/MTMR.svg)](https://github.com/Toxblh/MTMR/releases)
<p align="center">
<img src="Resources/TouchBar-v0.3.png">
</p>
My the idea is to create the program like a platform for plugins for customization TouchBar. I very like BTT and a full custom TouchBar. And I want to create it. And it's my the first Swift project for MacOS :)
My the idea is to create the program like a platform for plugins for customization TouchBar. I very like BTT and a full custom TouchBar (my [BTT preset](https://github.com/Toxblh/btt-touchbar-preset)). And I want to create it. And it's my the first Swift project for MacOS :)
### Roadmap
- [x] Create the first prototype with TouchBar in Storyboard
@@ -17,6 +19,22 @@ My the idea is to create the program like a platform for plugins for customizati
- [x] Time in touchbar!
- [x] First the weather plugin
- [x] Find how to open full-screen TouchBar without the cross and stripe menu
- [ ] Create the same panel like in my [BTT preset](https://github.com/Toxblh/btt-touchbar-preset)
- [ ] Find how to add haptic feedback
- [x] Find how to add haptic feedback
- [x] Add icon and menu in StatusBar
- [x] Hide from Dock
- [x] Status menu: "preferences", "quit"
- [x] JSON or another approch for save preset, maybe in `~/Library/Application Support/MTMR/`
- [ ] Layout: [always left, NSSliderView for center, always right]
- [ ] Custom buttons size, actions by click in settings
- [ ] Overwrite default values from item types (e.g. title for brightness)
- [ ] System for autoupdate (maybe https://sparkle-project.org/)
Settings:
- [ ] Intarface for plugins and export like presets
- [ ] Startup at login
- [ ] Show on/off in Dock
- [ ] Show on/off in StatusBar
- [ ] On/off Haptic Feedback
Maybe:
- [ ] Refactoring the application on packages (AppleScript, JavaScript? and Swift?)
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
## TODOs
* try view controllers on `NSCustomTouchBarItem` instead of subclassing item itself
* try move away from enums when parse preset – enums are hard to extend
* find better way to hide bar items