From 20699e9de73c65fb3661dd390e1a70245e56380a Mon Sep 17 00:00:00 2001 From: ad Date: Mon, 16 Apr 2018 23:42:44 +0300 Subject: [PATCH 01/21] * removed unused code --- MTMR/VolumeViewController.swift | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/MTMR/VolumeViewController.swift b/MTMR/VolumeViewController.swift index 3ca4615..c9d950a 100644 --- a/MTMR/VolumeViewController.swift +++ b/MTMR/VolumeViewController.swift @@ -14,9 +14,7 @@ class VolumeViewController: NSCustomTouchBarItem { mScope: kAudioDevicePropertyScopeOutput, mElement: kAudioObjectPropertyElementMaster) - addListenerBlock(listenerBlock: audioObjectPropertyListenerBlock, - onAudioObjectID: defaultDeviceID, - forPropertyAddress: &forPropertyAddress) + AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock) if (image == nil) { sliderItem = CustomSlider() @@ -32,27 +30,9 @@ class VolumeViewController: NSCustomTouchBarItem { self.view = sliderItem } - func addListenerBlock( listenerBlock: @escaping AudioObjectPropertyListenerBlock, onAudioObjectID: AudioObjectID, forPropertyAddress: UnsafePointer) { - - if (kAudioHardwareNoError != AudioObjectAddPropertyListenerBlock(onAudioObjectID, forPropertyAddress, nil, listenerBlock)) { - print("Error calling: AudioObjectAddPropertyListenerBlock") } - } - func audioObjectPropertyListenerBlock (numberAddresses: UInt32, addresses: UnsafePointer) { - var index: UInt32 = 0 - while index < numberAddresses { - let address: AudioObjectPropertyAddress = addresses[Int(index)] - switch address.mSelector { - case kAudioHardwareServiceDeviceProperty_VirtualMasterVolume: - DispatchQueue.main.async { - self.sliderItem.floatValue = self.getInputGain() * 100 - } - default: - - print("We didn't expect this!") - - } - index += 1 + DispatchQueue.main.async { + self.sliderItem.floatValue = self.getInputGain() * 100 } } From 7774b1fa5e0a9ac91852b6503a05286a629853e1 Mon Sep 17 00:00:00 2001 From: ad Date: Tue, 17 Apr 2018 10:55:21 +0300 Subject: [PATCH 02/21] * add shadow to app scrubber --- MTMR/AppScrubberTouchBarItem.swift | 2 ++ MTMR/AppleScriptTouchBarItem.swift | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/MTMR/AppScrubberTouchBarItem.swift b/MTMR/AppScrubberTouchBarItem.swift index 3c5a80a..50b652f 100644 --- a/MTMR/AppScrubberTouchBarItem.swift +++ b/MTMR/AppScrubberTouchBarItem.swift @@ -35,8 +35,10 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub scrubber.mode = .free // .fixed let layout = NSScrubberFlowLayout(); layout.itemSize = NSSize(width: 44, height: 30) + layout.itemSpacing = 2 scrubber.scrubberLayout = layout scrubber.selectionBackgroundStyle = .roundedBackground + scrubber.showsAdditionalContentIndicators = true view = scrubber diff --git a/MTMR/AppleScriptTouchBarItem.swift b/MTMR/AppleScriptTouchBarItem.swift index c49914b..352ec8d 100644 --- a/MTMR/AppleScriptTouchBarItem.swift +++ b/MTMR/AppleScriptTouchBarItem.swift @@ -7,7 +7,7 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, onTap: @escaping ()->()) { self.interval = interval - super.init(identifier: identifier, title: "compile", onTap: onTap) + super.init(identifier: identifier, title: "⏳", onTap: onTap) self.forceHideConstraint = self.view.widthAnchor.constraint(equalToConstant: 0) guard let script = source.appleScript else { button.title = "no script" @@ -18,9 +18,9 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { DispatchQueue.main.async { var error: NSDictionary? guard script.compileAndReturnError(&error) else { - print(error?.description ?? "unknown error") +// print(error?.description ?? "unknown error") DispatchQueue.main.async { - self.button.title = "compile error" + self.button.title = "error" } return } @@ -33,7 +33,7 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { } func refreshAndSchedule() { - print("refresh happened") +// print("refresh happened") let scriptResult = self.execute() DispatchQueue.main.async { self.button.title = scriptResult From 4c16321a4a2fd21dd6acc2aea59e7996f7bf3f46 Mon Sep 17 00:00:00 2001 From: ad Date: Wed, 18 Apr 2018 18:27:28 +0300 Subject: [PATCH 03/21] + weather widget --- MTMR.xcodeproj/project.pbxproj | 4 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + MTMR/Info.plist | 2 + MTMR/ItemsParsing.swift | 17 +- MTMR/TouchBarController.swift | 5 + MTMR/WeatherBarItem.swift | 152 ++++++++++++++++++ 6 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 MTMR.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 MTMR/WeatherBarItem.swift diff --git a/MTMR.xcodeproj/project.pbxproj b/MTMR.xcodeproj/project.pbxproj index 2958cd6..7e26678 100644 --- a/MTMR.xcodeproj/project.pbxproj +++ b/MTMR.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; }; 6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */; }; 6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */; }; + 607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */; }; B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; }; B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05600D22083E9BB00EB218D /* CustomSlider.swift */; }; B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; }; @@ -66,6 +67,7 @@ 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppScrubberTouchBarItem.swift; sourceTree = ""; }; 6042B6A82083E1F500C525C8 /* DeprecatedCarbonAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeprecatedCarbonAPI.h; sourceTree = ""; }; 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DeprecatedCarbonAPI.c; sourceTree = ""; }; + 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherBarItem.swift; sourceTree = ""; }; B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = ""; }; B05600D22083E9BB00EB218D /* CustomSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSlider.swift; sourceTree = ""; }; B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = ""; }; @@ -172,6 +174,7 @@ 368EDDE620812A1D00E10953 /* ScrollViewItem.swift */, 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */, B05600D22083E9BB00EB218D /* CustomSlider.swift */, + 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */, ); path = MTMR; sourceTree = ""; @@ -340,6 +343,7 @@ B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */, B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */, 6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */, + 607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */, 6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */, B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */, 36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */, diff --git a/MTMR.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/MTMR.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..3ddf867 --- /dev/null +++ b/MTMR.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Latest + + diff --git a/MTMR/Info.plist b/MTMR/Info.plist index 20be9f0..e110343 100644 --- a/MTMR/Info.plist +++ b/MTMR/Info.plist @@ -26,6 +26,8 @@ NSHumanReadableCopyright Copyright © 2018 Anton Palgunov. All rights reserved. + NSLocationUsageDescription + ... NSMainStoryboardFile Main NSPrincipalClass diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 5851f67..7de744d 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -73,12 +73,12 @@ class SupportedTypesHolder { return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_NEXT), parameters: [.image: imageParameter]) }, "weather": { decoder in - enum CodingKeys: String, CodingKey { case refreshInterval } + enum CodingKeys: String, CodingKey { case refreshInterval; case units; case api_key } let container = try decoder.container(keyedBy: CodingKeys.self) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) - let scriptPath = Bundle.main.path(forResource: "Weather", ofType: "scpt")! - let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0) - return (item: item, action: .none, parameters: [:]) + 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: [:]) }, "dock": { decoder in return (item: .dock(), action: .none, parameters: [:]) @@ -140,12 +140,15 @@ enum ItemType: Decodable { case dock() case volume() case brightness(refreshInterval: Double) + case weather(interval: Double, units: String, api_key: String) private enum CodingKeys: String, CodingKey { case type case title case source case refreshInterval + case units + case api_key case formatTemplate case image } @@ -157,6 +160,7 @@ enum ItemType: Decodable { case dock case volume case brightness + case weather } init(from decoder: Decoder) throws { @@ -180,6 +184,11 @@ enum ItemType: Decodable { 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" + self = .weather(interval: interval, units: units, api_key: api_key) } } } diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index ada3da1..df8259b 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -29,6 +29,8 @@ extension ItemType { return "com.toxblh.mtmr.volume" case .brightness(refreshInterval: _): return "com.toxblh.mtmr.brightness" + case .weather(interval: _, units: _, api_key: _): + return "com.toxblh.mtmr.weather" } } @@ -166,7 +168,10 @@ 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) } + if case .width(let value)? = item.additionalParameters[.width], let widthBarItem = barItem as? CanSetWidth { widthBarItem.setWidth(value: value) } diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift new file mode 100644 index 0000000..b902375 --- /dev/null +++ b/MTMR/WeatherBarItem.swift @@ -0,0 +1,152 @@ +// +// WeatherBarItem.swift +// MTMR +// +// Created by Daniel Apatin on 18.04.2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +import Cocoa +import CoreLocation + +class WeatherBarItem: NSCustomTouchBarItem, 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 var manager:CLLocationManager! + + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String) { + self.interval = interval + self.units = units + self.api_key = api_key + + if self.units == "metric" { + units_str = "°C" + } + + super.init(identifier: identifier) + + button.bezelColor = .clear + button.title = "⏳" + self.view = button + + let status = CLLocationManager.authorizationStatus() + if status == .restricted || status == .denied { + print("User permission not given") + return + } + + if !CLLocationManager.locationServicesEnabled() { + print("not enabled"); + return + } + + timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(updateWeather), userInfo: nil, repeats: true) + + manager = CLLocationManager() + manager.delegate = self + manager.desiredAccuracy = kCLLocationAccuracyHundredMeters + manager.startUpdatingLocation() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func updateWeather() { + if self.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=\(self.units)&appid=\(self.api_key)")!) + + let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in + + if error == nil { + do { + let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject] + + var temperature: Int! + var condition_icon = "" + + if let main = json["main"] as? [String : AnyObject] { + if let temp = main["temp"] as? Int { + temperature = temp + } + } + + 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 temperature != nil { + DispatchQueue.main.async { + self.setWeather(text: "\(condition_icon) \(temperature!)\(self.units_str)") + } + } + } catch let jsonError { + print(jsonError.localizedDescription) + } + } + } + + task.resume() + } + } + + func setWeather(text: String) { + button.title = text + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + let lastLocation = locations.last! + self.location = lastLocation + if prev_location == nil { + updateWeather() + } + prev_location = lastLocation + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + print(error); + } + + func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { + print("inside didChangeAuthorization "); + updateWeather() + } + +} + From 42c1ff27c4bacba1e3e6d605026de08f73bc62f2 Mon Sep 17 00:00:00 2001 From: ad Date: Wed, 18 Apr 2018 19:50:23 +0300 Subject: [PATCH 04/21] + currency widget { "type": "currency", "refreshInterval": 600, "align": "right", "from": "USD", "to": "RUB" }, --- MTMR.xcodeproj/project.pbxproj | 4 ++ MTMR/CurrencyBarItem.swift | 73 ++++++++++++++++++++++++++++++++++ MTMR/ItemsParsing.swift | 17 ++++++++ MTMR/TouchBarController.swift | 4 ++ 4 files changed, 98 insertions(+) create mode 100644 MTMR/CurrencyBarItem.swift diff --git a/MTMR.xcodeproj/project.pbxproj b/MTMR.xcodeproj/project.pbxproj index 7e26678..d2b0a60 100644 --- a/MTMR.xcodeproj/project.pbxproj +++ b/MTMR.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */; }; 6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */; }; 607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */; }; + 607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */; }; B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; }; B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05600D22083E9BB00EB218D /* CustomSlider.swift */; }; B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; }; @@ -68,6 +69,7 @@ 6042B6A82083E1F500C525C8 /* DeprecatedCarbonAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeprecatedCarbonAPI.h; sourceTree = ""; }; 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DeprecatedCarbonAPI.c; sourceTree = ""; }; 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherBarItem.swift; sourceTree = ""; }; + 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyBarItem.swift; sourceTree = ""; }; B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = ""; }; B05600D22083E9BB00EB218D /* CustomSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSlider.swift; sourceTree = ""; }; B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = ""; }; @@ -175,6 +177,7 @@ 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */, B05600D22083E9BB00EB218D /* CustomSlider.swift */, 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */, + 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */, ); path = MTMR; sourceTree = ""; @@ -349,6 +352,7 @@ 36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */, B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */, 36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */, + 607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */, 6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */, 368EDDE720812A1D00E10953 /* ScrollViewItem.swift in Sources */, ); diff --git a/MTMR/CurrencyBarItem.swift b/MTMR/CurrencyBarItem.swift new file mode 100644 index 0000000..7636c84 --- /dev/null +++ b/MTMR/CurrencyBarItem.swift @@ -0,0 +1,73 @@ +// +// CurrencyBarItem.swift +// MTMR +// +// Created by Daniel Apatin on 18.04.2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +import Cocoa +import CoreLocation + +class CurrencyBarItem: NSCustomTouchBarItem { + private var timer: Timer! + private var interval: TimeInterval! + private var from: String + private var to: String + private let button = NSButton(title: "", target: nil, action: nil) + + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String) { + self.interval = interval + self.from = from + self.to = to + + super.init(identifier: identifier) + + button.bezelColor = .clear + button.title = "⏳" + self.view = button + + timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(updateCurrency), userInfo: nil, repeats: true) + + updateCurrency() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func updateCurrency() { + let urlRequest = URLRequest(url: URL(string: "https://api.coinbase.com/v2/exchange-rates?currency=\(from)")!) + + let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in + if error == nil { + do { + let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject] + + var value: String! + + 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 + } + } + } + if value != nil { + DispatchQueue.main.async { + self.setCurrency(text: "\(self.from)\(value!)") + } + } + } catch let jsonError { + print(jsonError.localizedDescription) + } + } + } + + task.resume() + } + + func setCurrency(text: String) { + button.title = text + } +} diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 7de744d..39db97c 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -80,6 +80,14 @@ class SupportedTypesHolder { 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: [:]) }, + "currency": { decoder in + 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) + 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: [:]) + }, "dock": { decoder in return (item: .dock(), action: .none, parameters: [:]) }, @@ -141,12 +149,15 @@ enum ItemType: Decodable { case volume() case brightness(refreshInterval: Double) case weather(interval: Double, units: String, api_key: String) + case currency(interval: Double, from: String, to: String) private enum CodingKeys: String, CodingKey { case type case title case source case refreshInterval + case from + case to case units case api_key case formatTemplate @@ -161,6 +172,7 @@ enum ItemType: Decodable { case volume case brightness case weather + case currency } init(from decoder: Decoder) throws { @@ -189,6 +201,11 @@ enum ItemType: Decodable { 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) + case .currency: + let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 + let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB" + let to = try container.decodeIfPresent(String.self, forKey: .to) ?? "USD" + self = .currency(interval: interval, from: from, to: to) } } } diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index df8259b..c6b246e 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -31,6 +31,8 @@ extension ItemType { return "com.toxblh.mtmr.brightness" case .weather(interval: _, units: _, api_key: _): return "com.toxblh.mtmr.weather" + case .currency(interval: _, from: _, to: _): + return "com.toxblh.mtmr.currency" } } @@ -170,6 +172,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { } 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 .currency(interval: let interval, from: let from, to: let to): + barItem = CurrencyBarItem(identifier: identifier, interval: interval, from: from, to: to) } if case .width(let value)? = item.additionalParameters[.width], let widthBarItem = barItem as? CanSetWidth { From 242e2d3c22457e68cbb97097d7a0c2c5ec312a86 Mon Sep 17 00:00:00 2001 From: ad Date: Wed, 18 Apr 2018 22:14:10 +0300 Subject: [PATCH 05/21] * currency list --- MTMR/CurrencyBarItem.swift | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/MTMR/CurrencyBarItem.swift b/MTMR/CurrencyBarItem.swift index 7636c84..584f9b9 100644 --- a/MTMR/CurrencyBarItem.swift +++ b/MTMR/CurrencyBarItem.swift @@ -12,15 +12,39 @@ import CoreLocation class CurrencyBarItem: NSCustomTouchBarItem { private var timer: Timer! private var interval: TimeInterval! + private var prefix: String private var from: String private var to: String private let button = NSButton(title: "", target: nil, action: nil) + private let currencies = [ + "USD": "$", + "EUR": "€", + "RUB": "₽", + "JPY": "¥", + "GBP": "₤", + "CAD": "$", + "KRW": "₩", + "CNY": "¥", + "AUD": "$", + "BRL": "R$", + "IDR": "Rp", + "MXN": "$", + "SGD": "$", + "CHF": "Fr." + ] + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String) { self.interval = interval self.from = from self.to = to + if let prefix = currencies[from] { + self.prefix = prefix + } else { + self.prefix = from + } + super.init(identifier: identifier) button.bezelColor = .clear @@ -55,7 +79,7 @@ class CurrencyBarItem: NSCustomTouchBarItem { } if value != nil { DispatchQueue.main.async { - self.setCurrency(text: "\(self.from)\(value!)") + self.setCurrency(text: "\(value!)") } } } catch let jsonError { @@ -68,6 +92,6 @@ class CurrencyBarItem: NSCustomTouchBarItem { } func setCurrency(text: String) { - button.title = text + button.title = "\(self.prefix)\(text)" } } From 3a572695103906768487e574acd451b3595c7988 Mon Sep 17 00:00:00 2001 From: ad Date: Thu, 19 Apr 2018 18:01:16 +0300 Subject: [PATCH 06/21] + open preset from dialog (not replacing default file) --- MTMR/AppDelegate.swift | 25 +++++++++++++++++++++++++ MTMR/TouchBarController.swift | 20 ++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/MTMR/AppDelegate.swift b/MTMR/AppDelegate.swift index c2ded9b..3c4e037 100644 --- a/MTMR/AppDelegate.swift +++ b/MTMR/AppDelegate.swift @@ -39,10 +39,35 @@ class AppDelegate: NSObject, NSApplicationDelegate { TouchBarController.shared.createAndUpdatePreset() } + @objc func openPreset(_ sender: Any?) { + let dialog = NSOpenPanel(); + + dialog.title = "Choose a items.json file"; + dialog.showsResizeIndicator = true; + dialog.showsHiddenFiles = true; + dialog.canChooseDirectories = false; + dialog.canCreateDirectories = false; + dialog.allowsMultipleSelection = false; + dialog.allowedFileTypes = ["json"]; + + if (dialog.runModal() == NSApplication.ModalResponse.OK) { + let result = dialog.url + + if (result != nil) { + let path = result!.path + let jsonData = path.fileData + let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [:])] + + TouchBarController.shared.createAndUpdatePreset(jsonItems: jsonItems) + } + } + } + func createMenu() { let menu = NSMenu() menu.addItem(withTitle: "Preferences", action: #selector(openPrefereces(_:)), keyEquivalent: ",") menu.addItem(withTitle: "Reload Preset", action: #selector(updatePreset(_:)), keyEquivalent: "r") + menu.addItem(withTitle: "Open Preset", action: #selector(openPreset(_:)), keyEquivalent: "O") menu.addItem(NSMenuItem.separator()) menu.addItem(withTitle: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q") statusItem.menu = menu diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index ada3da1..c652951 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -60,14 +60,18 @@ class TouchBarController: NSObject, NSTouchBarDelegate { createAndUpdatePreset() } - func createAndUpdatePreset() { + func createAndUpdatePreset(jsonItems: [BarItemDefinition]? = nil) { + var jsonItems = jsonItems self.itemDefinitions = [:] self.items = [:] self.leftIdentifiers = [] self.centerItems = [] self.rightIdentifiers = [] - loadItemDefinitions() + if (jsonItems == nil) { + jsonItems = readConfig() + } + loadItemDefinitions(jsonItems: jsonItems!) createItems() centerItems = self.itemDefinitions.compactMap { (identifier, definition) -> NSTouchBarItem? in return definition.align == .center ? items[identifier] : nil @@ -77,8 +81,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { touchBar.defaultItemIdentifiers = self.leftIdentifiers + [.centerScrollArea] + self.rightIdentifiers self.presentTouchBar() } - - func loadItemDefinitions() { + + func readConfig() -> [BarItemDefinition]? { let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR") let presetPath = appSupportDirectory.appending("/items.json") if !FileManager.default.fileExists(atPath: presetPath), @@ -86,9 +90,13 @@ class TouchBarController: NSObject, NSTouchBarDelegate { try? FileManager.default.createDirectory(atPath: appSupportDirectory, withIntermediateDirectories: true, attributes: nil) try? FileManager.default.copyItem(atPath: defaultPreset, toPath: presetPath) } + let jsonData = presetPath.fileData - let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [:])] - + + return jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [:])] + } + + func loadItemDefinitions(jsonItems: [BarItemDefinition]) { for item in jsonItems { let identifierString = item.type.identifierBase.appending(UUID().uuidString) let identifier = NSTouchBarItem.Identifier(identifierString) From fdd30413c4b8a5acfbf0db749e20dc2406767fdc Mon Sep 17 00:00:00 2001 From: ad Date: Thu, 19 Apr 2018 18:18:54 +0300 Subject: [PATCH 07/21] * open dialog at default configs directory --- MTMR/AppDelegate.swift | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/MTMR/AppDelegate.swift b/MTMR/AppDelegate.swift index 3c4e037..850031a 100644 --- a/MTMR/AppDelegate.swift +++ b/MTMR/AppDelegate.swift @@ -42,13 +42,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { @objc func openPreset(_ sender: Any?) { let dialog = NSOpenPanel(); - dialog.title = "Choose a items.json file"; - dialog.showsResizeIndicator = true; - dialog.showsHiddenFiles = true; - dialog.canChooseDirectories = false; - dialog.canCreateDirectories = false; - dialog.allowsMultipleSelection = false; - dialog.allowedFileTypes = ["json"]; + dialog.title = "Choose a items.json file" + dialog.showsResizeIndicator = true + dialog.showsHiddenFiles = true + dialog.canChooseDirectories = false + dialog.canCreateDirectories = false + dialog.allowsMultipleSelection = false + dialog.allowedFileTypes = ["json"] + dialog.directoryURL = NSURL.fileURL(withPath: NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR"), isDirectory: true) if (dialog.runModal() == NSApplication.ModalResponse.OK) { let result = dialog.url From fe07ea3b46529b7ce8fb4f7ad821d70247f094eb Mon Sep 17 00:00:00 2001 From: ad Date: Thu, 19 Apr 2018 18:53:29 +0300 Subject: [PATCH 08/21] * fixed deminiaturization and Finder opening --- MTMR/AppScrubberTouchBarItem.swift | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/MTMR/AppScrubberTouchBarItem.swift b/MTMR/AppScrubberTouchBarItem.swift index 50b652f..5f30481 100644 --- a/MTMR/AppScrubberTouchBarItem.swift +++ b/MTMR/AppScrubberTouchBarItem.swift @@ -92,20 +92,19 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub } public func didFinishInteracting(with scrubber: NSScrubber) { - runningApplications[scrubber.selectedIndex].activate(options: [ .activateIgnoringOtherApps ]) +// runningApplications[scrubber.selectedIndex].activate(options: [ .activateIgnoringOtherApps ]) + + let bundleIdentifier = runningApplications[scrubber.selectedIndex].bundleIdentifier + if bundleIdentifier!.contains("file://") { + NSWorkspace.shared.openFile(bundleIdentifier!.replacingOccurrences(of: "file://", with: "")) + + } else { + NSWorkspace.shared.launchApplication(withBundleIdentifier: bundleIdentifier!, options: [.default], additionalEventParamDescriptor: nil, launchIdentifier: nil) + } // NB: if you can't open app which on another space, try to check mark // "When switching to an application, switch to a Space with open windows for the application" // in Mission control settings - - // TODO: deminiaturize app -// if let info = CGWindowListCopyWindowInfo(.optionOnScreenOnly, kCGNullWindowID) as? [[ String : Any]] { -// for dict in info { -// if dict["kCGWindowOwnerName"] as! String == runningApplications[scrubber.selectedIndex].localizedName { -// print(dict["kCGWindowNumber"], dict["kCGWindowOwnerName"]) -// } -// } -// } } } From c5a7a3142b4cdf6b14951d2e0880a39143c70ef1 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Thu, 19 Apr 2018 21:54:12 +0300 Subject: [PATCH 09/21] Fixed currency 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 4eb14ea16634404f216fec2f7be1140c4362d10f Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 11:16:50 +0300 Subject: [PATCH 10/21] Update TouchBarController.swift --- MTMR/TouchBarController.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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) } From bfc4dcf22c9e656002fe5c488f4b66ffff2beb60 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 11:17:29 +0300 Subject: [PATCH 11/21] Update ItemsParsing.swift --- MTMR/ItemsParsing.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 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" From 7bc8458d8ba8a20bef819547fc6d51c97daf0b31 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 11:18:11 +0300 Subject: [PATCH 12/21] Update WeatherBarItem.swift --- MTMR/WeatherBarItem.swift | 45 ++++++++++++--------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift index b902375..87ad8be 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,9 +128,8 @@ class WeatherBarItem: NSCustomTouchBarItem, CLLocationManagerDelegate { } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { - print("inside didChangeAuthorization "); +// print("inside didChangeAuthorization "); updateWeather() } } - From 73411368976ecfd7f3834de829d59e4f0160694c Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 13:34:56 +0300 Subject: [PATCH 13/21] Update TouchBarController.swift --- MTMR/TouchBarController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 { From 94d519cd65a52d9658977fea641064e9865b0120 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 13:35:21 +0300 Subject: [PATCH 14/21] Update CurrencyBarItem.swift --- MTMR/CurrencyBarItem.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 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) From 92c4eed4edcdb4d9eacd3ee70579ccac06541d57 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 13:35:41 +0300 Subject: [PATCH 15/21] Update WeatherBarItem.swift --- MTMR/WeatherBarItem.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift index 87ad8be..fb120e9 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 3e35e03bfb379c7b233e7f41210052f756791efd Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 14:25:31 +0300 Subject: [PATCH 16/21] + 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 055fb09..f7965e9 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 2aecb2ffb36f29eaf3918646531b3fcf0ac1ded7 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 15:20:01 +0300 Subject: [PATCH 17/21] Update ItemsParsing.swift --- MTMR/ItemsParsing.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index f7965e9..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) @@ -167,6 +167,7 @@ enum ItemType: Decodable { case icon_type case formatTemplate case image + case url } enum ItemTypeRaw: String, Decodable { @@ -223,6 +224,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 @@ -230,6 +232,7 @@ enum ActionType: Decodable { case actionAppleScript case executablePath case shellArguments + case url } private enum ActionTypeRaw: String, Decodable { @@ -237,6 +240,7 @@ enum ActionType: Decodable { case keyPress case appleScript case shellScript + case openUrl } init(from decoder: Decoder) throws { @@ -256,6 +260,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 } @@ -287,6 +294,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 } From e6d84888ba6062d56017893849534a17ba471645 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 15:21:30 +0300 Subject: [PATCH 18/21] Update TouchBarController.swift --- MTMR/TouchBarController.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 4cf4086..290b483 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 ac234aa4bfa8919df00b08c9553c63901c850724 Mon Sep 17 00:00:00 2001 From: Daniel Apatin Date: Fri, 20 Apr 2018 16:24:00 +0300 Subject: [PATCH 19/21] Fix for temperature value with decimals --- MTMR/WeatherBarItem.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MTMR/WeatherBarItem.swift b/MTMR/WeatherBarItem.swift index fb120e9..8951853 100644 --- a/MTMR/WeatherBarItem.swift +++ b/MTMR/WeatherBarItem.swift @@ -81,8 +81,8 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { var condition_icon = "" if let main = json["main"] as? [String : AnyObject] { - if let temp = main["temp"] as? Int { - temperature = temp + if let temp = main["temp"] as? Double { + temperature = Int(temp) } } From 4109f6efd4789b51e3f144b103f4702085dc97bf Mon Sep 17 00:00:00 2001 From: Toxblh Date: Fri, 20 Apr 2018 22:50:36 +0100 Subject: [PATCH 20/21] delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index e2b9d508cae647566a3b45c0b56da4057e055d3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5T3C?DuVRrai2iw8!V+By)-_6m`Fup6Ixn4=0QFC9DcJil_Une3F-{& zezUvtv-?4IGepFTeK{wZ5z!P)kVP30nI2s_G2>GpON???RQGjVVenf-_MXuV-J-3! z`~R3c55*cpqfg0poX^4o~rdcFY4z;PyhP%oqhAzvF9LeU&bHo z<&0Lyy+h_b@)x3ak09Y(oB?OR8E^)ifguC-Oi#~;3qE!RoPmGOfZPuOO)wg^is|Y= zmr4L&hUp~GrIrw%U>FTsMXW$rU4iP#R${QaV?LN&G;9^so!E*Gw#>)kg;RFK56PT3 zDthk>I0JnKCOVwS`+tp3X0*ufyZFc%a0dPu1Dq}M8cW5GF*NOsx m-unr_K<<&tw5aPrbl641R#BqJd~yf+k3b^CJ7?er7 Date: Fri, 20 Apr 2018 22:54:38 +0100 Subject: [PATCH 21/21] Added Button mute `{ "type": "mute", "width": 40, "align": "right" },` #23 --- MTMR/ItemsParsing.swift | 4 ++++ MTMR/KeyPress.swift | 2 ++ 2 files changed, 6 insertions(+) diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index a01af0c..17cee83 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -60,6 +60,10 @@ class SupportedTypesHolder { let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeUpTemplate)!) return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP), 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]) + }, "previous": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarRewindTemplate)!) return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS), parameters: [.image: imageParameter]) diff --git a/MTMR/KeyPress.swift b/MTMR/KeyPress.swift index 5421d97..fe0f109 100644 --- a/MTMR/KeyPress.swift +++ b/MTMR/KeyPress.swift @@ -58,6 +58,7 @@ func HIDPostAuxKey(_ key: Int) { // hidsystem/ev_keymap.h let NX_KEYTYPE_SOUND_UP = 0 let NX_KEYTYPE_SOUND_DOWN = 1 +let NX_KEYTYPE_MUTE = 7 let NX_KEYTYPE_BRIGHTNESS_UP = 2 let NX_KEYTYPE_BRIGHTNESS_DOWN = 3 @@ -69,3 +70,4 @@ let NX_KEYTYPE_PREVIOUS = 18 +