diff --git a/MTMR/AppDelegate.swift b/MTMR/AppDelegate.swift index dfb5d8f..6b988cd 100644 --- a/MTMR/AppDelegate.swift +++ b/MTMR/AppDelegate.swift @@ -11,54 +11,50 @@ import Sparkle @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength) + let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) var isBlockedApp: Bool = false - + private var fileSystemSource: DispatchSourceFileSystemObject? - - func applicationDidFinishLaunching(_ aNotification: Notification) { + + func applicationDidFinishLaunching(_: Notification) { // Configure Sparkle SUUpdater.shared().automaticallyDownloadsUpdates = false SUUpdater.shared().automaticallyChecksForUpdates = true SUUpdater.shared().checkForUpdatesInBackground() - - let _ = AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true] as NSDictionary) - + + AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true] as NSDictionary) + TouchBarController.shared.setupControlStripPresence() - + if let button = statusItem.button { button.image = #imageLiteral(resourceName: "StatusImage") } createMenu() - + reloadOnDefaultConfigChanged() - + NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(updateIsBlockedApp), name: NSWorkspace.didLaunchApplicationNotification, object: nil) NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(updateIsBlockedApp), name: NSWorkspace.didTerminateApplicationNotification, object: nil) NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(updateIsBlockedApp), name: NSWorkspace.didActivateApplicationNotification, object: nil) } - func applicationWillTerminate(_ aNotification: Notification) { - - } - - @objc func updateIsBlockedApp() -> Void { + func applicationWillTerminate(_: Notification) {} + + @objc func updateIsBlockedApp() { var blacklistAppIdentifiers: [String] = [] if let blackListed = UserDefaults.standard.stringArray(forKey: "com.toxblh.mtmr.blackListedApps") { blacklistAppIdentifiers = blackListed } var frontmostApplicationIdentifier: String? { - get { - guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil } - return frontmostId - } + guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil } + return frontmostId } - - self.isBlockedApp = blacklistAppIdentifiers.index(of: frontmostApplicationIdentifier!) != nil + + isBlockedApp = blacklistAppIdentifiers.index(of: frontmostApplicationIdentifier!) != nil createMenu() } - - @objc func openPreferences(_ sender: Any?) { + + @objc func openPreferences(_: Any?) { let task = Process() let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR") let presetPath = appSupportDirectory.appending("/items.json") @@ -66,14 +62,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { task.arguments = [presetPath] task.launch() } - - @objc func toggleControlStrip(_ sender: Any?) { + + @objc func toggleControlStrip(_: Any?) { TouchBarController.shared.showControlStripState = !TouchBarController.shared.showControlStripState TouchBarController.shared.resetControlStrip() createMenu() } - - @objc func toggleBlackListedApp(_ sender: Any?) { + + @objc func toggleBlackListedApp(_: Any?) { let appIdentifier = TouchBarController.shared.frontmostApplicationIdentifier if appIdentifier != nil { if let index = TouchBarController.shared.blacklistAppIdentifiers.index(of: appIdentifier!) { @@ -81,56 +77,56 @@ class AppDelegate: NSObject, NSApplicationDelegate { } else { TouchBarController.shared.blacklistAppIdentifiers.append(appIdentifier!) } - + UserDefaults.standard.set(TouchBarController.shared.blacklistAppIdentifiers, forKey: "com.toxblh.mtmr.blackListedApps") UserDefaults.standard.synchronize() - + TouchBarController.shared.updateActiveApp() updateIsBlockedApp() } } - - @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 + + @objc func openPreset(_: 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.allowedFileTypes = ["json"] dialog.directoryURL = NSURL.fileURL(withPath: NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR"), isDirectory: true) - + if dialog.runModal() == .OK, let path = dialog.url?.path { TouchBarController.shared.reloadPreset(path: path) } } - - @objc func toggleStartAtLogin(_ sender: Any?) { + + @objc func toggleStartAtLogin(_: Any?) { LaunchAtLoginController().setLaunchAtLogin(!LaunchAtLoginController().launchAtLogin, for: NSURL.fileURL(withPath: Bundle.main.bundlePath)) createMenu() } - + func createMenu() { let menu = NSMenu() - + let startAtLogin = NSMenuItem(title: "Start at login", action: #selector(toggleStartAtLogin(_:)), keyEquivalent: "L") startAtLogin.state = LaunchAtLoginController().launchAtLogin ? .on : .off - + let toggleBlackList = NSMenuItem(title: "Toggle current app in blacklist", action: #selector(toggleBlackListedApp(_:)), keyEquivalent: "B") - toggleBlackList.state = self.isBlockedApp ? .on : .off - + toggleBlackList.state = isBlockedApp ? .on : .off + let hideControlStrip = NSMenuItem(title: "Hide Control Strip", action: #selector(toggleControlStrip(_:)), keyEquivalent: "T") hideControlStrip.state = TouchBarController.shared.showControlStripState ? .off : .on - + let settingSeparator = NSMenuItem(title: "Settings", action: nil, keyEquivalent: "") settingSeparator.isEnabled = false - + menu.addItem(withTitle: "Preferences", action: #selector(openPreferences(_:)), keyEquivalent: ",") menu.addItem(withTitle: "Open preset", action: #selector(openPreset(_:)), keyEquivalent: "O") menu.addItem(withTitle: "Check for Updates...", action: #selector(SUUpdater.checkForUpdates(_:)), keyEquivalent: "").target = SUUpdater.shared() - + menu.addItem(NSMenuItem.separator()) menu.addItem(settingSeparator) menu.addItem(hideControlStrip) @@ -143,23 +139,22 @@ class AppDelegate: NSObject, NSApplicationDelegate { func reloadOnDefaultConfigChanged() { let file = NSURL.fileURL(withPath: standardConfigPath) - + let fd = open(file.path, O_EVTONLY) - - self.fileSystemSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fd, eventMask: .write, queue: DispatchQueue(label: "DefaultConfigChanged")) - - self.fileSystemSource?.setEventHandler(handler: { + + fileSystemSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fd, eventMask: .write, queue: DispatchQueue(label: "DefaultConfigChanged")) + + fileSystemSource?.setEventHandler(handler: { print("Config changed, reloading...") DispatchQueue.main.async { TouchBarController.shared.reloadPreset(path: file.path) } }) - - self.fileSystemSource?.setCancelHandler(handler: { + + fileSystemSource?.setCancelHandler(handler: { close(fd) }) - - self.fileSystemSource?.resume() + + fileSystemSource?.resume() } } - diff --git a/MTMR/AppleScriptTouchBarItem.swift b/MTMR/AppleScriptTouchBarItem.swift index e606269..b6526c7 100644 --- a/MTMR/AppleScriptTouchBarItem.swift +++ b/MTMR/AppleScriptTouchBarItem.swift @@ -4,17 +4,17 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { private var script: NSAppleScript! private let interval: TimeInterval private var forceHideConstraint: NSLayoutConstraint! - + init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) { self.interval = interval super.init(identifier: identifier, title: "⏳") - self.forceHideConstraint = self.view.widthAnchor.constraint(equalToConstant: 0) + forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0) guard let script = source.appleScript else { - self.title = "no script" + title = "no script" return } self.script = script - self.isBordered = false + isBordered = false DispatchQueue.appleScriptQueue.async { var error: NSDictionary? guard script.compileAndReturnError(&error) else { @@ -29,28 +29,28 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { self.refreshAndSchedule() } } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func refreshAndSchedule() { #if DEBUG - print("refresh happened (interval \(self.interval)), self \(self.identifier.rawValue))") + print("refresh happened (interval \(interval)), self \(identifier.rawValue))") #endif - let scriptResult = self.execute() + let scriptResult = execute() DispatchQueue.main.async { self.title = scriptResult self.forceHideConstraint.isActive = scriptResult == "" #if DEBUG - print("did set new script result title \(scriptResult)") + print("did set new script result title \(scriptResult)") #endif } - DispatchQueue.appleScriptQueue.asyncAfter(deadline: .now() + self.interval) { [weak self] in + DispatchQueue.appleScriptQueue.asyncAfter(deadline: .now() + interval) { [weak self] in self?.refreshAndSchedule() } } - + func execute() -> String { var error: NSDictionary? let output = script.executeAndReturnError(&error) @@ -60,7 +60,6 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { } return output.stringValue ?? "" } - } extension DispatchQueue { diff --git a/MTMR/CustomButtonTouchBarItem.swift b/MTMR/CustomButtonTouchBarItem.swift index a181668..647aca9 100644 --- a/MTMR/CustomButtonTouchBarItem.swift +++ b/MTMR/CustomButtonTouchBarItem.swift @@ -9,69 +9,69 @@ import Cocoa class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { - var tapClosure: (() -> ())? - var longTapClosure: (() -> ())? + var tapClosure: (() -> Void)? + var longTapClosure: (() -> Void)? private var button: NSButton! - + private var singleClick: NSClickGestureRecognizer! private var longClick: NSPressGestureRecognizer! init(identifier: NSTouchBarItem.Identifier, title: String) { - self.attributedTitle = title.defaultTouchbarAttributedString - + attributedTitle = title.defaultTouchbarAttributedString + super.init(identifier: identifier) button = CustomHeightButton(title: title, target: nil, action: nil) - + 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 - + reinstallButton() button.attributedTitle = attributedTitle } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + var isBordered: Bool = true { didSet { reinstallButton() } } - + var backgroundColor: NSColor? { didSet { reinstallButton() } } - + var title: String { get { - return self.attributedTitle.string + return attributedTitle.string } set { - self.attributedTitle = newValue.defaultTouchbarAttributedString + attributedTitle = newValue.defaultTouchbarAttributedString } } - + var attributedTitle: NSAttributedString { didSet { - self.button?.imagePosition = attributedTitle.length > 0 ? .imageLeading : .imageOnly - self.button?.attributedTitle = attributedTitle + button?.imagePosition = attributedTitle.length > 0 ? .imageLeading : .imageOnly + button?.attributedTitle = attributedTitle } } - + var image: NSImage? { didSet { button.image = image } } - + private func reinstallButton() { let title = button.attributedTitle let image = button.image @@ -88,12 +88,12 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat button.imageScaling = .scaleProportionallyDown button.imageHugsTitle = true button.attributedTitle = title - self.button?.imagePosition = title.length > 0 ? .imageLeading : .imageOnly + button?.imagePosition = title.length > 0 ? .imageLeading : .imageOnly button.image = image - self.view = button - - self.view.addGestureRecognizer(longClick) - self.view.addGestureRecognizer(singleClick) + view = button + + view.addGestureRecognizer(longClick) + view.addGestureRecognizer(singleClick) } func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool { @@ -102,19 +102,19 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat } return true } - + @objc func handleGestureSingle(gr: NSClickGestureRecognizer) { let hf: HapticFeedback = HapticFeedback() switch gr.state { case .ended: hf.tap(strong: 2) - self.tapClosure?() + tapClosure?() break default: break } } - + @objc func handleGestureLong(gr: NSPressGestureRecognizer) { let hf: HapticFeedback = HapticFeedback() switch gr.state { @@ -130,57 +130,52 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat break default: break - } } } -class CustomHeightButton : NSButton { - +class CustomHeightButton: NSButton { override var intrinsicContentSize: NSSize { var size = super.intrinsicContentSize size.height = 30 return size } - } class CustomButtonCell: NSButtonCell { weak var parentItem: CustomButtonTouchBarItem? - + init(parentItem: CustomButtonTouchBarItem) { super.init(textCell: "") self.parentItem = parentItem } - + override func highlight(_ flag: Bool, withFrame cellFrame: NSRect, in controlView: NSView) { super.highlight(flag, withFrame: cellFrame, in: controlView) - if !self.isBordered { + if !isBordered { if flag { - self.setAttributedTitle(self.attributedTitle, withColor: .lightGray) + setAttributedTitle(attributedTitle, withColor: .lightGray) } else if let parentItem = self.parentItem { - self.attributedTitle = parentItem.attributedTitle + attributedTitle = parentItem.attributedTitle } } } - - required init(coder: NSCoder) { + + required init(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } func setAttributedTitle(_ title: NSAttributedString, withColor color: NSColor) { let attrTitle = NSMutableAttributedString(attributedString: title) attrTitle.addAttributes([.foregroundColor: color], range: NSRange(location: 0, length: attrTitle.length)) - self.attributedTitle = attrTitle + attributedTitle = attrTitle } - } extension String { var defaultTouchbarAttributedString: NSAttributedString { let attrTitle = NSMutableAttributedString(string: self, attributes: [.foregroundColor: NSColor.white, .font: NSFont.systemFont(ofSize: 15, weight: .regular), .baselineOffset: 1]) - attrTitle.setAlignment(.center, range: NSRange(location: 0, length: self.count)) + attrTitle.setAlignment(.center, range: NSRange(location: 0, length: count)) return attrTitle } } - diff --git a/MTMR/CustomSlider.swift b/MTMR/CustomSlider.swift index 621b6cb..7d03501 100644 --- a/MTMR/CustomSlider.swift +++ b/MTMR/CustomSlider.swift @@ -9,34 +9,34 @@ import Foundation class CustomSliderCell: NSSliderCell { - var knobImage:NSImage! - private var _currentKnobRect:NSRect! - private var _barRect:NSRect! - + var knobImage: NSImage! + private var _currentKnobRect: NSRect! + private var _barRect: NSRect! + required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } - + override init() { super.init() } - - init(knob:NSImage?) { - knobImage = knob; + + init(knob: NSImage?) { + knobImage = knob super.init() } - + override func drawKnob(_ knobRect: NSRect) { - if (knobImage == nil) { + if knobImage == nil { super.drawKnob(knobRect) - return; + return } - _currentKnobRect = knobRect; + _currentKnobRect = knobRect drawBar(inside: _barRect, flipped: true) - let x = (knobRect.origin.x * (_barRect.size.width - (knobImage.size.width - knobRect.size.width)) / _barRect.size.width)+1; - let y = knobRect.origin.y+3 + let x = (knobRect.origin.x * (_barRect.size.width - (knobImage.size.width - knobRect.size.width)) / _barRect.size.width) + 1 + let y = knobRect.origin.y + 3 knobImage.draw( at: NSPoint(x: x, y: y), @@ -45,63 +45,62 @@ class CustomSliderCell: NSSliderCell { fraction: 1 ) } - - override func drawBar(inside aRect: NSRect, flipped: Bool) { + + override func drawBar(inside aRect: NSRect, flipped _: Bool) { _barRect = aRect - + let barRadius = CGFloat(2) var bgRect = aRect bgRect.size.height = CGFloat(4) - + let bg = NSBezierPath(roundedRect: bgRect, xRadius: barRadius, yRadius: barRadius) NSColor.lightGray.setFill() bg.fill() - + var activeRect = bgRect - activeRect.size.width = CGFloat((Double(bgRect.size.width) / (self.maxValue - self.minValue)) * self.doubleValue) + activeRect.size.width = CGFloat((Double(bgRect.size.width) / (maxValue - minValue)) * doubleValue) let active = NSBezierPath(roundedRect: activeRect, xRadius: barRadius, yRadius: barRadius) NSColor.darkGray.setFill() active.fill() } } -class CustomSlider:NSSlider { - - var currentValue:CGFloat = 0 - +class CustomSlider: NSSlider { + var currentValue: CGFloat = 0 + override func setNeedsDisplay(_ invalidRect: NSRect) { super.setNeedsDisplay(invalidRect) } - + override func awakeFromNib() { super.awakeFromNib() - if ((self.cell?.isKind(of: CustomSliderCell.self)) == false) { - let cell:CustomSliderCell = CustomSliderCell() + if (cell?.isKind(of: CustomSliderCell.self)) == false { + let cell: CustomSliderCell = CustomSliderCell() self.cell = cell } } - - convenience init(knob:NSImage) { + + convenience init(knob: NSImage) { self.init() - self.cell = CustomSliderCell(knob: knob) + cell = CustomSliderCell(knob: knob) } - + required init?(coder: NSCoder) { super.init(coder: coder) } - + override init(frame frameRect: NSRect) { super.init(frame: frameRect) } - + func knobImage() -> NSImage { let cell = self.cell as! CustomSliderCell return cell.knobImage } - - func setKnobImage(image:NSImage) { + + func setKnobImage(image: NSImage) { let cell = self.cell as! CustomSliderCell cell.knobImage = image } diff --git a/MTMR/GeneralExtensions.swift b/MTMR/GeneralExtensions.swift index be4bf2c..1e8ca05 100644 --- a/MTMR/GeneralExtensions.swift +++ b/MTMR/GeneralExtensions.swift @@ -11,9 +11,7 @@ import Foundation #endif extension String { - var ifNotEmpty: String? { - return self.count > 0 ? self : nil + return count > 0 ? self : nil } - } diff --git a/MTMR/HapticFeedback.swift b/MTMR/HapticFeedback.swift index 415cc93..11c7e77 100644 --- a/MTMR/HapticFeedback.swift +++ b/MTMR/HapticFeedback.swift @@ -10,7 +10,7 @@ import IOKit class HapticFeedback { private var actuatorRef: CFTypeRef? - private var deviceID: UInt64 = 0x200000001000000 + private var deviceID: UInt64 = 0x200_0000_0100_0000 private var error: IOReturn = 0 // Don't know how to do strong is enum one of @@ -24,7 +24,7 @@ class HapticFeedback { // 16 nothing // you can get a plist `otool -s __TEXT __tpad_act_plist /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/Current/MultitouchSupport|tail -n +3|awk -F'\t' '{print $2}'|xxd -r -p` - func tap(strong:Int32) -> Void { + func tap(strong: Int32) { actuatorRef = MTActuatorCreateFromDeviceID(deviceID).takeRetainedValue() guard actuatorRef != nil else { @@ -53,5 +53,3 @@ class HapticFeedback { return } } - - diff --git a/MTMR/Info.plist b/MTMR/Info.plist index b1ab140..038ca21 100644 --- a/MTMR/Info.plist +++ b/MTMR/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 0.18.5 CFBundleVersion - 79 + 82 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 79ea8c9..26fc5b3 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -1,9 +1,9 @@ -import Foundation import AppKit +import Foundation extension Data { func barItemDefinitions() -> [BarItemDefinition]? { - return try? JSONDecoder().decode([BarItemDefinition].self, from: self.utf8string!.stripComments().data(using: .utf8)!) + return try? JSONDecoder().decode([BarItemDefinition].self, from: utf8string!.stripComments().data(using: .utf8)!) } } @@ -12,24 +12,24 @@ struct BarItemDefinition: Decodable { let action: ActionType let longAction: LongActionType let additionalParameters: [GeneralParameters.CodingKeys: GeneralParameter] - + private enum CodingKeys: String, CodingKey { case type } - - init(type: ItemType, action: ActionType, longAction: LongActionType, 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 } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let type = try container.decode(String.self, forKey: .type) let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type) var additionalParameters = try GeneralParameters(from: decoder).parameters - + if let result = try? parametersDecoder(decoder), case let (itemType, action, longAction, parameters) = result { parameters.forEach { additionalParameters[$0] = $1 } @@ -38,68 +38,127 @@ struct BarItemDefinition: Decodable { self.init(type: .staticButton(title: "unknown"), action: .none, longAction: .none, additionalParameters: additionalParameters) } } - } class SupportedTypesHolder { - typealias ParametersDecoder = (Decoder) throws ->(item: ItemType, action: ActionType, longAction: LongActionType, 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), longAction: .none, parameters: [.align: .align(.left)]) }, - - "delete": { _ in return (item: .staticButton(title: "del"), action: .keyPress(keycode: 117), longAction: .none, parameters: [:])}, - + "escape": { _ in ( + item: .staticButton(title: "esc"), + action: .keyPress(keycode: 53), + longAction: .none, + parameters: [.align: .align(.left)] + ) }, + + "delete": { _ in ( + item: .staticButton(title: "del"), + action: .keyPress(keycode: 117), + longAction: .none, + parameters: [:] + ) }, + "brightnessUp": { _ in let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessUp")) - return (item: .staticButton(title: ""), action: .keyPress(keycode: 144), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .keyPress(keycode: 144), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "brightnessDown": { _ in let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessDown")) - return (item: .staticButton(title: ""), action: .keyPress(keycode: 145), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .keyPress(keycode: 145), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "illuminationUp": { _ in let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "ill_up")) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_ILLUMINATION_UP), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_ILLUMINATION_UP), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "illuminationDown": { _ in let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "ill_down")) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_ILLUMINATION_DOWN), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_ILLUMINATION_DOWN), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "volumeDown": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarVolumeDownTemplateName)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "volumeUp": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarVolumeUpTemplateName)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "mute": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarAudioOutputMuteTemplateName)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_MUTE), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_MUTE), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "previous": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarRewindTemplateName)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "play": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarPlayPauseTemplateName)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PLAY), longAction: .none, parameters: [.image: imageParameter]) + return ( + item: .staticButton(title: ""), + action: .hidKey(keycode: NX_KEYTYPE_PLAY), + longAction: .none, + parameters: [.image: imageParameter] + ) }, - + "next": { _ in let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarFastForwardTemplateName)!) - return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_NEXT), longAction: .none, parameters: [.image: imageParameter]) + 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 } + 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) @@ -107,9 +166,14 @@ class SupportedTypesHolder { let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) let action = try ActionType(from: decoder) 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: [:]) + return ( + item: .weather(interval: interval ?? 1800.00, units: units ?? "metric", api_key: api_key ?? "32c4256d09a4c52b38aecddba7a078f6", icon_type: icon_type ?? "text"), + action, + longAction, + parameters: [:] + ) }, - + "currency": { decoder in enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to } let container = try decoder.container(keyedBy: CodingKeys.self) @@ -118,42 +182,87 @@ class SupportedTypesHolder { let to = try container.decodeIfPresent(String.self, forKey: .to) let action = try ActionType(from: decoder) let longAction = try LongActionType(from: decoder) - return (item: .currency(interval: interval ?? 600.00, from: from ?? "RUB", to: to ?? "USD"), action: action, longAction: longAction, parameters: [:]) + return ( + item: .currency(interval: interval ?? 600.00, from: from ?? "RUB", to: to ?? "USD"), + action, + longAction, + parameters: [:] + ) }, - - "dock": { decoder in - return (item: .dock(), action: .none, longAction: .none, parameters: [:]) + + "dock": { _ in + ( + item: .dock(), + action: .none, + longAction: .none, + parameters: [:] + ) }, - - "inputsource": { decoder in - return (item: .inputsource(), action: .none, longAction: .none, parameters: [:]) + + "inputsource": { _ in + ( + item: .inputsource(), + 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, longAction: .none, parameters: [.image: .image(source: img)]) + return ( + item: .volume(), + action: .none, + longAction: .none, + parameters: [.image: .image(source: img)] + ) } else { - return (item: .volume(), action: .none, longAction: .none, parameters: [:]) + return ( + item: .volume(), + action: .none, + longAction: .none, + parameters: [:] + ) } }, - + "brightness": { decoder in enum CodingKeys: String, CodingKey { case refreshInterval; case image } 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, longAction: .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, longAction: .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"]), longAction: .none, parameters: [:]) }, - - "displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), longAction: .none, parameters: [:])}, - + + "sleep": { _ in ( + item: .staticButton(title: "☕️"), + action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]), + longAction: .none, + parameters: [:] + ) }, + + "displaySleep": { _ in ( + item: .staticButton(title: "☕️"), + action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), + longAction: .none, + parameters: [:] + ) }, + "music": { decoder in enum CodingKeys: String, CodingKey { case refreshInterval } let container = try decoder.container(keyedBy: CodingKeys.self) @@ -165,7 +274,7 @@ class SupportedTypesHolder { parameters: [:] ) }, - + "group": { decoder in enum CodingKeys: CodingKey { case items } let container = try decoder.container(keyedBy: CodingKeys.self) @@ -177,42 +286,46 @@ class SupportedTypesHolder { parameters: [:] ) }, - - "nightShift": {_ in - return ( + + "nightShift": { _ in + ( item: .nightShift(), action: .none, longAction: .none, parameters: [:] ) }, - + "dnd": { _ in - return ( + ( item: .dnd(), action: .none, 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), longAction: try LongActionType(from: decoder), parameters: [:]) + (item: try ItemType(from: decoder), action: try ActionType(from: decoder), longAction: try LongActionType(from: decoder), parameters: [:]) } } - + func register(typename: String, decoder: @escaping ParametersDecoder) { supportedTypes[typename] = decoder } - + func register(typename: String, item: ItemType, action: ActionType, longAction: LongActionType) { register(typename: typename) { _ in - return (item: item, action: action, longAction: longAction, parameters: [:]) + ( + item: item, + action, + longAction, + parameters: [:] + ) } } } @@ -232,7 +345,7 @@ enum ItemType: Decodable { case groupBar(items: [BarItemDefinition]) case nightShift() case dnd() - + private enum CodingKeys: String, CodingKey { case type case title @@ -249,7 +362,7 @@ enum ItemType: Decodable { case longUrl case items } - + enum ItemTypeRaw: String, Decodable { case staticButton case appleScriptTitledButton @@ -266,65 +379,64 @@ enum ItemType: Decodable { case nightShift case dnd } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let type = try container.decode(ItemTypeRaw.self, forKey: .type) switch type { - case .appleScriptTitledButton: let source = try container.decode(Source.self, forKey: .source) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 self = .appleScriptTitledButton(source: source, refreshInterval: interval) - + case .staticButton: let title = try container.decode(String.self, forKey: .title) self = .staticButton(title: title) - + case .timeButton: let template = try container.decodeIfPresent(String.self, forKey: .formatTemplate) ?? "HH:mm" self = .timeButton(formatTemplate: template) - + case .battery: self = .battery() - + case .dock: self = .dock() - + case .volume: self = .volume() - + case .brightness: let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 0.5 self = .brightness(refreshInterval: interval) - + case .weather: let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 let units = try container.decodeIfPresent(String.self, forKey: .units) ?? "metric" let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6" let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) ?? "text" self = .weather(interval: interval, units: units, api_key: api_key, icon_type: icon_type) - + case .currency: let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 600.0 let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB" let to = try container.decodeIfPresent(String.self, forKey: .to) ?? "USD" self = .currency(interval: interval, from: from, to: to) - + case .inputsource: self = .inputsource() - + case .music: let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 self = .music(interval: interval) - + case .groupBar: let items = try container.decode([BarItemDefinition].self, forKey: .items) self = .groupBar(items: items) - + case .nightShift: self = .nightShift() - + case .dnd: self = .dnd() } @@ -337,9 +449,9 @@ enum ActionType: Decodable { case keyPress(keycode: Int) case appleScript(source: SourceProtocol) case shellScript(executable: String, parameters: [String]) - case custom(closure: ()->()) + case custom(closure: () -> Void) case openUrl(url: String) - + private enum CodingKeys: String, CodingKey { case action case keycode @@ -348,7 +460,7 @@ enum ActionType: Decodable { case shellArguments case url } - + private enum ActionTypeRaw: String, Decodable { case hidKey case keyPress @@ -356,49 +468,48 @@ enum ActionType: Decodable { case shellScript case openUrl } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let type = try container.decodeIfPresent(ActionTypeRaw.self, forKey: .action) - + switch type { - case .some(.hidKey): - let keycode = try container.decode(Int32.self, forKey: .keycode) - self = .hidKey(keycode: keycode) - - case .some(.keyPress): - let keycode = try container.decode(Int.self, forKey: .keycode) - self = .keyPress(keycode: keycode) - - case .some(.appleScript): - let source = try container.decode(Source.self, forKey: .actionAppleScript) - self = .appleScript(source: source) - - case .some(.shellScript): - let executable = try container.decode(String.self, forKey: .executablePath) - let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? [] - self = .shellScript(executable: executable, parameters: parameters) - - case .some(.openUrl): - let url = try container.decode(String.self, forKey: .url) - self = .openUrl(url: url) - - case .none: - self = .none + case .some(.hidKey): + let keycode = try container.decode(Int32.self, forKey: .keycode) + self = .hidKey(keycode: keycode) + + case .some(.keyPress): + let keycode = try container.decode(Int.self, forKey: .keycode) + self = .keyPress(keycode: keycode) + + case .some(.appleScript): + let source = try container.decode(Source.self, forKey: .actionAppleScript) + self = .appleScript(source: source) + + case .some(.shellScript): + let executable = try container.decode(String.self, forKey: .executablePath) + let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? [] + self = .shellScript(executable: executable, parameters: parameters) + + case .some(.openUrl): + let url = try container.decode(String.self, forKey: .url) + self = .openUrl(url: url) + + case .none: + self = .none } } } - enum LongActionType: Decodable { case none case hidKey(keycode: Int32) case keyPress(keycode: Int) case appleScript(source: SourceProtocol) case shellScript(executable: String, parameters: [String]) - case custom(closure: ()->()) + case custom(closure: () -> Void) case openUrl(url: String) - + private enum CodingKeys: String, CodingKey { case longAction case longKeycode @@ -407,7 +518,7 @@ enum LongActionType: Decodable { case longShellArguments case longUrl } - + private enum LongActionTypeRaw: String, Decodable { case hidKey case keyPress @@ -415,52 +526,51 @@ enum LongActionType: Decodable { case shellScript case openUrl } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let longType = try container.decodeIfPresent(LongActionTypeRaw.self, forKey: .longAction) - + switch longType { - case .some(.hidKey): - let keycode = try container.decode(Int32.self, forKey: .longKeycode) - self = .hidKey(keycode: keycode) - - case .some(.keyPress): - let keycode = try container.decode(Int.self, forKey: .longKeycode) - self = .keyPress(keycode: keycode) - - case .some(.appleScript): - let source = try container.decode(Source.self, forKey: .longActionAppleScript) - self = .appleScript(source: source) - - case .some(.shellScript): - let executable = try container.decode(String.self, forKey: .longExecutablePath) - let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? [] - self = .shellScript(executable: executable, parameters: parameters) - - case .some(.openUrl): - let longUrl = try container.decode(String.self, forKey: .longUrl) - self = .openUrl(url: longUrl) - - case .none: - self = .none + case .some(.hidKey): + let keycode = try container.decode(Int32.self, forKey: .longKeycode) + self = .hidKey(keycode: keycode) + + case .some(.keyPress): + let keycode = try container.decode(Int.self, forKey: .longKeycode) + self = .keyPress(keycode: keycode) + + case .some(.appleScript): + let source = try container.decode(Source.self, forKey: .longActionAppleScript) + self = .appleScript(source: source) + + case .some(.shellScript): + let executable = try container.decode(String.self, forKey: .longExecutablePath) + let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? [] + self = .shellScript(executable: executable, parameters: parameters) + + case .some(.openUrl): + let longUrl = try container.decode(String.self, forKey: .longUrl) + self = .openUrl(url: longUrl) + + case .none: + self = .none } } } - enum GeneralParameter { case width(_: CGFloat) case image(source: SourceProtocol) case align(_: Align) case bordered(_: Bool) - case background(_:NSColor) - case title(_:String) + case background(_: NSColor) + case title(_: String) } struct GeneralParameters: Decodable { let parameters: [GeneralParameters.CodingKeys: GeneralParameter] - + enum CodingKeys: String, CodingKey { case width case image @@ -469,34 +579,34 @@ struct GeneralParameters: Decodable { case background case title } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) var result: [GeneralParameters.CodingKeys: GeneralParameter] = [:] - + if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) { result[.width] = .width(value) } - + if let imageSource = try container.decodeIfPresent(Source.self, forKey: .image) { result[.image] = .image(source: imageSource) } - + let align = try container.decodeIfPresent(Align.self, forKey: .align) ?? .center result[.align] = .align(align) - + if let borderedFlag = try container.decodeIfPresent(Bool.self, forKey: .bordered) { result[.bordered] = .bordered(borderedFlag) } - + if let backgroundColor = try container.decodeIfPresent(String.self, forKey: .background)?.hexColor { result[.background] = .background(backgroundColor) } - + if let title = try container.decodeIfPresent(String.self, forKey: .title) { result[.title] = .title(title) } - + parameters = result } } @@ -512,35 +622,35 @@ struct Source: Decodable, SourceProtocol { let filePath: String? let base64: String? let inline: String? - + private enum CodingKeys: String, CodingKey { case filePath case base64 case inline } - + var data: Data? { return base64?.base64Data ?? inline?.data(using: .utf8) ?? filePath?.fileData } - + var string: String? { return inline ?? filePath?.fileString } - + var image: NSImage? { return data?.image } - + var appleScript: NSAppleScript? { - return filePath?.fileURL.appleScript ?? self.string?.appleScript + return filePath?.fileURL.appleScript ?? string?.appleScript } - + private init(filePath: String?, base64: String?, inline: String?) { self.filePath = filePath self.base64 = base64 self.inline = inline } - + init(filePath: String) { self.init(filePath: filePath, base64: nil, inline: nil) } @@ -550,15 +660,15 @@ extension NSImage: SourceProtocol { var data: Data? { return nil } - + var string: String? { return nil } - + var image: NSImage? { return self } - + var appleScript: NSAppleScript? { return nil } @@ -568,23 +678,22 @@ extension String { var base64Data: Data? { return Data(base64Encoded: self) } - + var fileData: Data? { return try? Data(contentsOf: URL(fileURLWithPath: self)) } - + var fileString: String? { var encoding: String.Encoding = .utf8 return try? String(contentsOfFile: self, usedEncoding: &encoding) } - } extension Data { var utf8string: String? { return String(data: self, encoding: .utf8) } - + var image: NSImage? { return NSImage(data: self)?.resize(maxSize: NSSize(width: 24, height: 24)) } @@ -600,7 +709,7 @@ extension String { var fileURL: URL { return URL(fileURLWithPath: self) } - + var appleScript: NSAppleScript? { return NSAppleScript(source: self) } @@ -608,7 +717,7 @@ extension String { extension URL { var appleScript: NSAppleScript? { - guard FileManager.default.fileExists(atPath: self.path) else { return nil } + guard FileManager.default.fileExists(atPath: path) else { return nil } return NSAppleScript(contentsOf: self, error: nil) } } diff --git a/MTMR/KeyPress.swift b/MTMR/KeyPress.swift index 54766d9..1f68768 100644 --- a/MTMR/KeyPress.swift +++ b/MTMR/KeyPress.swift @@ -18,7 +18,7 @@ struct GenericKeyPress: KeyPress { } extension KeyPress { - func send () { + func send() { let src = CGEventSource(stateID: .hidSystemState) let keyDown = CGEvent(keyboardEventSource: src, virtualKey: keyCode, keyDown: true) let keyUp = CGEvent(keyboardEventSource: src, virtualKey: keyCode, keyDown: false) diff --git a/MTMR/ScrollViewItem.swift b/MTMR/ScrollViewItem.swift index d9ff78e..325e77d 100644 --- a/MTMR/ScrollViewItem.swift +++ b/MTMR/ScrollViewItem.swift @@ -3,7 +3,7 @@ import Foundation class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { var twofingersPrev: CGFloat = 0.0 var threefingersPrev: CGFloat = 0.0 - + init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem]) { super.init(identifier: identifier) let views = items.compactMap { $0.view } @@ -12,31 +12,31 @@ class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { stackView.orientation = .horizontal let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize)) scrollView.documentView = stackView - self.view = scrollView - + view = scrollView + let twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:))) twofingers.allowedTouchTypes = .direct twofingers.numberOfTouchesRequired = 2 - self.view.addGestureRecognizer(twofingers) - + view.addGestureRecognizer(twofingers) + let threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:))) threefingers.allowedTouchTypes = .direct threefingers.numberOfTouchesRequired = 3 - self.view.addGestureRecognizer(threefingers) + view.addGestureRecognizer(threefingers) } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + @objc func twofingersHandler(_ sender: NSGestureRecognizer?) { // Volume let position = (sender?.location(in: sender?.view).x)! - + switch sender!.state { case .began: twofingersPrev = position case .changed: - if (((position-twofingersPrev) > 10) || ((twofingersPrev-position) > 10)) { + if ((position - twofingersPrev) > 10) || ((twofingersPrev - position) > 10) { if position > twofingersPrev { HIDPostAuxKey(NX_KEYTYPE_SOUND_UP) } else if position < twofingersPrev { @@ -50,15 +50,15 @@ class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { break } } - + @objc func threefingersHandler(_ sender: NSGestureRecognizer?) { // Brightness let position = (sender?.location(in: sender?.view).x)! - + switch sender!.state { case .began: threefingersPrev = position case .changed: - if (((position-threefingersPrev) > 15) || ((threefingersPrev-position) > 15)) { + if ((position - threefingersPrev) > 15) || ((threefingersPrev - position) > 15) { if position > threefingersPrev { GenericKeyPress(keyCode: CGKeyCode(144)).send() } else if position < threefingersPrev { diff --git a/MTMR/SupportHelpers.swift b/MTMR/SupportHelpers.swift index a0a84f6..5ff7110 100644 --- a/MTMR/SupportHelpers.swift +++ b/MTMR/SupportHelpers.swift @@ -13,12 +13,12 @@ extension String { func trim() -> String { return self.trimmingCharacters(in: NSCharacterSet.whitespaces) } - + func stripComments() -> String { // ((\s|,)\/\*[\s\S]*?\*\/)|(( |, ")\/\/.*) return self.replacingOccurrences(of: "((\\s|,)\\/\\*[\\s\\S]*?\\*\\/)|(( |, \\\")\\/\\/.*)", with: "", options: .regularExpression) } - + var hexColor: NSColor? { let hex = trimmingCharacters(in: CharacterSet.alphanumerics.inverted) var int = UInt32() @@ -45,7 +45,7 @@ extension NSImage { let imageHeight = Float(self.size.height) let maxWidth = Float(maxSize.width) let maxHeight = Float(maxSize.height) - + // Get ratio (landscape or portrait) if (imageWidth > imageHeight) { // Landscape @@ -55,27 +55,27 @@ extension NSImage { // Portrait ratio = maxHeight / imageHeight; } - + // Calculate new size based on the ratio let newWidth = imageWidth * ratio let newHeight = imageHeight * ratio - + // Create a new NSSize object with the newly calculated size let newSize:NSSize = NSSize(width: Int(newWidth), height: Int(newHeight)) - + // Cast the NSImage to a CGImage var imageRect:NSRect = NSMakeRect(0, 0, self.size.width, self.size.height) let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil) - + // Create NSImage from the CGImage using the new size let imageWithNewSize = NSImage(cgImage: imageRef!, size: newSize) - + // Return the new image return imageWithNewSize } - + func rotateByDegreess(degrees:CGFloat) -> NSImage { - + var imageBounds = NSZeroRect ; imageBounds.size = self.size let pathBounds = NSBezierPath(rect: imageBounds) var transform = NSAffineTransform() @@ -83,11 +83,11 @@ extension NSImage { pathBounds.transform(using: transform as AffineTransform) let rotatedBounds:NSRect = NSMakeRect(NSZeroPoint.x, NSZeroPoint.y , self.size.width, self.size.height ) let rotatedImage = NSImage(size: rotatedBounds.size) - + //Center the image within the rotated bounds imageBounds.origin.x = NSMidX(rotatedBounds) - (NSWidth(imageBounds) / 2) imageBounds.origin.y = NSMidY(rotatedBounds) - (NSHeight(imageBounds) / 2) - + // Start a new transform transform = NSAffineTransform() // Move coordinate system to the center (since we want to rotate around the center) @@ -100,7 +100,7 @@ extension NSImage { transform.concat() self.draw(in: imageBounds, from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0) rotatedImage.unlockFocus() - + return rotatedImage } diff --git a/MTMR/SupportNSTouchBar.swift b/MTMR/SupportNSTouchBar.swift index 506e0bd..75c83ed 100644 --- a/MTMR/SupportNSTouchBar.swift +++ b/MTMR/SupportNSTouchBar.swift @@ -6,7 +6,7 @@ // Copyright © 2018 Anton Palgunov. All rights reserved. // -func presentSystemModal(_ touchBar: NSTouchBar!, systemTrayItemIdentifier identifier: NSTouchBarItem.Identifier!) -> Void { +func presentSystemModal(_ touchBar: NSTouchBar!, systemTrayItemIdentifier identifier: NSTouchBarItem.Identifier!) { if #available(OSX 10.14, *) { NSTouchBar.presentSystemModalTouchBar(touchBar, systemTrayItemIdentifier: identifier) } else { @@ -14,7 +14,7 @@ func presentSystemModal(_ touchBar: NSTouchBar!, systemTrayItemIdentifier identi } } -func presentSystemModal(_ touchBar: NSTouchBar!, placement: Int64, systemTrayItemIdentifier identifier: NSTouchBarItem.Identifier!) -> Void { +func presentSystemModal(_ touchBar: NSTouchBar!, placement: Int64, systemTrayItemIdentifier identifier: NSTouchBarItem.Identifier!) { if #available(OSX 10.14, *) { NSTouchBar.presentSystemModalTouchBar(touchBar, placement: placement, systemTrayItemIdentifier: identifier) } else { @@ -22,7 +22,7 @@ func presentSystemModal(_ touchBar: NSTouchBar!, placement: Int64, systemTrayIte } } -func minimizeSystemModal(_ touchBar: NSTouchBar!) -> Void { +func minimizeSystemModal(_ touchBar: NSTouchBar!) { if #available(OSX 10.14, *) { NSTouchBar.minimizeSystemModalTouchBar(touchBar) } else { diff --git a/MTMR/Widgets/AppScrubberTouchBarItem.swift b/MTMR/Widgets/AppScrubberTouchBarItem.swift index 7d44dfc..8d15966 100644 --- a/MTMR/Widgets/AppScrubberTouchBarItem.swift +++ b/MTMR/Widgets/AppScrubberTouchBarItem.swift @@ -8,11 +8,10 @@ import Cocoa class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrubberDataSource { - private var scrubber: NSScrubber! - + private let hf: HapticFeedback = HapticFeedback() - + private var timer: Timer! private var ticks: Int = 0 private let minTicks: Int = 5 @@ -21,24 +20,22 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub private var persistentAppIdentifiers: [String] = [] private var runningAppsIdentifiers: [String] = [] - + private var frontmostApplicationIdentifier: String? { - get { - guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil } - return frontmostId - } + guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil } + return frontmostId } - + private var applications: [DockItem] = [] - + override init(identifier: NSTouchBarItem.Identifier) { super.init(identifier: identifier) - - scrubber = NSScrubber(); + + scrubber = NSScrubber() scrubber.delegate = self scrubber.dataSource = self scrubber.mode = .free // .fixed - let layout = NSScrubberFlowLayout(); + let layout = NSScrubberFlowLayout() layout.itemSize = NSSize(width: 36, height: 32) layout.itemSpacing = 2 scrubber.scrubberLayout = layout @@ -46,35 +43,35 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub scrubber.showsAdditionalContentIndicators = true view = scrubber - + scrubber.register(NSScrubberImageItemView.self, forItemIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ScrubberApplicationsItemReuseIdentifier")) - + NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didLaunchApplicationNotification, object: nil) NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didTerminateApplicationNotification, object: nil) NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didActivateApplicationNotification, object: nil) - + if let persistent = UserDefaults.standard.stringArray(forKey: "com.toxblh.mtmr.dock.persistent") { - self.persistentAppIdentifiers = persistent + persistentAppIdentifiers = persistent } - + updateRunningApplication() } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - - @objc func activeApplicationChanged(n: Notification) { + + @objc func activeApplicationChanged(n _: Notification) { updateRunningApplication() } - - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + + override func observeValue(forKeyPath _: String?, of _: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) { updateRunningApplication() } - + func updateRunningApplication() { let newApplications = launchedApplications() - + let index = newApplications.index { $0.bundleIdentifier == frontmostApplicationIdentifier } @@ -82,30 +79,30 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub applications = newApplications applications += getDockPersistentAppsList() scrubber.reloadData() - + scrubber.selectedIndex = index ?? 0 } - - public func numberOfItems(for scrubber: NSScrubber) -> Int { + + public func numberOfItems(for _: NSScrubber) -> Int { return applications.count } - + public func scrubber(_ scrubber: NSScrubber, viewForItemAt index: Int) -> NSScrubberItemView { let item = scrubber.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ScrubberApplicationsItemReuseIdentifier"), owner: self) as? NSScrubberImageItemView ?? NSScrubberImageItemView() item.imageView.imageScaling = .scaleProportionallyDown - + let app = applications[index] - + if let icon = app.icon { item.image = icon item.image.size = NSSize(width: 26, height: 26) } item.removeFromSuperview() - + let dotView = NSView(frame: .zero) dotView.wantsLayer = true - if self.runningAppsIdentifiers.contains(app.bundleIdentifier!) { + if runningAppsIdentifiers.contains(app.bundleIdentifier!) { dotView.layer?.backgroundColor = NSColor.white.cgColor } else { dotView.layer?.backgroundColor = NSColor.black.cgColor @@ -117,48 +114,48 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub return item } - - public func didBeginInteracting(with scrubber: NSScrubber) { + + public func didBeginInteracting(with _: NSScrubber) { stopTimer() - self.ticks = 0 - self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(checkTimer), userInfo: nil, repeats: true) + ticks = 0 + timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(checkTimer), userInfo: nil, repeats: true) } - + @objc private func checkTimer() { - self.ticks += 1 - - if (self.ticks == minTicks) { + ticks += 1 + + if ticks == minTicks { hf.tap(strong: 2) } - - if (self.ticks > maxTicks) { + + if ticks > maxTicks { stopTimer() hf.tap(strong: 6) } } - + private func stopTimer() { - self.timer?.invalidate() - self.timer = nil - self.lastSelected = 0 + timer?.invalidate() + timer = nil + lastSelected = 0 } - - public func didCancelInteracting(with scrubber: NSScrubber) { + + public func didCancelInteracting(with _: NSScrubber) { stopTimer() } - + public func didFinishInteracting(with scrubber: NSScrubber) { stopTimer() - - if (ticks == 0) { + + if ticks == 0 { return } - - if (self.ticks >= minTicks && scrubber.selectedIndex > 0) { - self.longPress(selected: scrubber.selectedIndex) + + if ticks >= minTicks && scrubber.selectedIndex > 0 { + longPress(selected: scrubber.selectedIndex) return } - + let bundleIdentifier = applications[scrubber.selectedIndex].bundleIdentifier if bundleIdentifier!.contains("file://") { NSWorkspace.shared.openFile(bundleIdentifier!.replacingOccurrences(of: "file://", with: "")) @@ -167,16 +164,16 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub hf.tap(strong: 6) } updateRunningApplication() - + // 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 } - + private func longPress(selected: Int) { let bundleIdentifier = applications[selected].bundleIdentifier - - if (self.ticks > maxTicks) { + + if ticks > maxTicks { if let processIdentifier = applications[selected].pid { if !(NSRunningApplication(processIdentifier: processIdentifier)?.terminate())! { NSRunningApplication(processIdentifier: processIdentifier)?.forceTerminate() @@ -185,34 +182,34 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub } else { hf.tap(strong: 6) if let index = self.persistentAppIdentifiers.index(of: bundleIdentifier!) { - self.persistentAppIdentifiers.remove(at: index) + persistentAppIdentifiers.remove(at: index) } else { - self.persistentAppIdentifiers.append(bundleIdentifier!) + persistentAppIdentifiers.append(bundleIdentifier!) } - - UserDefaults.standard.set(self.persistentAppIdentifiers, forKey: "com.toxblh.mtmr.dock.persistent") + + UserDefaults.standard.set(persistentAppIdentifiers, forKey: "com.toxblh.mtmr.dock.persistent") UserDefaults.standard.synchronize() } - self.ticks = 0 + ticks = 0 updateRunningApplication() } private func launchedApplications() -> [DockItem] { - self.runningAppsIdentifiers = [] + runningAppsIdentifiers = [] var returnable: [DockItem] = [] for app in NSWorkspace.shared.runningApplications { guard app.activationPolicy == NSApplication.ActivationPolicy.regular else { continue } guard let bundleIdentifier = app.bundleIdentifier else { continue } - - self.runningAppsIdentifiers.append(bundleIdentifier) - + + runningAppsIdentifiers.append(bundleIdentifier) + let dockItem = DockItem(bundleIdentifier: bundleIdentifier, icon: getIcon(forBundleIdentifier: bundleIdentifier), pid: app.processIdentifier) returnable.append(dockItem) } return returnable } - public func getIcon(forBundleIdentifier bundleIdentifier: String? = nil, orPath path: String? = nil, orType type: String? = nil) -> NSImage { + public func getIcon(forBundleIdentifier bundleIdentifier: String? = nil, orPath path: String? = nil, orType _: String? = nil) -> NSImage { if bundleIdentifier != nil { if let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: bundleIdentifier!) { return NSWorkspace.shared.icon(forFile: appPath) @@ -226,13 +223,12 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub let genericIcon = NSImage(contentsOfFile: "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericDocumentIcon.icns") return genericIcon ?? NSImage(size: .zero) } - public func getDockPersistentAppsList() -> [DockItem] { var returnable: [DockItem] = [] - + for bundleIdentifier in persistentAppIdentifiers { - if !self.runningAppsIdentifiers.contains(bundleIdentifier) { + if !runningAppsIdentifiers.contains(bundleIdentifier) { let dockItem = DockItem(bundleIdentifier: bundleIdentifier, icon: getIcon(forBundleIdentifier: bundleIdentifier)) returnable.append(dockItem) } diff --git a/MTMR/Widgets/BatteryBarItem.swift b/MTMR/Widgets/BatteryBarItem.swift index e1dd246..7eb686b 100644 --- a/MTMR/Widgets/BatteryBarItem.swift +++ b/MTMR/Widgets/BatteryBarItem.swift @@ -6,29 +6,29 @@ // Copyright © 2018 Anton Palgunov. All rights reserved. // -import IOKit.ps import Foundation +import IOKit.ps class BatteryBarItem: CustomButtonTouchBarItem { private let batteryInfo = BatteryInfo() - + init(identifier: NSTouchBarItem.Identifier) { super.init(identifier: identifier, title: " ") - + batteryInfo.start { [weak self] in self?.refresh() } - self.refresh() + refresh() } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func refresh() { - self.attributedTitle = self.batteryInfo.formattedInfo() + attributedTitle = batteryInfo.formattedInfo() } - + deinit { batteryInfo.stop() } @@ -42,85 +42,85 @@ class BatteryInfo: NSObject { var isCharging: Bool = false var ACPower: String = "" var timeRemaining: String = "" - var notifyBlock: ()->() = {} - var loop:CFRunLoopSource? - - func start(notifyBlock: @escaping ()->()) { + var notifyBlock: () -> Void = {} + var loop: CFRunLoopSource? + + func start(notifyBlock: @escaping () -> Void) { self.notifyBlock = notifyBlock let opaque = Unmanaged.passRetained(self).toOpaque() let context = UnsafeMutableRawPointer(opaque) - loop = IOPSNotificationCreateRunLoopSource({ (context) in + loop = IOPSNotificationCreateRunLoopSource({ context in guard let ctx = context else { return } - + let watcher = Unmanaged.fromOpaque(ctx).takeUnretainedValue() watcher.notifyBlock() }, context).takeRetainedValue() as CFRunLoopSource CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode) } - + func stop() { - self.notifyBlock = {} + notifyBlock = {} guard let loop = self.loop else { return } CFRunLoopRemoveSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode) self.loop = nil } - + func getPSInfo() { let psInfo = IOPSCopyPowerSourcesInfo().takeRetainedValue() let psList = IOPSCopyPowerSourcesList(psInfo).takeRetainedValue() as [CFTypeRef] - + for ps in psList { if let psDesc = IOPSGetPowerSourceDescription(psInfo, ps).takeUnretainedValue() as? [String: Any] { let current = psDesc[kIOPSCurrentCapacityKey] - if (current != nil) { + if current != nil { self.current = current as! Int } - + let timeToEmpty = psDesc[kIOPSTimeToEmptyKey] - if (timeToEmpty != nil) { + if timeToEmpty != nil { self.timeToEmpty = timeToEmpty as! Int } - + let timeToFull = psDesc[kIOPSTimeToFullChargeKey] - if (timeToFull != nil) { + if timeToFull != nil { self.timeToFull = timeToFull as! Int } - + let isCharged = psDesc[kIOPSIsChargedKey] - if (isCharged != nil) { + if isCharged != nil { self.isCharged = isCharged as! Bool } - + let isCharging = psDesc[kIOPSIsChargingKey] - if (isCharging != nil) { + if isCharging != nil { self.isCharging = isCharging as! Bool } - + let ACPower = psDesc[kIOPSPowerSourceStateKey] - if (ACPower != nil) { + if ACPower != nil { self.ACPower = ACPower as! String } } } } - + func getFormattedTime(time: Int) -> String { - if (time > 0) { + if time > 0 { let timeFormatted = NSString(format: " %d:%02d", time / 60, time % 60) as String return timeFormatted } - + return "" } - + public func formattedInfo() -> NSAttributedString { var title = "" - self.getPSInfo() - + getPSInfo() + if ACPower == "AC Power" { if current < 100 { title += "⚡️" @@ -129,19 +129,18 @@ class BatteryInfo: NSObject { } else { timeRemaining = getFormattedTime(time: timeToEmpty) } - + title += String(current) + "%" - + var color = NSColor.white if current <= 10 && ACPower != "AC Power" { color = NSColor.red } - + let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: NSFont.systemFont(ofSize: 15), .baselineOffset: 1]) let newTitleSecond = NSMutableAttributedString(string: timeRemaining as String, attributes: [NSAttributedString.Key.foregroundColor: color, NSAttributedString.Key.font: NSFont.systemFont(ofSize: 8, weight: .regular), NSAttributedString.Key.baselineOffset: 7]) newTitle.append(newTitleSecond) newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count)) return newTitle } - } diff --git a/MTMR/Widgets/BrightnessViewController.swift b/MTMR/Widgets/BrightnessViewController.swift index bd036f5..ac83201 100644 --- a/MTMR/Widgets/BrightnessViewController.swift +++ b/MTMR/Widgets/BrightnessViewController.swift @@ -1,54 +1,54 @@ -import Cocoa import AppKit import AVFoundation +import Cocoa import CoreAudio class BrightnessViewController: NSCustomTouchBarItem { private(set) var sliderItem: CustomSlider! - + init(identifier: NSTouchBarItem.Identifier, refreshInterval: Double, image: NSImage? = nil) { super.init(identifier: identifier) - - if (image == nil) { + + if image == nil { sliderItem = CustomSlider() } else { sliderItem = CustomSlider(knob: image!) } sliderItem.target = self - sliderItem.action = #selector(BrightnessViewController.sliderValueChanged(_:)) + sliderItem.action = #selector(BrightnessViewController.sliderValueChanged(_:)) sliderItem.minValue = 0.0 sliderItem.maxValue = 100.0 sliderItem.floatValue = getBrightness() * 100 - - self.view = sliderItem - + + view = sliderItem + let timer = Timer.scheduledTimer(timeInterval: refreshInterval, target: self, selector: #selector(BrightnessViewController.updateBrightnessSlider), userInfo: nil, repeats: true) RunLoop.current.add(timer, forMode: RunLoop.Mode.common) } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } deinit { sliderItem.unbind(NSBindingName.value) } - + @objc func updateBrightnessSlider() { DispatchQueue.main.async { self.sliderItem.floatValue = self.getBrightness() * 100 } } - + @objc func sliderValueChanged(_ sender: Any) { if let sliderItem = sender as? NSSlider { - setBrightness(level: Float32(sliderItem.intValue)/100.0) + setBrightness(level: Float32(sliderItem.intValue) / 100.0) } } - + private func getBrightness() -> Float32 { if #available(OSX 10.13, *) { - return Float32(CoreDisplay_Display_GetUserBrightness(0)); + return Float32(CoreDisplay_Display_GetUserBrightness(0)) } else { var level: Float32 = 0.5 let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect")) @@ -57,16 +57,15 @@ class BrightnessViewController: NSCustomTouchBarItem { return level } } - + private func setBrightness(level: Float) { if #available(OSX 10.13, *) { - CoreDisplay_Display_SetUserBrightness(0, Double(level)); + CoreDisplay_Display_SetUserBrightness(0, Double(level)) } else { let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect")) IODisplaySetFloatParameter(service, 1, kIODisplayBrightnessKey as CFString, level) IOObjectRelease(service) } - } } diff --git a/MTMR/Widgets/CurrencyBarItem.swift b/MTMR/Widgets/CurrencyBarItem.swift index f7d05a0..1733a0a 100644 --- a/MTMR/Widgets/CurrencyBarItem.swift +++ b/MTMR/Widgets/CurrencyBarItem.swift @@ -45,7 +45,7 @@ class CurrencyBarItem: CustomButtonTouchBarItem { if let prefix = currencies[from] { self.prefix = prefix } else { - self.prefix = from + prefix = from } super.init(identifier: identifier, title: "⏳") @@ -59,21 +59,21 @@ class CurrencyBarItem: CustomButtonTouchBarItem { updateCurrency() } - required init?(coder: NSCoder) { + 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 + let task = URLSession.shared.dataTask(with: urlRequest) { data, _, error in if error == nil { do { - let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject] + let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject] var value: Float32! - if let data_array = json["data"] as? [String : AnyObject] { - if let rates = data_array["rates"] as? [String : AnyObject] { + 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 = Float32(item) } @@ -103,13 +103,13 @@ class CurrencyBarItem: CustomButtonTouchBarItem { color = NSColor.red } } - self.oldValue = value + oldValue = value - let title = String(format: "%@%.2f", self.prefix, value) + let title = String(format: "%@%.2f", prefix, value) - let regularFont = self.attributedTitle.attribute(.font, at: 0, effectiveRange: nil) as? NSFont ?? NSFont.systemFont(ofSize: 15) + let regularFont = attributedTitle.attribute(.font, at: 0, effectiveRange: nil) as? NSFont ?? NSFont.systemFont(ofSize: 15) let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: regularFont]) newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count)) - self.attributedTitle = newTitle + attributedTitle = newTitle } } diff --git a/MTMR/Widgets/DnDBarItem.swift b/MTMR/Widgets/DnDBarItem.swift index 1b6f2af..18344ca 100644 --- a/MTMR/Widgets/DnDBarItem.swift +++ b/MTMR/Widgets/DnDBarItem.swift @@ -8,49 +8,49 @@ import Foundation -class DnDBarItem : CustomButtonTouchBarItem { +class DnDBarItem: CustomButtonTouchBarItem { private var timer: Timer! - + init(identifier: NSTouchBarItem.Identifier) { super.init(identifier: identifier, title: "") - self.isBordered = false - self.setWidth(value: 32) - - self.tapClosure = { [weak self] in self?.DnDToggle() } - + isBordered = false + setWidth(value: 32) + + tapClosure = { [weak self] in self?.DnDToggle() } + timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true) - - self.refresh() + + refresh() } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func DnDToggle() { DoNotDisturb.isEnabled = !DoNotDisturb.isEnabled refresh() } - + @objc func refresh() { - self.image = DoNotDisturb.isEnabled ? #imageLiteral(resourceName: "dnd-on") : #imageLiteral(resourceName: "dnd-off") + image = DoNotDisturb.isEnabled ? #imageLiteral(resourceName: "dnd-on") : #imageLiteral(resourceName: "dnd-off") } } public struct DoNotDisturb { private static let appId = "com.apple.notificationcenterui" as CFString private static let dndPref = "com.apple.notificationcenterui.dndprefs_changed" - + private static func set(_ key: String, value: CFPropertyList?) { CFPreferencesSetValue(key as CFString, value, appId, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) } - + private static func commitChanges() { CFPreferencesSynchronize(appId, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) DistributedNotificationCenter.default().postNotificationName(NSNotification.Name(dndPref), object: nil, userInfo: nil, deliverImmediately: true) NSRunningApplication.runningApplications(withBundleIdentifier: appId as String).first?.terminate() } - + private static func enable() { set("dndStart", value: nil) set("dndEnd", value: nil) @@ -58,7 +58,7 @@ public struct DoNotDisturb { set("doNotDisturbDate", value: Date() as CFPropertyList) commitChanges() } - + private static func disable() { set("dndStart", value: nil) set("dndEnd", value: nil) @@ -66,8 +66,8 @@ public struct DoNotDisturb { set("doNotDisturbDate", value: nil) commitChanges() } - - static var isEnabled:Bool { + + static var isEnabled: Bool { get { return CFPreferencesGetAppBooleanValue("doNotDisturb" as CFString, appId, nil) } diff --git a/MTMR/Widgets/GroupBarItem.swift b/MTMR/Widgets/GroupBarItem.swift index cc5fd49..e307833 100644 --- a/MTMR/Widgets/GroupBarItem.swift +++ b/MTMR/Widgets/GroupBarItem.swift @@ -8,9 +8,8 @@ import Cocoa class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate { - var jsonItems: [BarItemDefinition] - + var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:] var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:] var leftIdentifiers: [NSTouchBarItem.Identifier] = [] @@ -19,62 +18,60 @@ class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate { var rightIdentifiers: [NSTouchBarItem.Identifier] = [] var scrollArea: NSCustomTouchBarItem? var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) - + init(identifier: NSTouchBarItem.Identifier, items: [BarItemDefinition]) { jsonItems = items super.init(identifier: identifier) - self.popoverTouchBar.delegate = self + popoverTouchBar.delegate = self } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - - deinit { - - } - - @objc override func showPopover(_ sender: Any?) { - self.itemDefinitions = [:] - self.items = [:] - self.leftIdentifiers = [] - self.centerItems = [] - self.rightIdentifiers = [] - - self.loadItemDefinitions(jsonItems: jsonItems) - self.createItems() - + + deinit {} + + @objc override func showPopover(_: Any?) { + itemDefinitions = [:] + items = [:] + leftIdentifiers = [] + centerItems = [] + rightIdentifiers = [] + + loadItemDefinitions(jsonItems: jsonItems) + createItems() + centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in - return items[identifier] + items[identifier] }) - - self.centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) - self.scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems) - + + centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) + scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems) + TouchBarController.shared.touchBar.delegate = self TouchBarController.shared.touchBar.defaultItemIdentifiers = [] - TouchBarController.shared.touchBar.defaultItemIdentifiers = self.leftIdentifiers + [centerScrollArea] + self.rightIdentifiers - + TouchBarController.shared.touchBar.defaultItemIdentifiers = leftIdentifiers + [centerScrollArea] + rightIdentifiers + if TouchBarController.shared.showControlStripState { presentSystemModal(TouchBarController.shared.touchBar, systemTrayItemIdentifier: .controlStripItem) } else { presentSystemModal(TouchBarController.shared.touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem) } } - - func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? { + + func touchBar(_: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? { if identifier == centerScrollArea { - return self.scrollArea + return scrollArea } - + guard let item = self.items[identifier], let definition = self.itemDefinitions[identifier], definition.align != .center else { - return nil + return nil } return item } - + func loadItemDefinitions(jsonItems: [BarItemDefinition]) { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "HH-mm-ss" @@ -94,10 +91,10 @@ class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate { } } } - + func createItems() { - for (identifier, definition) in self.itemDefinitions { - self.items[identifier] = TouchBarController.shared.createItem(forIdentifier: identifier, definition: definition) + for (identifier, definition) in itemDefinitions { + items[identifier] = TouchBarController.shared.createItem(forIdentifier: identifier, definition: definition) } } } diff --git a/MTMR/Widgets/InputSourceBarItem.swift b/MTMR/Widgets/InputSourceBarItem.swift index e543303..6e8b15b 100644 --- a/MTMR/Widgets/InputSourceBarItem.swift +++ b/MTMR/Widgets/InputSourceBarItem.swift @@ -9,33 +9,32 @@ import Cocoa class InputSourceBarItem: CustomButtonTouchBarItem { - fileprivate var notificationCenter: CFNotificationCenter let buttonSize = NSSize(width: 21, height: 21) init(identifier: NSTouchBarItem.Identifier) { - notificationCenter = CFNotificationCenterGetDistributedCenter(); + notificationCenter = CFNotificationCenterGetDistributedCenter() super.init(identifier: identifier, title: "⏳") - observeIputSourceChangedNotification(); + observeIputSourceChangedNotification() textInputSourceDidChange() - self.tapClosure = { [weak self] in + tapClosure = { [weak self] in self?.switchInputSource() } } - required init?(coder: NSCoder) { + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + deinit { - CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())); + CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())) } - + @objc public func textInputSourceDidChange() { let currentSource = TISCopyCurrentKeyboardInputSource().takeUnretainedValue() - var iconImage: NSImage? = nil + var iconImage: NSImage? if let imageURL = currentSource.iconImageURL, let image = NSImage(contentsOf: imageURL) { @@ -46,10 +45,10 @@ class InputSourceBarItem: CustomButtonTouchBarItem { if let iconImage = iconImage { iconImage.size = buttonSize - self.image = iconImage - self.title = "" + image = iconImage + title = "" } else { - self.title = currentSource.name + title = currentSource.name } } @@ -65,15 +64,15 @@ class InputSourceBarItem: CustomButtonTouchBarItem { }) for item in inputSources { - if (item.id != currentSource.id) { + if item.id != currentSource.id { TISSelectInputSource(item) break } } } - @objc public func observeIputSourceChangedNotification(){ - let callback: CFNotificationCallback = { center, observer, name, object, info in + @objc public func observeIputSourceChangedNotification() { + let callback: CFNotificationCallback = { _, observer, _, _, _ in let mySelf = Unmanaged.fromOpaque(observer!).takeUnretainedValue() mySelf.textInputSourceDidChange() } @@ -96,7 +95,7 @@ extension TISInputSource { private func getProperty(_ key: CFString) -> AnyObject? { let cfType = TISGetInputSourceProperty(self, key) - if (cfType != nil) { + if cfType != nil { return Unmanaged.fromOpaque(cfType!).takeUnretainedValue() } else { return nil @@ -131,4 +130,3 @@ extension TISInputSource { return OpaquePointer(TISGetInputSourceProperty(self, kTISPropertyIconRef)) as IconRef? } } - diff --git a/MTMR/Widgets/MusicBarItem.swift b/MTMR/Widgets/MusicBarItem.swift index d17130e..c6c1cab 100644 --- a/MTMR/Widgets/MusicBarItem.swift +++ b/MTMR/Widgets/MusicBarItem.swift @@ -14,57 +14,57 @@ class MusicBarItem: CustomButtonTouchBarItem { private var songTitle: String? private var timer: Timer? let buttonSize = NSSize(width: 21, height: 21) - + let playerBundleIdentifiers = [ "com.apple.iTunes", "com.spotify.client", "com.coppertino.Vox", "com.google.Chrome", - "com.apple.Safari" + "com.apple.Safari", ] - + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval) { self.interval = interval - + super.init(identifier: identifier, title: "⏳") - self.isBordered = false - - self.tapClosure = { [weak self] in self?.playPause() } - self.longTapClosure = { [weak self] in self?.nextTrack() } - - self.refreshAndSchedule() + isBordered = false + + tapClosure = { [weak self] in self?.playPause() } + longTapClosure = { [weak self] in self?.nextTrack() } + + refreshAndSchedule() } - - @objc func marquee(){ - let str = self.title - if (str.count > 10) { + + @objc func marquee() { + let str = title + if str.count > 10 { let indexFirst = str.index(str.startIndex, offsetBy: 0) let indexSecond = str.index(str.startIndex, offsetBy: 1) - self.title = String(str.suffix(from: indexSecond)) + String(str[indexFirst]) + title = String(str.suffix(from: indexSecond)) + String(str[indexFirst]) } } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + @objc func playPause() { for ident in playerBundleIdentifiers { if let musicPlayer = SBApplication(bundleIdentifier: ident) { - if (musicPlayer.isRunning) { - if (musicPlayer.className == "SpotifyApplication") { + if musicPlayer.isRunning { + if musicPlayer.className == "SpotifyApplication" { let mp = (musicPlayer as SpotifyApplication) mp.playpause!() return - } else if (musicPlayer.className == "ITunesApplication") { + } else if musicPlayer.className == "ITunesApplication" { let mp = (musicPlayer as iTunesApplication) mp.playpause!() return - } else if (musicPlayer.className == "VOXApplication") { + } else if musicPlayer.className == "VOXApplication" { let mp = (musicPlayer as VoxApplication) mp.playpause!() return - } else if (musicPlayer.className == "SafariApplication") { + } else if musicPlayer.className == "SafariApplication" { // You must enable the 'Allow JavaScript from Apple Events' option in Safari's Develop menu to use 'do JavaScript'. let safariApplication = musicPlayer as SafariApplication let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow }) @@ -74,7 +74,7 @@ class MusicBarItem: CustomButtonTouchBarItem { if (tab.URL?.starts(with: "https://music.yandex.ru"))! { _ = safariApplication.doJavaScript!("document.getElementsByClassName('player-controls__btn_play')[0].click()", in: tab) return - } else if ((tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))!) { + } else if (tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))! { _ = safariApplication.doJavaScript!("document.getElementsByClassName('audio_page_player_play')[0].click()", in: tab) return } else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! { @@ -108,27 +108,27 @@ class MusicBarItem: CustomButtonTouchBarItem { } } } - + @objc func nextTrack() { for ident in playerBundleIdentifiers { if let musicPlayer = SBApplication(bundleIdentifier: ident) { - if (musicPlayer.isRunning) { - if (musicPlayer.className == "SpotifyApplication") { + if musicPlayer.isRunning { + if musicPlayer.className == "SpotifyApplication" { let mp = (musicPlayer as SpotifyApplication) mp.nextTrack!() updatePlayer() return - } else if (musicPlayer.className == "ITunesApplication") { + } else if musicPlayer.className == "ITunesApplication" { let mp = (musicPlayer as iTunesApplication) mp.nextTrack!() updatePlayer() return - } else if (musicPlayer.className == "VOXApplication") { + } else if musicPlayer.className == "VOXApplication" { let mp = (musicPlayer as VoxApplication) mp.next!() updatePlayer() return - } else if (musicPlayer.className == "SafariApplication") { + } else if musicPlayer.className == "SafariApplication" { // You must enable the 'Allow JavaScript from Apple Events' option in Safari's Develop menu to use 'do JavaScript'. let safariApplication = musicPlayer as SafariApplication let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow }) @@ -139,7 +139,7 @@ class MusicBarItem: CustomButtonTouchBarItem { _ = safariApplication.doJavaScript!("document.getElementsByClassName('player-controls__btn_next')[0].click()", in: tab) updatePlayer() return - } else if ((tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))!) { + } else if (tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))! { _ = safariApplication.doJavaScript!("document.getElementsByClassName('audio_page_player_next')[0].click()", in: tab) updatePlayer() return @@ -155,7 +155,7 @@ class MusicBarItem: CustomButtonTouchBarItem { } } } - + func refreshAndSchedule() { DispatchQueue.main.async { self.updatePlayer() @@ -164,22 +164,22 @@ class MusicBarItem: CustomButtonTouchBarItem { } } } - + func updatePlayer() { var iconUpdated = false var titleUpdated = false - + for var ident in playerBundleIdentifiers { if let musicPlayer = SBApplication(bundleIdentifier: ident) { - if (musicPlayer.isRunning) { + if musicPlayer.isRunning { var tempTitle = "" - if (musicPlayer.className == "SpotifyApplication") { + if musicPlayer.className == "SpotifyApplication" { tempTitle = (musicPlayer as SpotifyApplication).title - } else if (musicPlayer.className == "ITunesApplication") { + } else if musicPlayer.className == "ITunesApplication" { tempTitle = (musicPlayer as iTunesApplication).title - } else if (musicPlayer.className == "VOXApplication") { + } else if musicPlayer.className == "VOXApplication" { tempTitle = (musicPlayer as VoxApplication).title - } else if (musicPlayer.className == "SafariApplication") { + } else if musicPlayer.className == "SafariApplication" { let safariApplication = musicPlayer as SafariApplication let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow }) for window in safariWindows! { @@ -190,7 +190,7 @@ class MusicBarItem: CustomButtonTouchBarItem { tempTitle = (tab.name)! break // } - } else if ((tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))!) { + } else if (tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))! { tempTitle = (tab.name)! break } else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! { @@ -202,18 +202,18 @@ class MusicBarItem: CustomButtonTouchBarItem { if tempTitle == "" { ident = "" } - } else if (musicPlayer.className == "GoogleChromeApplication") { + } else if musicPlayer.className == "GoogleChromeApplication" { let chromeApplication = musicPlayer as GoogleChromeApplication let chromeWindows = chromeApplication.windows?().compactMap({ $0 as? GoogleChromeWindow }) for window in chromeWindows! { for tab in window.tabs!() { let tab = tab as! GoogleChromeTab if (tab.URL?.starts(with: "https://music.yandex.ru"))! { - if (!(tab.title?.hasSuffix("на Яндекс.Музыке"))!) { + if !(tab.title?.hasSuffix("на Яндекс.Музыке"))! { tempTitle = tab.title! break } - } else if ((tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))!) { + } else if (tab.URL?.starts(with: "https://vk.com/audios"))! || (tab.URL?.starts(with: "https://vk.com/music"))! { tempTitle = tab.title! break } else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! { @@ -226,13 +226,13 @@ class MusicBarItem: CustomButtonTouchBarItem { ident = "" } } - - if (tempTitle == self.songTitle) { + + if tempTitle == self.songTitle { return } else { self.songTitle = tempTitle } - + if let songTitle = self.songTitle?.ifNotEmpty { self.title = " " + songTitle + " " titleUpdated = true @@ -251,12 +251,12 @@ class MusicBarItem: CustomButtonTouchBarItem { } } } - + DispatchQueue.main.async { if !iconUpdated { self.image = nil } - + if !titleUpdated { self.title = "" } @@ -265,18 +265,20 @@ class MusicBarItem: CustomButtonTouchBarItem { } @objc protocol SpotifyApplication { - @objc optional var currentTrack: SpotifyTrack {get} + @objc optional var currentTrack: SpotifyTrack { get } @objc optional func nextTrack() @objc optional func previousTrack() @objc optional func playpause() } -extension SBApplication: SpotifyApplication{} + +extension SBApplication: SpotifyApplication {} @objc protocol SpotifyTrack { - @objc optional var artist: String {get} - @objc optional var name: String {get} + @objc optional var artist: String { get } + @objc optional var name: String { get } } -extension SBObject: SpotifyTrack{} + +extension SBObject: SpotifyTrack {} extension SpotifyApplication { var title: String { @@ -285,20 +287,21 @@ extension SpotifyApplication { } } - @objc protocol iTunesApplication { - @objc optional var currentTrack: iTunesTrack {get} + @objc optional var currentTrack: iTunesTrack { get } @objc optional func playpause() @objc optional func nextTrack() @objc optional func previousTrack() } -extension SBApplication: iTunesApplication{} + +extension SBApplication: iTunesApplication {} @objc protocol iTunesTrack { - @objc optional var artist: String {get} - @objc optional var name: String {get} + @objc optional var artist: String { get } + @objc optional var name: String { get } } -extension SBObject: iTunesTrack{} + +extension SBObject: iTunesTrack {} extension iTunesApplication { var title: String { @@ -307,16 +310,15 @@ extension iTunesApplication { } } - - @objc protocol VoxApplication { @objc optional func playpause() @objc optional func next() @objc optional func previous() - @objc optional var track: String {get} - @objc optional var artist: String {get} + @objc optional var track: String { get } + @objc optional var artist: String { get } } -extension SBApplication: VoxApplication{} + +extension SBApplication: VoxApplication {} extension VoxApplication { var title: String { @@ -324,7 +326,6 @@ extension VoxApplication { } } - @objc public protocol SBObjectProtocol: NSObjectProtocol { func get() -> Any! } @@ -338,6 +339,7 @@ extension VoxApplication { @objc optional func windows() -> SBElementArray @objc optional func doJavaScript(_ x: String!, in in_: Any!) -> Any // Applies a string of JavaScript code to a document. } + extension SBApplication: SafariApplication {} @objc public protocol SafariWindow: SBObjectProtocol { @@ -346,36 +348,39 @@ extension SBApplication: SafariApplication {} // @objc optional var document: SafariDocument { get } // The document whose contents are displayed in the window. // @objc optional func setCurrentTab(_ currentTab: SafariTab!) // The current tab. } + extension SBObject: SafariWindow {} -//@objc public protocol SafariDocument: SBObjectProtocol { +// @objc public protocol SafariDocument: SBObjectProtocol { // @objc optional var name: String { get } // Its name. // @objc optional var URL: String { get } // The current URL of the document. -//} -//extension SBObject: SafariDocument {} +// } +// extension SBObject: SafariDocument {} @objc public protocol SafariTab: SBObjectProtocol { @objc optional var URL: String { get } // The current URL of the tab. @objc optional var name: String { get } // The name of the tab. } + extension SBObject: SafariTab {} - - @objc public protocol GoogleChromeApplication: SBApplicationProtocol { @objc optional func windows() -> SBElementArray @objc optional func executeJavaScript(javascript: String!) -> Any // Applies a string of JavaScript code to a document. //, id: Any! } + extension SBApplication: GoogleChromeApplication {} @objc public protocol GoogleChromeWindow: SBObjectProtocol { @objc optional var name: String { get } // The title of the window. @objc optional func tabs() -> SBElementArray } + extension SBObject: GoogleChromeWindow {} @objc public protocol GoogleChromeTab: SBObjectProtocol { @objc optional var URL: String { get } // The current URL of the tab. @objc optional var title: String { get } // The name of the tab. } + extension SBObject: GoogleChromeTab {} diff --git a/MTMR/Widgets/NightShiftBarItem.swift b/MTMR/Widgets/NightShiftBarItem.swift index 00c13a8..517a8e7 100644 --- a/MTMR/Widgets/NightShiftBarItem.swift +++ b/MTMR/Widgets/NightShiftBarItem.swift @@ -11,43 +11,43 @@ import Foundation class NightShiftBarItem: CustomButtonTouchBarItem { private let nsclient = CBBlueLightClient() private var timer: Timer! - + private var blueLightStatus: Status { var status: Status = Status() nsclient.getBlueLightStatus(&status) return status } - + private var isNightShiftEnabled: Bool { - return self.blueLightStatus.enabled.boolValue + return blueLightStatus.enabled.boolValue } - + private func setNightShift(state: Bool) { - self.nsclient.setEnabled(state) + nsclient.setEnabled(state) } - + init(identifier: NSTouchBarItem.Identifier) { super.init(identifier: identifier, title: "") - self.isBordered = false - self.setWidth(value: 28) + isBordered = false + setWidth(value: 28) + + tapClosure = { [weak self] in self?.nightShiftAction() } - self.tapClosure = { [weak self] in self?.nightShiftAction() } - timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true) - - self.refresh() + + refresh() } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func nightShiftAction() { - self.setNightShift(state: !self.isNightShiftEnabled) - self.refresh() + setNightShift(state: !isNightShiftEnabled) + refresh() } - + @objc func refresh() { - self.image = isNightShiftEnabled ? #imageLiteral(resourceName: "nightShiftOn") : #imageLiteral(resourceName: "nightShiftOff") + image = isNightShiftEnabled ? #imageLiteral(resourceName: "nightShiftOn") : #imageLiteral(resourceName: "nightShiftOff") } } diff --git a/MTMR/Widgets/TimeTouchBarItem.swift b/MTMR/Widgets/TimeTouchBarItem.swift index 5f7810a..8a2be40 100644 --- a/MTMR/Widgets/TimeTouchBarItem.swift +++ b/MTMR/Widgets/TimeTouchBarItem.swift @@ -3,21 +3,20 @@ import Cocoa class TimeTouchBarItem: CustomButtonTouchBarItem { private let dateFormatter = DateFormatter() private var timer: Timer! - + init(identifier: NSTouchBarItem.Identifier, formatTemplate: String) { dateFormatter.setLocalizedDateFormatFromTemplate(formatTemplate) super.init(identifier: identifier, title: " ") timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true) - self.isBordered = false + isBordered = false updateTime() } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + @objc func updateTime() { - self.title = self.dateFormatter.string(from: Date()) + title = dateFormatter.string(from: Date()) } - } diff --git a/MTMR/Widgets/VolumeViewController.swift b/MTMR/Widgets/VolumeViewController.swift index c9d950a..b46f0f5 100644 --- a/MTMR/Widgets/VolumeViewController.swift +++ b/MTMR/Widgets/VolumeViewController.swift @@ -1,55 +1,56 @@ -import Cocoa import AppKit import AVFoundation +import Cocoa import CoreAudio class VolumeViewController: NSCustomTouchBarItem { private(set) var sliderItem: CustomSlider! - + init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) { super.init(identifier: identifier) - + var forPropertyAddress = AudioObjectPropertyAddress( mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume, mScope: kAudioDevicePropertyScopeOutput, - mElement: kAudioObjectPropertyElementMaster) - + mElement: kAudioObjectPropertyElementMaster + ) + AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock) - - if (image == nil) { + + if image == nil { sliderItem = CustomSlider() } else { sliderItem = CustomSlider(knob: image!) } sliderItem.target = self - sliderItem.action = #selector(VolumeViewController.sliderValueChanged(_:)) + sliderItem.action = #selector(VolumeViewController.sliderValueChanged(_:)) sliderItem.minValue = 0.0 sliderItem.maxValue = 100.0 - sliderItem.floatValue = getInputGain()*100 + sliderItem.floatValue = getInputGain() * 100 - self.view = sliderItem + view = sliderItem } - - func audioObjectPropertyListenerBlock (numberAddresses: UInt32, addresses: UnsafePointer) { + + func audioObjectPropertyListenerBlock(numberAddresses _: UInt32, addresses _: UnsafePointer) { DispatchQueue.main.async { self.sliderItem.floatValue = self.getInputGain() * 100 } } - - required init?(coder: NSCoder) { + + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } deinit { sliderItem.unbind(NSBindingName.value) } - + @objc func sliderValueChanged(_ sender: Any) { if let sliderItem = sender as? NSSlider { - _ = setInputGain(Float32(sliderItem.intValue)/100.0) + _ = setInputGain(Float32(sliderItem.intValue) / 100.0) } } - + private var defaultDeviceID: AudioObjectID { var deviceID: AudioObjectID = AudioObjectID(0) var size: UInt32 = UInt32(MemoryLayout.size) @@ -60,7 +61,7 @@ class VolumeViewController: NSCustomTouchBarItem { AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &size, &deviceID) return deviceID } - + private func getInputGain() -> Float32 { var volume: Float32 = 0.5 var size: UInt32 = UInt32(MemoryLayout.size(ofValue: volume)) @@ -71,16 +72,16 @@ class VolumeViewController: NSCustomTouchBarItem { AudioObjectGetPropertyData(defaultDeviceID, &address, 0, nil, &size, &volume) return volume } - + private func setInputGain(_ volume: Float32) -> OSStatus { var inputVolume: Float32 = volume - + if inputVolume == 0.0 { - _ = setMute( mute: 1) + _ = setMute(mute: 1) } else { - _ = setMute( mute: 0) + _ = setMute(mute: 0) } - + let size: UInt32 = UInt32(MemoryLayout.size(ofValue: inputVolume)) var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress() address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput) @@ -88,8 +89,8 @@ class VolumeViewController: NSCustomTouchBarItem { address.mSelector = AudioObjectPropertySelector(kAudioHardwareServiceDeviceProperty_VirtualMasterVolume) return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &inputVolume) } - - private func setMute( mute: Int) -> OSStatus { + + private func setMute(mute: Int) -> OSStatus { var muteVal: Int = mute var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress() address.mSelector = AudioObjectPropertySelector(kAudioDevicePropertyMute) @@ -99,4 +100,3 @@ class VolumeViewController: NSCustomTouchBarItem { return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &muteVal) } } - diff --git a/MTMR/Widgets/WeatherBarItem.swift b/MTMR/Widgets/WeatherBarItem.swift index 8d1e242..711e00a 100644 --- a/MTMR/Widgets/WeatherBarItem.swift +++ b/MTMR/Widgets/WeatherBarItem.swift @@ -16,42 +16,42 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { private var units_str = "°F" 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 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! - + + private var manager: CLLocationManager! + init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text") { activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck") activity.interval = interval self.units = units self.api_key = api_key - + if self.units == "metric" { units_str = "°C" } - + if self.units == "imperial" { units_str = "°F" } - + if icon_type == "images" { iconsSource = iconsImages } else { iconsSource = iconsText } - + super.init(identifier: identifier, title: "⏳") - + let status = CLLocationManager.authorizationStatus() if status == .restricted || status == .denied { print("User permission not given") return } - + if !CLLocationManager.locationServicesEnabled() { - print("Location services not enabled"); + print("Location services not enabled") return } @@ -62,43 +62,43 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { completion(NSBackgroundActivityScheduler.Result.finished) } updateWeather() - + manager = CLLocationManager() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyHundredMeters manager.startUpdatingLocation() } - - required init?(coder: NSCoder) { + + 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 location != nil { + let urlRequest = URLRequest(url: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)&units=\(units)&appid=\(api_key)")!) + + let task = URLSession.shared.dataTask(with: urlRequest) { data, _, error in + if error == nil { do { - let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject] + let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject] // print(json) var temperature: Int! var condition_icon = "" - - if let main = json["main"] as? [String : AnyObject] { + + if let main = json["main"] as? [String: AnyObject] { if let temp = main["temp"] as? Double { temperature = Int(temp) } } - + if let weather = json["weather"] as? NSArray, let item = weather[0] as? NSDictionary { let icon = item["icon"] as! String if let test = self.iconsSource[icon] { condition_icon = test } } - + if temperature != nil { DispatchQueue.main.async { self.setWeather(text: "\(condition_icon) \(temperature!)\(self.units_str)") @@ -109,31 +109,30 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate { } } } - + task.resume() } } - + func setWeather(text: String) { - self.title = text + title = text } - - func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + + func locationManager(_: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let lastLocation = locations.last! - self.location = lastLocation + location = lastLocation if prev_location == nil { updateWeather() } prev_location = lastLocation } - - func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { - print(error); + + func locationManager(_: CLLocationManager, didFailWithError error: Error) { + print(error) } - - func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { + + func locationManager(_: CLLocationManager, didChangeAuthorization _: CLAuthorizationStatus) { // print("inside didChangeAuthorization "); updateWeather() } - }