From 641eb18b89c8fb4c9ed52ac6ada514eeb18bbaeb Mon Sep 17 00:00:00 2001 From: ad Date: Sat, 21 Apr 2018 10:20:12 +0300 Subject: [PATCH] + 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