mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-11-02 19:28:36 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5bb90249f | ||
|
|
3e82676008 | ||
|
|
a2ad47c7ba | ||
|
|
bbe901a572 | ||
|
|
54eaa3fd9f | ||
|
|
6660bb2d8f | ||
|
|
221cc8a176 | ||
|
|
a6b52ebe95 | ||
|
|
a4fee54ae0 |
+1
-1
@@ -3,4 +3,4 @@
|
|||||||
issuehunt: Toxblh
|
issuehunt: Toxblh
|
||||||
patreon: toxblh
|
patreon: toxblh
|
||||||
ko_fi: toxblh
|
ko_fi: toxblh
|
||||||
custom: https://www.paypal.me/toxblh
|
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WUAAG2HH58WE4
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ playground.xcworkspace
|
|||||||
# Carthage
|
# Carthage
|
||||||
#
|
#
|
||||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
# Carthage/Checkouts
|
Carthage/Checkouts
|
||||||
|
|
||||||
Carthage/Build
|
Carthage/Build
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
github "stephencelis/SQLite.swift" "0.12.2"
|
||||||
@@ -34,10 +34,14 @@
|
|||||||
607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */; };
|
607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */; };
|
||||||
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */; };
|
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */; };
|
||||||
60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */; };
|
60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */; };
|
||||||
|
8338290C2360CA31008981D7 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8338290B2360CA31008981D7 /* SQLite.framework */; };
|
||||||
|
8338290D2360CA3F008981D7 /* SQLite.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = 8338290B2360CA31008981D7 /* SQLite.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
839ECD8523600BF500BE2DA5 /* NotificationTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839ECD8423600BF500BE2DA5 /* NotificationTouchBarItem.swift */; };
|
||||||
|
839ECD882360160100BE2DA5 /* Mail.scpt in Sources */ = {isa = PBXBuildFile; fileRef = 839ECD872360160100BE2DA5 /* Mail.scpt */; };
|
||||||
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; };
|
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; };
|
||||||
B002E642216C0E38002774BA /* CoreDisplay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B002E641216C0E38002774BA /* CoreDisplay.framework */; };
|
B002E642216C0E38002774BA /* CoreDisplay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B002E641216C0E38002774BA /* CoreDisplay.framework */; };
|
||||||
B00D181D2152F4A5000806F4 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; };
|
B00D181D2152F4A5000806F4 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; };
|
||||||
B00D181F2152F521000806F4 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
B00D181F2152F521000806F4 /* Sparkle.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
B04B7BB72087398C00C835D0 /* BatteryBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */; };
|
B04B7BB72087398C00C835D0 /* BatteryBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */; };
|
||||||
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05600D22083E9BB00EB218D /* CustomSlider.swift */; };
|
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05600D22083E9BB00EB218D /* CustomSlider.swift */; };
|
||||||
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
|
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
|
||||||
@@ -75,14 +79,16 @@
|
|||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
B00D181E2152F507000806F4 /* CopyFiles */ = {
|
B00D181E2152F507000806F4 /* Copy Files */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 12;
|
buildActionMask = 12;
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
B00D181F2152F521000806F4 /* Sparkle.framework in CopyFiles */,
|
B00D181F2152F521000806F4 /* Sparkle.framework in Copy Files */,
|
||||||
|
8338290D2360CA3F008981D7 /* SQLite.framework in Copy Files */,
|
||||||
);
|
);
|
||||||
|
name = "Copy Files";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
@@ -119,6 +125,10 @@
|
|||||||
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyBarItem.swift; sourceTree = "<group>"; };
|
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyBarItem.swift; sourceTree = "<group>"; };
|
||||||
60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicBarItem.swift; sourceTree = "<group>"; };
|
60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicBarItem.swift; sourceTree = "<group>"; };
|
||||||
60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputSourceBarItem.swift; sourceTree = "<group>"; };
|
60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputSourceBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
8338290B2360CA31008981D7 /* SQLite.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SQLite.framework; path = Carthage/Build/Mac/SQLite.framework; sourceTree = "<group>"; };
|
||||||
|
839ECD8423600BF500BE2DA5 /* NotificationTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTouchBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
839ECD86236015E300BE2DA5 /* Messages.scpt */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = Messages.scpt; sourceTree = "<group>"; };
|
||||||
|
839ECD872360160100BE2DA5 /* Mail.scpt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Mail.scpt; sourceTree = "<group>"; };
|
||||||
B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = "<group>"; };
|
B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = "<group>"; };
|
||||||
B002E641216C0E38002774BA /* CoreDisplay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreDisplay.framework; path = ../../../../../System/Library/Frameworks/CoreDisplay.framework; sourceTree = "<group>"; };
|
B002E641216C0E38002774BA /* CoreDisplay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreDisplay.framework; path = ../../../../../System/Library/Frameworks/CoreDisplay.framework; sourceTree = "<group>"; };
|
||||||
B00D181C2152F4A5000806F4 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = "<group>"; };
|
B00D181C2152F4A5000806F4 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = "<group>"; };
|
||||||
@@ -174,6 +184,7 @@
|
|||||||
files = (
|
files = (
|
||||||
B002E642216C0E38002774BA /* CoreDisplay.framework in Frameworks */,
|
B002E642216C0E38002774BA /* CoreDisplay.framework in Frameworks */,
|
||||||
B081732A2135F354005D4908 /* CoreBrightness.framework in Frameworks */,
|
B081732A2135F354005D4908 /* CoreBrightness.framework in Frameworks */,
|
||||||
|
8338290C2360CA31008981D7 /* SQLite.framework in Frameworks */,
|
||||||
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */,
|
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */,
|
||||||
B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */,
|
B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */,
|
||||||
B00D181D2152F4A5000806F4 /* Sparkle.framework in Frameworks */,
|
B00D181D2152F4A5000806F4 /* Sparkle.framework in Frameworks */,
|
||||||
@@ -193,6 +204,7 @@
|
|||||||
B059D62B205F11E8006E6B86 /* Frameworks */ = {
|
B059D62B205F11E8006E6B86 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
8338290B2360CA31008981D7 /* SQLite.framework */,
|
||||||
B002E641216C0E38002774BA /* CoreDisplay.framework */,
|
B002E641216C0E38002774BA /* CoreDisplay.framework */,
|
||||||
B00D181C2152F4A5000806F4 /* Sparkle.framework */,
|
B00D181C2152F4A5000806F4 /* Sparkle.framework */,
|
||||||
B08173292135F354005D4908 /* CoreBrightness.framework */,
|
B08173292135F354005D4908 /* CoreBrightness.framework */,
|
||||||
@@ -282,6 +294,8 @@
|
|||||||
B0B1742E207D6B590004B740 /* Vox.next.scpt */,
|
B0B1742E207D6B590004B740 /* Vox.next.scpt */,
|
||||||
B0B1742F207D6B590004B740 /* Vox.nowPlaying.scpt */,
|
B0B1742F207D6B590004B740 /* Vox.nowPlaying.scpt */,
|
||||||
B0B17428207D6B580004B740 /* Weather.scpt */,
|
B0B17428207D6B580004B740 /* Weather.scpt */,
|
||||||
|
839ECD86236015E300BE2DA5 /* Messages.scpt */,
|
||||||
|
839ECD872360160100BE2DA5 /* Mail.scpt */,
|
||||||
);
|
);
|
||||||
path = AppleScripts;
|
path = AppleScripts;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -324,6 +338,7 @@
|
|||||||
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */,
|
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */,
|
||||||
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
|
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
|
||||||
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */,
|
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */,
|
||||||
|
839ECD8423600BF500BE2DA5 /* NotificationTouchBarItem.swift */,
|
||||||
F29F6A2424BC7148004FF8E4 /* UpNextScrubberTouchBarItem.swift */,
|
F29F6A2424BC7148004FF8E4 /* UpNextScrubberTouchBarItem.swift */,
|
||||||
);
|
);
|
||||||
path = Widgets;
|
path = Widgets;
|
||||||
@@ -339,7 +354,7 @@
|
|||||||
B082B24B205C7D8000BC04DC /* Sources */,
|
B082B24B205C7D8000BC04DC /* Sources */,
|
||||||
B082B24C205C7D8000BC04DC /* Frameworks */,
|
B082B24C205C7D8000BC04DC /* Frameworks */,
|
||||||
B082B24D205C7D8000BC04DC /* Resources */,
|
B082B24D205C7D8000BC04DC /* Resources */,
|
||||||
B00D181E2152F507000806F4 /* CopyFiles */,
|
B00D181E2152F507000806F4 /* Copy Files */,
|
||||||
B0679BBF215AE085000FC6B4 /* ShellScript */,
|
B0679BBF215AE085000FC6B4 /* ShellScript */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
@@ -499,8 +514,10 @@
|
|||||||
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */,
|
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */,
|
||||||
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */,
|
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */,
|
||||||
60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */,
|
60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */,
|
||||||
|
839ECD882360160100BE2DA5 /* Mail.scpt in Sources */,
|
||||||
36A778BE20A6C27100B38714 /* GeneralExtensions.swift in Sources */,
|
36A778BE20A6C27100B38714 /* GeneralExtensions.swift in Sources */,
|
||||||
60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */,
|
60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */,
|
||||||
|
839ECD8523600BF500BE2DA5 /* NotificationTouchBarItem.swift in Sources */,
|
||||||
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
|
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
|
||||||
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
|
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
|
||||||
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
|
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
|
||||||
@@ -657,9 +674,15 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
|
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
|
||||||
"$(PROJECT_DIR)",
|
"$(PROJECT_DIR)",
|
||||||
|
"$(PROJECT_DIR)/Carthage/Build/Mac",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = MTMR/Info.plist;
|
INFOPLIST_FILE = MTMR/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-framework",
|
||||||
|
"\"SQLite\"",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
|
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -680,9 +703,15 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
|
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
|
||||||
"$(PROJECT_DIR)",
|
"$(PROJECT_DIR)",
|
||||||
|
"$(PROJECT_DIR)/Carthage/Build/Mac",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = MTMR/Info.plist;
|
INFOPLIST_FILE = MTMR/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-framework",
|
||||||
|
"\"SQLite\"",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
|
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
if application "Mail" is running then
|
||||||
|
tell application "Mail"
|
||||||
|
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 ""
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
if application "Messages" is running then
|
||||||
|
tell application "Messages"
|
||||||
|
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 ""
|
||||||
+10
-10
@@ -15,12 +15,12 @@ class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
var fourfingers: NSPanGestureRecognizer!
|
var fourfingers: NSPanGestureRecognizer!
|
||||||
var swipeItems: [SwipeItem] = []
|
var swipeItems: [SwipeItem] = []
|
||||||
var prevPositions: [Int: CGFloat] = [2:0, 3:0, 4:0]
|
var prevPositions: [Int: CGFloat] = [2:0, 3:0, 4:0]
|
||||||
|
|
||||||
// legacy gesture positions
|
// legacy gesture positions
|
||||||
// by legacy I mean gestures to increse/decrease volume/brigtness which can be checked from app menu
|
// by legacy I mean gestures to increse/decrease volume/brigtness which can be checked from app menu
|
||||||
var legacyPrevPositions: [Int: CGFloat] = [2:0, 3:0, 4:0]
|
var legacyPrevPositions: [Int: CGFloat] = [2:0, 3:0, 4:0]
|
||||||
var legacyGesturesEnabled = false
|
var legacyGesturesEnabled = false
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem], swipeItems: [SwipeItem]) {
|
init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem], swipeItems: [SwipeItem]) {
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
self.swipeItems = swipeItems
|
self.swipeItems = swipeItems
|
||||||
@@ -29,27 +29,27 @@ class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
stackView.spacing = 8
|
stackView.spacing = 8
|
||||||
stackView.orientation = .horizontal
|
stackView.orientation = .horizontal
|
||||||
view = stackView
|
view = stackView
|
||||||
|
|
||||||
twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:)))
|
twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:)))
|
||||||
twofingers.numberOfTouchesRequired = 2
|
twofingers.numberOfTouchesRequired = 2
|
||||||
twofingers.allowedTouchTypes = .direct
|
twofingers.allowedTouchTypes = .direct
|
||||||
view.addGestureRecognizer(twofingers)
|
view.addGestureRecognizer(twofingers)
|
||||||
|
|
||||||
threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:)))
|
threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:)))
|
||||||
threefingers.numberOfTouchesRequired = 3
|
threefingers.numberOfTouchesRequired = 3
|
||||||
threefingers.allowedTouchTypes = .direct
|
threefingers.allowedTouchTypes = .direct
|
||||||
view.addGestureRecognizer(threefingers)
|
view.addGestureRecognizer(threefingers)
|
||||||
|
|
||||||
fourfingers = NSPanGestureRecognizer(target: self, action: #selector(fourfingersHandler(_:)))
|
fourfingers = NSPanGestureRecognizer(target: self, action: #selector(fourfingersHandler(_:)))
|
||||||
fourfingers.numberOfTouchesRequired = 4
|
fourfingers.numberOfTouchesRequired = 4
|
||||||
fourfingers.allowedTouchTypes = .direct
|
fourfingers.allowedTouchTypes = .direct
|
||||||
view.addGestureRecognizer(fourfingers)
|
view.addGestureRecognizer(fourfingers)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func gestureHandler(position: CGFloat, fingers: Int, state: NSGestureRecognizer.State) {
|
func gestureHandler(position: CGFloat, fingers: Int, state: NSGestureRecognizer.State) {
|
||||||
switch state {
|
switch state {
|
||||||
case .began:
|
case .began:
|
||||||
@@ -72,9 +72,9 @@ class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
let prevPos = legacyPrevPositions[fingers]!
|
let prevPos = legacyPrevPositions[fingers]!
|
||||||
if ((position - prevPos) > 15) || ((prevPos - position) > 15) {
|
if ((position - prevPos) > 15) || ((prevPos - position) > 15) {
|
||||||
if position > prevPos {
|
if position > prevPos {
|
||||||
GenericKeyPress(keyCode: CGKeyCode(144)).send()
|
HIDPostAuxKey(NX_KEYTYPE_BRIGHTNESS_UP)
|
||||||
} else if position < prevPos {
|
} else if position < prevPos {
|
||||||
GenericKeyPress(keyCode: CGKeyCode(145)).send()
|
HIDPostAuxKey(NX_KEYTYPE_BRIGHTNESS_DOWN)
|
||||||
}
|
}
|
||||||
legacyPrevPositions[fingers] = position
|
legacyPrevPositions[fingers] = position
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func twofingersHandler(_ sender: NSGestureRecognizer?) {
|
@objc func twofingersHandler(_ sender: NSGestureRecognizer?) {
|
||||||
let position = (sender?.location(in: sender?.view).x)!
|
let position = (sender?.location(in: sender?.view).x)!
|
||||||
self.gestureHandler(position: position, fingers: 2, state: sender!.state)
|
self.gestureHandler(position: position, fingers: 2, state: sender!.state)
|
||||||
|
|||||||
+2
-2
@@ -17,9 +17,9 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.26.1</string>
|
<string>0.27</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>425</string>
|
<string>434</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.utilities</string>
|
<string>public.app-category.utilities</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|||||||
+47
-12
@@ -64,6 +64,13 @@ class SupportedTypesHolder {
|
|||||||
parameters: [.align: .align(.left)]
|
parameters: [.align: .align(.left)]
|
||||||
) },
|
) },
|
||||||
|
|
||||||
|
"reply": { _ in (
|
||||||
|
item: .staticButton(title: "Reply"),
|
||||||
|
action: .shellScript(executable: "/usr/bin/open", parameters: ["sms://"]),
|
||||||
|
longAction: .none,
|
||||||
|
parameters: [.align: .align(.right)]
|
||||||
|
) },
|
||||||
|
|
||||||
"delete": { _ in (
|
"delete": { _ in (
|
||||||
item: .staticButton(title: "del"),
|
item: .staticButton(title: "del"),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -79,7 +86,7 @@ class SupportedTypesHolder {
|
|||||||
return (
|
return (
|
||||||
item: .staticButton(title: ""),
|
item: .staticButton(title: ""),
|
||||||
actions: [
|
actions: [
|
||||||
Action(trigger: .singleTap, value: .keyPress(keycode: 144))
|
Action(trigger: .singleTap, value: .hidKey(keycode: NX_KEYTYPE_BRIGHTNESS_UP))
|
||||||
],
|
],
|
||||||
legacyAction: .none,
|
legacyAction: .none,
|
||||||
legacyLongAction: .none,
|
legacyLongAction: .none,
|
||||||
@@ -92,7 +99,7 @@ class SupportedTypesHolder {
|
|||||||
return (
|
return (
|
||||||
item: .staticButton(title: ""),
|
item: .staticButton(title: ""),
|
||||||
actions: [
|
actions: [
|
||||||
Action(trigger: .singleTap, value: .keyPress(keycode: 145))
|
Action(trigger: .singleTap, value: .hidKey(keycode: NX_KEYTYPE_BRIGHTNESS_DOWN))
|
||||||
],
|
],
|
||||||
legacyAction: .none,
|
legacyAction: .none,
|
||||||
legacyLongAction: .none,
|
legacyLongAction: .none,
|
||||||
@@ -224,6 +231,27 @@ class SupportedTypesHolder {
|
|||||||
parameters: [:]
|
parameters: [:]
|
||||||
) },
|
) },
|
||||||
|
|
||||||
|
"notification": { decoder in
|
||||||
|
enum CodingKeys: String, CodingKey { case refreshInterval; case disableMarquee; case image }
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
|
||||||
|
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee)
|
||||||
|
if var img = try container.decodeIfPresent(Source.self, forKey: .image) {
|
||||||
|
return (
|
||||||
|
item: .notification(interval: interval ?? 5.0, disableMarquee: disableMarquee ?? false),
|
||||||
|
action: .shellScript(executable: "/usr/bin/open", parameters: ["sms://"]),
|
||||||
|
longAction: .none,
|
||||||
|
parameters: [.image: .image(source: img)]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
item: .notification(interval: interval ?? 5.0, disableMarquee: disableMarquee ?? false),
|
||||||
|
action: .shellScript(executable: "/usr/bin/open", parameters: ["sms://"]),
|
||||||
|
longAction: .none,
|
||||||
|
parameters: [:]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
static let sharedInstance = SupportedTypesHolder()
|
static let sharedInstance = SupportedTypesHolder()
|
||||||
@@ -269,6 +297,7 @@ enum ItemType: Decodable {
|
|||||||
case currency(interval: Double, from: String, to: String, full: Bool)
|
case currency(interval: Double, from: String, to: String, full: Bool)
|
||||||
case inputsource
|
case inputsource
|
||||||
case music(interval: Double, disableMarquee: Bool)
|
case music(interval: Double, disableMarquee: Bool)
|
||||||
|
case notification(interval: Double, disableMarquee: Bool)
|
||||||
case group(items: [BarItemDefinition])
|
case group(items: [BarItemDefinition])
|
||||||
case nightShift
|
case nightShift
|
||||||
case dnd
|
case dnd
|
||||||
@@ -325,6 +354,7 @@ enum ItemType: Decodable {
|
|||||||
case currency
|
case currency
|
||||||
case inputsource
|
case inputsource
|
||||||
case music
|
case music
|
||||||
|
case notification
|
||||||
case group
|
case group
|
||||||
case nightShift
|
case nightShift
|
||||||
case dnd
|
case dnd
|
||||||
@@ -344,7 +374,7 @@ enum ItemType: Decodable {
|
|||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
let alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
|
let alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
|
||||||
self = .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages)
|
self = .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages)
|
||||||
|
|
||||||
case .shellScriptTitledButton:
|
case .shellScriptTitledButton:
|
||||||
let source = try container.decode(Source.self, forKey: .source)
|
let source = try container.decode(Source.self, forKey: .source)
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
@@ -381,7 +411,7 @@ enum ItemType: Decodable {
|
|||||||
let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6"
|
let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6"
|
||||||
let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) ?? "text"
|
let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) ?? "text"
|
||||||
self = .weather(interval: interval, units: units, api_key: api_key, icon_type: icon_type)
|
self = .weather(interval: interval, units: units, api_key: api_key, icon_type: icon_type)
|
||||||
|
|
||||||
case .yandexWeather:
|
case .yandexWeather:
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
self = .yandexWeather(interval: interval)
|
self = .yandexWeather(interval: interval)
|
||||||
@@ -401,6 +431,11 @@ enum ItemType: Decodable {
|
|||||||
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
|
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
|
||||||
self = .music(interval: interval, disableMarquee: disableMarquee)
|
self = .music(interval: interval, disableMarquee: disableMarquee)
|
||||||
|
|
||||||
|
case .notification:
|
||||||
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 5.0
|
||||||
|
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
|
||||||
|
self = .notification(interval: interval, disableMarquee: disableMarquee)
|
||||||
|
|
||||||
case .group:
|
case .group:
|
||||||
let items = try container.decode([BarItemDefinition].self, forKey: .items)
|
let items = try container.decode([BarItemDefinition].self, forKey: .items)
|
||||||
self = .group(items: items)
|
self = .group(items: items)
|
||||||
@@ -422,7 +457,7 @@ enum ItemType: Decodable {
|
|||||||
|
|
||||||
case .darkMode:
|
case .darkMode:
|
||||||
self = .darkMode
|
self = .darkMode
|
||||||
|
|
||||||
case .swipe:
|
case .swipe:
|
||||||
let sourceApple = try container.decodeIfPresent(Source.self, forKey: .sourceApple)
|
let sourceApple = try container.decodeIfPresent(Source.self, forKey: .sourceApple)
|
||||||
let sourceBash = try container.decodeIfPresent(Source.self, forKey: .sourceBash)
|
let sourceBash = try container.decodeIfPresent(Source.self, forKey: .sourceBash)
|
||||||
@@ -459,7 +494,7 @@ struct Action: Decodable {
|
|||||||
case tripleTap
|
case tripleTap
|
||||||
case longTap
|
case longTap
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Value {
|
enum Value {
|
||||||
case none
|
case none
|
||||||
case hidKey(keycode: Int32)
|
case hidKey(keycode: Int32)
|
||||||
@@ -469,7 +504,7 @@ struct Action: Decodable {
|
|||||||
case custom(closure: () -> Void)
|
case custom(closure: () -> Void)
|
||||||
case openUrl(url: String)
|
case openUrl(url: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum ActionTypeRaw: String, Decodable {
|
private enum ActionTypeRaw: String, Decodable {
|
||||||
case hidKey
|
case hidKey
|
||||||
case keyPress
|
case keyPress
|
||||||
@@ -477,7 +512,7 @@ struct Action: Decodable {
|
|||||||
case shellScript
|
case shellScript
|
||||||
case openUrl
|
case openUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case trigger
|
case trigger
|
||||||
case action
|
case action
|
||||||
@@ -487,13 +522,13 @@ struct Action: Decodable {
|
|||||||
case shellArguments
|
case shellArguments
|
||||||
case url
|
case url
|
||||||
}
|
}
|
||||||
|
|
||||||
let trigger: Trigger
|
let trigger: Trigger
|
||||||
let value: Value
|
let value: Value
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
trigger = try container.decode(Trigger.self, forKey: .trigger)
|
trigger = try container.decode(Trigger.self, forKey: .trigger)
|
||||||
let type = try container.decodeIfPresent(ActionTypeRaw.self, forKey: .action)
|
let type = try container.decodeIfPresent(ActionTypeRaw.self, forKey: .action)
|
||||||
|
|
||||||
@@ -522,7 +557,7 @@ struct Action: Decodable {
|
|||||||
value = .none
|
value = .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(trigger: Trigger, value: Value) {
|
init(trigger: Trigger, value: Value) {
|
||||||
self.trigger = trigger
|
self.trigger = trigger
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ extension ItemType {
|
|||||||
return "com.toxblh.mtmr.inputsource."
|
return "com.toxblh.mtmr.inputsource."
|
||||||
case .music(interval: _):
|
case .music(interval: _):
|
||||||
return "com.toxblh.mtmr.music."
|
return "com.toxblh.mtmr.music."
|
||||||
|
case .notification(interval: _):
|
||||||
|
return "com.toxblh.mtmr.notification."
|
||||||
case .group(items: _):
|
case .group(items: _):
|
||||||
return "com.toxblh.mtmr.groupBar."
|
return "com.toxblh.mtmr.groupBar."
|
||||||
case .nightShift:
|
case .nightShift:
|
||||||
@@ -282,7 +284,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
} else {
|
} else {
|
||||||
barItem = AppScrubberTouchBarItem(identifier: identifier, autoResize: autoResize)
|
barItem = AppScrubberTouchBarItem(identifier: identifier, autoResize: autoResize)
|
||||||
}
|
}
|
||||||
case .volume:
|
case .volume:
|
||||||
if case let .image(source)? = item.additionalParameters[.image] {
|
if case let .image(source)? = item.additionalParameters[.image] {
|
||||||
barItem = VolumeViewController(identifier: identifier, image: source.image)
|
barItem = VolumeViewController(identifier: identifier, image: source.image)
|
||||||
} else {
|
} else {
|
||||||
@@ -304,6 +306,12 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
barItem = InputSourceBarItem(identifier: identifier)
|
barItem = InputSourceBarItem(identifier: identifier)
|
||||||
case let .music(interval: interval, disableMarquee: disableMarquee):
|
case let .music(interval: interval, disableMarquee: disableMarquee):
|
||||||
barItem = MusicBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee)
|
barItem = MusicBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee)
|
||||||
|
case let .notification(interval: interval, disableMarquee: disableMarquee):
|
||||||
|
if case let .image(source)? = item.additionalParameters[.image] {
|
||||||
|
barItem = NotificationBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee, image: source.image)
|
||||||
|
} else {
|
||||||
|
barItem = NotificationBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee)
|
||||||
|
}
|
||||||
case let .group(items: items):
|
case let .group(items: items):
|
||||||
barItem = GroupBarItem(identifier: identifier, items: items)
|
barItem = GroupBarItem(identifier: identifier, items: items)
|
||||||
case .nightShift:
|
case .nightShift:
|
||||||
|
|||||||
@@ -0,0 +1,566 @@
|
|||||||
|
//
|
||||||
|
// NotificationsTouchBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Matthew Cox on 10/22/19.
|
||||||
|
// Copyright © 2019 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Cocoa
|
||||||
|
import ScriptingBridge
|
||||||
|
import SQLite
|
||||||
|
import Contacts
|
||||||
|
import UserNotifications
|
||||||
|
|
||||||
|
class NotificationBarItem: CustomButtonTouchBarItem {
|
||||||
|
public enum Message: String {
|
||||||
|
case Messages = "com.apple.iChat"
|
||||||
|
case Mail = "com.apple.mail"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private let notificationIdentifiers = [
|
||||||
|
Message.Messages,
|
||||||
|
Message.Mail,
|
||||||
|
]
|
||||||
|
|
||||||
|
private let interval: TimeInterval
|
||||||
|
private let disableMarquee: Bool
|
||||||
|
private var messageText: String?
|
||||||
|
private var messageFrom: String?
|
||||||
|
private var timer: Timer?
|
||||||
|
private let iconSize = NSSize(width: 21, height: 21)
|
||||||
|
private let activity: NSBackgroundActivityScheduler
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, disableMarquee: Bool, image: NSImage? = nil) {
|
||||||
|
|
||||||
|
self.interval = interval
|
||||||
|
self.disableMarquee = disableMarquee
|
||||||
|
//tapClosure = { [weak self] in self?.DarkModeToggle() }
|
||||||
|
if image == nil {
|
||||||
|
//sliderItem = CustomSlider()
|
||||||
|
} else {
|
||||||
|
// sliderItem = CustomSlider(knob: image!)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||||
|
activity.interval = interval
|
||||||
|
|
||||||
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
//var systemBlue: NSColor { set }
|
||||||
|
isBordered = false
|
||||||
|
backgroundColor = NSColor.systemRed
|
||||||
|
//button = item.view as? NSButton else { continue }
|
||||||
|
|
||||||
|
//let textRange = NSRange(location: 0, length: button.title.characters.count)
|
||||||
|
//let titleColor = useCustomColor.state == NSControl.StateValue.on ? NSColor.black : NSColor.white
|
||||||
|
//let newTitle = NSMutableAttributedString(string: button.title)
|
||||||
|
//newTitle.addAttribute(NSAttributedStringKey.foregroundColor, value: titleColor, range: textRange)
|
||||||
|
//newTitle.addAttribute(NSAttributedStringKey.font, value: button.font!, range: textRange)
|
||||||
|
//newTitle.setAlignment(.center, range: textRange)
|
||||||
|
//button.attributedTitle = newTitle
|
||||||
|
//attributedTitle = "test"
|
||||||
|
//image = NSImage(name: NSUserGroup)
|
||||||
|
//title = "\(Noti.0)"
|
||||||
|
// func getDeliveredNotifications(completionHandler: @escaping ([UNNotification]) -> Void) {
|
||||||
|
// print("")
|
||||||
|
// }
|
||||||
|
// let notificationCenter = UNUserNotificationCenter.current()
|
||||||
|
|
||||||
|
// notificationCenter.requestAuthorization(options: [.alert, .badge, .provisional]) {}
|
||||||
|
|
||||||
|
// UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
|
||||||
|
// print("Noti")
|
||||||
|
// print(notifications)
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* let center = UNUserNotificationCenter.current()
|
||||||
|
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
|
||||||
|
center.requestAuthorization(options: options) { (granted, error) in
|
||||||
|
if granted {
|
||||||
|
application.registerForRemoteNotifications()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||||
|
let actionIdentifier = response.actionIdentifier
|
||||||
|
let content = response.notification.request.content
|
||||||
|
print("\(content)")
|
||||||
|
switch actionIdentifier {
|
||||||
|
case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
|
||||||
|
// Do something
|
||||||
|
completionHandler()
|
||||||
|
case UNNotificationDefaultActionIdentifier: // App was opened from notification
|
||||||
|
// Do something
|
||||||
|
completionHandler()
|
||||||
|
case "com.usernotificationstutorial.reply":
|
||||||
|
if let textResponse = response as? UNTextInputNotificationResponse {
|
||||||
|
let reply = textResponse.userText
|
||||||
|
// Send reply message
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
case "com.usernotificationstutorial.delete":
|
||||||
|
// Delete message
|
||||||
|
completionHandler()
|
||||||
|
default:
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*let replyAction = UNTextInputNotificationAction(identifier: "com.usernotificationstutorial.reply", title: "Reply", options: [], textInputButtonTitle: "Send", textInputPlaceholder: "Type your message")
|
||||||
|
let deleteAction = UNNotificationAction(identifier: "com.usernotificationstutorial.delete", title: "Delete", options: [.authenticationRequired, .destructive])
|
||||||
|
let category = UNNotificationCategory(identifier: "com.usernotificationstutorial.message", actions: [replyAction, deleteAction], intentIdentifiers: [], options: [])
|
||||||
|
center.setNotificationCategories([category])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
userNotificationCenter(center: center)
|
||||||
|
*/
|
||||||
|
tapClosure = { [weak self] in self?.playPause() }
|
||||||
|
longTapClosure = { [weak self] in self?.nextTrack() }
|
||||||
|
|
||||||
|
refreshAndSchedule()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func marquee() {
|
||||||
|
let str = title
|
||||||
|
if str.count > 10 {
|
||||||
|
let indexFirst = str.index(str.startIndex, offsetBy: 0)
|
||||||
|
let indexSecond = str.index(str.startIndex, offsetBy: 1)
|
||||||
|
title = String(str.suffix(from: indexSecond)) + String(str[indexFirst])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func playPause() {
|
||||||
|
for ident in notificationIdentifiers {
|
||||||
|
if let messageApplication = SBApplication(bundleIdentifier: ident.rawValue) {
|
||||||
|
if messageApplication.isRunning {
|
||||||
|
if ident == .Messages {
|
||||||
|
let mp = (messageApplication as MessagesApplication)
|
||||||
|
mp.playpause!()
|
||||||
|
return
|
||||||
|
} else if ident == .Mail {
|
||||||
|
let mp = (messageApplication as MailApplication)
|
||||||
|
mp.playpause!()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func nextTrack() {
|
||||||
|
for ident in notificationIdentifiers {
|
||||||
|
if let messageApplication = SBApplication(bundleIdentifier: ident.rawValue) {
|
||||||
|
if messageApplication.isRunning {
|
||||||
|
if ident == .Messages {
|
||||||
|
let mp = (messageApplication as MessagesApplication)
|
||||||
|
mp.nextTrack!()
|
||||||
|
updateNotification()
|
||||||
|
return
|
||||||
|
} else if ident == .Mail {
|
||||||
|
let mp = (messageApplication as MailApplication)
|
||||||
|
mp.nextTrack!()
|
||||||
|
updateNotification()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshAndSchedule() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.updateNotification()
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + self.interval) { [weak self] in
|
||||||
|
self?.refreshAndSchedule()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func updateNotification() {
|
||||||
|
var iconUpdated = false
|
||||||
|
var titleUpdated = false
|
||||||
|
var notificationbuilder = ""
|
||||||
|
|
||||||
|
let name = ""
|
||||||
|
let message = ""
|
||||||
|
let durl = ""
|
||||||
|
let person = ""
|
||||||
|
let dbpath = ""
|
||||||
|
let Noti = NotiBar().getAll(name: name, message: message, durl: durl, person: person, dbpath: dbpath)
|
||||||
|
//let lastNotificationItem = ""
|
||||||
|
|
||||||
|
print("\(Noti.0) \(Noti.1) \(Noti.3)")
|
||||||
|
//icon \(Noti.0)
|
||||||
|
//Message \(Noti.1)
|
||||||
|
//button path \(Noti.2)
|
||||||
|
//Number \(Noti.3)
|
||||||
|
let fromBox = String(Noti.3)
|
||||||
|
let messageBox = String(Noti.1)
|
||||||
|
|
||||||
|
if fromBox.isEmpty
|
||||||
|
{
|
||||||
|
notificationbuilder = ""
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notificationbuilder = "\(fromBox) - \(messageBox)"
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastNotificationItem = "\(notificationbuilder)"
|
||||||
|
|
||||||
|
for ident in notificationIdentifiers {
|
||||||
|
if let messageApplication = SBApplication(bundleIdentifier: ident.rawValue) {
|
||||||
|
if messageApplication.isRunning {
|
||||||
|
|
||||||
|
var tempTitle = ""
|
||||||
|
if ident == .Messages {
|
||||||
|
tempTitle = lastNotificationItem
|
||||||
|
} else if ident == .Mail {
|
||||||
|
tempTitle = (messageApplication as MailApplication).title
|
||||||
|
}
|
||||||
|
|
||||||
|
if tempTitle == self.messageText {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
self.messageText = tempTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
if let messageText = self.messageText?.ifNotEmpty {
|
||||||
|
self.timer?.invalidate()
|
||||||
|
self.timer = nil
|
||||||
|
|
||||||
|
if (disableMarquee) {
|
||||||
|
self.title = " " + messageText
|
||||||
|
} else {
|
||||||
|
self.title = " " + messageText + " "
|
||||||
|
self.timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(self.marquee), userInfo: nil, repeats: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleUpdated = true
|
||||||
|
}
|
||||||
|
if let _ = tempTitle.ifNotEmpty,
|
||||||
|
let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: ident.rawValue) {
|
||||||
|
let image = NSWorkspace.shared.icon(forFile: appPath)
|
||||||
|
image.size = self.iconSize
|
||||||
|
self.image = image
|
||||||
|
iconUpdated = true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if !iconUpdated {
|
||||||
|
self.image = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !titleUpdated {
|
||||||
|
self.title = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class NotiRun {
|
||||||
|
static func shell(launchPath path: String, arguments args: [String]) -> String {
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = path
|
||||||
|
task.arguments = args
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
task.standardOutput = pipe
|
||||||
|
task.standardError = pipe
|
||||||
|
task.launch()
|
||||||
|
|
||||||
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
|
let output = String(data: data, encoding: .utf8)
|
||||||
|
task.waitUntilExit()
|
||||||
|
|
||||||
|
return(output!)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotiBar
|
||||||
|
{
|
||||||
|
|
||||||
|
func getAll(name:String, message:String, durl: String, person:String, dbpath: String) -> (String, String, String, String, String)
|
||||||
|
{
|
||||||
|
|
||||||
|
let res = NotiRun.shell(launchPath: "/usr/bin/getconf", arguments: ["DARWIN_USER_DIR"])
|
||||||
|
let trimmedres = res.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
let db = try! Connection("\(trimmedres)com.apple.notificationcenter/db2/db")
|
||||||
|
|
||||||
|
let record = Table("record")
|
||||||
|
let app = Table("app")
|
||||||
|
let presented = Expression<Int?>("presented")
|
||||||
|
let identifier = Expression<String?>("identifier")
|
||||||
|
let delivered_date = Expression<Int?>("delivered_date")
|
||||||
|
let app_id = Expression<Int?>("app_id")
|
||||||
|
// let app_id = Expression<Int64>("app_id")
|
||||||
|
let data = Expression<Data>("data")
|
||||||
|
var name = ""
|
||||||
|
var message = ""
|
||||||
|
var durl = ""
|
||||||
|
var person = ""
|
||||||
|
var dbpath = ""
|
||||||
|
let timestamp = Int(NSDate().timeIntervalSinceReferenceDate - 86400)
|
||||||
|
//var image = ""
|
||||||
|
//var reply = ""
|
||||||
|
//var dismiss = ""
|
||||||
|
//var other = ""
|
||||||
|
let Messages = String("com.apple.iChat")
|
||||||
|
let Mail = String("com.apple.mail")
|
||||||
|
|
||||||
|
for app in try! db.prepare(app.select(app[*]))
|
||||||
|
{
|
||||||
|
if ("\(app[identifier]!)" == Messages)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
if ("\(app[identifier]!)" == Mail)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
// Messages
|
||||||
|
// Mail
|
||||||
|
}
|
||||||
|
// print("\(timestamp)")
|
||||||
|
//for record in try! db.prepare(record.join(app, on: record[app_id] == app[app_id]).select(record[*]).filter(delivered_date > timestamp) ) {
|
||||||
|
//app_id == 4 ||
|
||||||
|
for record in try! db.prepare(record.select(record[*]).filter(delivered_date > timestamp && app_id == 5) ) {
|
||||||
|
|
||||||
|
guard let notifierout = try? PropertyListSerialization.propertyList(from: record[data], options: [], format: nil) else {
|
||||||
|
fatalError("failed to deserialize")
|
||||||
|
}
|
||||||
|
if let notiDescAppName = (notifierout as AnyObject)["app"]! as? String
|
||||||
|
{
|
||||||
|
if let ret = self.getPath(appNamedNew: "\(notiDescAppName)") {
|
||||||
|
let retfix = ("\(ret)")
|
||||||
|
let rettrimmed = retfix.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
|
||||||
|
let notifierbuilder = Bundle(url: URL(fileURLWithPath: "\(rettrimmed)"))?.infoDictionary?["CFBundleDisplayName"] as? String ?? Bundle(url: URL(fileURLWithPath: "\(rettrimmed)"))?.infoDictionary?["CFBundleName"] as? String
|
||||||
|
if notifierbuilder == nil
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (notifierbuilder == "Messages" || notifierbuilder == "Mail")
|
||||||
|
{
|
||||||
|
if (notifierbuilder == "Messages")
|
||||||
|
{
|
||||||
|
name = "💬"
|
||||||
|
}
|
||||||
|
else if notifierbuilder == "Mail"
|
||||||
|
{
|
||||||
|
name = "✉️"
|
||||||
|
}
|
||||||
|
|
||||||
|
if let notiDescAppMessageTop = (notifierout as AnyObject)["req"]! as? AnyObject
|
||||||
|
{
|
||||||
|
if let notiDescAppMail = (notiDescAppMessageTop as AnyObject)["subt"]! as? String
|
||||||
|
{
|
||||||
|
message = notiDescAppMail
|
||||||
|
}
|
||||||
|
else if let notiDescAppMessage = (notiDescAppMessageTop as AnyObject)["body"]! as? String
|
||||||
|
{
|
||||||
|
message = notiDescAppMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let notiDescAppURLTop = (notifierout as AnyObject)["req"]! as? AnyObject
|
||||||
|
{
|
||||||
|
if let notiDescAppURL = (notiDescAppURLTop as AnyObject)["durl"]! as? String
|
||||||
|
{
|
||||||
|
durl = notiDescAppURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let notiDescAppPersonTop = (notifierout as AnyObject)["req"]! as? AnyObject
|
||||||
|
{
|
||||||
|
if let notiDescAppPerson = (notiDescAppPersonTop as AnyObject)["titl"]! as? String
|
||||||
|
{
|
||||||
|
|
||||||
|
person = notiDescAppPerson
|
||||||
|
}
|
||||||
|
// let imagee = getContactImage(imgu: "\(person)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = notifierbuilder!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbpath = "\(trimmedres)com.apple.notificationcenter/db2/db"
|
||||||
|
}
|
||||||
|
//print("\(name)-\(message)-\(durl)-\(person)-\(dbpath)")
|
||||||
|
return (name, message, durl, person, dbpath)
|
||||||
|
}
|
||||||
|
// static func getImage(image: String) -> String
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
//static func getOptionReply(reply: String) -> String
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
//static func getOptionDismiss(dismiss: String) -> String
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
//static func getOptionOther(otNSView()her: String) -> String
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
func getPath(appNamedNew: String) -> String? {
|
||||||
|
|
||||||
|
if let absopath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: appNamedNew) {
|
||||||
|
return "\(absopath)"
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lastModified(path: String) -> NSDate? {
|
||||||
|
let fileUrl = NSURL(fileURLWithPath: path)
|
||||||
|
var modified: AnyObject?
|
||||||
|
do {
|
||||||
|
try fileUrl.getResourceValue(&modified, forKey: URLResourceKey.contentModificationDateKey)
|
||||||
|
return modified as? NSDate
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("\(#function) Error: \(error)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContactImage(imgu:String) -> NSImage?
|
||||||
|
{
|
||||||
|
let store = CNContactStore()
|
||||||
|
//let contactStore = CNContactStore()
|
||||||
|
let keys = [CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNicknameKey, CNContactImageDataKey] as! CNKeyDescriptor
|
||||||
|
// let request = CNContactFetchRequest(keysToFetch: keys)
|
||||||
|
|
||||||
|
// try? contactStore.enumerateContacts(with: request) { (contact, error) in
|
||||||
|
|
||||||
|
// Do something with contact
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let contacts = try! store.unifiedContacts(matching: CNContact.predicateForContacts(matchingName: imgu), keysToFetch:[keys])
|
||||||
|
|
||||||
|
if contacts.count > 0
|
||||||
|
{
|
||||||
|
if let image = contacts[0].imageData
|
||||||
|
{
|
||||||
|
return NSImage.init(data: image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc protocol MessagesApplication {
|
||||||
|
@objc optional var currentTrack: SpotifyTrack { get }
|
||||||
|
@objc optional func nextTrack()
|
||||||
|
@objc optional func previousTrack()
|
||||||
|
@objc optional func playpause()
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SBApplication: MessagesApplication {}
|
||||||
|
|
||||||
|
@objc protocol MessagesTrack {
|
||||||
|
@objc optional var artist: String { get }
|
||||||
|
@objc optional var name: String { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SBObject: MessagesTrack {}
|
||||||
|
|
||||||
|
extension MessagesApplication {
|
||||||
|
var title: String {
|
||||||
|
guard let t = currentTrack else { return "" }
|
||||||
|
return (t.artist ?? "") + " — " + (t.name ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc protocol MailApplication {
|
||||||
|
@objc optional var currentTrack: MailTrack { get }
|
||||||
|
@objc optional func playpause()
|
||||||
|
@objc optional func nextTrack()
|
||||||
|
@objc optional func previousTrack()
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SBApplication: MailApplication {}
|
||||||
|
|
||||||
|
@objc protocol MailTrack {
|
||||||
|
@objc optional var artist: String { get }
|
||||||
|
@objc optional var name: String { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SBObject: MailTrack {}
|
||||||
|
|
||||||
|
extension MailApplication {
|
||||||
|
var title: String {
|
||||||
|
guard let t = currentTrack else { return "" }
|
||||||
|
return (t.artist ?? "") + " — " + (t.name ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ My idea is to create a platform for creating plugins to customize the TouchBar.
|
|||||||
<a href="https://t.me/joinchat/AmVYGg8vW38c13_3MxdE_g"><img height="20px" src="https://telegram.org/img/t_logo.png" /> Telegram</a>
|
<a href="https://t.me/joinchat/AmVYGg8vW38c13_3MxdE_g"><img height="20px" src="https://telegram.org/img/t_logo.png" /> Telegram</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center"><a href="https://www.paypal.me/toxblh/10" title="Donate via Paypal"><img height="36px" src="Resources/support_paypal.svg" alt="PayPal donate button" /></a>
|
<p align="center"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WUAAG2HH58WE4" title="Donate via Paypal"><img height="36px" src="Resources/support_paypal.svg" alt="PayPal donate button" /></a>
|
||||||
<a href="https://www.buymeacoffee.com/toxblh" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" height="36px" ></a>
|
<a href="https://www.buymeacoffee.com/toxblh" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" height="36px" ></a>
|
||||||
<a href="https://www.patreon.com/bePatron?u=9900748"><img height="36px" src="https://c5.patreon.com/external/logo/become_a_patron_button.png" srcset="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png 2x"></a>
|
<a href="https://www.patreon.com/bePatron?u=9900748"><img height="36px" src="https://c5.patreon.com/external/logo/become_a_patron_button.png" srcset="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png 2x"></a>
|
||||||
<a href="https://www.producthunt.com/posts/my-touchbar-my-rules-mtmr">
|
<a href="https://www.producthunt.com/posts/my-touchbar-my-rules-mtmr">
|
||||||
@@ -480,8 +480,8 @@ by using background with color "#000000" and bordered == false you can create bu
|
|||||||
- Opening another program which can't edit text
|
- Opening another program which can't edit text
|
||||||
1. Open Terminal.app
|
1. Open Terminal.app
|
||||||
2. Put `open -a TextEdit ~/Library/Application\ Support/MTMR/items.json` command and press <kbd>Enter</kbd>
|
2. Put `open -a TextEdit ~/Library/Application\ Support/MTMR/items.json` command and press <kbd>Enter</kbd>
|
||||||
|
|
||||||
|
|
||||||
#### Buttons or gestures doesn't work:
|
#### Buttons or gestures doesn't work:
|
||||||
- "After the last update my mtmr is not working anymore!"
|
- "After the last update my mtmr is not working anymore!"
|
||||||
- "Buttons sometimes do not trigger action"
|
- "Buttons sometimes do not trigger action"
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ echo "<?xml version=\"1.0\" standalone=\"yes\"?>
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Homebrew https://github.com/Homebrew/homebrew-cask/edit/master/Casks/mtmr.rb"
|
echo "Homebrew https://github.com/Homebrew/homebrew-cask/edit/master/Casks/mtmr.rb"
|
||||||
echo ""
|
echo ""
|
||||||
echo " version '${VERSION}'"
|
echo " version \"${VERSION}\""
|
||||||
echo " sha256 '${SHA256}'"
|
echo " sha256 \"${SHA256}\""
|
||||||
echo ""
|
echo ""
|
||||||
echo "Update MTMR v${VERSION}"
|
echo "Update MTMR v${VERSION}"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user