From 5b08861dec168a01a7da730677a4782d9bf228e6 Mon Sep 17 00:00:00 2001 From: ad Date: Thu, 19 Apr 2018 21:50:06 +0300 Subject: [PATCH 1/8] * fixed formatting (trailing zero), added colours --- MTMR/CurrencyBarItem.swift | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/MTMR/CurrencyBarItem.swift b/MTMR/CurrencyBarItem.swift index 584f9b9..af05bbd 100644 --- a/MTMR/CurrencyBarItem.swift +++ b/MTMR/CurrencyBarItem.swift @@ -15,6 +15,7 @@ class CurrencyBarItem: NSCustomTouchBarItem { private var prefix: String private var from: String private var to: String + private var oldValue: Float32! private let button = NSButton(title: "", target: nil, action: nil) private let currencies = [ @@ -68,18 +69,18 @@ class CurrencyBarItem: NSCustomTouchBarItem { do { let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject] - var value: String! + var value: Float32! if let data_array = json["data"] as? [String : AnyObject] { if let rates = data_array["rates"] as? [String : AnyObject] { if let item = rates["\(self.to)"] as? String { - value = item + value = Float32(item) } } } if value != nil { DispatchQueue.main.async { - self.setCurrency(text: "\(value!)") + self.setCurrency(value: value!) } } } catch let jsonError { @@ -91,7 +92,26 @@ class CurrencyBarItem: NSCustomTouchBarItem { task.resume() } - func setCurrency(text: String) { - button.title = "\(self.prefix)\(text)" + func setCurrency(value: Float32) { + var color = NSColor.white + + if let oldValue = self.oldValue { + if oldValue < value { + color = NSColor(red: 95.0/255.0, green: 185.0/255.0, blue: 50.0/255.0, alpha: 1.0) + } else if oldValue > value { + color = NSColor(red: 185.0/255.0, green: 95.0/255.0, blue: 50.0/255.0, alpha: 1.0) + } + } + self.oldValue = value + + button.title = String(format: "%@%.2f", self.prefix, value) + + let textRange = NSRange(location: 0, length: button.title.count) + let newTitle = NSMutableAttributedString(string: button.title) + newTitle.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: textRange) + newTitle.addAttribute(NSAttributedStringKey.font, value: button.font!, range: textRange) + newTitle.setAlignment(.center, range: textRange) + + button.attributedTitle = newTitle } } From c15488b61f13d9990375a8acbd35aa98329368e3 Mon Sep 17 00:00:00 2001 From: ad Date: Fri, 20 Apr 2018 11:13:03 +0300 Subject: [PATCH 2/8] + text and image sets for weather condition --- MTMR/ItemsParsing.swift | 11 +++++---- MTMR/TouchBarController.swift | 6 ++--- MTMR/WeatherBarItem.swift | 44 +++++++++++------------------------ 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 39db97c..055fb09 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -73,12 +73,13 @@ class SupportedTypesHolder { return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_NEXT), parameters: [.image: imageParameter]) }, "weather": { decoder in - enum CodingKeys: String, CodingKey { case refreshInterval; case units; case api_key } + enum CodingKeys: String, CodingKey { case refreshInterval; case units; case api_key ; case icon_type } let container = try decoder.container(keyedBy: CodingKeys.self) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) let units = try container.decodeIfPresent(String.self, forKey: .units) let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) - return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6"), action: .none, parameters: [:]) + let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) + return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), action: .none, parameters: [:]) }, "currency": { decoder in enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to } @@ -148,7 +149,7 @@ enum ItemType: Decodable { case dock() case volume() case brightness(refreshInterval: Double) - case weather(interval: Double, units: String, api_key: String) + case weather(interval: Double, units: String, api_key: String, icon_type: String) case currency(interval: Double, from: String, to: String) private enum CodingKeys: String, CodingKey { @@ -160,6 +161,7 @@ enum ItemType: Decodable { case to case units case api_key + case icon_type case formatTemplate case image } @@ -200,7 +202,8 @@ enum ItemType: Decodable { 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" - self = .weather(interval: interval, units: units, api_key: api_key) + 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 .currency: let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB" diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 2ff16a4..11bae48 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -29,7 +29,7 @@ extension ItemType { return "com.toxblh.mtmr.volume" case .brightness(refreshInterval: _): return "com.toxblh.mtmr.brightness" - case .weather(interval: _, units: _, api_key: _): + case .weather(interval: _, units: _, api_key: _, icon_type: _): return "com.toxblh.mtmr.weather" case .currency(interval: _, from: _, to: _): return "com.toxblh.mtmr.currency" @@ -178,8 +178,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { } else { barItem = BrightnessViewController(identifier: identifier, refreshInterval: interval) } - case .weather(interval: let interval, units: let units, api_key: let api_key): - barItem = WeatherBarItem(identifier: identifier, interval: interval, units: units, api_key: api_key) + case .weather(interval: let interval, units: let units, api_key: let api_key, icon_type: let icon_type): + barItem = WeatherBarItem(identifier: identifier, interval: interval, units: units, api_key: api_key, icon_type: icon_type) case .currency(interval: let interval, from: let from, to: let to): barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to) } diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift index b902375..6092d5b 100644 --- a/MTMR/WeatherBarItem.swift +++ b/MTMR/WeatherBarItem.swift @@ -19,10 +19,13 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { private let button = NSButton(title: "", target: nil, action: nil) private var prev_location: CLLocation! private var location: CLLocation! + private let iconsImages = ["01d": "☀️", "01n": "☀️", "02d": "⛅️", "02n": "⛅️", "03d": "☁️", "03n": "☁️", "04d": "☁️", "04n": "☁️", "09d": "⛅️", "09n": "⛅️", "10d": "🌦", "10n": "🌦", "11d": "🌩", "11n": "🌩", "13d": "❄️", "13n": "❄️", "50d": "🌫", "50n": "🌫"] + private let iconsText = ["01d": "☀", "01n": "☀", "02d": "☁", "02n": "☁", "03d": "☁", "03n": "☁", "04d": "☁", "04n": "☁", "09d": "☂", "09n": "☂", "10d": "☂", "10n": "☂", "11d": "☈", "11n": "☈", "13d": "☃", "13n": "☃", "50d": "♨", "50n": "♨"] + private var iconsSource: Dictionary private var manager:CLLocationManager! - init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String) { + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text") { self.interval = interval self.units = units self.api_key = api_key @@ -31,6 +34,12 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { units_str = "°C" } + if icon_type == "images" { + iconsSource = iconsImages + } else { + iconsSource = iconsText + } + super.init(identifier: identifier) button.bezelColor = .clear @@ -44,7 +53,7 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { } if !CLLocationManager.locationServicesEnabled() { - print("not enabled"); + print("Location services not enabled"); return } @@ -81,33 +90,8 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { if let weather = json["weather"] as? NSArray, let item = weather[0] as? NSDictionary { let icon = item["icon"] as! String - switch (icon) { - case "01d", "01n": - condition_icon = "☀️" - break - case "02d", "02n": - condition_icon = "⛅️" - break - case "03d", "03n", "04d", "04n": - condition_icon = "☁️" - break - case "09d", "09n": - condition_icon = "⛅️" - break - case "10d", "10n": - condition_icon = "🌦" - break - case "11d", "11n": - condition_icon = "🌩" - break - case "13d", "13n": - condition_icon = "❄️" - break - case "50d", "50n": - condition_icon = "🌫" - break - default: - condition_icon = "" + if let test = self.iconsSource[icon] { + condition_icon = test } } @@ -144,7 +128,7 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { - print("inside didChangeAuthorization "); +// print("inside didChangeAuthorization "); updateWeather() } From a7060b74e43a5671a55f80672b51f687ee713f1b Mon Sep 17 00:00:00 2001 From: ad Date: Fri, 20 Apr 2018 13:42:08 +0300 Subject: [PATCH 3/8] * weather and currency now is CustomButtonTouchBarItem --- MTMR/CurrencyBarItem.swift | 8 +++----- MTMR/TouchBarController.swift | 4 ++-- MTMR/WeatherBarItem.swift | 8 +++----- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/MTMR/CurrencyBarItem.swift b/MTMR/CurrencyBarItem.swift index af05bbd..8d2ed32 100644 --- a/MTMR/CurrencyBarItem.swift +++ b/MTMR/CurrencyBarItem.swift @@ -9,14 +9,13 @@ import Cocoa import CoreLocation -class CurrencyBarItem: NSCustomTouchBarItem { +class CurrencyBarItem: CustomButtonTouchBarItem { private var timer: Timer! private var interval: TimeInterval! private var prefix: String private var from: String private var to: String private var oldValue: Float32! - private let button = NSButton(title: "", target: nil, action: nil) private let currencies = [ "USD": "$", @@ -35,7 +34,7 @@ class CurrencyBarItem: NSCustomTouchBarItem { "CHF": "Fr." ] - init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String) { + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, onTap: @escaping () -> ()) { self.interval = interval self.from = from self.to = to @@ -46,10 +45,9 @@ class CurrencyBarItem: NSCustomTouchBarItem { self.prefix = from } - super.init(identifier: identifier) + super.init(identifier: identifier, title: "⏳", onTap: onTap) button.bezelColor = .clear - button.title = "⏳" self.view = button timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(updateCurrency), userInfo: nil, repeats: true) diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 11bae48..4cf4086 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -179,9 +179,9 @@ class TouchBarController: NSObject, NSTouchBarDelegate { barItem = BrightnessViewController(identifier: identifier, refreshInterval: interval) } case .weather(interval: let interval, units: let units, api_key: let api_key, icon_type: let icon_type): - barItem = WeatherBarItem(identifier: identifier, 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, onTap: action) case .currency(interval: let interval, from: let from, to: let to): - barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to) + barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to, onTap: action) } if case .width(let value)? = item.additionalParameters[.width], let widthBarItem = barItem as? CanSetWidth { diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift index 6092d5b..9ace384 100644 --- a/MTMR/WeatherBarItem.swift +++ b/MTMR/WeatherBarItem.swift @@ -9,14 +9,13 @@ import Cocoa import CoreLocation -class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { +class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { private let dateFormatter = DateFormatter() private var timer: Timer! private var interval: TimeInterval! private var units: String private var api_key: String private var units_str = "°F" - private let button = NSButton(title: "", target: nil, action: nil) private var prev_location: CLLocation! private var location: CLLocation! private let iconsImages = ["01d": "☀️", "01n": "☀️", "02d": "⛅️", "02n": "⛅️", "03d": "☁️", "03n": "☁️", "04d": "☁️", "04n": "☁️", "09d": "⛅️", "09n": "⛅️", "10d": "🌦", "10n": "🌦", "11d": "🌩", "11n": "🌩", "13d": "❄️", "13n": "❄️", "50d": "🌫", "50n": "🌫"] @@ -25,7 +24,7 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { private var manager:CLLocationManager! - 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", onTap: @escaping () -> ()) { self.interval = interval self.units = units self.api_key = api_key @@ -40,10 +39,9 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { iconsSource = iconsText } - super.init(identifier: identifier) + super.init(identifier: identifier, title: "⏳", onTap: onTap) button.bezelColor = .clear - button.title = "⏳" self.view = button let status = CLLocationManager.authorizationStatus() From 0c007b79407e552a2b0acc8f31975fc17dbc74d9 Mon Sep 17 00:00:00 2001 From: ad Date: Fri, 20 Apr 2018 13:53:25 +0300 Subject: [PATCH 4/8] + action openURL --- MTMR/ItemsParsing.swift | 9 +++++++++ MTMR/TouchBarController.swift | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 055fb09..06177c5 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -164,6 +164,7 @@ enum ItemType: Decodable { case icon_type case formatTemplate case image + case url } enum ItemTypeRaw: String, Decodable { @@ -220,6 +221,7 @@ enum ActionType: Decodable { case appleSctipt(source: SourceProtocol) case shellScript(executable: String, parameters: [String]) case custom(closure: ()->()) + case openUrl(url: String) private enum CodingKeys: String, CodingKey { case action @@ -227,6 +229,7 @@ enum ActionType: Decodable { case actionAppleScript case executablePath case shellArguments + case url } private enum ActionTypeRaw: String, Decodable { @@ -234,6 +237,7 @@ enum ActionType: Decodable { case keyPress case appleScript case shellScript + case openUrl } init(from decoder: Decoder) throws { @@ -253,6 +257,9 @@ enum ActionType: Decodable { 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 } @@ -284,6 +291,8 @@ func ==(lhs: ActionType, rhs: ActionType) -> Bool { return a == b case let (.shellScript(a, b), .shellScript(c, d)): return a == c && b == d + case let (.openUrl(a), .openUrl(b)): + return a == b default: return false } diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 11bae48..9ed2c88 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -222,6 +222,14 @@ class TouchBarController: NSObject, NSTouchBarDelegate { task.arguments = parameters task.launch() } + case .openUrl(url: let url): + return { + if let url = URL(string: url), NSWorkspace.shared.open(url) { + print("URL was successfully opened") + } else { + print("error", url) + } + } case .custom(closure: let closure): return closure case .none: From 76934e6ff0ad112ab523095dc7cc4cbd35842dd7 Mon Sep 17 00:00:00 2001 From: ad Date: Fri, 20 Apr 2018 14:26:26 +0300 Subject: [PATCH 5/8] + action for currency, weather, battery It will allow to process custom action on click by widget --- MTMR/ItemsParsing.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 06177c5..9c13304 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -79,15 +79,17 @@ class SupportedTypesHolder { let units = try container.decodeIfPresent(String.self, forKey: .units) let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) - return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), action: .none, parameters: [:]) + let action = try ActionType(from: decoder) + return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), action: action, parameters: [:]) }, "currency": { decoder in - enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to } + enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to; case action } let container = try decoder.container(keyedBy: CodingKeys.self) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) let from = try container.decodeIfPresent(String.self, forKey: .from) let to = try container.decodeIfPresent(String.self, forKey: .to) - return (item: .currency(interval: interval ?? 600.00, from: from ?? "RUB", to: to ?? "USD"), action: .none, parameters: [:]) + let action = try ActionType(from: decoder) + return (item: .currency(interval: interval ?? 600.00, from: from ?? "RUB", to: to ?? "USD"), action: action, parameters: [:]) }, "dock": { decoder in return (item: .dock(), action: .none, parameters: [:]) @@ -117,7 +119,8 @@ class SupportedTypesHolder { let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) let scriptPath = Bundle.main.path(forResource: "Battery", ofType: "scpt")! let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0) - return (item: item, action: .none, parameters: [:]) + let action = try ActionType(from: decoder) + return (item: item, action: action, parameters: [:]) }, "sleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]), parameters: [:]) }, "displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), parameters: [:]) }, From cd8b5955526022797099f96a3d1ad01ce0f60501 Mon Sep 17 00:00:00 2001 From: ad Date: Fri, 20 Apr 2018 14:42:36 +0300 Subject: [PATCH 6/8] - --- MTMR/ItemsParsing.swift | 2 +- MTMR/TouchBarController.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 9c13304..a01af0c 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -83,7 +83,7 @@ class SupportedTypesHolder { return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), action: action, parameters: [:]) }, "currency": { decoder in - enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to; case action } + enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to } let container = try decoder.container(keyedBy: CodingKeys.self) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) let from = try container.decodeIfPresent(String.self, forKey: .from) diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index e351dc0..290b483 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -225,7 +225,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate { case .openUrl(url: let url): return { if let url = URL(string: url), NSWorkspace.shared.open(url) { - print("URL was successfully opened") +// print("URL was successfully opened") } else { print("error", url) } From d76e16b9e60ca7eed8eabcd6324bf4d9a1dc5cc2 Mon Sep 17 00:00:00 2001 From: ad Date: Sat, 21 Apr 2018 08:27:02 +0300 Subject: [PATCH 7/8] * action for battery plugin --- MTMR/BatteryBarItem.swift | 7 +++---- MTMR/TouchBarController.swift | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/MTMR/BatteryBarItem.swift b/MTMR/BatteryBarItem.swift index 69de2ce..3b107ec 100644 --- a/MTMR/BatteryBarItem.swift +++ b/MTMR/BatteryBarItem.swift @@ -9,12 +9,11 @@ import IOKit.ps import Foundation -class BatteryBarItem: NSCustomTouchBarItem { +class BatteryBarItem: CustomButtonTouchBarItem { private var timer: Timer! - private let button = NSButton(title: "", target: nil, action: nil) - override init(identifier: NSTouchBarItem.Identifier) { - super.init(identifier: identifier) + init(identifier: NSTouchBarItem.Identifier, onTap: @escaping () -> ()) { + super.init(identifier: identifier, title: " ", onTap: onTap) self.view = button button.bezelColor = .clear diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 92f74fa..4b2ba47 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -172,7 +172,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate { case .timeButton(formatTemplate: let template): barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template) case .battery(): - barItem = BatteryBarItem(identifier: identifier) + barItem = BatteryBarItem(identifier: identifier, onTap: action) case .dock: barItem = AppScrubberTouchBarItem(identifier: identifier) case .volume: From 641eb18b89c8fb4c9ed52ac6ada514eeb18bbaeb Mon Sep 17 00:00:00 2001 From: ad Date: Sat, 21 Apr 2018 10:20:12 +0300 Subject: [PATCH 8/8] + longAction (action for long press on widgets, now working only with longUrl). TODO: nested options for action/longAction like for image/sourse/actionAppleScript --- MTMR/AppDelegate.swift | 2 +- MTMR/AppleScriptTouchBarItem.swift | 4 +- MTMR/BatteryBarItem.swift | 4 +- MTMR/CurrencyBarItem.swift | 4 +- MTMR/CustomButtonTouchBarItem.swift | 64 ++++++++++++-- MTMR/ItemsParsing.swift | 130 ++++++++++++++++++++++------ MTMR/TouchBarController.swift | 59 +++++++++++-- MTMR/WeatherBarItem.swift | 4 +- 8 files changed, 220 insertions(+), 51 deletions(-) diff --git a/MTMR/AppDelegate.swift b/MTMR/AppDelegate.swift index 19b3dd7..6a936a4 100644 --- a/MTMR/AppDelegate.swift +++ b/MTMR/AppDelegate.swift @@ -56,7 +56,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { if (result != nil) { let path = result!.path let jsonData = path.fileData - let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [:])] + let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, longAction: .none, additionalParameters: [:])] TouchBarController.shared.createAndUpdatePreset(jsonItems: jsonItems) } diff --git a/MTMR/AppleScriptTouchBarItem.swift b/MTMR/AppleScriptTouchBarItem.swift index 87c876a..1f3af9b 100644 --- a/MTMR/AppleScriptTouchBarItem.swift +++ b/MTMR/AppleScriptTouchBarItem.swift @@ -5,9 +5,9 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { private let interval: TimeInterval private var forceHideConstraint: NSLayoutConstraint! - init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, onTap: @escaping ()->()) { + init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, onTap: @escaping ()->(), onLongTap: @escaping ()->()) { self.interval = interval - super.init(identifier: identifier, title: "⏳", onTap: onTap) + super.init(identifier: identifier, title: "⏳", onTap: onTap, onLongTap: onLongTap) self.forceHideConstraint = self.view.widthAnchor.constraint(equalToConstant: 0) guard let script = source.appleScript else { button.title = "no script" diff --git a/MTMR/BatteryBarItem.swift b/MTMR/BatteryBarItem.swift index 3b107ec..4cf7c1d 100644 --- a/MTMR/BatteryBarItem.swift +++ b/MTMR/BatteryBarItem.swift @@ -12,8 +12,8 @@ import Foundation class BatteryBarItem: CustomButtonTouchBarItem { private var timer: Timer! - init(identifier: NSTouchBarItem.Identifier, onTap: @escaping () -> ()) { - super.init(identifier: identifier, title: " ", onTap: onTap) + init(identifier: NSTouchBarItem.Identifier, onTap: @escaping () -> (), onLongTap: @escaping () -> ()) { + super.init(identifier: identifier, title: " ", onTap: onTap, onLongTap: onLongTap) self.view = button button.bezelColor = .clear diff --git a/MTMR/CurrencyBarItem.swift b/MTMR/CurrencyBarItem.swift index 440d3b1..ae2e0fa 100644 --- a/MTMR/CurrencyBarItem.swift +++ b/MTMR/CurrencyBarItem.swift @@ -37,7 +37,7 @@ class CurrencyBarItem: CustomButtonTouchBarItem { "ETH": "Ξ", ] - init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, onTap: @escaping () -> ()) { + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, onTap: @escaping () -> (), onLongTap: @escaping () -> ()) { self.interval = interval self.from = from self.to = to @@ -48,7 +48,7 @@ class CurrencyBarItem: CustomButtonTouchBarItem { self.prefix = from } - super.init(identifier: identifier, title: "⏳", onTap: onTap) + super.init(identifier: identifier, title: "⏳", onTap: onTap, onLongTap: onLongTap) button.bezelColor = .clear self.view = button diff --git a/MTMR/CustomButtonTouchBarItem.swift b/MTMR/CustomButtonTouchBarItem.swift index e85fa44..96130b8 100644 --- a/MTMR/CustomButtonTouchBarItem.swift +++ b/MTMR/CustomButtonTouchBarItem.swift @@ -8,26 +8,76 @@ import Cocoa -class CustomButtonTouchBarItem: NSCustomTouchBarItem { - let tapClosure: () -> () +class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { + private let tapClosure: () -> ()? + private let longTapClosure: () -> ()? private(set) var button: NSButton! + + private var singleClick: NSClickGestureRecognizer! + private var longClick: NSPressGestureRecognizer! - init(identifier: NSTouchBarItem.Identifier, title: String, onTap callback: @escaping () -> ()) { + init(identifier: NSTouchBarItem.Identifier, title: String, onTap callback: @escaping () -> (), onLongTap callbackLong: @escaping () -> ()) { self.tapClosure = callback + self.longTapClosure = callbackLong + super.init(identifier: identifier) - button = NSButton(title: title, target: self, action: #selector(didTapped)) + button = NSButton(title: title, target: self, action: nil) button.title = title self.view = button + + longClick = NSPressGestureRecognizer(target: self, action: #selector(handleGestureLong)) + longClick.allowedTouchTypes = .direct + longClick.delegate = self + + singleClick = NSClickGestureRecognizer(target: self, action: #selector(handleGestureSingle)) + singleClick.allowedTouchTypes = .direct + singleClick.delegate = self + + self.view.addGestureRecognizer(longClick) + self.view.addGestureRecognizer(singleClick) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + - @objc func didTapped() { - self.tapClosure() + func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool { + if gestureRecognizer == singleClick && otherGestureRecognizer == longClick { + return false + } + return true + } + + @objc func handleGestureSingle(gr: NSClickGestureRecognizer) { let hf: HapticFeedback = HapticFeedback() - hf.tap(strong: 6) + switch gr.state { + case .ended: + hf.tap(strong: 2) + self.tapClosure() + break + default: + break + } + } + + @objc func handleGestureLong(gr: NSPressGestureRecognizer) { + let hf: HapticFeedback = HapticFeedback() + switch gr.state { + case .began: + if self.longTapClosure != nil { + hf.tap(strong: 2) + self.tapClosure() + } else { + hf.tap(strong: 6) + self.longTapClosure() + print("long click") + } + break + default: + break + + } } } diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 2a4b1eb..fce3b8d 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -12,15 +12,17 @@ extension Data { struct BarItemDefinition: Decodable { let type: ItemType let action: ActionType + let longAction: LongActionType let additionalParameters: [GeneralParameters.CodingKeys: GeneralParameter] private enum CodingKeys: String, CodingKey { case type } - init(type: ItemType, action: ActionType, additionalParameters: [GeneralParameters.CodingKeys:GeneralParameter]) { + init(type: ItemType, action: ActionType, longAction: LongActionType, additionalParameters: [GeneralParameters.CodingKeys:GeneralParameter]) { self.type = type self.action = action + self.longAction = longAction self.additionalParameters = additionalParameters } @@ -30,51 +32,51 @@ struct BarItemDefinition: Decodable { let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type) var additionalParameters = try GeneralParameters(from: decoder).parameters if let result = try? parametersDecoder(decoder), - case let (itemType, action, parameters) = result { + case let (itemType, action, longAction, parameters) = result { parameters.forEach { additionalParameters[$0] = $1 } - self.init(type: itemType, action: action, additionalParameters: additionalParameters) + self.init(type: itemType, action: action, longAction: longAction, additionalParameters: additionalParameters) } else { - self.init(type: .staticButton(title: "unknown"), action: .none, additionalParameters: additionalParameters) + self.init(type: .staticButton(title: "unknown"), action: .none, longAction: .none, additionalParameters: additionalParameters) } } } class SupportedTypesHolder { - typealias ParametersDecoder = (Decoder) throws ->(item: ItemType, action: ActionType, parameters: [GeneralParameters.CodingKeys: GeneralParameter]) + typealias ParametersDecoder = (Decoder) throws ->(item: ItemType, action: ActionType, longAction: LongActionType, parameters: [GeneralParameters.CodingKeys: GeneralParameter]) private var supportedTypes: [String: ParametersDecoder] = [ - "escape": { _ in return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53), parameters: [.align: .align(.left)]) }, + "escape": { _ in return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53), longAction: .none, parameters: [.align: .align(.left)]) }, "brightnessUp": { _ in let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessUp")) - return (item: .staticButton(title: ""), action: .keyPress(keycode: 113), parameters: [.image: imageParameter]) + return (item: .staticButton(title: ""), action: .keyPress(keycode: 113), longAction: .none, parameters: [.image: imageParameter]) }, "brightnessDown": { _ in let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessDown")) - return (item: .staticButton(title: ""), action: .keyPress(keycode: 107), parameters: [.image: imageParameter]) + return (item: .staticButton(title: ""), action: .keyPress(keycode: 107), longAction: .none, parameters: [.image: imageParameter]) }, "volumeDown": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeDownTemplate)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN), parameters: [.image: imageParameter]) + 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: .touchBarVolumeUpTemplate)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP), parameters: [.image: imageParameter]) + 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: .touchBarAudioOutputMuteTemplate)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_MUTE), parameters: [.image: imageParameter]) + return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_MUTE), longAction: .none, parameters: [.image: imageParameter]) }, "previous": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarRewindTemplate)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS), parameters: [.image: imageParameter]) + return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS), longAction: .none, parameters: [.image: imageParameter]) }, "play": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarPlayPauseTemplate)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PLAY), parameters: [.image: imageParameter]) + return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PLAY), longAction: .none, parameters: [.image: imageParameter]) }, "next": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarFastForwardTemplate)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_NEXT), parameters: [.image: imageParameter]) + return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_NEXT), longAction: .none, parameters: [.image: imageParameter]) }, "weather": { decoder in enum CodingKeys: String, CodingKey { case refreshInterval; case units; case api_key ; case icon_type } @@ -84,7 +86,8 @@ class SupportedTypesHolder { let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) let action = try ActionType(from: decoder) - return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), action: action, parameters: [:]) + let longAction = try LongActionType(from: decoder) + return (item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), action: action, longAction: longAction, parameters: [:]) }, "currency": { decoder in enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to } @@ -93,18 +96,19 @@ class SupportedTypesHolder { let from = try container.decodeIfPresent(String.self, forKey: .from) let to = try container.decodeIfPresent(String.self, forKey: .to) let action = try ActionType(from: decoder) - return (item: .currency(interval: interval ?? 600.00, from: from ?? "RUB", to: to ?? "USD"), action: action, parameters: [:]) + let longAction = try LongActionType(from: decoder) + return (item: .currency(interval: interval ?? 600.00, from: from ?? "RUB", to: to ?? "USD"), action: action, longAction: longAction, parameters: [:]) }, "dock": { decoder in - return (item: .dock(), action: .none, parameters: [:]) + return (item: .dock(), action: .none, longAction: .none, parameters: [:]) }, "volume": { decoder in enum CodingKeys: String, CodingKey { case image } let container = try decoder.container(keyedBy: CodingKeys.self) if var img = try container.decodeIfPresent(Source.self, forKey: .image) { - return (item: .volume(), action: .none, parameters: [.image: .image(source: img)]) + return (item: .volume(), action: .none, longAction: .none, parameters: [.image: .image(source: img)]) } else { - return (item: .volume(), action: .none, parameters: [:]) + return (item: .volume(), action: .none, longAction: .none, parameters: [:]) } }, "brightness": { decoder in @@ -112,20 +116,20 @@ class SupportedTypesHolder { let container = try decoder.container(keyedBy: CodingKeys.self) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) if var img = try container.decodeIfPresent(Source.self, forKey: .image) { - return (item: .brightness(refreshInterval: interval ?? 0.5), action: .none, parameters: [.image: .image(source: img)]) + return (item: .brightness(refreshInterval: interval ?? 0.5), action: .none, longAction: .none, parameters: [.image: .image(source: img)]) } else { - return (item: .brightness(refreshInterval: interval ?? 0.5), action: .none, parameters: [:]) + return (item: .brightness(refreshInterval: interval ?? 0.5), action: .none, longAction: .none, parameters: [:]) } }, - "sleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]), parameters: [:]) }, - "displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), parameters: [:]) }, + "sleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]), longAction: .none, parameters: [:]) }, + "displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), longAction: .none, parameters: [:])}, ] static let sharedInstance = SupportedTypesHolder() func lookup(by type: String) -> ParametersDecoder { return supportedTypes[type] ?? { decoder in - return (item: try ItemType(from: decoder), action: try ActionType(from: decoder), parameters: [:]) + return (item: try ItemType(from: decoder), action: try ActionType(from: decoder), longAction: try LongActionType(from: decoder), parameters: [:]) } } @@ -133,9 +137,9 @@ class SupportedTypesHolder { supportedTypes[typename] = decoder } - func register(typename: String, item: ItemType, action: ActionType) { + func register(typename: String, item: ItemType, action: ActionType, longAction: LongActionType) { register(typename: typename) { _ in - return (item: item, action: action, parameters: [:]) + return (item: item, action: action, longAction: longAction, parameters: [:]) } } } @@ -164,6 +168,7 @@ enum ItemType: Decodable { case formatTemplate case image case url + case longUrl } enum ItemTypeRaw: String, Decodable { @@ -268,6 +273,59 @@ enum ActionType: Decodable { } } + +enum LongActionType: Decodable { + case none + case hidKey(keycode: Int) + case keyPress(keycode: Int) + case appleSctipt(source: SourceProtocol) + case shellScript(executable: String, parameters: [String]) + case custom(closure: ()->()) + case openUrl(url: String) + + private enum CodingKeys: String, CodingKey { + case longAction + case keycode + case actionAppleScript + case executablePath + case shellArguments + 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(Int.self, forKey: .keycode) + self = .hidKey(keycode: keycode) + case .some(.keyPress): + let keycode = try container.decode(Int.self, forKey: .keycode) + self = .keyPress(keycode: keycode) + case .some(.appleScript): + let source = try container.decode(Source.self, forKey: .actionAppleScript) + self = .appleSctipt(source: source) + case .some(.shellScript): + let executable = try container.decode(String.self, forKey: .executablePath) + let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? [] + self = .shellScript(executable: executable, parameters: parameters) + case .some(.openUrl): + let longUrl = try container.decode(String.self, forKey: .longUrl) + self = .openUrl(url: longUrl) + case .none: + self = .none + } + } +} + extension ItemType: Equatable {} func ==(lhs: ItemType, rhs: ItemType) -> Bool { switch (lhs, rhs) { @@ -300,6 +358,26 @@ func ==(lhs: ActionType, rhs: ActionType) -> Bool { } } + +extension LongActionType: Equatable {} +func ==(lhs: LongActionType, rhs: LongActionType) -> Bool { + switch (lhs, rhs) { + case (.none, .none): + return true + case let (.hidKey(a), .hidKey(b)), + let (.keyPress(a), .keyPress(b)): + return a == b + case let (.appleSctipt(a), .appleSctipt(b)): + return a == b + case let (.shellScript(a, b), .shellScript(c, d)): + return a == c && b == d + case let (.openUrl(a), .openUrl(b)): + return a == b + default: + return false + } +} + enum GeneralParameter { case width(_: CGFloat) case image(source: SourceProtocol) diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 4b2ba47..4f68516 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -60,9 +60,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate { private override init() { super.init() - SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in - self?.dismissTouchBar() - })) + SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in self?.dismissTouchBar()}), longAction: .none) createAndUpdatePreset() } @@ -104,7 +102,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate { let jsonData = presetPath.fileData - return jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [:])] + return jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, longAction: .none, additionalParameters: [:])] } func loadItemDefinitions(jsonItems: [BarItemDefinition]) { @@ -162,17 +160,18 @@ class TouchBarController: NSObject, NSTouchBarDelegate { func createItem(forIdentifier identifier: NSTouchBarItem.Identifier, definition item: BarItemDefinition) -> NSTouchBarItem? { let action = self.action(forItem: item) + let longAction = self.longAction(forItem: item) var barItem: NSTouchBarItem! switch item.type { case .staticButton(title: let title): - barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action) + barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action, onLongTap: longAction) case .appleScriptTitledButton(source: let source, refreshInterval: let interval): - barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, onTap: action) + barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, onTap: action, onLongTap: longAction) case .timeButton(formatTemplate: let template): barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template) case .battery(): - barItem = BatteryBarItem(identifier: identifier, onTap: action) + barItem = BatteryBarItem(identifier: identifier, onTap: action, onLongTap: longAction) case .dock: barItem = AppScrubberTouchBarItem(identifier: identifier) case .volume: @@ -188,9 +187,9 @@ class TouchBarController: NSObject, NSTouchBarDelegate { barItem = BrightnessViewController(identifier: identifier, refreshInterval: interval) } case .weather(interval: let interval, units: let units, api_key: let api_key, icon_type: let icon_type): - barItem = WeatherBarItem(identifier: identifier, interval: interval, units: units, api_key: api_key, icon_type: icon_type, onTap: action) + barItem = WeatherBarItem(identifier: identifier, interval: interval, units: units, api_key: api_key, icon_type: icon_type, onTap: action, onLongTap: longAction) case .currency(interval: let interval, from: let from, to: let to): - barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to, onTap: action) + barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to, onTap: action, onLongTap: longAction) } if case .width(let value)? = item.additionalParameters[.width], let widthBarItem = barItem as? CanSetWidth { @@ -248,6 +247,48 @@ class TouchBarController: NSObject, NSTouchBarDelegate { } } + + func longAction(forItem item: BarItemDefinition) -> ()->() { + switch item.longAction { + case .hidKey(keycode: let keycode): + return { HIDPostAuxKey(keycode) } + case .keyPress(keycode: let keycode): + return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() } + case .appleSctipt(source: let source): + guard let appleScript = source.appleScript else { + print("cannot create apple script for item \(item)") + return {} + } + return { + var error: NSDictionary? + appleScript.executeAndReturnError(&error) + if let error = error { + print("error \(error) when handling \(item) ") + } + } + case .shellScript(executable: let executable, parameters: let parameters): + return { + let task = Process() + task.launchPath = executable + task.arguments = parameters + task.launch() + } + case .openUrl(url: let 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 .custom(closure: let closure): + return closure + case .none: + return {} + } + } } protocol CanSetWidth { diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift index 7140bd8..a8dac74 100644 --- a/MTMR/WeatherBarItem.swift +++ b/MTMR/WeatherBarItem.swift @@ -24,7 +24,7 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { private var manager:CLLocationManager! - init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text", onTap: @escaping () -> ()) { + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text", onTap: @escaping () -> (), onLongTap: @escaping () -> ()) { self.interval = interval self.units = units self.api_key = api_key @@ -43,7 +43,7 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { iconsSource = iconsText } - super.init(identifier: identifier, title: "⏳", onTap: onTap) + super.init(identifier: identifier, title: "⏳", onTap: onTap, onLongTap: onLongTap) button.bezelColor = .clear self.view = button