Compare commits

..
59 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
toxblh af83fa8a72 base added for plugins on appleScript 2018-04-09 12:29:14 +01:00
toxblh ab4aef4e2a added weather 2018-04-09 12:22:31 +01:00
toxblh e3f5da0294 Different approach 2018-04-09 11:59:44 +01:00
toxblh aaa7bc33bc avaliable for >=10.12.2 2018-04-09 11:50:41 +01:00
Anton Palgunov 74d57cdc7d Merge pull request #3 from ReDetection/master
Basic AppleScript support
2018-04-09 11:42:19 +01:00
Serg d48d590462 AppleScript and battery items 2018-04-09 17:32:27 +07:00
Serg b3f461db45 time in separate file, divide bar in two parts 2018-04-09 17:11:52 +07:00
Serg ee0eab6a76 convenient keycode buttons 2018-04-09 17:05:38 +07:00
toxblh 2dc1148a2a fix readme 2018-04-09 08:52:07 +01:00
toxblh d12bdd2bd4 added new screenshot 2018-04-09 08:46:09 +01:00
toxblh 92b6e5ef33 full media keys 2018-04-09 08:40:38 +01:00
Anton Palgunov d97d8efdd4 Merge pull request #2 from Toxblh/add-license-1
Create LICENSE
2018-04-09 08:33:20 +01:00
Anton Palgunov 9f6f7d9404 Create LICENSE 2018-04-09 08:33:02 +01:00
Anton Palgunov 528506f276 Merge pull request #1 from ReDetection/master
TouchBar without the cross and stripe menu
2018-04-09 08:31:34 +01:00
Serg ce7c3c5883 display custom touchbar without control strip and builtin close button 2018-04-09 13:16:14 +07:00
Serg 3d3ad0f076 add readme into project (no target) for convenience 2018-04-09 13:15:52 +07:00
51 changed files with 995 additions and 553 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Anton Palgunov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+104 -152
View File
@@ -7,19 +7,32 @@
objects = {
/* 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 */; };
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 */
@@ -30,39 +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>"; };
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 */
@@ -71,6 +89,7 @@
buildActionMask = 2147483647;
files = (
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */,
B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -81,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;
@@ -102,9 +115,10 @@
B082B246205C7D8000BC04DC = {
isa = PBXGroup;
children = (
36C2ECD2207B3B1D003CDA33 /* README.md */,
36BDC22F207CDA8600FCFEBE /* TECHNICAL_DEBT.md */,
B082B251205C7D8000BC04DC /* MTMR */,
B082B264205C7D8000BC04DC /* MTMRTests */,
B082B26F205C7D8000BC04DC /* MTMRUITests */,
B082B250205C7D8000BC04DC /* Products */,
B059D62B205F11E8006E6B86 /* Frameworks */,
);
@@ -115,7 +129,6 @@
children = (
B082B24F205C7D8000BC04DC /* MTMR.app */,
B082B261205C7D8000BC04DC /* MTMRTests.xctest */,
B082B26C205C7D8000BC04DC /* MTMRUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -123,21 +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 */,
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */,
);
path = MTMR;
sourceTree = "<group>";
@@ -145,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 */
@@ -198,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 */
@@ -228,7 +242,7 @@
TargetAttributes = {
B082B24E205C7D8000BC04DC = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 0;
@@ -237,13 +251,6 @@
};
B082B260205C7D8000BC04DC = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
TestTargetID = B082B24E205C7D8000BC04DC;
};
B082B26B205C7D8000BC04DC = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
TestTargetID = B082B24E205C7D8000BC04DC;
};
};
};
@@ -262,7 +269,6 @@
targets = (
B082B24E205C7D8000BC04DC /* MTMR */,
B082B260205C7D8000BC04DC /* MTMRTests */,
B082B26B205C7D8000BC04DC /* MTMRUITests */,
);
};
/* End PBXProject section */
@@ -272,9 +278,19 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
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;
};
@@ -285,13 +301,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B082B26A205C7D8000BC04DC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -300,12 +309,14 @@
buildActionMask = 2147483647;
files = (
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
B082B255205C7D8000BC04DC /* ViewController.swift in Sources */,
B0C1CFCA205C97D30021C862 /* WindowController.swift in Sources */,
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.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 */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -313,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;
};
@@ -333,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 */
@@ -383,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;
@@ -402,7 +400,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.12.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
@@ -455,7 +453,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.12.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
@@ -466,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",
@@ -477,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;
@@ -486,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 = (
@@ -497,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;
@@ -506,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;
};
@@ -523,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;
};
@@ -598,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 -5
View File
@@ -10,18 +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
}
}
+64
View File
@@ -0,0 +1,64 @@
import Foundation
class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
private var script: NSAppleScript!
private let interval: TimeInterval
private var forceHideConstraint: NSLayoutConstraint!
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
button.bezelColor = .clear
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")
}
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 {
var error: NSDictionary?
let output = script.executeAndReturnError(&error)
if let error = error {
print(error)
return "error"
}
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)
+25
View File
@@ -0,0 +1,25 @@
import Cocoa
class TimeTouchBarItem: NSCustomTouchBarItem {
private let dateFormatter = DateFormatter()
private var timer: Timer!
private let button = NSButton(title: "", target: nil, action: nil)
init(identifier: NSTouchBarItem.Identifier, formatTemplate: String) {
dateFormatter.setLocalizedDateFormatFromTemplate(formatTemplate)
super.init(identifier: identifier)
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
self.view = button
button.bezelColor = .clear
updateTime()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func updateTime() {
button.title = self.dateFormatter.string(from: Date())
}
}
+120 -127
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 timer = Timer()
var timeButton: NSButton = NSButton()
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,
.brightDown,
.brightUp,
.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)
@@ -47,7 +83,6 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
item.view = NSButton(image: #imageLiteral(resourceName: "Strip"), target: self, action: #selector(presentTouchBar))
NSTouchBarItem.addSystemTrayItem(item)
DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true)
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateTime), userInfo: nil, repeats: true)
}
func updateControlStripPresence() {
@@ -55,123 +90,81 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
}
@objc private func presentTouchBar() {
NSTouchBar.presentSystemModalFunctionBar(touchBar, systemTrayItemIdentifier: .controlStripItem)
NSTouchBar.presentSystemModalFunctionBar(touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem)
}
private func dismissTouchBar() {
@objc private func dismissTouchBar() {
NSTouchBar.minimizeSystemModalFunctionBar(touchBar)
}
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
switch identifier {
case .escButton:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "esc", target: self, action: #selector(handleEsc))
return item
case .brightUp:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "🔆", target: self, action: #selector(handleBrightUp))
return item
case .brightDown:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "🔅", target: self, action: #selector(handleBrightDown))
return item
case .volumeDown:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "🔉", target: self, action: #selector(handleVolumeDown))
return item
case .volumeUp:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "🔊", target: self, action: #selector(handleVolumeUp))
return item
// case .prev:
// let item = NSCustomTouchBarItem(identifier: identifier)
// item.view = NSButton(title: "⏪", target: self, action: #selector(handlePrev))
// return item
case .play:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "⏯", target: self, action: #selector(handlePlay))
return item
case .next:
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = NSButton(title: "⏩", target: self, action: #selector(handleNext))
return item
case .time:
let item = NSCustomTouchBarItem(identifier: identifier)
timeButton = NSButton(title: self.getCurrentTime(), target: self, action: nil)
item.view = timeButton
return item
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 getCurrentTime() -> String {
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.setLocalizedDateFormatFromTemplate("HH:mm")
let timestamp = dateFormatter.string(from: date)
return timestamp
}
@objc func updateTime() {
timeButton.title = getCurrentTime()
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 {}
}
}
@objc func handleEsc() {
let sender = ESCKeyPress()
sender.send()
}
@objc func handleVolumeUp() {
HIDPostAuxKey(Int(NX_KEYTYPE_SOUND_UP))
}
@objc func handleVolumeDown() {
HIDPostAuxKey(Int(NX_KEYTYPE_SOUND_DOWN))
}
@objc func handleBrightDown() {
// HIDPostAuxKey(Int(NX_KEYTYPE_BRIGHTNESS_DOWN))
let sender = BrightnessUpPress()
sender.send()
}
@objc func handleBrightUp() {
// HIDPostAuxKey(Int(NX_KEYTYPE_BRIGHTNESS_UP))
let sender = BrightnessDownPress()
sender.send()
}
@objc func handlePrev() {
HIDPostAuxKey(Int(NX_KEYTYPE_PREVIOUS))
}
@objc func handlePlay() {
HIDPostAuxKey(Int(NX_KEYTYPE_PLAY))
}
@objc func handleNext() {
HIDPostAuxKey(Int(NX_KEYTYPE_NEXT))
}
// func getBattery() {
// var error: NSDictionary?
// if let scriptObject = NSAppleScript(source: <#T##String#>) {
// if let output: NSAppleEventDescriptor = scriptObject.executeAndReturnError(
// &error) {
// print(output.stringValue)
// } else if (error != nil) {
// print("error: \(error)")
// }
// }
// }
}
protocol CanSetWidth {
func setWidth(value: CGFloat)
}
extension NSCustomTouchBarItem: CanSetWidth {
func setWidth(value: CGFloat) {
self.view.widthAnchor.constraint(equalToConstant: value).isActive = true
}
}
-35
View File
@@ -1,35 +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")
// 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")
}
-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" },
]
-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.
}
}
+24 -6
View File
@@ -1,22 +1,40 @@
<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/TouchBarV0.1.png">
<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
- [x] Put in stripe menu on startup the application
- [x] Find how to simulate real buttons like brightness, volume, night shift and etc.
- [x] Time in touchbar!
- [ ] First the weather plugin
- [ ] Create the same panel like in my [BTT preset](https://github.com/Toxblh/btt-touchbar-preset)
- [ ] Find how to open full-screen TouchBar without the cross and stripe menu
- [ ] Find how to add haptic feedback
- [x] First the weather plugin
- [x] Find how to open full-screen TouchBar without the cross and stripe menu
- [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.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

+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