mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-11 17:38:38 +00:00
Merge ff6d07f2d6 into 52758f947d
This commit is contained in:
commit
fe499b2b44
@ -69,6 +69,23 @@
|
|||||||
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */; };
|
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */; };
|
||||||
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */; };
|
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */; };
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */; };
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */; };
|
||||||
|
BA6EEC332457B48F009AC2D3 /* EventActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC322457B48F009AC2D3 /* EventActions.swift */; };
|
||||||
|
BA6EEC372457B727009AC2D3 /* EscapeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC362457B727009AC2D3 /* EscapeBarItem.swift */; };
|
||||||
|
BA6EEC392457B839009AC2D3 /* DeleteBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC382457B839009AC2D3 /* DeleteBarItem.swift */; };
|
||||||
|
BA6EEC3B2457BA7D009AC2D3 /* BrightnessUpBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC3A2457BA7D009AC2D3 /* BrightnessUpBarItem.swift */; };
|
||||||
|
BA6EEC3D2457BD2E009AC2D3 /* BrightnessDownBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC3C2457BD2E009AC2D3 /* BrightnessDownBarItem.swift */; };
|
||||||
|
BA6EEC3F2457BF79009AC2D3 /* IlluminationUpBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC3E2457BF79009AC2D3 /* IlluminationUpBarItem.swift */; };
|
||||||
|
BA6EEC412457BFCE009AC2D3 /* IlluminationDownBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC402457BFCE009AC2D3 /* IlluminationDownBarItem.swift */; };
|
||||||
|
BA6EEC432457C010009AC2D3 /* VolumeDownBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC422457C010009AC2D3 /* VolumeDownBarItem.swift */; };
|
||||||
|
BA6EEC452457C072009AC2D3 /* VolumeUpBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC442457C072009AC2D3 /* VolumeUpBarItem.swift */; };
|
||||||
|
BA6EEC472457C0C7009AC2D3 /* MuteBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC462457C0C7009AC2D3 /* MuteBarItem.swift */; };
|
||||||
|
BA6EEC492457C0FA009AC2D3 /* PreviousBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC482457C0FA009AC2D3 /* PreviousBarItem.swift */; };
|
||||||
|
BA6EEC4B2457C12E009AC2D3 /* PlayBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC4A2457C12E009AC2D3 /* PlayBarItem.swift */; };
|
||||||
|
BA6EEC4D2457C164009AC2D3 /* NextBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC4C2457C164009AC2D3 /* NextBarItem.swift */; };
|
||||||
|
BA6EEC4F2457C1AB009AC2D3 /* SleepBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC4E2457C1AB009AC2D3 /* SleepBarItem.swift */; };
|
||||||
|
BA6EEC512457C217009AC2D3 /* DisplaySleepBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC502457C217009AC2D3 /* DisplaySleepBarItem.swift */; };
|
||||||
|
BA6EEC53245AE228009AC2D3 /* ExitTouchbarBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC52245AE227009AC2D3 /* ExitTouchbarBarItem.swift */; };
|
||||||
|
BA6EEC55245B8D75009AC2D3 /* CloseBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6EEC54245B8D75009AC2D3 /* CloseBarItem.swift */; };
|
||||||
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF5AB5624317B4300B04904 /* BasicView.swift */; };
|
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF5AB5624317B4300B04904 /* BasicView.swift */; };
|
||||||
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF5AB5824317CAF00B04904 /* SwipeItem.swift */; };
|
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF5AB5824317CAF00B04904 /* SwipeItem.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
@ -161,6 +178,23 @@
|
|||||||
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkModeBarItem.swift; sourceTree = "<group>"; };
|
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkModeBarItem.swift; sourceTree = "<group>"; };
|
||||||
B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TouchBarSupport.m; 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>"; };
|
B0F8771B207AC92700D6E430 /* TouchBarSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarSupport.h; sourceTree = "<group>"; };
|
||||||
|
BA6EEC322457B48F009AC2D3 /* EventActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventActions.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC362457B727009AC2D3 /* EscapeBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EscapeBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC382457B839009AC2D3 /* DeleteBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC3A2457BA7D009AC2D3 /* BrightnessUpBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrightnessUpBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC3C2457BD2E009AC2D3 /* BrightnessDownBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrightnessDownBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC3E2457BF79009AC2D3 /* IlluminationUpBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IlluminationUpBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC402457BFCE009AC2D3 /* IlluminationDownBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IlluminationDownBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC422457C010009AC2D3 /* VolumeDownBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeDownBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC442457C072009AC2D3 /* VolumeUpBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeUpBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC462457C0C7009AC2D3 /* MuteBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MuteBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC482457C0FA009AC2D3 /* PreviousBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviousBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC4A2457C12E009AC2D3 /* PlayBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC4C2457C164009AC2D3 /* NextBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC4E2457C1AB009AC2D3 /* SleepBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SleepBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC502457C217009AC2D3 /* DisplaySleepBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaySleepBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC52245AE227009AC2D3 /* ExitTouchbarBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExitTouchbarBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
BA6EEC54245B8D75009AC2D3 /* CloseBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseBarItem.swift; sourceTree = "<group>"; };
|
||||||
BAF5AB5624317B4300B04904 /* BasicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicView.swift; sourceTree = "<group>"; };
|
BAF5AB5624317B4300B04904 /* BasicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicView.swift; sourceTree = "<group>"; };
|
||||||
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeItem.swift; sourceTree = "<group>"; };
|
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeItem.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
@ -249,6 +283,7 @@
|
|||||||
B05600D22083E9BB00EB218D /* CustomSlider.swift */,
|
B05600D22083E9BB00EB218D /* CustomSlider.swift */,
|
||||||
36A778BD20A6C27100B38714 /* GeneralExtensions.swift */,
|
36A778BD20A6C27100B38714 /* GeneralExtensions.swift */,
|
||||||
B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */,
|
B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */,
|
||||||
|
BA6EEC322457B48F009AC2D3 /* EventActions.swift */,
|
||||||
);
|
);
|
||||||
path = MTMR;
|
path = MTMR;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -307,21 +342,37 @@
|
|||||||
children = (
|
children = (
|
||||||
6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */,
|
6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */,
|
||||||
B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */,
|
B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */,
|
||||||
|
BA6EEC3C2457BD2E009AC2D3 /* BrightnessDownBarItem.swift */,
|
||||||
|
BA6EEC3A2457BA7D009AC2D3 /* BrightnessUpBarItem.swift */,
|
||||||
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */,
|
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */,
|
||||||
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */,
|
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */,
|
||||||
|
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */,
|
||||||
|
BA6EEC382457B839009AC2D3 /* DeleteBarItem.swift */,
|
||||||
|
BA6EEC502457C217009AC2D3 /* DisplaySleepBarItem.swift */,
|
||||||
B081732B213739FE005D4908 /* DnDBarItem.swift */,
|
B081732B213739FE005D4908 /* DnDBarItem.swift */,
|
||||||
|
BA6EEC362457B727009AC2D3 /* EscapeBarItem.swift */,
|
||||||
60669B4220AD8FA80074E817 /* GroupBarItem.swift */,
|
60669B4220AD8FA80074E817 /* GroupBarItem.swift */,
|
||||||
|
BA6EEC402457BFCE009AC2D3 /* IlluminationDownBarItem.swift */,
|
||||||
|
BA6EEC3E2457BF79009AC2D3 /* IlluminationUpBarItem.swift */,
|
||||||
60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */,
|
60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */,
|
||||||
60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */,
|
60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */,
|
||||||
|
BA6EEC462457C0C7009AC2D3 /* MuteBarItem.swift */,
|
||||||
B0846A742220C968000288A7 /* NetworkBarItem.swift */,
|
B0846A742220C968000288A7 /* NetworkBarItem.swift */,
|
||||||
|
BA6EEC4C2457C164009AC2D3 /* NextBarItem.swift */,
|
||||||
B08173262135F02B005D4908 /* NightShiftBarItem.swift */,
|
B08173262135F02B005D4908 /* NightShiftBarItem.swift */,
|
||||||
|
BA6EEC4A2457C12E009AC2D3 /* PlayBarItem.swift */,
|
||||||
B08126EE217BD0B900A98970 /* PomodoroBarItem.swift */,
|
B08126EE217BD0B900A98970 /* PomodoroBarItem.swift */,
|
||||||
|
BA6EEC482457C0FA009AC2D3 /* PreviousBarItem.swift */,
|
||||||
|
BA6EEC4E2457C1AB009AC2D3 /* SleepBarItem.swift */,
|
||||||
36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */,
|
36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */,
|
||||||
|
BA6EEC422457C010009AC2D3 /* VolumeDownBarItem.swift */,
|
||||||
|
BA6EEC442457C072009AC2D3 /* VolumeUpBarItem.swift */,
|
||||||
6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */,
|
6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */,
|
||||||
607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */,
|
607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */,
|
||||||
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */,
|
|
||||||
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
|
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
|
||||||
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */,
|
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */,
|
||||||
|
BA6EEC52245AE227009AC2D3 /* ExitTouchbarBarItem.swift */,
|
||||||
|
BA6EEC54245B8D75009AC2D3 /* CloseBarItem.swift */,
|
||||||
);
|
);
|
||||||
path = Widgets;
|
path = Widgets;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -469,28 +520,37 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
|
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
|
||||||
|
BA6EEC4F2457C1AB009AC2D3 /* SleepBarItem.swift in Sources */,
|
||||||
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
|
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
|
||||||
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
||||||
|
BA6EEC512457C217009AC2D3 /* DisplaySleepBarItem.swift in Sources */,
|
||||||
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */,
|
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */,
|
||||||
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
|
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
|
||||||
|
BA6EEC55245B8D75009AC2D3 /* CloseBarItem.swift in Sources */,
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
||||||
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */,
|
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */,
|
||||||
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
||||||
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
|
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
|
||||||
|
BA6EEC4B2457C12E009AC2D3 /* PlayBarItem.swift in Sources */,
|
||||||
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */,
|
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */,
|
||||||
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
||||||
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
|
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
|
||||||
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
||||||
|
BA6EEC412457BFCE009AC2D3 /* IlluminationDownBarItem.swift in Sources */,
|
||||||
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */,
|
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */,
|
||||||
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */,
|
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */,
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
||||||
|
BA6EEC492457C0FA009AC2D3 /* PreviousBarItem.swift in Sources */,
|
||||||
60173D3E20C0031B002C305F /* LaunchAtLoginController.m in Sources */,
|
60173D3E20C0031B002C305F /* LaunchAtLoginController.m in Sources */,
|
||||||
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */,
|
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */,
|
||||||
|
BA6EEC3B2457BA7D009AC2D3 /* BrightnessUpBarItem.swift in Sources */,
|
||||||
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */,
|
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */,
|
||||||
607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */,
|
607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */,
|
||||||
|
BA6EEC332457B48F009AC2D3 /* EventActions.swift in Sources */,
|
||||||
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */,
|
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */,
|
||||||
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */,
|
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */,
|
||||||
6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */,
|
6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */,
|
||||||
|
BA6EEC372457B727009AC2D3 /* EscapeBarItem.swift in Sources */,
|
||||||
B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */,
|
B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */,
|
||||||
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */,
|
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */,
|
||||||
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */,
|
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */,
|
||||||
@ -499,11 +559,19 @@
|
|||||||
60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */,
|
60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */,
|
||||||
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
|
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
|
||||||
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
|
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
|
||||||
|
BA6EEC472457C0C7009AC2D3 /* MuteBarItem.swift in Sources */,
|
||||||
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
|
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
|
||||||
|
BA6EEC53245AE228009AC2D3 /* ExitTouchbarBarItem.swift in Sources */,
|
||||||
607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */,
|
607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */,
|
||||||
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */,
|
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */,
|
||||||
|
BA6EEC4D2457C164009AC2D3 /* NextBarItem.swift in Sources */,
|
||||||
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */,
|
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */,
|
||||||
|
BA6EEC392457B839009AC2D3 /* DeleteBarItem.swift in Sources */,
|
||||||
|
BA6EEC432457C010009AC2D3 /* VolumeDownBarItem.swift in Sources */,
|
||||||
|
BA6EEC452457C072009AC2D3 /* VolumeUpBarItem.swift in Sources */,
|
||||||
|
BA6EEC3D2457BD2E009AC2D3 /* BrightnessDownBarItem.swift in Sources */,
|
||||||
368EDDE720812A1D00E10953 /* ScrollViewItem.swift in Sources */,
|
368EDDE720812A1D00E10953 /* ScrollViewItem.swift in Sources */,
|
||||||
|
BA6EEC3F2457BF79009AC2D3 /* IlluminationUpBarItem.swift in Sources */,
|
||||||
B04B7BB72087398C00C835D0 /* BatteryBarItem.swift in Sources */,
|
B04B7BB72087398C00C835D0 /* BatteryBarItem.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@ -6,10 +6,42 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
private var forceHideConstraint: NSLayoutConstraint!
|
private var forceHideConstraint: NSLayoutConstraint!
|
||||||
private let alternativeImages: [String: SourceProtocol]
|
private let alternativeImages: [String: SourceProtocol]
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case source
|
||||||
|
case alternativeImages
|
||||||
|
case refreshInterval
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "appleScriptTitledButton"
|
||||||
|
}
|
||||||
|
|
||||||
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, alternativeImages: [String: SourceProtocol]) {
|
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, alternativeImages: [String: SourceProtocol]) {
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
self.alternativeImages = alternativeImages
|
self.alternativeImages = alternativeImages
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
|
||||||
|
initScripts(source: source)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let source = try container.decode(Source.self, forKey: .source)
|
||||||
|
self.interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
|
self.alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
|
||||||
|
|
||||||
|
print("AppleScriptTouchBarItem.init(from decoder)")
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.title = "⏳"
|
||||||
|
|
||||||
|
initScripts(source: source)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initScripts(source: SourceProtocol) {
|
||||||
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
||||||
title = "scheduled"
|
title = "scheduled"
|
||||||
DispatchQueue.appleScriptQueue.async {
|
DispatchQueue.appleScriptQueue.async {
|
||||||
@ -38,10 +70,6 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func refreshAndSchedule() {
|
func refreshAndSchedule() {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
print("refresh happened (interval \(interval)), self \(identifier.rawValue))")
|
print("refresh happened (interval \(interval)), self \(identifier.rawValue))")
|
||||||
@ -62,7 +90,7 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
func updateIcon(iconLabel: String) {
|
func updateIcon(iconLabel: String) {
|
||||||
if alternativeImages[iconLabel] != nil {
|
if alternativeImages[iconLabel] != nil {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.image = self.alternativeImages[iconLabel]!.image
|
self.setImage(self.alternativeImages[iconLabel]!.image)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("Cannot find icon with label \"\(iconLabel)\"")
|
print("Cannot find icon with label \"\(iconLabel)\"")
|
||||||
|
|||||||
@ -15,6 +15,7 @@ class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
var threefingers: NSPanGestureRecognizer!
|
var threefingers: NSPanGestureRecognizer!
|
||||||
var fourfingers: NSPanGestureRecognizer!
|
var fourfingers: NSPanGestureRecognizer!
|
||||||
var swipeItems: [SwipeItem] = []
|
var swipeItems: [SwipeItem] = []
|
||||||
|
var items: [NSTouchBarItem] = []
|
||||||
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
|
||||||
@ -25,6 +26,7 @@ class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
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
|
||||||
|
self.items = items
|
||||||
let views = items.compactMap { $0.view }
|
let views = items.compactMap { $0.view }
|
||||||
let stackView = NSStackView(views: views)
|
let stackView = NSStackView(views: views)
|
||||||
stackView.spacing = 1
|
stackView.spacing = 1
|
||||||
|
|||||||
@ -8,24 +8,130 @@
|
|||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
enum Align: String, Decodable {
|
||||||
var tapClosure: (() -> Void)?
|
case left
|
||||||
var longTapClosure: (() -> Void)? {
|
case center
|
||||||
didSet {
|
case right
|
||||||
longClick.isEnabled = longTapClosure != nil
|
}
|
||||||
|
|
||||||
|
// CustomTouchBarItem is a base class for all widgets
|
||||||
|
// This class provides some basic parameter parsing (width, align)
|
||||||
|
// To implement a new class:
|
||||||
|
// 1. Derive your class from CustomTouchBarItem (for static) or CustomButtonTouchBarItem (for buttons)
|
||||||
|
// 2. Override class var typeIdentifier with your object identificator
|
||||||
|
// 3. Override init(from decoder: Decoder) and read all custom json params you need
|
||||||
|
// 4. Don't forget to call super.init(identifier: CustomTouchBarItem.createIdentifier(type)) in the init() function
|
||||||
|
// 5. Add your new class to BarItemDefinition.types in ItemParsing.swift
|
||||||
|
//
|
||||||
|
// Good example is PomodoroBarItem
|
||||||
|
//
|
||||||
|
// If you want to inherid from some other NS class (NSSlider or NSPopoverTouchBarItem or other) then
|
||||||
|
// look into GroupBarItem and BrightnessViewController
|
||||||
|
|
||||||
|
class CustomTouchBarItem: NSCustomTouchBarItem, Decodable {
|
||||||
|
var align: Align
|
||||||
|
private var width: NSLayoutConstraint?
|
||||||
|
|
||||||
|
class var typeIdentifier: String {
|
||||||
|
return "NOTDEFINED"
|
||||||
|
}
|
||||||
|
|
||||||
|
func setWidth(value: CGFloat) {
|
||||||
|
guard value > 0 else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let width = self.width {
|
||||||
|
width.isActive = false
|
||||||
|
}
|
||||||
|
self.width = view.widthAnchor.constraint(equalToConstant: value)
|
||||||
|
self.width!.isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func getWidth() -> CGFloat {
|
||||||
|
return width?.constant ?? 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case type
|
||||||
|
case width
|
||||||
|
case align
|
||||||
|
// TODO move bordered and background from custom button class
|
||||||
|
//case bordered
|
||||||
|
//case background
|
||||||
|
//case title
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(identifier: NSTouchBarItem.Identifier) {
|
||||||
|
self.align = .center
|
||||||
|
|
||||||
|
// setting width here wouldn't make any affect
|
||||||
|
super.init(identifier: identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
let type = try container.decode(String.self, forKey: .type)
|
||||||
|
self.align = try container.decodeIfPresent(Align.self, forKey: .align) ?? .center
|
||||||
|
|
||||||
|
super.init(identifier: CustomTouchBarItem.createIdentifier(type))
|
||||||
|
|
||||||
|
if let width = try container.decodeIfPresent(CGFloat.self, forKey: .width) {
|
||||||
|
self.setWidth(value: width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func identifierBase(_ type: String) -> String {
|
||||||
|
return "com.toxblh.mtmr." + type
|
||||||
|
}
|
||||||
|
|
||||||
|
static func createIdentifier(_ type: String) -> NSTouchBarItem.Identifier {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.dateFormat = "HH-mm-ss"
|
||||||
|
let time = dateFormatter.string(from: Date())
|
||||||
|
let identifierString = CustomTouchBarItem.identifierBase(type).appending(time + "--" + UUID().uuidString)
|
||||||
|
return NSTouchBarItem.Identifier(identifierString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomButtonTouchBarItem: CustomTouchBarItem, NSGestureRecognizerDelegate {
|
||||||
|
private var tapAction: EventAction?
|
||||||
|
private var longTapAction: EventAction?
|
||||||
var finishViewConfiguration: ()->() = {}
|
var finishViewConfiguration: ()->() = {}
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "staticButton"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case title
|
||||||
|
case bordered
|
||||||
|
case background
|
||||||
|
case image
|
||||||
|
case action
|
||||||
|
case longAction
|
||||||
|
}
|
||||||
|
|
||||||
private var button: NSButton!
|
private var button: NSButton!
|
||||||
private var singleClick: HapticClickGestureRecognizer!
|
private var singleClick: HapticClickGestureRecognizer!
|
||||||
private var longClick: LongPressGestureRecognizer!
|
private var longClick: LongPressGestureRecognizer!
|
||||||
|
private var attributedTitle: NSAttributedString
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, title: String) {
|
init(identifier: NSTouchBarItem.Identifier, title: String) {
|
||||||
attributedTitle = title.defaultTouchbarAttributedString
|
attributedTitle = title.defaultTouchbarAttributedString
|
||||||
|
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
|
|
||||||
|
initButton(title: title, imageSource: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initButton(title: String, imageSource: Source?) {
|
||||||
button = CustomHeightButton(title: title, target: nil, action: nil)
|
button = CustomHeightButton(title: title, target: nil, action: nil)
|
||||||
|
self.setImage(imageSource?.image)
|
||||||
|
|
||||||
longClick = LongPressGestureRecognizer(target: self, action: #selector(handleGestureLong))
|
longClick = LongPressGestureRecognizer(target: self, action: #selector(handleGestureLong))
|
||||||
longClick.isEnabled = false
|
longClick.isEnabled = false
|
||||||
@ -33,6 +139,7 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
|||||||
longClick.delegate = self
|
longClick.delegate = self
|
||||||
|
|
||||||
singleClick = HapticClickGestureRecognizer(target: self, action: #selector(handleGestureSingle))
|
singleClick = HapticClickGestureRecognizer(target: self, action: #selector(handleGestureSingle))
|
||||||
|
singleClick.isEnabled = false
|
||||||
singleClick.allowedTouchTypes = .direct
|
singleClick.allowedTouchTypes = .direct
|
||||||
singleClick.delegate = self
|
singleClick.delegate = self
|
||||||
|
|
||||||
@ -40,6 +147,45 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
|||||||
button.attributedTitle = attributedTitle
|
button.attributedTitle = attributedTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
attributedTitle = "".defaultTouchbarAttributedString
|
||||||
|
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
if let borderedFlag = try container.decodeIfPresent(Bool.self, forKey: .bordered) {
|
||||||
|
self.isBordered = borderedFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
if let bgColor = try container.decodeIfPresent(String.self, forKey: .background)?.hexColor {
|
||||||
|
self.backgroundColor = bgColor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let imageSource = try container.decodeIfPresent(Source.self, forKey: .image)
|
||||||
|
initButton(title: title, imageSource: imageSource)
|
||||||
|
|
||||||
|
self.setTapAction(try? SingleTapEventAction(from: decoder))
|
||||||
|
self.setLongTapAction(try? LongTapEventAction(from: decoder))
|
||||||
|
}
|
||||||
|
|
||||||
|
// From for static buttons
|
||||||
|
convenience init(title: String) {
|
||||||
|
self.init(identifier: CustomTouchBarItem.createIdentifier(CustomButtonTouchBarItem.typeIdentifier), title: title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTapAction(_ action: EventAction?) {
|
||||||
|
self.tapAction = action
|
||||||
|
self.singleClick?.isEnabled = action != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setLongTapAction(_ action: EventAction?) {
|
||||||
|
self.longTapAction = action
|
||||||
|
self.longClick?.isEnabled = action != nil
|
||||||
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
@ -58,27 +204,35 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
|||||||
|
|
||||||
var title: String {
|
var title: String {
|
||||||
get {
|
get {
|
||||||
return attributedTitle.string
|
return getAttributedTitle().string
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
attributedTitle = newValue.defaultTouchbarAttributedString
|
setAttributedTitle(newValue.defaultTouchbarAttributedString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var attributedTitle: NSAttributedString {
|
func getAttributedTitle() -> NSAttributedString {
|
||||||
didSet {
|
return attributedTitle
|
||||||
button?.imagePosition = attributedTitle.length > 0 ? .imageLeading : .imageOnly
|
|
||||||
button?.attributedTitle = attributedTitle
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var image: NSImage? {
|
func setAttributedTitle(_ attributedTitle: NSAttributedString) {
|
||||||
didSet {
|
self.attributedTitle = attributedTitle
|
||||||
button.image = image
|
button?.imagePosition = attributedTitle.length > 0 ? .imageLeading : .imageOnly
|
||||||
}
|
button?.attributedTitle = attributedTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
private func reinstallButton() {
|
private var image: NSImage?
|
||||||
|
|
||||||
|
func getImage() -> NSImage? {
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
|
||||||
|
func setImage(_ image: NSImage?) {
|
||||||
|
self.image = image
|
||||||
|
button.image = image
|
||||||
|
}
|
||||||
|
|
||||||
|
func reinstallButton() {
|
||||||
let title = button.attributedTitle
|
let title = button.attributedTitle
|
||||||
let image = button.image
|
let image = button.image
|
||||||
let cell = CustomButtonCell(parentItem: self)
|
let cell = CustomButtonCell(parentItem: self)
|
||||||
@ -116,7 +270,7 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
|||||||
@objc func handleGestureSingle(gr: NSClickGestureRecognizer) {
|
@objc func handleGestureSingle(gr: NSClickGestureRecognizer) {
|
||||||
switch gr.state {
|
switch gr.state {
|
||||||
case .ended:
|
case .ended:
|
||||||
tapClosure?()
|
self.tapAction?.closure(self)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -126,7 +280,7 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
|||||||
@objc func handleGestureLong(gr: NSPressGestureRecognizer) {
|
@objc func handleGestureLong(gr: NSPressGestureRecognizer) {
|
||||||
switch gr.state {
|
switch gr.state {
|
||||||
case .possible: // tiny hack because we're calling action manually
|
case .possible: // tiny hack because we're calling action manually
|
||||||
(self.longTapClosure ?? self.tapClosure)?()
|
(self.longTapAction?.closure ?? self.tapAction?.closure)?(self)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -156,7 +310,7 @@ class CustomButtonCell: NSButtonCell {
|
|||||||
if flag {
|
if flag {
|
||||||
setAttributedTitle(attributedTitle, withColor: .lightGray)
|
setAttributedTitle(attributedTitle, withColor: .lightGray)
|
||||||
} else if let parentItem = self.parentItem {
|
} else if let parentItem = self.parentItem {
|
||||||
attributedTitle = parentItem.attributedTitle
|
attributedTitle = parentItem.getAttributedTitle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
184
MTMR/EventActions.swift
Normal file
184
MTMR/EventActions.swift
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
//
|
||||||
|
// EventActions.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class EventAction {
|
||||||
|
var closure: ((_ caller: CustomButtonTouchBarItem) -> Void)
|
||||||
|
|
||||||
|
func setHidKeyClosure(keycode: Int32) -> EventAction {
|
||||||
|
closure = { (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
HIDPostAuxKey(keycode)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func setKeyPressClosure(keycode: Int) -> EventAction {
|
||||||
|
closure = { (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
GenericKeyPress(keyCode: CGKeyCode(keycode)).send()
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func setAppleScriptClosure(appleScript: NSAppleScript) -> EventAction {
|
||||||
|
closure = { (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
DispatchQueue.appleScriptQueue.async {
|
||||||
|
var error: NSDictionary?
|
||||||
|
appleScript.executeAndReturnError(&error)
|
||||||
|
if let error = error {
|
||||||
|
print("error \(error) when handling apple script ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func setShellScriptClosure(executable: String, parameters: [String]) -> EventAction {
|
||||||
|
closure = { (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = executable
|
||||||
|
task.arguments = parameters
|
||||||
|
task.launch()
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func setOpenUrlClosure(url: String) -> EventAction {
|
||||||
|
closure = { (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
if let url = URL(string: url), NSWorkspace.shared.open(url) {
|
||||||
|
#if DEBUG
|
||||||
|
print("URL was successfully opened")
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
print("error", url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.closure = { (_ caller: CustomButtonTouchBarItem) in }
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_ closure: @escaping (_ caller: CustomButtonTouchBarItem) -> Void) {
|
||||||
|
self.closure = closure
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class LongTapEventAction: EventAction, Decodable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case longAction
|
||||||
|
case longKeycode
|
||||||
|
case longActionAppleScript
|
||||||
|
case longExecutablePath
|
||||||
|
case longShellArguments
|
||||||
|
case longUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum LongActionTypeRaw: String, Decodable {
|
||||||
|
case hidKey
|
||||||
|
case keyPress
|
||||||
|
case appleScript
|
||||||
|
case shellScript
|
||||||
|
case openUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
super.init()
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let type = try container.decodeIfPresent(LongActionTypeRaw.self, forKey: .longAction)
|
||||||
|
|
||||||
|
switch type {
|
||||||
|
case .some(.hidKey):
|
||||||
|
let keycode = try container.decode(Int32.self, forKey: .longKeycode)
|
||||||
|
|
||||||
|
_ = setHidKeyClosure(keycode: keycode)
|
||||||
|
case .some(.keyPress):
|
||||||
|
let keycode = try container.decode(Int.self, forKey: .longKeycode)
|
||||||
|
|
||||||
|
_ = setKeyPressClosure(keycode: keycode)
|
||||||
|
case .some(.appleScript):
|
||||||
|
let source = try container.decode(Source.self, forKey: .longActionAppleScript)
|
||||||
|
|
||||||
|
guard let appleScript = source.appleScript else {
|
||||||
|
print("cannot create apple script")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = setAppleScriptClosure(appleScript: appleScript)
|
||||||
|
case .some(.shellScript):
|
||||||
|
let executable = try container.decode(String.self, forKey: .longExecutablePath)
|
||||||
|
let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? []
|
||||||
|
|
||||||
|
_ = setShellScriptClosure(executable: executable, parameters: parameters)
|
||||||
|
case .some(.openUrl):
|
||||||
|
let url = try container.decode(String.self, forKey: .longUrl)
|
||||||
|
|
||||||
|
_ = setOpenUrlClosure(url: url)
|
||||||
|
case .none:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SingleTapEventAction: EventAction, Decodable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case action
|
||||||
|
case keycode
|
||||||
|
case actionAppleScript
|
||||||
|
case executablePath
|
||||||
|
case shellArguments
|
||||||
|
case url
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ActionTypeRaw: String, Decodable {
|
||||||
|
case hidKey
|
||||||
|
case keyPress
|
||||||
|
case appleScript
|
||||||
|
case shellScript
|
||||||
|
case openUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
super.init()
|
||||||
|
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(Int32.self, forKey: .keycode)
|
||||||
|
|
||||||
|
_ = setHidKeyClosure(keycode: keycode)
|
||||||
|
case .some(.keyPress):
|
||||||
|
let keycode = try container.decode(Int.self, forKey: .keycode)
|
||||||
|
|
||||||
|
_ = setKeyPressClosure(keycode: keycode)
|
||||||
|
case .some(.appleScript):
|
||||||
|
let source = try container.decode(Source.self, forKey: .actionAppleScript)
|
||||||
|
|
||||||
|
guard let appleScript = source.appleScript else {
|
||||||
|
print("cannot create apple script")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = setAppleScriptClosure(appleScript: appleScript)
|
||||||
|
case .some(.shellScript):
|
||||||
|
let executable = try container.decode(String.self, forKey: .executablePath)
|
||||||
|
let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? []
|
||||||
|
|
||||||
|
_ = setShellScriptClosure(executable: executable, parameters: parameters)
|
||||||
|
case .some(.openUrl):
|
||||||
|
let url = try container.decode(String.self, forKey: .url)
|
||||||
|
|
||||||
|
_ = setOpenUrlClosure(url: url)
|
||||||
|
case .none:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.25</string>
|
<string>0.25</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>402</string>
|
<string>624</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>
|
||||||
|
|||||||
@ -3,550 +3,90 @@ import Foundation
|
|||||||
|
|
||||||
extension Data {
|
extension Data {
|
||||||
func barItemDefinitions() -> [BarItemDefinition]? {
|
func barItemDefinitions() -> [BarItemDefinition]? {
|
||||||
return try? JSONDecoder().decode([BarItemDefinition].self, from: utf8string!.stripComments().data(using: .utf8)!)
|
return try? JSONDecoder().decode([BarItemDefinition].self, from: utf8string!.stripComments().data(using: .utf8)!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BarItemDefinition: Decodable {
|
struct BarItemDefinition: Decodable {
|
||||||
let type: ItemType
|
let obj: CustomTouchBarItem
|
||||||
let action: ActionType
|
|
||||||
let longAction: LongActionType
|
enum ParsingErrors: Error {
|
||||||
let additionalParameters: [GeneralParameters.CodingKeys: GeneralParameter]
|
case noMatchingType(description: String)
|
||||||
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case objtype = "type"
|
||||||
}
|
}
|
||||||
|
|
||||||
init(type: ItemType, action: ActionType, longAction: LongActionType, additionalParameters: [GeneralParameters.CodingKeys: GeneralParameter]) {
|
static let types: [CustomTouchBarItem.Type] = [
|
||||||
self.type = type
|
|
||||||
self.action = action
|
|
||||||
self.longAction = longAction
|
|
||||||
self.additionalParameters = additionalParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
// custom buttons
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
CustomButtonTouchBarItem.self,
|
||||||
let type = try container.decode(String.self, forKey: .type)
|
AppleScriptTouchBarItem.self,
|
||||||
let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type)
|
ShellScriptTouchBarItem.self,
|
||||||
var additionalParameters = try GeneralParameters(from: decoder).parameters
|
|
||||||
|
|
||||||
if let result = try? parametersDecoder(decoder),
|
|
||||||
case let (itemType, action, longAction, parameters) = result {
|
|
||||||
parameters.forEach { additionalParameters[$0] = $1 }
|
|
||||||
self.init(type: itemType, action: action, longAction: longAction, additionalParameters: additionalParameters)
|
|
||||||
} else {
|
|
||||||
self.init(type: .staticButton(title: "unknown"), action: .none, longAction: .none, additionalParameters: additionalParameters)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typealias ParametersDecoder = (Decoder) throws -> (
|
// basic widget buttons
|
||||||
item: ItemType,
|
EscapeBarItem.self,
|
||||||
action: ActionType,
|
DeleteBarItem.self,
|
||||||
longAction: LongActionType,
|
BrightnessUpBarItem.self,
|
||||||
parameters: [GeneralParameters.CodingKeys: GeneralParameter]
|
BrightnessDownBarItem.self,
|
||||||
)
|
IlluminationUpBarItem.self,
|
||||||
|
IlluminationDownBarItem.self,
|
||||||
|
VolumeUpBarItem.self,
|
||||||
|
VolumeDownBarItem.self,
|
||||||
|
MuteBarItem.self,
|
||||||
|
PreviousBarItem.self,
|
||||||
|
PlayBarItem.self,
|
||||||
|
NextBarItem.self,
|
||||||
|
SleepBarItem.self,
|
||||||
|
DisplaySleepBarItem.self,
|
||||||
|
|
||||||
class SupportedTypesHolder {
|
|
||||||
private var supportedTypes: [String: ParametersDecoder] = [
|
|
||||||
"escape": { _ in (
|
|
||||||
item: .staticButton(title: "esc"),
|
|
||||||
action: .keyPress(keycode: 53),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.align: .align(.left)]
|
|
||||||
) },
|
|
||||||
|
|
||||||
"delete": { _ in (
|
// custom widgets
|
||||||
item: .staticButton(title: "del"),
|
TimeTouchBarItem.self,
|
||||||
action: .keyPress(keycode: 117),
|
BatteryBarItem.self,
|
||||||
longAction: .none,
|
AppScrubberTouchBarItem.self,
|
||||||
parameters: [:]
|
VolumeViewController.self,
|
||||||
) },
|
BrightnessViewController.self,
|
||||||
|
WeatherBarItem.self,
|
||||||
|
YandexWeatherBarItem.self,
|
||||||
|
CurrencyBarItem.self,
|
||||||
|
InputSourceBarItem.self,
|
||||||
|
MusicBarItem.self,
|
||||||
|
NightShiftBarItem.self,
|
||||||
|
DnDBarItem.self,
|
||||||
|
PomodoroBarItem.self,
|
||||||
|
NetworkBarItem.self,
|
||||||
|
DarkModeBarItem.self,
|
||||||
|
|
||||||
"brightnessUp": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessUp"))
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .keyPress(keycode: 144),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"brightnessDown": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessDown"))
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .keyPress(keycode: 145),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"illuminationUp": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "ill_up"))
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_ILLUMINATION_UP),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"illuminationDown": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "ill_down"))
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_ILLUMINATION_DOWN),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"volumeDown": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarVolumeDownTemplateName)!)
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"volumeUp": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarVolumeUpTemplateName)!)
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"mute": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarAudioOutputMuteTemplateName)!)
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_MUTE),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"previous": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarRewindTemplateName)!)
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"play": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarPlayPauseTemplateName)!)
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_PLAY),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"next": { _ in
|
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarFastForwardTemplateName)!)
|
|
||||||
return (
|
|
||||||
item: .staticButton(title: ""),
|
|
||||||
action: .hidKey(keycode: NX_KEYTYPE_NEXT),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [.image: imageParameter]
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
"sleep": { _ in (
|
|
||||||
item: .staticButton(title: "☕️"),
|
|
||||||
action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [:]
|
|
||||||
) },
|
|
||||||
|
|
||||||
"displaySleep": { _ in (
|
|
||||||
item: .staticButton(title: "☕️"),
|
|
||||||
action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]),
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [:]
|
|
||||||
) },
|
|
||||||
|
|
||||||
|
// custom-custom objects!
|
||||||
|
SwipeItem.self,
|
||||||
|
GroupBarItem.self,
|
||||||
|
ExitTouchbarBarItem.self,
|
||||||
|
CloseBarItem.self,
|
||||||
]
|
]
|
||||||
|
|
||||||
static let sharedInstance = SupportedTypesHolder()
|
init(obj: CustomTouchBarItem) {
|
||||||
|
self.obj = obj
|
||||||
func lookup(by type: String) -> ParametersDecoder {
|
|
||||||
return supportedTypes[type] ?? { decoder in (
|
|
||||||
item: try ItemType(from: decoder),
|
|
||||||
action: try ActionType(from: decoder),
|
|
||||||
longAction: try LongActionType(from: decoder),
|
|
||||||
parameters: [:]
|
|
||||||
) }
|
|
||||||
}
|
|
||||||
|
|
||||||
func register(typename: String, decoder: @escaping ParametersDecoder) {
|
|
||||||
supportedTypes[typename] = decoder
|
|
||||||
}
|
|
||||||
|
|
||||||
func register(typename: String, item: ItemType, action: ActionType, longAction: LongActionType) {
|
|
||||||
register(typename: typename) { _ in
|
|
||||||
(
|
|
||||||
item: item,
|
|
||||||
action,
|
|
||||||
longAction,
|
|
||||||
parameters: [:]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ItemType: Decodable {
|
|
||||||
case staticButton(title: String)
|
|
||||||
case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double, alternativeImages: [String: SourceProtocol])
|
|
||||||
case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
|
||||||
case timeButton(formatTemplate: String, timeZone: String?, locale: String?)
|
|
||||||
case battery
|
|
||||||
case dock(autoResize: Bool, filter: String?)
|
|
||||||
case volume
|
|
||||||
case brightness(refreshInterval: Double)
|
|
||||||
case weather(interval: Double, units: String, api_key: String, icon_type: String)
|
|
||||||
case yandexWeather(interval: Double)
|
|
||||||
case currency(interval: Double, from: String, to: String, full: Bool)
|
|
||||||
case inputsource
|
|
||||||
case music(interval: Double, disableMarquee: Bool)
|
|
||||||
case group(items: [BarItemDefinition])
|
|
||||||
case nightShift
|
|
||||||
case dnd
|
|
||||||
case pomodoro(workTime: Double, restTime: Double)
|
|
||||||
case network(flip: Bool)
|
|
||||||
case darkMode
|
|
||||||
case swipe(direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?)
|
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
|
||||||
case type
|
|
||||||
case title
|
|
||||||
case source
|
|
||||||
case refreshInterval
|
|
||||||
case from
|
|
||||||
case to
|
|
||||||
case full
|
|
||||||
case timeZone
|
|
||||||
case units
|
|
||||||
case api_key
|
|
||||||
case icon_type
|
|
||||||
case formatTemplate
|
|
||||||
case locale
|
|
||||||
case image
|
|
||||||
case url
|
|
||||||
case longUrl
|
|
||||||
case items
|
|
||||||
case workTime
|
|
||||||
case restTime
|
|
||||||
case flip
|
|
||||||
case autoResize
|
|
||||||
case filter
|
|
||||||
case disableMarquee
|
|
||||||
case alternativeImages
|
|
||||||
case sourceApple
|
|
||||||
case sourceBash
|
|
||||||
case direction
|
|
||||||
case fingers
|
|
||||||
case minOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ItemTypeRaw: String, Decodable {
|
|
||||||
case staticButton
|
|
||||||
case appleScriptTitledButton
|
|
||||||
case shellScriptTitledButton
|
|
||||||
case timeButton
|
|
||||||
case battery
|
|
||||||
case dock
|
|
||||||
case volume
|
|
||||||
case brightness
|
|
||||||
case weather
|
|
||||||
case yandexWeather
|
|
||||||
case currency
|
|
||||||
case inputsource
|
|
||||||
case music
|
|
||||||
case group
|
|
||||||
case nightShift
|
|
||||||
case dnd
|
|
||||||
case pomodoro
|
|
||||||
case network
|
|
||||||
case darkMode
|
|
||||||
case swipe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
let type = try container.decode(ItemTypeRaw.self, forKey: .type)
|
let objType = try container.decode(String.self, forKey: .objtype)
|
||||||
switch type {
|
|
||||||
case .appleScriptTitledButton:
|
|
||||||
let source = try container.decode(Source.self, forKey: .source)
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
|
||||||
let alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
|
|
||||||
self = .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages)
|
|
||||||
|
|
||||||
case .shellScriptTitledButton:
|
|
||||||
let source = try container.decode(Source.self, forKey: .source)
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
|
||||||
self = .shellScriptTitledButton(source: source, refreshInterval: interval)
|
|
||||||
|
|
||||||
case .staticButton:
|
for obj in BarItemDefinition.types {
|
||||||
let title = try container.decode(String.self, forKey: .title)
|
if obj.typeIdentifier == objType {
|
||||||
self = .staticButton(title: title)
|
self.obj = try obj.init(from: decoder)
|
||||||
|
return
|
||||||
case .timeButton:
|
}
|
||||||
let template = try container.decodeIfPresent(String.self, forKey: .formatTemplate) ?? "HH:mm"
|
|
||||||
let timeZone = try container.decodeIfPresent(String.self, forKey: .timeZone) ?? nil
|
|
||||||
let locale = try container.decodeIfPresent(String.self, forKey: .locale) ?? nil
|
|
||||||
self = .timeButton(formatTemplate: template, timeZone: timeZone, locale: locale)
|
|
||||||
|
|
||||||
case .battery:
|
|
||||||
self = .battery
|
|
||||||
|
|
||||||
case .dock:
|
|
||||||
let autoResize = try container.decodeIfPresent(Bool.self, forKey: .autoResize) ?? false
|
|
||||||
let filterRegexString = try container.decodeIfPresent(String.self, forKey: .filter)
|
|
||||||
self = .dock(autoResize: autoResize, filter: filterRegexString)
|
|
||||||
|
|
||||||
case .volume:
|
|
||||||
self = .volume
|
|
||||||
|
|
||||||
case .brightness:
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 0.5
|
|
||||||
self = .brightness(refreshInterval: interval)
|
|
||||||
|
|
||||||
case .weather:
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
|
||||||
let units = try container.decodeIfPresent(String.self, forKey: .units) ?? "metric"
|
|
||||||
let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6"
|
|
||||||
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)
|
|
||||||
|
|
||||||
case .yandexWeather:
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
|
||||||
self = .yandexWeather(interval: interval)
|
|
||||||
|
|
||||||
case .currency:
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 600.0
|
|
||||||
let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB"
|
|
||||||
let to = try container.decodeIfPresent(String.self, forKey: .to) ?? "USD"
|
|
||||||
let full = try container.decodeIfPresent(Bool.self, forKey: .full) ?? false
|
|
||||||
self = .currency(interval: interval, from: from, to: to, full: full)
|
|
||||||
|
|
||||||
case .inputsource:
|
|
||||||
self = .inputsource
|
|
||||||
|
|
||||||
case .music:
|
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 5.0
|
|
||||||
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
|
|
||||||
self = .music(interval: interval, disableMarquee: disableMarquee)
|
|
||||||
|
|
||||||
case .group:
|
|
||||||
let items = try container.decode([BarItemDefinition].self, forKey: .items)
|
|
||||||
self = .group(items: items)
|
|
||||||
|
|
||||||
case .nightShift:
|
|
||||||
self = .nightShift
|
|
||||||
|
|
||||||
case .dnd:
|
|
||||||
self = .dnd
|
|
||||||
|
|
||||||
case .pomodoro:
|
|
||||||
let workTime = try container.decodeIfPresent(Double.self, forKey: .workTime) ?? 1500.0
|
|
||||||
let restTime = try container.decodeIfPresent(Double.self, forKey: .restTime) ?? 600.0
|
|
||||||
self = .pomodoro(workTime: workTime, restTime: restTime)
|
|
||||||
|
|
||||||
case .network:
|
|
||||||
let flip = try container.decodeIfPresent(Bool.self, forKey: .flip) ?? false
|
|
||||||
self = .network(flip: flip)
|
|
||||||
|
|
||||||
case .darkMode:
|
|
||||||
self = .darkMode
|
|
||||||
|
|
||||||
case .swipe:
|
|
||||||
let sourceApple = try container.decodeIfPresent(Source.self, forKey: .sourceApple)
|
|
||||||
let sourceBash = try container.decodeIfPresent(Source.self, forKey: .sourceBash)
|
|
||||||
let direction = try container.decode(String.self, forKey: .direction)
|
|
||||||
let fingers = try container.decode(Int.self, forKey: .fingers)
|
|
||||||
let minOffset = try container.decodeIfPresent(Float.self, forKey: .minOffset) ?? 0.0
|
|
||||||
self = .swipe(direction: direction, fingers: fingers, minOffset: minOffset, sourceApple: sourceApple, sourceBash: sourceBash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ActionType: Decodable {
|
|
||||||
case none
|
|
||||||
case hidKey(keycode: Int32)
|
|
||||||
case keyPress(keycode: Int)
|
|
||||||
case appleScript(source: SourceProtocol)
|
|
||||||
case shellScript(executable: String, parameters: [String])
|
|
||||||
case custom(closure: () -> Void)
|
|
||||||
case openUrl(url: String)
|
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
|
||||||
case action
|
|
||||||
case keycode
|
|
||||||
case actionAppleScript
|
|
||||||
case executablePath
|
|
||||||
case shellArguments
|
|
||||||
case url
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum ActionTypeRaw: String, Decodable {
|
|
||||||
case hidKey
|
|
||||||
case keyPress
|
|
||||||
case appleScript
|
|
||||||
case shellScript
|
|
||||||
case openUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
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(Int32.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 = .appleScript(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 .some(.openUrl):
|
|
||||||
let url = try container.decode(String.self, forKey: .url)
|
|
||||||
self = .openUrl(url: url)
|
|
||||||
|
|
||||||
case .none:
|
|
||||||
self = .none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LongActionType: Decodable {
|
|
||||||
case none
|
|
||||||
case hidKey(keycode: Int32)
|
|
||||||
case keyPress(keycode: Int)
|
|
||||||
case appleScript(source: SourceProtocol)
|
|
||||||
case shellScript(executable: String, parameters: [String])
|
|
||||||
case custom(closure: () -> Void)
|
|
||||||
case openUrl(url: String)
|
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
|
||||||
case longAction
|
|
||||||
case longKeycode
|
|
||||||
case longActionAppleScript
|
|
||||||
case longExecutablePath
|
|
||||||
case longShellArguments
|
|
||||||
case longUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum LongActionTypeRaw: String, Decodable {
|
|
||||||
case hidKey
|
|
||||||
case keyPress
|
|
||||||
case appleScript
|
|
||||||
case shellScript
|
|
||||||
case openUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
let longType = try container.decodeIfPresent(LongActionTypeRaw.self, forKey: .longAction)
|
|
||||||
|
|
||||||
switch longType {
|
|
||||||
case .some(.hidKey):
|
|
||||||
let keycode = try container.decode(Int32.self, forKey: .longKeycode)
|
|
||||||
self = .hidKey(keycode: keycode)
|
|
||||||
|
|
||||||
case .some(.keyPress):
|
|
||||||
let keycode = try container.decode(Int.self, forKey: .longKeycode)
|
|
||||||
self = .keyPress(keycode: keycode)
|
|
||||||
|
|
||||||
case .some(.appleScript):
|
|
||||||
let source = try container.decode(Source.self, forKey: .longActionAppleScript)
|
|
||||||
self = .appleScript(source: source)
|
|
||||||
|
|
||||||
case .some(.shellScript):
|
|
||||||
let executable = try container.decode(String.self, forKey: .longExecutablePath)
|
|
||||||
let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? []
|
|
||||||
self = .shellScript(executable: executable, parameters: parameters)
|
|
||||||
|
|
||||||
case .some(.openUrl):
|
|
||||||
let longUrl = try container.decode(String.self, forKey: .longUrl)
|
|
||||||
self = .openUrl(url: longUrl)
|
|
||||||
|
|
||||||
case .none:
|
|
||||||
self = .none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GeneralParameter {
|
|
||||||
case width(_: CGFloat)
|
|
||||||
case image(source: SourceProtocol)
|
|
||||||
case align(_: Align)
|
|
||||||
case bordered(_: Bool)
|
|
||||||
case background(_: NSColor)
|
|
||||||
case title(_: String)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GeneralParameters: Decodable {
|
|
||||||
let parameters: [GeneralParameters.CodingKeys: GeneralParameter]
|
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case width
|
|
||||||
case image
|
|
||||||
case align
|
|
||||||
case bordered
|
|
||||||
case background
|
|
||||||
case title
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
var result: [GeneralParameters.CodingKeys: GeneralParameter] = [:]
|
|
||||||
|
|
||||||
if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) {
|
|
||||||
result[.width] = .width(value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let imageSource = try container.decodeIfPresent(Source.self, forKey: .image) {
|
|
||||||
result[.image] = .image(source: imageSource)
|
|
||||||
}
|
|
||||||
|
|
||||||
let align = try container.decodeIfPresent(Align.self, forKey: .align) ?? .center
|
print("Cannot find preset mapping for \(objType)")
|
||||||
result[.align] = .align(align)
|
throw ParsingErrors.noMatchingType(description: "Cannot find preset mapping for \(objType)")
|
||||||
|
|
||||||
if let borderedFlag = try container.decodeIfPresent(Bool.self, forKey: .bordered) {
|
|
||||||
result[.bordered] = .bordered(borderedFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let backgroundColor = try container.decodeIfPresent(String.self, forKey: .background)?.hexColor {
|
|
||||||
result[.background] = .background(backgroundColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let title = try container.decodeIfPresent(String.self, forKey: .title) {
|
|
||||||
result[.title] = .title(title)
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters = result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,12 +186,6 @@ extension Data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Align: String, Decodable {
|
|
||||||
case left
|
|
||||||
case center
|
|
||||||
case right
|
|
||||||
}
|
|
||||||
|
|
||||||
extension URL {
|
extension URL {
|
||||||
var appleScript: NSAppleScript? {
|
var appleScript: NSAppleScript? {
|
||||||
guard FileManager.default.fileExists(atPath: path) else { return nil }
|
guard FileManager.default.fileExists(atPath: path) else { return nil }
|
||||||
|
|||||||
@ -12,11 +12,40 @@ class ShellScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
private let source: String
|
private let source: String
|
||||||
private var forceHideConstraint: NSLayoutConstraint!
|
private var forceHideConstraint: NSLayoutConstraint!
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case source
|
||||||
|
case refreshInterval
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "shellScriptTitledButton"
|
||||||
|
}
|
||||||
|
|
||||||
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) {
|
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) {
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
self.source = source.string ?? "echo No \"source\""
|
self.source = source.string ?? "echo No \"source\""
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
|
||||||
|
initScripts()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let source = try container.decode(Source.self, forKey: .source)
|
||||||
|
self.source = source.string ?? "echo No \"source\""
|
||||||
|
self.interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.title = "⏳"
|
||||||
|
|
||||||
|
initScripts()
|
||||||
|
}
|
||||||
|
|
||||||
|
func initScripts() {
|
||||||
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
||||||
|
|
||||||
DispatchQueue.shellScriptQueue.async {
|
DispatchQueue.shellScriptQueue.async {
|
||||||
@ -24,10 +53,6 @@ class ShellScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func refreshAndSchedule() {
|
func refreshAndSchedule() {
|
||||||
// Execute script and get result
|
// Execute script and get result
|
||||||
let scriptResult = execute(source)
|
let scriptResult = execute(source)
|
||||||
@ -45,7 +70,7 @@ class ShellScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
if (newBackgoundColor != self?.backgroundColor) { // performance optimization because of reinstallButton
|
if (newBackgoundColor != self?.backgroundColor) { // performance optimization because of reinstallButton
|
||||||
self?.backgroundColor = newBackgoundColor
|
self?.backgroundColor = newBackgoundColor
|
||||||
}
|
}
|
||||||
self?.attributedTitle = title
|
self?.setAttributedTitle(title)
|
||||||
self?.forceHideConstraint.isActive = scriptResult == ""
|
self?.forceHideConstraint.isActive = scriptResult == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,12 +9,25 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class SwipeItem: NSCustomTouchBarItem {
|
class SwipeItem: CustomTouchBarItem {
|
||||||
private var scriptApple: NSAppleScript?
|
private var scriptApple: NSAppleScript?
|
||||||
private var scriptBash: String?
|
private var scriptBash: String?
|
||||||
private var direction: String
|
private var direction: String
|
||||||
private var fingers: Int
|
private var fingers: Int
|
||||||
private var minOffset: Float
|
private var minOffset: Float
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case sourceApple
|
||||||
|
case sourceBash
|
||||||
|
case direction
|
||||||
|
case fingers
|
||||||
|
case minOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "swipe"
|
||||||
|
}
|
||||||
|
|
||||||
init?(identifier: NSTouchBarItem.Identifier, direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?) {
|
init?(identifier: NSTouchBarItem.Identifier, direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?) {
|
||||||
self.direction = direction
|
self.direction = direction
|
||||||
self.fingers = fingers
|
self.fingers = fingers
|
||||||
@ -28,6 +41,19 @@ class SwipeItem: NSCustomTouchBarItem {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.scriptApple = try container.decodeIfPresent(Source.self, forKey: .sourceApple)?.appleScript
|
||||||
|
self.scriptBash = try container.decodeIfPresent(Source.self, forKey: .sourceBash)?.string
|
||||||
|
self.direction = try container.decode(String.self, forKey: .direction)
|
||||||
|
self.fingers = try container.decode(Int.self, forKey: .fingers)
|
||||||
|
self.minOffset = try container.decodeIfPresent(Float.self, forKey: .minOffset) ?? 0.0
|
||||||
|
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
}
|
||||||
|
|
||||||
func processEvent(offset: CGFloat, fingers: Int) {
|
func processEvent(offset: CGFloat, fingers: Int) {
|
||||||
if direction == "right" && Float(offset) > self.minOffset && self.fingers == fingers {
|
if direction == "right" && Float(offset) > self.minOffset && self.fingers == fingers {
|
||||||
self.execute()
|
self.execute()
|
||||||
|
|||||||
@ -16,52 +16,6 @@ struct ExactItem {
|
|||||||
let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR")
|
let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR")
|
||||||
let standardConfigPath = appSupportDirectory.appending("/items.json")
|
let standardConfigPath = appSupportDirectory.appending("/items.json")
|
||||||
|
|
||||||
extension ItemType {
|
|
||||||
var identifierBase: String {
|
|
||||||
switch self {
|
|
||||||
case .staticButton(title: _):
|
|
||||||
return "com.toxblh.mtmr.staticButton."
|
|
||||||
case .appleScriptTitledButton(source: _):
|
|
||||||
return "com.toxblh.mtmr.appleScriptButton."
|
|
||||||
case .shellScriptTitledButton(source: _):
|
|
||||||
return "com.toxblh.mtmr.shellScriptButton."
|
|
||||||
case .timeButton(formatTemplate: _, timeZone: _, locale: _):
|
|
||||||
return "com.toxblh.mtmr.timeButton."
|
|
||||||
case .battery:
|
|
||||||
return "com.toxblh.mtmr.battery."
|
|
||||||
case .dock(autoResize: _, filter: _):
|
|
||||||
return "com.toxblh.mtmr.dock"
|
|
||||||
case .volume:
|
|
||||||
return "com.toxblh.mtmr.volume"
|
|
||||||
case .brightness(refreshInterval: _):
|
|
||||||
return "com.toxblh.mtmr.brightness"
|
|
||||||
case .weather(interval: _, units: _, api_key: _, icon_type: _):
|
|
||||||
return "com.toxblh.mtmr.weather"
|
|
||||||
case .yandexWeather(interval: _):
|
|
||||||
return "com.toxblh.mtmr.yandexWeather"
|
|
||||||
case .currency(interval: _, from: _, to: _, full: _):
|
|
||||||
return "com.toxblh.mtmr.currency"
|
|
||||||
case .inputsource:
|
|
||||||
return "com.toxblh.mtmr.inputsource."
|
|
||||||
case .music(interval: _):
|
|
||||||
return "com.toxblh.mtmr.music."
|
|
||||||
case .group(items: _):
|
|
||||||
return "com.toxblh.mtmr.groupBar."
|
|
||||||
case .nightShift:
|
|
||||||
return "com.toxblh.mtmr.nightShift."
|
|
||||||
case .dnd:
|
|
||||||
return "com.toxblh.mtmr.dnd."
|
|
||||||
case .pomodoro(interval: _):
|
|
||||||
return PomodoroBarItem.identifier
|
|
||||||
case .network(flip: _):
|
|
||||||
return NetworkBarItem.identifier
|
|
||||||
case .darkMode:
|
|
||||||
return DarkModeBarItem.identifier
|
|
||||||
case .swipe(direction: _, fingers: _, minOffset: _, sourceApple: _, sourceBash: _):
|
|
||||||
return "com.toxblh.mtmr.swipe."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension NSTouchBarItem.Identifier {
|
extension NSTouchBarItem.Identifier {
|
||||||
static let controlStripItem = NSTouchBarItem.Identifier("com.toxblh.mtmr.controlStrip")
|
static let controlStripItem = NSTouchBarItem.Identifier("com.toxblh.mtmr.controlStrip")
|
||||||
@ -73,12 +27,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
var touchBar: NSTouchBar!
|
var touchBar: NSTouchBar!
|
||||||
|
|
||||||
fileprivate var lastPresetPath = ""
|
fileprivate var lastPresetPath = ""
|
||||||
var jsonItems: [BarItemDefinition] = []
|
var items: [CustomTouchBarItem] = []
|
||||||
var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
|
|
||||||
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
|
|
||||||
var leftIdentifiers: [NSTouchBarItem.Identifier] = []
|
|
||||||
var centerIdentifiers: [NSTouchBarItem.Identifier] = []
|
|
||||||
var rightIdentifiers: [NSTouchBarItem.Identifier] = []
|
|
||||||
var basicViewIdentifier = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollView.".appending(UUID().uuidString))
|
var basicViewIdentifier = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollView.".appending(UUID().uuidString))
|
||||||
var basicView: BasicView?
|
var basicView: BasicView?
|
||||||
var swipeItems: [SwipeItem] = []
|
var swipeItems: [SwipeItem] = []
|
||||||
@ -90,14 +39,6 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
|
|
||||||
private override init() {
|
private override init() {
|
||||||
super.init()
|
super.init()
|
||||||
SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in self?.dismissTouchBar() }), longAction: .none)
|
|
||||||
|
|
||||||
SupportedTypesHolder.sharedInstance.register(typename: "close") { _ in
|
|
||||||
(item: .staticButton(title: ""), action: .custom(closure: { [weak self] in
|
|
||||||
guard let `self` = self else { return }
|
|
||||||
self.reloadPreset(path: self.lastPresetPath)
|
|
||||||
}), longAction: .none, parameters: [.width: .width(30), .image: .image(source: (NSImage(named: NSImage.stopProgressFreestandingTemplateName))!)])
|
|
||||||
}
|
|
||||||
|
|
||||||
blacklistAppIdentifiers = AppSettings.blacklistedAppIds
|
blacklistAppIdentifiers = AppSettings.blacklistedAppIds
|
||||||
|
|
||||||
@ -108,21 +49,23 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
reloadStandardConfig()
|
reloadStandardConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAndUpdatePreset(newJsonItems: [BarItemDefinition]) {
|
func createAndUpdatePreset(newItems: [BarItemDefinition]) {
|
||||||
if let oldBar = self.touchBar {
|
if let oldBar = self.touchBar {
|
||||||
minimizeSystemModal(oldBar)
|
minimizeSystemModal(oldBar)
|
||||||
}
|
}
|
||||||
touchBar = NSTouchBar()
|
touchBar = NSTouchBar()
|
||||||
jsonItems = newJsonItems
|
(items, swipeItems) = getItems(newItems: newItems)
|
||||||
itemDefinitions = [:]
|
|
||||||
items = [:]
|
|
||||||
|
|
||||||
loadItemDefinitions(jsonItems: jsonItems)
|
let leftItems = items.compactMap({ (item) -> CustomTouchBarItem? in
|
||||||
createItems()
|
item.align == .left ? item : nil
|
||||||
|
|
||||||
let centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
|
||||||
items[identifier]
|
|
||||||
})
|
})
|
||||||
|
let centerItems = items.compactMap({ (item) -> CustomTouchBarItem? in
|
||||||
|
item.align == .center ? item : nil
|
||||||
|
})
|
||||||
|
let rightItems = items.compactMap({ (item) -> CustomTouchBarItem? in
|
||||||
|
item.align == .right ? item : nil
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
let centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
let centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
||||||
let scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
|
let scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
|
||||||
@ -130,16 +73,18 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
touchBar.delegate = self
|
touchBar.delegate = self
|
||||||
touchBar.defaultItemIdentifiers = [basicViewIdentifier]
|
touchBar.defaultItemIdentifiers = [basicViewIdentifier]
|
||||||
|
|
||||||
let leftItems = leftIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
basicView = BasicView(identifier: basicViewIdentifier, items: leftItems + [scrollArea] + rightItems, swipeItems: swipeItems)
|
||||||
items[identifier]
|
|
||||||
})
|
|
||||||
let rightItems = rightIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
|
||||||
items[identifier]
|
|
||||||
})
|
|
||||||
|
|
||||||
basicView = BasicView(identifier: basicViewIdentifier, items:leftItems + [scrollArea] + rightItems, swipeItems: swipeItems)
|
|
||||||
basicView?.legacyGesturesEnabled = AppSettings.multitouchGestures
|
basicView?.legacyGesturesEnabled = AppSettings.multitouchGestures
|
||||||
|
|
||||||
|
// it seems that we need to set width only after we added them to the view
|
||||||
|
// so lets reset width here
|
||||||
|
for item in items {
|
||||||
|
item.setWidth(value: item.getWidth())
|
||||||
|
if item is CustomButtonTouchBarItem {
|
||||||
|
(item as! CustomButtonTouchBarItem).reinstallButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateActiveApp()
|
updateActiveApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,41 +111,26 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
reloadPreset(path: presetPath)
|
reloadPreset(path: presetPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadPreset(path: String) {
|
func reloadPreset(path: String?) {
|
||||||
lastPresetPath = path
|
if path != nil {
|
||||||
let items = path.fileData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, longAction: .none, additionalParameters: [:])]
|
lastPresetPath = path!
|
||||||
createAndUpdatePreset(newJsonItems: items)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadItemDefinitions(jsonItems: [BarItemDefinition]) {
|
|
||||||
let dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = "HH-mm-ss"
|
|
||||||
let time = dateFormatter.string(from: Date())
|
|
||||||
for item in jsonItems {
|
|
||||||
let identifierString = item.type.identifierBase.appending(time + "--" + UUID().uuidString)
|
|
||||||
let identifier = NSTouchBarItem.Identifier(identifierString)
|
|
||||||
itemDefinitions[identifier] = item
|
|
||||||
if item.align == .left {
|
|
||||||
leftIdentifiers.append(identifier)
|
|
||||||
}
|
|
||||||
if item.align == .right {
|
|
||||||
rightIdentifiers.append(identifier)
|
|
||||||
}
|
|
||||||
if item.align == .center {
|
|
||||||
centerIdentifiers.append(identifier)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let items = lastPresetPath.fileData?.barItemDefinitions() ?? [BarItemDefinition(obj: CustomButtonTouchBarItem(title: "bad preset"))]
|
||||||
|
createAndUpdatePreset(newItems: items)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createItems() {
|
func getItems(newItems: [BarItemDefinition]) -> ([CustomTouchBarItem], [SwipeItem]) {
|
||||||
for (identifier, definition) in itemDefinitions {
|
var items: [CustomTouchBarItem] = []
|
||||||
let item = createItem(forIdentifier: identifier, definition: definition)
|
var swipeItems: [SwipeItem] = []
|
||||||
if item is SwipeItem {
|
for item in newItems {
|
||||||
swipeItems.append(item as! SwipeItem)
|
if item.obj is SwipeItem {
|
||||||
|
swipeItems.append(item.obj as! SwipeItem)
|
||||||
} else {
|
} else {
|
||||||
items[identifier] = item
|
items.append(item.obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return (items, swipeItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setupControlStripPresence() {
|
@objc func setupControlStripPresence() {
|
||||||
@ -224,7 +154,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func dismissTouchBar() {
|
@objc func dismissTouchBar() {
|
||||||
minimizeSystemModal(touchBar)
|
minimizeSystemModal(touchBar)
|
||||||
updateControlStripPresence()
|
updateControlStripPresence()
|
||||||
}
|
}
|
||||||
@ -241,198 +171,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createItem(forIdentifier identifier: NSTouchBarItem.Identifier, definition item: BarItemDefinition) -> NSTouchBarItem? {
|
|
||||||
var barItem: NSTouchBarItem!
|
|
||||||
switch item.type {
|
|
||||||
case let .staticButton(title: title):
|
|
||||||
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title)
|
|
||||||
case let .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages):
|
|
||||||
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, alternativeImages: alternativeImages)
|
|
||||||
case let .shellScriptTitledButton(source: source, refreshInterval: interval):
|
|
||||||
barItem = ShellScriptTouchBarItem(identifier: identifier, source: source, interval: interval)
|
|
||||||
case let .timeButton(formatTemplate: template, timeZone: timeZone, locale: locale):
|
|
||||||
barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template, timeZone: timeZone, locale: locale)
|
|
||||||
case .battery:
|
|
||||||
barItem = BatteryBarItem(identifier: identifier)
|
|
||||||
case let .dock(autoResize: autoResize, filter: regexString):
|
|
||||||
if let regexString = regexString {
|
|
||||||
guard let regex = try? NSRegularExpression(pattern: regexString, options: []) else {
|
|
||||||
barItem = CustomButtonTouchBarItem(identifier: identifier, title: "Bad regex")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
barItem = AppScrubberTouchBarItem(identifier: identifier, autoResize: autoResize, filter: regex)
|
|
||||||
} else {
|
|
||||||
barItem = AppScrubberTouchBarItem(identifier: identifier, autoResize: autoResize)
|
|
||||||
}
|
|
||||||
case .volume:
|
|
||||||
if case let .image(source)? = item.additionalParameters[.image] {
|
|
||||||
barItem = VolumeViewController(identifier: identifier, image: source.image)
|
|
||||||
} else {
|
|
||||||
barItem = VolumeViewController(identifier: identifier)
|
|
||||||
}
|
|
||||||
case let .brightness(refreshInterval: interval):
|
|
||||||
if case let .image(source)? = item.additionalParameters[.image] {
|
|
||||||
barItem = BrightnessViewController(identifier: identifier, refreshInterval: interval, image: source.image)
|
|
||||||
} else {
|
|
||||||
barItem = BrightnessViewController(identifier: identifier, refreshInterval: interval)
|
|
||||||
}
|
|
||||||
case let .weather(interval: interval, units: units, api_key: api_key, icon_type: icon_type):
|
|
||||||
barItem = WeatherBarItem(identifier: identifier, interval: interval, units: units, api_key: api_key, icon_type: icon_type)
|
|
||||||
case let .yandexWeather(interval: interval):
|
|
||||||
barItem = YandexWeatherBarItem(identifier: identifier, interval: interval)
|
|
||||||
case let .currency(interval: interval, from: from, to: to, full: full):
|
|
||||||
barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to, full: full)
|
|
||||||
case .inputsource:
|
|
||||||
barItem = InputSourceBarItem(identifier: identifier)
|
|
||||||
case let .music(interval: interval, disableMarquee: disableMarquee):
|
|
||||||
barItem = MusicBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee)
|
|
||||||
case let .group(items: items):
|
|
||||||
barItem = GroupBarItem(identifier: identifier, items: items)
|
|
||||||
case .nightShift:
|
|
||||||
barItem = NightShiftBarItem(identifier: identifier)
|
|
||||||
case .dnd:
|
|
||||||
barItem = DnDBarItem(identifier: identifier)
|
|
||||||
case let .pomodoro(workTime: workTime, restTime: restTime):
|
|
||||||
barItem = PomodoroBarItem(identifier: identifier, workTime: workTime, restTime: restTime)
|
|
||||||
case let .network(flip: flip):
|
|
||||||
barItem = NetworkBarItem(identifier: identifier, flip: flip)
|
|
||||||
case .darkMode:
|
|
||||||
barItem = DarkModeBarItem(identifier: identifier)
|
|
||||||
case let .swipe(direction: direction, fingers: fingers, minOffset: minOffset, sourceApple: sourceApple, sourceBash: sourceBash):
|
|
||||||
barItem = SwipeItem(identifier: identifier, direction: direction, fingers: fingers, minOffset: minOffset, sourceApple: sourceApple, sourceBash: sourceBash)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem {
|
|
||||||
item.tapClosure = action
|
|
||||||
}
|
|
||||||
if let longAction = self.longAction(forItem: item), let item = barItem as? CustomButtonTouchBarItem {
|
|
||||||
item.longTapClosure = longAction
|
|
||||||
}
|
|
||||||
if case let .bordered(bordered)? = item.additionalParameters[.bordered], let item = barItem as? CustomButtonTouchBarItem {
|
|
||||||
item.isBordered = bordered
|
|
||||||
}
|
|
||||||
if case let .background(color)? = item.additionalParameters[.background], let item = barItem as? CustomButtonTouchBarItem {
|
|
||||||
item.backgroundColor = color
|
|
||||||
}
|
|
||||||
if case let .width(value)? = item.additionalParameters[.width], let widthBarItem = barItem as? CanSetWidth {
|
|
||||||
widthBarItem.setWidth(value: value)
|
|
||||||
}
|
|
||||||
if case let .image(source)? = item.additionalParameters[.image], let item = barItem as? CustomButtonTouchBarItem {
|
|
||||||
item.image = source.image
|
|
||||||
}
|
|
||||||
if case let .title(value)? = item.additionalParameters[.title] {
|
|
||||||
if let item = barItem as? GroupBarItem {
|
|
||||||
item.collapsedRepresentationLabel = value
|
|
||||||
} else if let item = barItem as? CustomButtonTouchBarItem {
|
|
||||||
item.title = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return barItem
|
|
||||||
}
|
|
||||||
|
|
||||||
func action(forItem item: BarItemDefinition) -> (() -> Void)? {
|
|
||||||
switch item.action {
|
|
||||||
case let .hidKey(keycode: keycode):
|
|
||||||
return { HIDPostAuxKey(keycode) }
|
|
||||||
case let .keyPress(keycode: keycode):
|
|
||||||
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
|
|
||||||
case let .appleScript(source: source):
|
|
||||||
guard let appleScript = source.appleScript else {
|
|
||||||
print("cannot create apple script for item \(item)")
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
DispatchQueue.appleScriptQueue.async {
|
|
||||||
var error: NSDictionary?
|
|
||||||
appleScript.executeAndReturnError(&error)
|
|
||||||
if let error = error {
|
|
||||||
print("error \(error) when handling \(item) ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case let .shellScript(executable: executable, parameters: parameters):
|
|
||||||
return {
|
|
||||||
let task = Process()
|
|
||||||
task.launchPath = executable
|
|
||||||
task.arguments = parameters
|
|
||||||
task.launch()
|
|
||||||
}
|
|
||||||
case let .openUrl(url: url):
|
|
||||||
return {
|
|
||||||
if let url = URL(string: url), NSWorkspace.shared.open(url) {
|
|
||||||
#if DEBUG
|
|
||||||
print("URL was successfully opened")
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
print("error", url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case let .custom(closure: closure):
|
|
||||||
return closure
|
|
||||||
case .none:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func longAction(forItem item: BarItemDefinition) -> (() -> Void)? {
|
|
||||||
switch item.longAction {
|
|
||||||
case let .hidKey(keycode: keycode):
|
|
||||||
return { HIDPostAuxKey(keycode) }
|
|
||||||
case let .keyPress(keycode: keycode):
|
|
||||||
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
|
|
||||||
case let .appleScript(source: 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 let .shellScript(executable: executable, parameters: parameters):
|
|
||||||
return {
|
|
||||||
let task = Process()
|
|
||||||
task.launchPath = executable
|
|
||||||
task.arguments = parameters
|
|
||||||
task.launch()
|
|
||||||
}
|
|
||||||
case let .openUrl(url: url):
|
|
||||||
return {
|
|
||||||
if let url = URL(string: url), NSWorkspace.shared.open(url) {
|
|
||||||
#if DEBUG
|
|
||||||
print("URL was successfully opened")
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
print("error", url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case let .custom(closure: closure):
|
|
||||||
return closure
|
|
||||||
case .none:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol CanSetWidth {
|
protocol CanSetWidth {
|
||||||
func setWidth(value: CGFloat)
|
func setWidth(value: CGFloat)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NSCustomTouchBarItem: CanSetWidth {
|
|
||||||
func setWidth(value: CGFloat) {
|
|
||||||
view.widthAnchor.constraint(equalToConstant: value).isActive = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BarItemDefinition {
|
|
||||||
var align: Align {
|
|
||||||
if case let .align(result)? = additionalParameters[.align] {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
return .center
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class AppScrubberTouchBarItem: NSCustomTouchBarItem {
|
class AppScrubberTouchBarItem: CustomTouchBarItem {
|
||||||
private var scrollView = NSScrollView()
|
private var scrollView = NSScrollView()
|
||||||
private var autoResize: Bool = false
|
private var autoResize: Bool = false
|
||||||
private var widthConstraint: NSLayoutConstraint?
|
private var widthConstraint: NSLayoutConstraint?
|
||||||
@ -20,6 +20,20 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem {
|
|||||||
return NSWorkspace.shared.frontmostApplication?.bundleIdentifier
|
return NSWorkspace.shared.frontmostApplication?.bundleIdentifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ParsingErrors: Error {
|
||||||
|
case IncorrectRegex(description: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case autoResize
|
||||||
|
case filter
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "dock"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private var applications: [DockItem] = []
|
private var applications: [DockItem] = []
|
||||||
private var items: [DockBarItem] = []
|
private var items: [DockBarItem] = []
|
||||||
|
|
||||||
@ -29,6 +43,35 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem {
|
|||||||
self.autoResize = autoResize
|
self.autoResize = autoResize
|
||||||
view = scrollView
|
view = scrollView
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.autoResize = try container.decodeIfPresent(Bool.self, forKey: .autoResize) ?? false
|
||||||
|
let filterRegexString = try container.decodeIfPresent(String.self, forKey: .filter)
|
||||||
|
|
||||||
|
if let filterRegexString = filterRegexString {
|
||||||
|
let regex = try? NSRegularExpression(pattern: filterRegexString, options: [])
|
||||||
|
if regex == nil {
|
||||||
|
throw ParsingErrors.IncorrectRegex(description: "incorrect regex")
|
||||||
|
}
|
||||||
|
self.filter = regex
|
||||||
|
} else {
|
||||||
|
self.filter = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
view = scrollView
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(hardReloadItems), name: NSWorkspace.didLaunchApplicationNotification, object: nil)
|
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(hardReloadItems), name: NSWorkspace.didLaunchApplicationNotification, object: nil)
|
||||||
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(hardReloadItems), name: NSWorkspace.didTerminateApplicationNotification, object: nil)
|
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(hardReloadItems), name: NSWorkspace.didTerminateApplicationNotification, object: nil)
|
||||||
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(softReloadItems), name: NSWorkspace.didActivateApplicationNotification, object: nil)
|
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(softReloadItems), name: NSWorkspace.didActivateApplicationNotification, object: nil)
|
||||||
@ -37,9 +80,6 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem {
|
|||||||
hardReloadItems()
|
hardReloadItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func hardReloadItems() {
|
@objc func hardReloadItems() {
|
||||||
applications = launchedApplications()
|
applications = launchedApplications()
|
||||||
@ -82,12 +122,17 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem {
|
|||||||
public func createAppButton(for app: DockItem) -> DockBarItem {
|
public func createAppButton(for app: DockItem) -> DockBarItem {
|
||||||
let item = DockBarItem(app)
|
let item = DockBarItem(app)
|
||||||
item.isBordered = false
|
item.isBordered = false
|
||||||
item.tapClosure = { [weak self] in
|
|
||||||
self?.switchToApp(app: app)
|
item.setTapAction(
|
||||||
}
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
item.longTapClosure = { [weak self] in
|
self?.switchToApp(app: app)
|
||||||
self?.handleHalfLongPress(item: app)
|
} )
|
||||||
}
|
)
|
||||||
|
item.setLongTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.handleHalfLongPress(item: app)
|
||||||
|
} )
|
||||||
|
)
|
||||||
item.killAppClosure = {[weak self] in
|
item.killAppClosure = {[weak self] in
|
||||||
self?.handleLongPress(item: app)
|
self?.handleLongPress(item: app)
|
||||||
}
|
}
|
||||||
@ -212,8 +257,8 @@ class DockBarItem: CustomButtonTouchBarItem {
|
|||||||
super.init(identifier: .init(app.bundleIdentifier), title: "")
|
super.init(identifier: .init(app.bundleIdentifier), title: "")
|
||||||
dotView.wantsLayer = true
|
dotView.wantsLayer = true
|
||||||
|
|
||||||
image = app.icon
|
self.setImage(app.icon)
|
||||||
image?.size = NSSize(width: iconWidth, height: iconWidth)
|
self.getImage()?.size = NSSize(width: iconWidth, height: iconWidth)
|
||||||
|
|
||||||
killGestureRecognizer = LongPressGestureRecognizer(target: self, action: #selector(firePanGestureRecognizer))
|
killGestureRecognizer = LongPressGestureRecognizer(target: self, action: #selector(firePanGestureRecognizer))
|
||||||
killGestureRecognizer.allowedTouchTypes = .direct
|
killGestureRecognizer.allowedTouchTypes = .direct
|
||||||
@ -243,4 +288,8 @@ class DockBarItem: CustomButtonTouchBarItem {
|
|||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) {
|
||||||
|
fatalError("init(from decoder:) has not been implemented")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,21 +12,35 @@ import IOKit.ps
|
|||||||
class BatteryBarItem: CustomButtonTouchBarItem {
|
class BatteryBarItem: CustomButtonTouchBarItem {
|
||||||
private let batteryInfo = BatteryInfo()
|
private let batteryInfo = BatteryInfo()
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "battery"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier) {
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
super.init(identifier: identifier, title: " ")
|
super.init(identifier: identifier, title: " ")
|
||||||
|
|
||||||
batteryInfo.start { [weak self] in
|
self.setup()
|
||||||
self?.refresh()
|
|
||||||
}
|
|
||||||
refresh()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
batteryInfo.start { [weak self] in
|
||||||
|
self?.refresh()
|
||||||
|
}
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
func refresh() {
|
func refresh() {
|
||||||
attributedTitle = batteryInfo.formattedInfo()
|
setAttributedTitle(batteryInfo.formattedInfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|||||||
27
MTMR/Widgets/BrightnessDownBarItem.swift
Normal file
27
MTMR/Widgets/BrightnessDownBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// BrightnessDownBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class BrightnessDownBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "brightnessDown"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(#imageLiteral(resourceName: "brightnessDown"))
|
||||||
|
self.setTapAction(EventAction().setKeyPressClosure(keycode: 145))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
27
MTMR/Widgets/BrightnessUpBarItem.swift
Normal file
27
MTMR/Widgets/BrightnessUpBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// BrightnessUpBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class BrightnessUpBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "brightnessUp"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(#imageLiteral(resourceName: "brightnessUp"))
|
||||||
|
self.setTapAction(EventAction().setKeyPressClosure(keycode: 144))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -3,12 +3,39 @@ import AVFoundation
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
import CoreAudio
|
import CoreAudio
|
||||||
|
|
||||||
class BrightnessViewController: NSCustomTouchBarItem {
|
class BrightnessViewController: CustomTouchBarItem {
|
||||||
private(set) var sliderItem: CustomSlider!
|
private(set) var sliderItem: CustomSlider!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "brightness"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case image
|
||||||
|
case refreshInterval
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, refreshInterval: Double, image: NSImage? = nil) {
|
init(identifier: NSTouchBarItem.Identifier, refreshInterval: Double, image: NSImage? = nil) {
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
|
self.setup(image: nil, interval: refreshInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let image = try container.decodeIfPresent(Source.self, forKey: .image)?.image
|
||||||
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 0.5
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setup(image: image, interval: interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func setup(image: NSImage?, interval: Double) {
|
||||||
if image == nil {
|
if image == nil {
|
||||||
sliderItem = CustomSlider()
|
sliderItem = CustomSlider()
|
||||||
} else {
|
} else {
|
||||||
@ -22,14 +49,10 @@ class BrightnessViewController: NSCustomTouchBarItem {
|
|||||||
|
|
||||||
view = sliderItem
|
view = sliderItem
|
||||||
|
|
||||||
let timer = Timer.scheduledTimer(timeInterval: refreshInterval, target: self, selector: #selector(BrightnessViewController.updateBrightnessSlider), userInfo: nil, repeats: true)
|
let timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(BrightnessViewController.updateBrightnessSlider), userInfo: nil, repeats: true)
|
||||||
RunLoop.current.add(timer, forMode: RunLoop.Mode.common)
|
RunLoop.current.add(timer, forMode: RunLoop.Mode.common)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
sliderItem.unbind(NSBindingName.value)
|
sliderItem.unbind(NSBindingName.value)
|
||||||
}
|
}
|
||||||
|
|||||||
48
MTMR/Widgets/CloseBarItem.swift
Normal file
48
MTMR/Widgets/CloseBarItem.swift
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// CloseBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/30/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class CloseBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "close"
|
||||||
|
}
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
|
super.init(identifier: identifier, title: "")
|
||||||
|
|
||||||
|
if self.title == "" {
|
||||||
|
self.title = "close"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(EventAction.init({_ in
|
||||||
|
|
||||||
|
TouchBarController.shared.reloadPreset(path: nil)
|
||||||
|
|
||||||
|
} ))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
if self.title == "" {
|
||||||
|
self.title = "close"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(EventAction.init({_ in
|
||||||
|
|
||||||
|
TouchBarController.shared.reloadPreset(path: nil)
|
||||||
|
|
||||||
|
} ))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -59,6 +59,18 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
"ETH": 2,
|
"ETH": 2,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "currency"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case refreshInterval
|
||||||
|
case from
|
||||||
|
case to
|
||||||
|
case full
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, full: Bool) {
|
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, full: Bool) {
|
||||||
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||||
activity.interval = interval
|
activity.interval = interval
|
||||||
@ -87,7 +99,51 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
|
|
||||||
|
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 600.0
|
||||||
|
let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB"
|
||||||
|
let to = try container.decodeIfPresent(String.self, forKey: .to) ?? "USD"
|
||||||
|
let full = try container.decodeIfPresent(Bool.self, forKey: .full) ?? false
|
||||||
|
|
||||||
|
activity = NSBackgroundActivityScheduler(identifier: CustomTouchBarItem.createIdentifier("Currency.updatecheck").rawValue)
|
||||||
|
activity.interval = interval
|
||||||
|
self.from = from
|
||||||
|
self.to = to
|
||||||
|
self.full = full
|
||||||
|
|
||||||
|
if let prefix = currencies[from] {
|
||||||
|
self.prefix = prefix
|
||||||
|
} else {
|
||||||
|
prefix = from
|
||||||
|
}
|
||||||
|
|
||||||
|
if let postfix = currencies[to] {
|
||||||
|
self.postfix = postfix
|
||||||
|
} else {
|
||||||
|
postfix = to
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if let decimal = decimals[to] {
|
||||||
|
self.decimal = decimal
|
||||||
|
} else {
|
||||||
|
decimal = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
activity.repeats = true
|
activity.repeats = true
|
||||||
activity.qualityOfService = .utility
|
activity.qualityOfService = .utility
|
||||||
activity.schedule { (completion: NSBackgroundActivityScheduler.CompletionHandler) in
|
activity.schedule { (completion: NSBackgroundActivityScheduler.CompletionHandler) in
|
||||||
@ -97,10 +153,6 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
updateCurrency()
|
updateCurrency()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func updateCurrency() {
|
@objc func updateCurrency() {
|
||||||
let urlRequest = URLRequest(url: URL(string: "https://api.coinbase.com/v2/exchange-rates?currency=\(from)")!)
|
let urlRequest = URLRequest(url: URL(string: "https://api.coinbase.com/v2/exchange-rates?currency=\(from)")!)
|
||||||
|
|
||||||
@ -153,10 +205,10 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
title = String(format: "%@%.2f", prefix, value)
|
title = String(format: "%@%.2f", prefix, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
let regularFont = attributedTitle.attribute(.font, at: 0, effectiveRange: nil) as? NSFont ?? NSFont.systemFont(ofSize: 15)
|
let regularFont = getAttributedTitle().attribute(.font, at: 0, effectiveRange: nil) as? NSFont ?? NSFont.systemFont(ofSize: 15)
|
||||||
let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: regularFont, .baselineOffset: 1])
|
let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: regularFont, .baselineOffset: 1])
|
||||||
newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
|
newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
|
||||||
attributedTitle = newTitle
|
setAttributedTitle(newTitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|||||||
@ -1,34 +1,51 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class DarkModeBarItem: CustomButtonTouchBarItem, Widget {
|
class DarkModeBarItem: CustomButtonTouchBarItem {
|
||||||
static var name: String = "darkmode"
|
|
||||||
static var identifier: String = "com.toxblh.mtmr.darkmode"
|
|
||||||
|
|
||||||
private var timer: Timer!
|
private var timer: Timer!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "darkMode"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier) {
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
super.init(identifier: identifier, title: "")
|
super.init(identifier: identifier, title: "")
|
||||||
isBordered = false
|
|
||||||
setWidth(value: 24)
|
|
||||||
|
|
||||||
tapClosure = { [weak self] in self?.DarkModeToggle() }
|
self.setup()
|
||||||
|
|
||||||
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
|
|
||||||
|
|
||||||
refresh()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
if getWidth() == 0.0 {
|
||||||
|
setWidth(value: 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.DarkModeToggle()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
|
||||||
|
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
func DarkModeToggle() {
|
func DarkModeToggle() {
|
||||||
DarkMode.isEnabled = !DarkMode.isEnabled
|
DarkMode.isEnabled = !DarkMode.isEnabled
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func refresh() {
|
@objc func refresh() {
|
||||||
image = DarkMode.isEnabled ? #imageLiteral(resourceName: "dark-mode-on") : #imageLiteral(resourceName: "dark-mode-off")
|
self.setImage(DarkMode.isEnabled ? #imageLiteral(resourceName: "dark-mode-on") : #imageLiteral(resourceName: "dark-mode-off"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
MTMR/Widgets/DeleteBarItem.swift
Normal file
27
MTMR/Widgets/DeleteBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// DeleteBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class DeleteBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "delete"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
print("DeleteBarItem.init")
|
||||||
|
self.title = "del"
|
||||||
|
self.setTapAction(EventAction().setKeyPressClosure(keycode: 117))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
27
MTMR/Widgets/DisplaySleepBarItem.swift
Normal file
27
MTMR/Widgets/DisplaySleepBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// DisplaySleep.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class DisplaySleepBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "displaySleep"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.title = "☕️"
|
||||||
|
self.setTapAction(EventAction().setShellScriptClosure(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -11,29 +11,47 @@ import Foundation
|
|||||||
class DnDBarItem: CustomButtonTouchBarItem {
|
class DnDBarItem: CustomButtonTouchBarItem {
|
||||||
private var timer: Timer!
|
private var timer: Timer!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "dnd"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier) {
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
super.init(identifier: identifier, title: "")
|
super.init(identifier: identifier, title: "")
|
||||||
isBordered = false
|
self.setup()
|
||||||
setWidth(value: 32)
|
|
||||||
|
|
||||||
tapClosure = { [weak self] in self?.DnDToggle() }
|
|
||||||
|
|
||||||
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
|
|
||||||
|
|
||||||
refresh()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
if getWidth() == 0.0 {
|
||||||
|
setWidth(value: 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.DnDToggle()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
|
||||||
|
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
func DnDToggle() {
|
func DnDToggle() {
|
||||||
DoNotDisturb.isEnabled = !DoNotDisturb.isEnabled
|
DoNotDisturb.isEnabled = !DoNotDisturb.isEnabled
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func refresh() {
|
@objc func refresh() {
|
||||||
image = DoNotDisturb.isEnabled ? #imageLiteral(resourceName: "dnd-on") : #imageLiteral(resourceName: "dnd-off")
|
self.setImage(DoNotDisturb.isEnabled ? #imageLiteral(resourceName: "dnd-on") : #imageLiteral(resourceName: "dnd-off"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
MTMR/Widgets/EscapeBarItem.swift
Normal file
27
MTMR/Widgets/EscapeBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// EscapeBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class EscapeBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "escape"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.title = "escape"
|
||||||
|
self.setTapAction(EventAction().setKeyPressClosure(keycode: 53))
|
||||||
|
self.align = .left
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
50
MTMR/Widgets/ExitTouchbarBarItem.swift
Normal file
50
MTMR/Widgets/ExitTouchbarBarItem.swift
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// ExitTouchbarBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/30/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class ExitTouchbarBarItem: CustomButtonTouchBarItem {
|
||||||
|
private var timer: Timer!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "exitTouchbar"
|
||||||
|
}
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
|
super.init(identifier: identifier, title: "")
|
||||||
|
|
||||||
|
if self.title == "" {
|
||||||
|
self.title = "exit"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(EventAction.init({_ in
|
||||||
|
|
||||||
|
TouchBarController.shared.dismissTouchBar()
|
||||||
|
|
||||||
|
} ))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
if self.title == "" {
|
||||||
|
self.title = "exit"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(EventAction.init({_ in
|
||||||
|
|
||||||
|
TouchBarController.shared.dismissTouchBar()
|
||||||
|
|
||||||
|
} ))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -7,50 +7,96 @@
|
|||||||
//
|
//
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate {
|
|
||||||
var jsonItems: [BarItemDefinition]
|
class GroupBarItem: CustomTouchBarItem, NSTouchBarDelegate {
|
||||||
|
private(set) var popoverItem: NSPopoverTouchBarItem!
|
||||||
|
var jsonItems: [BarItemDefinition] = []
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "group"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case items
|
||||||
|
case title
|
||||||
|
}
|
||||||
|
|
||||||
var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
|
var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
|
||||||
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
|
var items: [CustomTouchBarItem] = []
|
||||||
var leftIdentifiers: [NSTouchBarItem.Identifier] = []
|
var leftIdentifiers: [NSTouchBarItem.Identifier] = []
|
||||||
var centerIdentifiers: [NSTouchBarItem.Identifier] = []
|
var centerIdentifiers: [NSTouchBarItem.Identifier] = []
|
||||||
var centerItems: [NSTouchBarItem] = []
|
var centerItems: [NSTouchBarItem] = []
|
||||||
var rightIdentifiers: [NSTouchBarItem.Identifier] = []
|
var rightIdentifiers: [NSTouchBarItem.Identifier] = []
|
||||||
var scrollArea: NSCustomTouchBarItem?
|
var scrollArea: NSCustomTouchBarItem?
|
||||||
var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
var swipeItems: [SwipeItem] = []
|
||||||
|
var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.GroupScrollArea.".appending(UUID().uuidString))
|
||||||
|
var basicView: BasicView?
|
||||||
|
var basicViewIdentifier = NSTouchBarItem.Identifier("com.toxblh.mtmr.GroupScrollView.".appending(UUID().uuidString))
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, items: [BarItemDefinition]) {
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, items: [BarItemDefinition], title: String) {
|
||||||
jsonItems = items
|
jsonItems = items
|
||||||
|
popoverItem = NSPopoverTouchBarItem(identifier: identifier)
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
popoverTouchBar.delegate = self
|
|
||||||
|
self.setup(title: title)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {}
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
popoverItem = NSPopoverTouchBarItem(identifier: identifier)
|
||||||
|
|
||||||
@objc override func showPopover(_: Any?) {
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
itemDefinitions = [:]
|
self.jsonItems = try container.decode([BarItemDefinition].self, forKey: .items)
|
||||||
items = [:]
|
let title = try container.decodeIfPresent(String.self, forKey: .title) ?? " "
|
||||||
leftIdentifiers = []
|
|
||||||
centerItems = []
|
|
||||||
rightIdentifiers = []
|
|
||||||
|
|
||||||
loadItemDefinitions(jsonItems: jsonItems)
|
self.setup(title: title)
|
||||||
createItems()
|
}
|
||||||
|
|
||||||
centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
|
||||||
items[identifier]
|
func setup(title: String) {
|
||||||
|
let button = NSButton(title: title, target: self,
|
||||||
|
action: #selector(GroupBarItem.showPopover(_:)))
|
||||||
|
|
||||||
|
// Use the built-in gesture recognizer for tap and hold to open our popover's NSTouchBar.
|
||||||
|
let gestureRecognizer = popoverItem.makeStandardActivatePopoverGestureRecognizer()
|
||||||
|
button.addGestureRecognizer(gestureRecognizer)
|
||||||
|
|
||||||
|
popoverItem.collapsedRepresentation = button
|
||||||
|
|
||||||
|
view = button
|
||||||
|
|
||||||
|
if getWidth() == 0.0 {
|
||||||
|
setWidth(value: 60)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func showPopover(_: Any?) {
|
||||||
|
items = getItems(newItems: jsonItems)
|
||||||
|
|
||||||
|
let leftItems = items.compactMap({ (item) -> CustomTouchBarItem? in
|
||||||
|
item.align == .left || item.align == .center ? item : nil
|
||||||
|
})
|
||||||
|
let centerItems = items.compactMap({ (item) -> CustomTouchBarItem? in
|
||||||
|
item.align == .center && false ? item : nil
|
||||||
|
})
|
||||||
|
let rightItems = items.compactMap({ (item) -> CustomTouchBarItem? in
|
||||||
|
item.align == .right ? item : nil
|
||||||
})
|
})
|
||||||
|
|
||||||
centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
let centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
||||||
scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
|
let scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
|
||||||
|
|
||||||
TouchBarController.shared.touchBar.delegate = self
|
TouchBarController.shared.touchBar.delegate = self
|
||||||
TouchBarController.shared.touchBar.defaultItemIdentifiers = []
|
TouchBarController.shared.touchBar.defaultItemIdentifiers = [basicViewIdentifier]
|
||||||
TouchBarController.shared.touchBar.defaultItemIdentifiers = leftIdentifiers + [centerScrollArea] + rightIdentifiers
|
|
||||||
|
basicView = BasicView(identifier: basicViewIdentifier, items: leftItems + [scrollArea] + rightItems, swipeItems: swipeItems)
|
||||||
|
basicView?.legacyGesturesEnabled = AppSettings.multitouchGestures
|
||||||
|
|
||||||
|
|
||||||
if AppSettings.showControlStripState {
|
if AppSettings.showControlStripState {
|
||||||
presentSystemModal(TouchBarController.shared.touchBar, systemTrayItemIdentifier: .controlStripItem)
|
presentSystemModal(TouchBarController.shared.touchBar, systemTrayItemIdentifier: .controlStripItem)
|
||||||
@ -60,41 +106,23 @@ class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func touchBar(_: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
|
func touchBar(_: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
|
||||||
if identifier == centerScrollArea {
|
if identifier == basicViewIdentifier {
|
||||||
return scrollArea
|
return basicView
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let item = self.items[identifier],
|
return nil
|
||||||
let definition = self.itemDefinitions[identifier],
|
|
||||||
definition.align != .center else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadItemDefinitions(jsonItems: [BarItemDefinition]) {
|
func getItems(newItems: [BarItemDefinition]) -> [CustomTouchBarItem] {
|
||||||
let dateFormatter = DateFormatter()
|
var items: [CustomTouchBarItem] = []
|
||||||
dateFormatter.dateFormat = "HH-mm-ss"
|
for item in newItems {
|
||||||
let time = dateFormatter.string(from: Date())
|
if item.obj is SwipeItem {
|
||||||
for item in jsonItems {
|
swipeItems.append(item.obj as! SwipeItem)
|
||||||
let identifierString = item.type.identifierBase.appending(time + "--" + UUID().uuidString)
|
} else {
|
||||||
let identifier = NSTouchBarItem.Identifier(identifierString)
|
items.append(item.obj)
|
||||||
itemDefinitions[identifier] = item
|
|
||||||
if item.align == .left {
|
|
||||||
leftIdentifiers.append(identifier)
|
|
||||||
}
|
|
||||||
if item.align == .right {
|
|
||||||
rightIdentifiers.append(identifier)
|
|
||||||
}
|
|
||||||
if item.align == .center {
|
|
||||||
centerIdentifiers.append(identifier)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return items
|
||||||
|
|
||||||
func createItems() {
|
|
||||||
for (identifier, definition) in itemDefinitions {
|
|
||||||
items[identifier] = TouchBarController.shared.createItem(forIdentifier: identifier, definition: definition)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
MTMR/Widgets/IlluminationDownBarItem.swift
Normal file
27
MTMR/Widgets/IlluminationDownBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// illuminationDownBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class IlluminationDownBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "illuminationDown"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(#imageLiteral(resourceName: "ill_down"))
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_ILLUMINATION_DOWN))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
27
MTMR/Widgets/IlluminationUpBarItem.swift
Normal file
27
MTMR/Widgets/IlluminationUpBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// illuminationUpBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class IlluminationUpBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "illuminationUp"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(#imageLiteral(resourceName: "ill_up"))
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_ILLUMINATION_UP))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -12,21 +12,38 @@ class InputSourceBarItem: CustomButtonTouchBarItem {
|
|||||||
fileprivate var notificationCenter: CFNotificationCenter
|
fileprivate var notificationCenter: CFNotificationCenter
|
||||||
let buttonSize = NSSize(width: 21, height: 21)
|
let buttonSize = NSSize(width: 21, height: 21)
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "inputsource"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier) {
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
notificationCenter = CFNotificationCenterGetDistributedCenter()
|
notificationCenter = CFNotificationCenterGetDistributedCenter()
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
|
||||||
observeIputSourceChangedNotification()
|
self.setup()
|
||||||
textInputSourceDidChange()
|
|
||||||
tapClosure = { [weak self] in
|
|
||||||
self?.switchInputSource()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
notificationCenter = CFNotificationCenterGetDistributedCenter()
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
observeIputSourceChangedNotification()
|
||||||
|
textInputSourceDidChange()
|
||||||
|
self.setTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.switchInputSource()
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque()))
|
CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque()))
|
||||||
}
|
}
|
||||||
@ -45,7 +62,7 @@ class InputSourceBarItem: CustomButtonTouchBarItem {
|
|||||||
|
|
||||||
if let iconImage = iconImage {
|
if let iconImage = iconImage {
|
||||||
iconImage.size = buttonSize
|
iconImage.size = buttonSize
|
||||||
image = iconImage
|
self.setImage(iconImage)
|
||||||
title = ""
|
title = ""
|
||||||
} else {
|
} else {
|
||||||
title = currentSource.name
|
title = currentSource.name
|
||||||
|
|||||||
@ -34,16 +34,35 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
private var timer: Timer?
|
private var timer: Timer?
|
||||||
private let iconSize = NSSize(width: 21, height: 21)
|
private let iconSize = NSSize(width: 21, height: 21)
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case refreshInterval
|
||||||
|
case disableMarquee
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "music"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, disableMarquee: Bool) {
|
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, disableMarquee: Bool) {
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
self.disableMarquee = disableMarquee
|
self.disableMarquee = disableMarquee
|
||||||
|
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
isBordered = false
|
|
||||||
|
|
||||||
tapClosure = { [weak self] in self?.playPause() }
|
self.setup()
|
||||||
longTapClosure = { [weak self] in self?.nextTrack() }
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
self.setTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.playPause()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
self.setLongTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.nextTrack()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
|
||||||
refreshAndSchedule()
|
refreshAndSchedule()
|
||||||
}
|
}
|
||||||
@ -61,10 +80,22 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
self.interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 5.0
|
||||||
|
self.disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
@objc func playPause() {
|
@objc func playPause() {
|
||||||
for ident in playerBundleIdentifiers {
|
for ident in playerBundleIdentifiers {
|
||||||
|
print("checking \(ident)")
|
||||||
if let musicPlayer = SBApplication(bundleIdentifier: ident.rawValue) {
|
if let musicPlayer = SBApplication(bundleIdentifier: ident.rawValue) {
|
||||||
|
print("musicPlayer \(musicPlayer)")
|
||||||
if musicPlayer.isRunning {
|
if musicPlayer.isRunning {
|
||||||
|
print("musicPlayer.isRunning \(musicPlayer.isRunning)")
|
||||||
if ident == .Spotify {
|
if ident == .Spotify {
|
||||||
let mp = (musicPlayer as SpotifyApplication)
|
let mp = (musicPlayer as SpotifyApplication)
|
||||||
mp.playpause!()
|
mp.playpause!()
|
||||||
@ -194,6 +225,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
for ident in playerBundleIdentifiers {
|
for ident in playerBundleIdentifiers {
|
||||||
if let musicPlayer = SBApplication(bundleIdentifier: ident.rawValue) {
|
if let musicPlayer = SBApplication(bundleIdentifier: ident.rawValue) {
|
||||||
if musicPlayer.isRunning {
|
if musicPlayer.isRunning {
|
||||||
|
print("musicPlayer \(musicPlayer)")
|
||||||
var tempTitle = ""
|
var tempTitle = ""
|
||||||
if ident == .Spotify {
|
if ident == .Spotify {
|
||||||
tempTitle = (musicPlayer as SpotifyApplication).title
|
tempTitle = (musicPlayer as SpotifyApplication).title
|
||||||
@ -268,7 +300,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: ident.rawValue) {
|
let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: ident.rawValue) {
|
||||||
let image = NSWorkspace.shared.icon(forFile: appPath)
|
let image = NSWorkspace.shared.icon(forFile: appPath)
|
||||||
image.size = self.iconSize
|
image.size = self.iconSize
|
||||||
self.image = image
|
self.setImage(image)
|
||||||
iconUpdated = true
|
iconUpdated = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -278,7 +310,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if !iconUpdated {
|
if !iconUpdated {
|
||||||
self.image = nil
|
self.setImage(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !titleUpdated {
|
if !titleUpdated {
|
||||||
|
|||||||
27
MTMR/Widgets/MuteBarItem.swift
Normal file
27
MTMR/Widgets/MuteBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// MuteBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class MuteBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "mute"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(NSImage(named: NSImage.touchBarAudioOutputMuteTemplateName)!)
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_MUTE))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -8,12 +8,17 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class NetworkBarItem: CustomButtonTouchBarItem, Widget {
|
class NetworkBarItem: CustomButtonTouchBarItem {
|
||||||
static var name: String = "network"
|
|
||||||
static var identifier: String = "com.toxblh.mtmr.network"
|
|
||||||
|
|
||||||
private let flip: Bool
|
private let flip: Bool
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case flip
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "network"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, flip: Bool = false) {
|
init(identifier: NSTouchBarItem.Identifier, flip: Bool = false) {
|
||||||
self.flip = flip
|
self.flip = flip
|
||||||
super.init(identifier: identifier, title: " ")
|
super.init(identifier: identifier, title: " ")
|
||||||
@ -24,6 +29,14 @@ class NetworkBarItem: CustomButtonTouchBarItem, Widget {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
self.flip = try container.decodeIfPresent(Bool.self, forKey: .flip) ?? false
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
startMonitoringProcess()
|
||||||
|
}
|
||||||
|
|
||||||
func startMonitoringProcess() {
|
func startMonitoringProcess() {
|
||||||
var pipe: Pipe
|
var pipe: Pipe
|
||||||
var outputHandle: FileHandle
|
var outputHandle: FileHandle
|
||||||
@ -144,6 +157,6 @@ class NetworkBarItem: CustomButtonTouchBarItem, Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self.attributedTitle = newTitle
|
self.setAttributedTitle(newTitle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
MTMR/Widgets/NextBarItem.swift
Normal file
27
MTMR/Widgets/NextBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// NextBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class NextBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "next"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(NSImage(named: NSImage.touchBarFastForwardTemplateName)!)
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_NEXT))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -12,6 +12,10 @@ class NightShiftBarItem: CustomButtonTouchBarItem {
|
|||||||
private let nsclient = CBBlueLightClient()
|
private let nsclient = CBBlueLightClient()
|
||||||
private var timer: Timer!
|
private var timer: Timer!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "nightShift"
|
||||||
|
}
|
||||||
|
|
||||||
private var blueLightStatus: Status {
|
private var blueLightStatus: Status {
|
||||||
var status: Status = Status()
|
var status: Status = Status()
|
||||||
nsclient.getBlueLightStatus(&status)
|
nsclient.getBlueLightStatus(&status)
|
||||||
@ -28,26 +32,40 @@ class NightShiftBarItem: CustomButtonTouchBarItem {
|
|||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier) {
|
init(identifier: NSTouchBarItem.Identifier) {
|
||||||
super.init(identifier: identifier, title: "")
|
super.init(identifier: identifier, title: "")
|
||||||
isBordered = false
|
self.setup()
|
||||||
setWidth(value: 28)
|
|
||||||
|
|
||||||
tapClosure = { [weak self] in self?.nightShiftAction() }
|
|
||||||
|
|
||||||
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
|
|
||||||
|
|
||||||
refresh()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
if getWidth() == 0.0 {
|
||||||
|
setWidth(value: 28)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setTapAction(
|
||||||
|
EventAction( { [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.nightShiftAction()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
|
||||||
|
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true)
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
func nightShiftAction() {
|
func nightShiftAction() {
|
||||||
setNightShift(state: !isNightShiftEnabled)
|
setNightShift(state: !isNightShiftEnabled)
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func refresh() {
|
@objc func refresh() {
|
||||||
image = isNightShiftEnabled ? #imageLiteral(resourceName: "nightShiftOn") : #imageLiteral(resourceName: "nightShiftOff")
|
self.setImage(isNightShiftEnabled ? #imageLiteral(resourceName: "nightShiftOn") : #imageLiteral(resourceName: "nightShiftOff"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
MTMR/Widgets/PlayBarItem.swift
Normal file
27
MTMR/Widgets/PlayBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// PlayBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class PlayBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "play"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(NSImage(named: NSImage.touchBarPlayPauseTemplateName)!)
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_PLAY))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -8,25 +8,14 @@
|
|||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class PomodoroBarItem: CustomButtonTouchBarItem, Widget {
|
class PomodoroBarItem: CustomButtonTouchBarItem {
|
||||||
static let identifier = "com.toxblh.mtmr.pomodoro."
|
override class var typeIdentifier: String {
|
||||||
static let name = "pomodoro"
|
return "pomodoro"
|
||||||
static let decoder: ParametersDecoder = { decoder in
|
}
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case workTime
|
|
||||||
case restTime
|
|
||||||
}
|
|
||||||
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
private enum CodingKeys: String, CodingKey {
|
||||||
let workTime = try container.decodeIfPresent(Double.self, forKey: .workTime)
|
case workTime
|
||||||
let restTime = try container.decodeIfPresent(Double.self, forKey: .restTime)
|
case restTime
|
||||||
|
|
||||||
return (
|
|
||||||
item: .pomodoro(workTime: workTime ?? 1500.00, restTime: restTime ?? 300),
|
|
||||||
action: .none,
|
|
||||||
longAction: .none,
|
|
||||||
parameters: [:]
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum TimeTypes {
|
private enum TimeTypes {
|
||||||
@ -46,18 +35,44 @@ class PomodoroBarItem: CustomButtonTouchBarItem, Widget {
|
|||||||
return String(format: "%.2i:%.2i", timeLeft / 60, timeLeft % 60)
|
return String(format: "%.2i:%.2i", timeLeft / 60, timeLeft % 60)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, workTime: TimeInterval, restTime: TimeInterval) {
|
init(identifier: NSTouchBarItem.Identifier, workTime: TimeInterval, restTime: TimeInterval) {
|
||||||
self.workTime = workTime
|
self.workTime = workTime
|
||||||
self.restTime = restTime
|
self.restTime = restTime
|
||||||
super.init(identifier: identifier, title: defaultTitle)
|
super.init(identifier: identifier, title: defaultTitle)
|
||||||
tapClosure = { [weak self] in self?.startStopWork() }
|
|
||||||
longTapClosure = { [weak self] in self?.startStopRest() }
|
self.setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.workTime = try container.decodeIfPresent(Double.self, forKey: .workTime) ?? 1500.0
|
||||||
|
self.restTime = try container.decodeIfPresent(Double.self, forKey: .restTime) ?? 600.0
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.title = defaultTitle
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
self.setTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.startStopWork()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
self.setLongTapAction(
|
||||||
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.startStopRest()
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
timer?.cancel()
|
timer?.cancel()
|
||||||
timer = nil
|
timer = nil
|
||||||
|
|||||||
27
MTMR/Widgets/PreviousBarItem.swift
Normal file
27
MTMR/Widgets/PreviousBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// PreviousBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class PreviousBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "previous"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(NSImage(named: NSImage.touchBarRewindTemplateName)!)
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_PREVIOUS))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
27
MTMR/Widgets/SleepBarItem.swift
Normal file
27
MTMR/Widgets/SleepBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// SleepBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class SleepBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "sleep"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.title = "☕️"
|
||||||
|
self.setTapAction(EventAction().setShellScriptClosure(executable: "/usr/bin/pmset", parameters: ["sleepnow"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -4,7 +4,40 @@ class TimeTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
private let dateFormatter = DateFormatter()
|
private let dateFormatter = DateFormatter()
|
||||||
private var timer: Timer!
|
private var timer: Timer!
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case formatTemplate
|
||||||
|
case timeZone
|
||||||
|
case locale
|
||||||
|
}
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "timeButton"
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, formatTemplate: String, timeZone: String? = nil, locale: String? = nil) {
|
init(identifier: NSTouchBarItem.Identifier, formatTemplate: String, timeZone: String? = nil, locale: String? = nil) {
|
||||||
|
super.init(identifier: identifier, title: " ")
|
||||||
|
self.setupFormatter(formatTemplate: formatTemplate, timeZone: timeZone, locale: locale)
|
||||||
|
self.setupTimer()
|
||||||
|
updateTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let template = try container.decodeIfPresent(String.self, forKey: .formatTemplate) ?? "HH:mm"
|
||||||
|
let timeZone = try container.decodeIfPresent(String.self, forKey: .timeZone) ?? nil
|
||||||
|
let locale = try container.decodeIfPresent(String.self, forKey: .locale) ?? nil
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.setupFormatter(formatTemplate: template, timeZone: timeZone, locale: locale)
|
||||||
|
self.setupTimer()
|
||||||
|
updateTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupFormatter(formatTemplate: String, timeZone: String? = nil, locale: String? = nil) {
|
||||||
dateFormatter.dateFormat = formatTemplate
|
dateFormatter.dateFormat = formatTemplate
|
||||||
if let locale = locale {
|
if let locale = locale {
|
||||||
dateFormatter.locale = Locale(identifier: locale)
|
dateFormatter.locale = Locale(identifier: locale)
|
||||||
@ -12,14 +45,10 @@ class TimeTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
if let abbr = timeZone {
|
if let abbr = timeZone {
|
||||||
dateFormatter.timeZone = TimeZone(abbreviation: abbr)
|
dateFormatter.timeZone = TimeZone(abbreviation: abbr)
|
||||||
}
|
}
|
||||||
super.init(identifier: identifier, title: " ")
|
|
||||||
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
|
|
||||||
isBordered = false
|
|
||||||
updateTime()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
func setupTimer() {
|
||||||
fatalError("init(coder:) has not been implemented")
|
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func updateTime() {
|
@objc func updateTime() {
|
||||||
|
|||||||
27
MTMR/Widgets/VolumeDownBarItem.swift
Normal file
27
MTMR/Widgets/VolumeDownBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// volumeDownBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class VolumeDownBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "volumeDown"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(NSImage(named: NSImage.touchBarVolumeDownTemplateName)!)
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_SOUND_DOWN))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
27
MTMR/Widgets/VolumeUpBarItem.swift
Normal file
27
MTMR/Widgets/VolumeUpBarItem.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// VolumeUpBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 4/27/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class VolumeUpBarItem: CustomButtonTouchBarItem {
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "volumeUp"
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setImage(NSImage(named: NSImage.touchBarVolumeUpTemplateName)!)
|
||||||
|
self.setTapAction(EventAction().setHidKeyClosure(keycode: NX_KEYTYPE_SOUND_UP))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -3,12 +3,33 @@ import AVFoundation
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
import CoreAudio
|
import CoreAudio
|
||||||
|
|
||||||
class VolumeViewController: NSCustomTouchBarItem {
|
class VolumeViewController: CustomTouchBarItem {
|
||||||
private(set) var sliderItem: CustomSlider!
|
private(set) var sliderItem: CustomSlider!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "volume"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case image
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) {
|
init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) {
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
|
|
||||||
|
self.setup(image: image)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let image = try container.decodeIfPresent(Source.self, forKey: .image)?.image
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setup(image: image)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup(image: NSImage?) {
|
||||||
var forPropertyAddress = AudioObjectPropertyAddress(
|
var forPropertyAddress = AudioObjectPropertyAddress(
|
||||||
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume,
|
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume,
|
||||||
mScope: kAudioDevicePropertyScopeOutput,
|
mScope: kAudioDevicePropertyScopeOutput,
|
||||||
@ -37,6 +58,7 @@ class VolumeViewController: NSCustomTouchBarItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,9 +22,20 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
|||||||
|
|
||||||
private var manager: CLLocationManager!
|
private var manager: CLLocationManager!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "weather"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case refreshInterval
|
||||||
|
case units
|
||||||
|
case api_key
|
||||||
|
case icon_type
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text") {
|
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text") {
|
||||||
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
self.activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||||
activity.interval = interval
|
self.activity.interval = interval
|
||||||
self.units = units
|
self.units = units
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
|
|
||||||
@ -44,6 +55,43 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
|||||||
|
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) ?? "text"
|
||||||
|
|
||||||
|
|
||||||
|
self.activity = NSBackgroundActivityScheduler(identifier: CustomTouchBarItem.createIdentifier("Weather.updatecheck").rawValue)
|
||||||
|
self.activity.interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
|
self.units = try container.decodeIfPresent(String.self, forKey: .units) ?? "metric"
|
||||||
|
self.api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6"
|
||||||
|
|
||||||
|
if self.units == "metric" {
|
||||||
|
units_str = "°C"
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.units == "imperial" {
|
||||||
|
units_str = "°F"
|
||||||
|
}
|
||||||
|
|
||||||
|
if icon_type == "images" {
|
||||||
|
iconsSource = iconsImages
|
||||||
|
} else {
|
||||||
|
iconsSource = iconsText
|
||||||
|
}
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
let status = CLLocationManager.authorizationStatus()
|
let status = CLLocationManager.authorizationStatus()
|
||||||
if status == .restricted || status == .denied {
|
if status == .restricted || status == .denied {
|
||||||
print("User permission not given")
|
print("User permission not given")
|
||||||
@ -69,10 +117,6 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
|||||||
manager.startUpdatingLocation()
|
manager.startUpdatingLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func updateWeather() {
|
@objc func updateWeather() {
|
||||||
if location != nil {
|
if location != nil {
|
||||||
let urlRequest = URLRequest(url: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)&units=\(units)&appid=\(api_key)")!)
|
let urlRequest = URLRequest(url: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)&units=\(units)&appid=\(api_key)")!)
|
||||||
|
|||||||
@ -20,12 +20,37 @@ class YandexWeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate
|
|||||||
private var prevLocation: CLLocation!
|
private var prevLocation: CLLocation!
|
||||||
private var manager: CLLocationManager!
|
private var manager: CLLocationManager!
|
||||||
|
|
||||||
|
override class var typeIdentifier: String {
|
||||||
|
return "weather"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case refreshInterval
|
||||||
|
}
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval) {
|
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval) {
|
||||||
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||||
activity.interval = interval
|
activity.interval = interval
|
||||||
|
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.activity = NSBackgroundActivityScheduler(identifier: CustomTouchBarItem.createIdentifier("YandexWeather.updatecheck").rawValue)
|
||||||
|
self.activity.interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
self.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
let status = CLLocationManager.authorizationStatus()
|
let status = CLLocationManager.authorizationStatus()
|
||||||
if status == .restricted || status == .denied {
|
if status == .restricted || status == .denied {
|
||||||
print("User permission not given")
|
print("User permission not given")
|
||||||
@ -50,11 +75,12 @@ class YandexWeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate
|
|||||||
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
|
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
|
||||||
manager.startUpdatingLocation()
|
manager.startUpdatingLocation()
|
||||||
|
|
||||||
tapClosure = tapClosure ?? defaultTapAction
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
self.setTapAction(
|
||||||
fatalError("init(coder:) has not been implemented")
|
EventAction({ [weak self] (_ caller: CustomButtonTouchBarItem) in
|
||||||
|
self?.defaultTapAction()
|
||||||
|
} )
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func updateWeather() {
|
@objc func updateWeather() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user