1
0
mirror of https://github.com/Toxblh/MTMR.git synced 2026-01-10 17:08:39 +00:00

code format

This commit is contained in:
Toxblh 2018-10-20 17:53:49 +01:00
parent 8554dfeb5e
commit 86954a7981
24 changed files with 822 additions and 737 deletions

View File

@ -11,54 +11,50 @@ import Sparkle
@NSApplicationMain @NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate { class AppDelegate: NSObject, NSApplicationDelegate {
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength) let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
var isBlockedApp: Bool = false var isBlockedApp: Bool = false
private var fileSystemSource: DispatchSourceFileSystemObject? private var fileSystemSource: DispatchSourceFileSystemObject?
func applicationDidFinishLaunching(_ aNotification: Notification) { func applicationDidFinishLaunching(_: Notification) {
// Configure Sparkle // Configure Sparkle
SUUpdater.shared().automaticallyDownloadsUpdates = false SUUpdater.shared().automaticallyDownloadsUpdates = false
SUUpdater.shared().automaticallyChecksForUpdates = true SUUpdater.shared().automaticallyChecksForUpdates = true
SUUpdater.shared().checkForUpdatesInBackground() SUUpdater.shared().checkForUpdatesInBackground()
let _ = AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true] as NSDictionary) AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true] as NSDictionary)
TouchBarController.shared.setupControlStripPresence() TouchBarController.shared.setupControlStripPresence()
if let button = statusItem.button { if let button = statusItem.button {
button.image = #imageLiteral(resourceName: "StatusImage") button.image = #imageLiteral(resourceName: "StatusImage")
} }
createMenu() createMenu()
reloadOnDefaultConfigChanged() reloadOnDefaultConfigChanged()
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(updateIsBlockedApp), name: NSWorkspace.didLaunchApplicationNotification, object: nil) 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.didTerminateApplicationNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(updateIsBlockedApp), name: NSWorkspace.didActivateApplicationNotification, object: nil) NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(updateIsBlockedApp), name: NSWorkspace.didActivateApplicationNotification, object: nil)
} }
func applicationWillTerminate(_ aNotification: Notification) { func applicationWillTerminate(_: Notification) {}
} @objc func updateIsBlockedApp() {
@objc func updateIsBlockedApp() -> Void {
var blacklistAppIdentifiers: [String] = [] var blacklistAppIdentifiers: [String] = []
if let blackListed = UserDefaults.standard.stringArray(forKey: "com.toxblh.mtmr.blackListedApps") { if let blackListed = UserDefaults.standard.stringArray(forKey: "com.toxblh.mtmr.blackListedApps") {
blacklistAppIdentifiers = blackListed blacklistAppIdentifiers = blackListed
} }
var frontmostApplicationIdentifier: String? { var frontmostApplicationIdentifier: String? {
get { guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil }
guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil } return frontmostId
return frontmostId
}
} }
self.isBlockedApp = blacklistAppIdentifiers.index(of: frontmostApplicationIdentifier!) != nil isBlockedApp = blacklistAppIdentifiers.index(of: frontmostApplicationIdentifier!) != nil
createMenu() createMenu()
} }
@objc func openPreferences(_ sender: Any?) { @objc func openPreferences(_: Any?) {
let task = Process() let task = Process()
let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR") let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR")
let presetPath = appSupportDirectory.appending("/items.json") let presetPath = appSupportDirectory.appending("/items.json")
@ -66,14 +62,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
task.arguments = [presetPath] task.arguments = [presetPath]
task.launch() task.launch()
} }
@objc func toggleControlStrip(_ sender: Any?) { @objc func toggleControlStrip(_: Any?) {
TouchBarController.shared.showControlStripState = !TouchBarController.shared.showControlStripState TouchBarController.shared.showControlStripState = !TouchBarController.shared.showControlStripState
TouchBarController.shared.resetControlStrip() TouchBarController.shared.resetControlStrip()
createMenu() createMenu()
} }
@objc func toggleBlackListedApp(_ sender: Any?) { @objc func toggleBlackListedApp(_: Any?) {
let appIdentifier = TouchBarController.shared.frontmostApplicationIdentifier let appIdentifier = TouchBarController.shared.frontmostApplicationIdentifier
if appIdentifier != nil { if appIdentifier != nil {
if let index = TouchBarController.shared.blacklistAppIdentifiers.index(of: appIdentifier!) { if let index = TouchBarController.shared.blacklistAppIdentifiers.index(of: appIdentifier!) {
@ -81,56 +77,56 @@ class AppDelegate: NSObject, NSApplicationDelegate {
} else { } else {
TouchBarController.shared.blacklistAppIdentifiers.append(appIdentifier!) TouchBarController.shared.blacklistAppIdentifiers.append(appIdentifier!)
} }
UserDefaults.standard.set(TouchBarController.shared.blacklistAppIdentifiers, forKey: "com.toxblh.mtmr.blackListedApps") UserDefaults.standard.set(TouchBarController.shared.blacklistAppIdentifiers, forKey: "com.toxblh.mtmr.blackListedApps")
UserDefaults.standard.synchronize() UserDefaults.standard.synchronize()
TouchBarController.shared.updateActiveApp() TouchBarController.shared.updateActiveApp()
updateIsBlockedApp() updateIsBlockedApp()
} }
} }
@objc func openPreset(_ sender: Any?) { @objc func openPreset(_: Any?) {
let dialog = NSOpenPanel(); let dialog = NSOpenPanel()
dialog.title = "Choose a items.json file" dialog.title = "Choose a items.json file"
dialog.showsResizeIndicator = true dialog.showsResizeIndicator = true
dialog.showsHiddenFiles = true dialog.showsHiddenFiles = true
dialog.canChooseDirectories = false dialog.canChooseDirectories = false
dialog.canCreateDirectories = false dialog.canCreateDirectories = false
dialog.allowsMultipleSelection = false dialog.allowsMultipleSelection = false
dialog.allowedFileTypes = ["json"] dialog.allowedFileTypes = ["json"]
dialog.directoryURL = NSURL.fileURL(withPath: NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR"), isDirectory: true) dialog.directoryURL = NSURL.fileURL(withPath: NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR"), isDirectory: true)
if dialog.runModal() == .OK, let path = dialog.url?.path { if dialog.runModal() == .OK, let path = dialog.url?.path {
TouchBarController.shared.reloadPreset(path: 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)) LaunchAtLoginController().setLaunchAtLogin(!LaunchAtLoginController().launchAtLogin, for: NSURL.fileURL(withPath: Bundle.main.bundlePath))
createMenu() createMenu()
} }
func createMenu() { func createMenu() {
let menu = NSMenu() let menu = NSMenu()
let startAtLogin = NSMenuItem(title: "Start at login", action: #selector(toggleStartAtLogin(_:)), keyEquivalent: "L") let startAtLogin = NSMenuItem(title: "Start at login", action: #selector(toggleStartAtLogin(_:)), keyEquivalent: "L")
startAtLogin.state = LaunchAtLoginController().launchAtLogin ? .on : .off startAtLogin.state = LaunchAtLoginController().launchAtLogin ? .on : .off
let toggleBlackList = NSMenuItem(title: "Toggle current app in blacklist", action: #selector(toggleBlackListedApp(_:)), keyEquivalent: "B") 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") let hideControlStrip = NSMenuItem(title: "Hide Control Strip", action: #selector(toggleControlStrip(_:)), keyEquivalent: "T")
hideControlStrip.state = TouchBarController.shared.showControlStripState ? .off : .on hideControlStrip.state = TouchBarController.shared.showControlStripState ? .off : .on
let settingSeparator = NSMenuItem(title: "Settings", action: nil, keyEquivalent: "") let settingSeparator = NSMenuItem(title: "Settings", action: nil, keyEquivalent: "")
settingSeparator.isEnabled = false settingSeparator.isEnabled = false
menu.addItem(withTitle: "Preferences", action: #selector(openPreferences(_:)), keyEquivalent: ",") menu.addItem(withTitle: "Preferences", action: #selector(openPreferences(_:)), keyEquivalent: ",")
menu.addItem(withTitle: "Open preset", action: #selector(openPreset(_:)), keyEquivalent: "O") 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(withTitle: "Check for Updates...", action: #selector(SUUpdater.checkForUpdates(_:)), keyEquivalent: "").target = SUUpdater.shared()
menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem.separator())
menu.addItem(settingSeparator) menu.addItem(settingSeparator)
menu.addItem(hideControlStrip) menu.addItem(hideControlStrip)
@ -143,23 +139,22 @@ class AppDelegate: NSObject, NSApplicationDelegate {
func reloadOnDefaultConfigChanged() { func reloadOnDefaultConfigChanged() {
let file = NSURL.fileURL(withPath: standardConfigPath) let file = NSURL.fileURL(withPath: standardConfigPath)
let fd = open(file.path, O_EVTONLY) let fd = open(file.path, O_EVTONLY)
self.fileSystemSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fd, eventMask: .write, queue: DispatchQueue(label: "DefaultConfigChanged")) fileSystemSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fd, eventMask: .write, queue: DispatchQueue(label: "DefaultConfigChanged"))
self.fileSystemSource?.setEventHandler(handler: { fileSystemSource?.setEventHandler(handler: {
print("Config changed, reloading...") print("Config changed, reloading...")
DispatchQueue.main.async { DispatchQueue.main.async {
TouchBarController.shared.reloadPreset(path: file.path) TouchBarController.shared.reloadPreset(path: file.path)
} }
}) })
self.fileSystemSource?.setCancelHandler(handler: { fileSystemSource?.setCancelHandler(handler: {
close(fd) close(fd)
}) })
self.fileSystemSource?.resume() fileSystemSource?.resume()
} }
} }

View File

@ -4,17 +4,17 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
private var script: NSAppleScript! private var script: NSAppleScript!
private let interval: TimeInterval private let interval: TimeInterval
private var forceHideConstraint: NSLayoutConstraint! private var forceHideConstraint: NSLayoutConstraint!
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) { init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) {
self.interval = interval self.interval = interval
super.init(identifier: identifier, title: "") 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 { guard let script = source.appleScript else {
self.title = "no script" title = "no script"
return return
} }
self.script = script self.script = script
self.isBordered = false isBordered = false
DispatchQueue.appleScriptQueue.async { DispatchQueue.appleScriptQueue.async {
var error: NSDictionary? var error: NSDictionary?
guard script.compileAndReturnError(&error) else { guard script.compileAndReturnError(&error) else {
@ -29,28 +29,28 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
self.refreshAndSchedule() self.refreshAndSchedule()
} }
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
func refreshAndSchedule() { func refreshAndSchedule() {
#if DEBUG #if DEBUG
print("refresh happened (interval \(self.interval)), self \(self.identifier.rawValue))") print("refresh happened (interval \(interval)), self \(identifier.rawValue))")
#endif #endif
let scriptResult = self.execute() let scriptResult = execute()
DispatchQueue.main.async { DispatchQueue.main.async {
self.title = scriptResult self.title = scriptResult
self.forceHideConstraint.isActive = scriptResult == "" self.forceHideConstraint.isActive = scriptResult == ""
#if DEBUG #if DEBUG
print("did set new script result title \(scriptResult)") print("did set new script result title \(scriptResult)")
#endif #endif
} }
DispatchQueue.appleScriptQueue.asyncAfter(deadline: .now() + self.interval) { [weak self] in DispatchQueue.appleScriptQueue.asyncAfter(deadline: .now() + interval) { [weak self] in
self?.refreshAndSchedule() self?.refreshAndSchedule()
} }
} }
func execute() -> String { func execute() -> String {
var error: NSDictionary? var error: NSDictionary?
let output = script.executeAndReturnError(&error) let output = script.executeAndReturnError(&error)
@ -60,7 +60,6 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
} }
return output.stringValue ?? "" return output.stringValue ?? ""
} }
} }
extension DispatchQueue { extension DispatchQueue {

View File

@ -9,69 +9,69 @@
import Cocoa import Cocoa
class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
var tapClosure: (() -> ())? var tapClosure: (() -> Void)?
var longTapClosure: (() -> ())? var longTapClosure: (() -> Void)?
private var button: NSButton! private var button: NSButton!
private var singleClick: NSClickGestureRecognizer! private var singleClick: NSClickGestureRecognizer!
private var longClick: NSPressGestureRecognizer! private var longClick: NSPressGestureRecognizer!
init(identifier: NSTouchBarItem.Identifier, title: String) { init(identifier: NSTouchBarItem.Identifier, title: String) {
self.attributedTitle = title.defaultTouchbarAttributedString attributedTitle = title.defaultTouchbarAttributedString
super.init(identifier: identifier) super.init(identifier: identifier)
button = CustomHeightButton(title: title, target: nil, action: nil) button = CustomHeightButton(title: title, target: nil, action: nil)
longClick = NSPressGestureRecognizer(target: self, action: #selector(handleGestureLong)) longClick = NSPressGestureRecognizer(target: self, action: #selector(handleGestureLong))
longClick.allowedTouchTypes = .direct longClick.allowedTouchTypes = .direct
longClick.delegate = self longClick.delegate = self
singleClick = NSClickGestureRecognizer(target: self, action: #selector(handleGestureSingle)) singleClick = NSClickGestureRecognizer(target: self, action: #selector(handleGestureSingle))
singleClick.allowedTouchTypes = .direct singleClick.allowedTouchTypes = .direct
singleClick.delegate = self singleClick.delegate = self
reinstallButton() reinstallButton()
button.attributedTitle = attributedTitle button.attributedTitle = attributedTitle
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
var isBordered: Bool = true { var isBordered: Bool = true {
didSet { didSet {
reinstallButton() reinstallButton()
} }
} }
var backgroundColor: NSColor? { var backgroundColor: NSColor? {
didSet { didSet {
reinstallButton() reinstallButton()
} }
} }
var title: String { var title: String {
get { get {
return self.attributedTitle.string return attributedTitle.string
} }
set { set {
self.attributedTitle = newValue.defaultTouchbarAttributedString attributedTitle = newValue.defaultTouchbarAttributedString
} }
} }
var attributedTitle: NSAttributedString { var attributedTitle: NSAttributedString {
didSet { didSet {
self.button?.imagePosition = attributedTitle.length > 0 ? .imageLeading : .imageOnly button?.imagePosition = attributedTitle.length > 0 ? .imageLeading : .imageOnly
self.button?.attributedTitle = attributedTitle button?.attributedTitle = attributedTitle
} }
} }
var image: NSImage? { var image: NSImage? {
didSet { didSet {
button.image = image button.image = image
} }
} }
private func reinstallButton() { private func reinstallButton() {
let title = button.attributedTitle let title = button.attributedTitle
let image = button.image let image = button.image
@ -88,12 +88,12 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
button.imageScaling = .scaleProportionallyDown button.imageScaling = .scaleProportionallyDown
button.imageHugsTitle = true button.imageHugsTitle = true
button.attributedTitle = title button.attributedTitle = title
self.button?.imagePosition = title.length > 0 ? .imageLeading : .imageOnly button?.imagePosition = title.length > 0 ? .imageLeading : .imageOnly
button.image = image button.image = image
self.view = button view = button
self.view.addGestureRecognizer(longClick) view.addGestureRecognizer(longClick)
self.view.addGestureRecognizer(singleClick) view.addGestureRecognizer(singleClick)
} }
func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool { func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool {
@ -102,19 +102,19 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
} }
return true return true
} }
@objc func handleGestureSingle(gr: NSClickGestureRecognizer) { @objc func handleGestureSingle(gr: NSClickGestureRecognizer) {
let hf: HapticFeedback = HapticFeedback() let hf: HapticFeedback = HapticFeedback()
switch gr.state { switch gr.state {
case .ended: case .ended:
hf.tap(strong: 2) hf.tap(strong: 2)
self.tapClosure?() tapClosure?()
break break
default: default:
break break
} }
} }
@objc func handleGestureLong(gr: NSPressGestureRecognizer) { @objc func handleGestureLong(gr: NSPressGestureRecognizer) {
let hf: HapticFeedback = HapticFeedback() let hf: HapticFeedback = HapticFeedback()
switch gr.state { switch gr.state {
@ -130,57 +130,52 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
break break
default: default:
break break
} }
} }
} }
class CustomHeightButton : NSButton { class CustomHeightButton: NSButton {
override var intrinsicContentSize: NSSize { override var intrinsicContentSize: NSSize {
var size = super.intrinsicContentSize var size = super.intrinsicContentSize
size.height = 30 size.height = 30
return size return size
} }
} }
class CustomButtonCell: NSButtonCell { class CustomButtonCell: NSButtonCell {
weak var parentItem: CustomButtonTouchBarItem? weak var parentItem: CustomButtonTouchBarItem?
init(parentItem: CustomButtonTouchBarItem) { init(parentItem: CustomButtonTouchBarItem) {
super.init(textCell: "") super.init(textCell: "")
self.parentItem = parentItem self.parentItem = parentItem
} }
override func highlight(_ flag: Bool, withFrame cellFrame: NSRect, in controlView: NSView) { override func highlight(_ flag: Bool, withFrame cellFrame: NSRect, in controlView: NSView) {
super.highlight(flag, withFrame: cellFrame, in: controlView) super.highlight(flag, withFrame: cellFrame, in: controlView)
if !self.isBordered { if !isBordered {
if flag { if flag {
self.setAttributedTitle(self.attributedTitle, withColor: .lightGray) setAttributedTitle(attributedTitle, withColor: .lightGray)
} else if let parentItem = self.parentItem { } 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") fatalError("init(coder:) has not been implemented")
} }
func setAttributedTitle(_ title: NSAttributedString, withColor color: NSColor) { func setAttributedTitle(_ title: NSAttributedString, withColor color: NSColor) {
let attrTitle = NSMutableAttributedString(attributedString: title) let attrTitle = NSMutableAttributedString(attributedString: title)
attrTitle.addAttributes([.foregroundColor: color], range: NSRange(location: 0, length: attrTitle.length)) attrTitle.addAttributes([.foregroundColor: color], range: NSRange(location: 0, length: attrTitle.length))
self.attributedTitle = attrTitle attributedTitle = attrTitle
} }
} }
extension String { extension String {
var defaultTouchbarAttributedString: NSAttributedString { var defaultTouchbarAttributedString: NSAttributedString {
let attrTitle = NSMutableAttributedString(string: self, attributes: [.foregroundColor: NSColor.white, .font: NSFont.systemFont(ofSize: 15, weight: .regular), .baselineOffset: 1]) 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 return attrTitle
} }
} }

View File

@ -9,34 +9,34 @@
import Foundation import Foundation
class CustomSliderCell: NSSliderCell { class CustomSliderCell: NSSliderCell {
var knobImage:NSImage! var knobImage: NSImage!
private var _currentKnobRect:NSRect! private var _currentKnobRect: NSRect!
private var _barRect:NSRect! private var _barRect: NSRect!
required init(coder aDecoder: NSCoder) { required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) super.init(coder: aDecoder)
} }
override init() { override init() {
super.init() super.init()
} }
init(knob:NSImage?) { init(knob: NSImage?) {
knobImage = knob; knobImage = knob
super.init() super.init()
} }
override func drawKnob(_ knobRect: NSRect) { override func drawKnob(_ knobRect: NSRect) {
if (knobImage == nil) { if knobImage == nil {
super.drawKnob(knobRect) super.drawKnob(knobRect)
return; return
} }
_currentKnobRect = knobRect; _currentKnobRect = knobRect
drawBar(inside: _barRect, flipped: true) drawBar(inside: _barRect, flipped: true)
let x = (knobRect.origin.x * (_barRect.size.width - (knobImage.size.width - knobRect.size.width)) / _barRect.size.width)+1; 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 y = knobRect.origin.y + 3
knobImage.draw( knobImage.draw(
at: NSPoint(x: x, y: y), at: NSPoint(x: x, y: y),
@ -45,63 +45,62 @@ class CustomSliderCell: NSSliderCell {
fraction: 1 fraction: 1
) )
} }
override func drawBar(inside aRect: NSRect, flipped: Bool) { override func drawBar(inside aRect: NSRect, flipped _: Bool) {
_barRect = aRect _barRect = aRect
let barRadius = CGFloat(2) let barRadius = CGFloat(2)
var bgRect = aRect var bgRect = aRect
bgRect.size.height = CGFloat(4) bgRect.size.height = CGFloat(4)
let bg = NSBezierPath(roundedRect: bgRect, xRadius: barRadius, yRadius: barRadius) let bg = NSBezierPath(roundedRect: bgRect, xRadius: barRadius, yRadius: barRadius)
NSColor.lightGray.setFill() NSColor.lightGray.setFill()
bg.fill() bg.fill()
var activeRect = bgRect 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) let active = NSBezierPath(roundedRect: activeRect, xRadius: barRadius, yRadius: barRadius)
NSColor.darkGray.setFill() NSColor.darkGray.setFill()
active.fill() active.fill()
} }
} }
class CustomSlider:NSSlider { class CustomSlider: NSSlider {
var currentValue: CGFloat = 0
var currentValue:CGFloat = 0
override func setNeedsDisplay(_ invalidRect: NSRect) { override func setNeedsDisplay(_ invalidRect: NSRect) {
super.setNeedsDisplay(invalidRect) super.setNeedsDisplay(invalidRect)
} }
override func awakeFromNib() { override func awakeFromNib() {
super.awakeFromNib() super.awakeFromNib()
if ((self.cell?.isKind(of: CustomSliderCell.self)) == false) { if (cell?.isKind(of: CustomSliderCell.self)) == false {
let cell:CustomSliderCell = CustomSliderCell() let cell: CustomSliderCell = CustomSliderCell()
self.cell = cell self.cell = cell
} }
} }
convenience init(knob:NSImage) { convenience init(knob: NSImage) {
self.init() self.init()
self.cell = CustomSliderCell(knob: knob) cell = CustomSliderCell(knob: knob)
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
super.init(coder: coder) super.init(coder: coder)
} }
override init(frame frameRect: NSRect) { override init(frame frameRect: NSRect) {
super.init(frame: frameRect) super.init(frame: frameRect)
} }
func knobImage() -> NSImage { func knobImage() -> NSImage {
let cell = self.cell as! CustomSliderCell let cell = self.cell as! CustomSliderCell
return cell.knobImage return cell.knobImage
} }
func setKnobImage(image:NSImage) { func setKnobImage(image: NSImage) {
let cell = self.cell as! CustomSliderCell let cell = self.cell as! CustomSliderCell
cell.knobImage = image cell.knobImage = image
} }

View File

@ -11,9 +11,7 @@ import Foundation
#endif #endif
extension String { extension String {
var ifNotEmpty: String? { var ifNotEmpty: String? {
return self.count > 0 ? self : nil return count > 0 ? self : nil
} }
} }

View File

@ -10,7 +10,7 @@ import IOKit
class HapticFeedback { class HapticFeedback {
private var actuatorRef: CFTypeRef? private var actuatorRef: CFTypeRef?
private var deviceID: UInt64 = 0x200000001000000 private var deviceID: UInt64 = 0x200_0000_0100_0000
private var error: IOReturn = 0 private var error: IOReturn = 0
// Don't know how to do strong is enum one of // Don't know how to do strong is enum one of
@ -24,7 +24,7 @@ class HapticFeedback {
// 16 nothing // 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` // 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() actuatorRef = MTActuatorCreateFromDeviceID(deviceID).takeRetainedValue()
guard actuatorRef != nil else { guard actuatorRef != nil else {
@ -53,5 +53,3 @@ class HapticFeedback {
return return
} }
} }

View File

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.18.5</string> <string>0.18.5</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>79</string> <string>82</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string> <string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View File

@ -1,9 +1,9 @@
import Foundation
import AppKit import AppKit
import Foundation
extension Data { extension Data {
func barItemDefinitions() -> [BarItemDefinition]? { 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 action: ActionType
let longAction: LongActionType let longAction: LongActionType
let additionalParameters: [GeneralParameters.CodingKeys: GeneralParameter] let additionalParameters: [GeneralParameters.CodingKeys: GeneralParameter]
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case type 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.type = type
self.action = action self.action = action
self.longAction = longAction self.longAction = longAction
self.additionalParameters = additionalParameters self.additionalParameters = additionalParameters
} }
init(from decoder: Decoder) throws { init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(String.self, forKey: .type) let type = try container.decode(String.self, forKey: .type)
let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type) let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type)
var additionalParameters = try GeneralParameters(from: decoder).parameters var additionalParameters = try GeneralParameters(from: decoder).parameters
if let result = try? parametersDecoder(decoder), if let result = try? parametersDecoder(decoder),
case let (itemType, action, longAction, parameters) = result { case let (itemType, action, longAction, parameters) = result {
parameters.forEach { additionalParameters[$0] = $1 } parameters.forEach { additionalParameters[$0] = $1 }
@ -38,68 +38,127 @@ struct BarItemDefinition: Decodable {
self.init(type: .staticButton(title: "unknown"), action: .none, longAction: .none, additionalParameters: additionalParameters) self.init(type: .staticButton(title: "unknown"), action: .none, longAction: .none, additionalParameters: additionalParameters)
} }
} }
} }
class SupportedTypesHolder { 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] = [ private var supportedTypes: [String: ParametersDecoder] = [
"escape": { _ in return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53), longAction: .none, parameters: [.align: .align(.left)]) }, "escape": { _ in (
item: .staticButton(title: "esc"),
"delete": { _ in return (item: .staticButton(title: "del"), action: .keyPress(keycode: 117), longAction: .none, parameters: [:])}, 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 "brightnessUp": { _ in
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessUp")) 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 "brightnessDown": { _ in
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "brightnessDown")) 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 "illuminationUp": { _ in
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "ill_up")) 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 "illuminationDown": { _ in
let imageParameter = GeneralParameter.image(source: #imageLiteral(resourceName: "ill_down")) 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 "volumeDown": { _ in
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarVolumeDownTemplateName)!) 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 "volumeUp": { _ in
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarVolumeUpTemplateName)!) 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 "mute": { _ in
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarAudioOutputMuteTemplateName)!) 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 "previous": { _ in
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarRewindTemplateName)!) 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 "play": { _ in
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarPlayPauseTemplateName)!) 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 "next": { _ in
let imageParameter = GeneralParameter.image(source: NSImage(named: NSImage.touchBarFastForwardTemplateName)!) 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 "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 container = try decoder.container(keyedBy: CodingKeys.self)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
let units = try container.decodeIfPresent(String.self, forKey: .units) 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 icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type)
let action = try ActionType(from: decoder) let action = try ActionType(from: decoder)
let longAction = try LongActionType(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 "currency": { decoder in
enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to } enum CodingKeys: String, CodingKey { case refreshInterval; case from; case to }
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
@ -118,42 +182,87 @@ class SupportedTypesHolder {
let to = try container.decodeIfPresent(String.self, forKey: .to) let to = try container.decodeIfPresent(String.self, forKey: .to)
let action = try ActionType(from: decoder) let action = try ActionType(from: decoder)
let longAction = try LongActionType(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 "dock": { _ in
return (item: .dock(), action: .none, longAction: .none, parameters: [:]) (
item: .dock(),
action: .none,
longAction: .none,
parameters: [:]
)
}, },
"inputsource": { decoder in "inputsource": { _ in
return (item: .inputsource(), action: .none, longAction: .none, parameters: [:]) (
item: .inputsource(),
action: .none,
longAction: .none,
parameters: [:]
)
}, },
"volume": { decoder in "volume": { decoder in
enum CodingKeys: String, CodingKey { case image } enum CodingKeys: String, CodingKey { case image }
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
if var img = try container.decodeIfPresent(Source.self, forKey: .image) { 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 { } else {
return (item: .volume(), action: .none, longAction: .none, parameters: [:]) return (
item: .volume(),
action: .none,
longAction: .none,
parameters: [:]
)
} }
}, },
"brightness": { decoder in "brightness": { decoder in
enum CodingKeys: String, CodingKey { case refreshInterval; case image } enum CodingKeys: String, CodingKey { case refreshInterval; case image }
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
if var img = try container.decodeIfPresent(Source.self, forKey: .image) { 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 { } 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: [:]) }, "sleep": { _ in (
item: .staticButton(title: "☕️"),
"displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), longAction: .none, parameters: [:])}, 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 "music": { decoder in
enum CodingKeys: String, CodingKey { case refreshInterval } enum CodingKeys: String, CodingKey { case refreshInterval }
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
@ -165,7 +274,7 @@ class SupportedTypesHolder {
parameters: [:] parameters: [:]
) )
}, },
"group": { decoder in "group": { decoder in
enum CodingKeys: CodingKey { case items } enum CodingKeys: CodingKey { case items }
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
@ -177,42 +286,46 @@ class SupportedTypesHolder {
parameters: [:] parameters: [:]
) )
}, },
"nightShift": {_ in "nightShift": { _ in
return ( (
item: .nightShift(), item: .nightShift(),
action: .none, action: .none,
longAction: .none, longAction: .none,
parameters: [:] parameters: [:]
) )
}, },
"dnd": { _ in "dnd": { _ in
return ( (
item: .dnd(), item: .dnd(),
action: .none, action: .none,
longAction: .none, longAction: .none,
parameters: [:] parameters: [:]
) )
},
}
] ]
static let sharedInstance = SupportedTypesHolder() static let sharedInstance = SupportedTypesHolder()
func lookup(by type: String) -> ParametersDecoder { func lookup(by type: String) -> ParametersDecoder {
return supportedTypes[type] ?? { decoder in 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) { func register(typename: String, decoder: @escaping ParametersDecoder) {
supportedTypes[typename] = decoder supportedTypes[typename] = decoder
} }
func register(typename: String, item: ItemType, action: ActionType, longAction: LongActionType) { func register(typename: String, item: ItemType, action: ActionType, longAction: LongActionType) {
register(typename: typename) { _ in 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 groupBar(items: [BarItemDefinition])
case nightShift() case nightShift()
case dnd() case dnd()
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case type case type
case title case title
@ -249,7 +362,7 @@ enum ItemType: Decodable {
case longUrl case longUrl
case items case items
} }
enum ItemTypeRaw: String, Decodable { enum ItemTypeRaw: String, Decodable {
case staticButton case staticButton
case appleScriptTitledButton case appleScriptTitledButton
@ -266,65 +379,64 @@ enum ItemType: Decodable {
case nightShift case nightShift
case dnd case dnd
} }
init(from decoder: Decoder) throws { init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(ItemTypeRaw.self, forKey: .type) let type = try container.decode(ItemTypeRaw.self, forKey: .type)
switch type { switch type {
case .appleScriptTitledButton: case .appleScriptTitledButton:
let source = try container.decode(Source.self, forKey: .source) let source = try container.decode(Source.self, forKey: .source)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
self = .appleScriptTitledButton(source: source, refreshInterval: interval) self = .appleScriptTitledButton(source: source, refreshInterval: interval)
case .staticButton: case .staticButton:
let title = try container.decode(String.self, forKey: .title) let title = try container.decode(String.self, forKey: .title)
self = .staticButton(title: title) self = .staticButton(title: title)
case .timeButton: case .timeButton:
let template = try container.decodeIfPresent(String.self, forKey: .formatTemplate) ?? "HH:mm" let template = try container.decodeIfPresent(String.self, forKey: .formatTemplate) ?? "HH:mm"
self = .timeButton(formatTemplate: template) self = .timeButton(formatTemplate: template)
case .battery: case .battery:
self = .battery() self = .battery()
case .dock: case .dock:
self = .dock() self = .dock()
case .volume: case .volume:
self = .volume() self = .volume()
case .brightness: case .brightness:
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 0.5 let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 0.5
self = .brightness(refreshInterval: interval) self = .brightness(refreshInterval: interval)
case .weather: case .weather:
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
let units = try container.decodeIfPresent(String.self, forKey: .units) ?? "metric" let units = try container.decodeIfPresent(String.self, forKey: .units) ?? "metric"
let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6" let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6"
let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) ?? "text" 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) self = .weather(interval: interval, units: units, api_key: api_key, icon_type: icon_type)
case .currency: case .currency:
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 600.0 let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 600.0
let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB" let from = try container.decodeIfPresent(String.self, forKey: .from) ?? "RUB"
let to = try container.decodeIfPresent(String.self, forKey: .to) ?? "USD" let to = try container.decodeIfPresent(String.self, forKey: .to) ?? "USD"
self = .currency(interval: interval, from: from, to: to) self = .currency(interval: interval, from: from, to: to)
case .inputsource: case .inputsource:
self = .inputsource() self = .inputsource()
case .music: case .music:
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
self = .music(interval: interval) self = .music(interval: interval)
case .groupBar: case .groupBar:
let items = try container.decode([BarItemDefinition].self, forKey: .items) let items = try container.decode([BarItemDefinition].self, forKey: .items)
self = .groupBar(items: items) self = .groupBar(items: items)
case .nightShift: case .nightShift:
self = .nightShift() self = .nightShift()
case .dnd: case .dnd:
self = .dnd() self = .dnd()
} }
@ -337,9 +449,9 @@ enum ActionType: Decodable {
case keyPress(keycode: Int) case keyPress(keycode: Int)
case appleScript(source: SourceProtocol) case appleScript(source: SourceProtocol)
case shellScript(executable: String, parameters: [String]) case shellScript(executable: String, parameters: [String])
case custom(closure: ()->()) case custom(closure: () -> Void)
case openUrl(url: String) case openUrl(url: String)
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case action case action
case keycode case keycode
@ -348,7 +460,7 @@ enum ActionType: Decodable {
case shellArguments case shellArguments
case url case url
} }
private enum ActionTypeRaw: String, Decodable { private enum ActionTypeRaw: String, Decodable {
case hidKey case hidKey
case keyPress case keyPress
@ -356,49 +468,48 @@ enum ActionType: Decodable {
case shellScript case shellScript
case openUrl case openUrl
} }
init(from decoder: Decoder) throws { init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decodeIfPresent(ActionTypeRaw.self, forKey: .action) let type = try container.decodeIfPresent(ActionTypeRaw.self, forKey: .action)
switch type { switch type {
case .some(.hidKey): case .some(.hidKey):
let keycode = try container.decode(Int32.self, forKey: .keycode) let keycode = try container.decode(Int32.self, forKey: .keycode)
self = .hidKey(keycode: keycode) self = .hidKey(keycode: keycode)
case .some(.keyPress): case .some(.keyPress):
let keycode = try container.decode(Int.self, forKey: .keycode) let keycode = try container.decode(Int.self, forKey: .keycode)
self = .keyPress(keycode: keycode) self = .keyPress(keycode: keycode)
case .some(.appleScript): case .some(.appleScript):
let source = try container.decode(Source.self, forKey: .actionAppleScript) let source = try container.decode(Source.self, forKey: .actionAppleScript)
self = .appleScript(source: source) self = .appleScript(source: source)
case .some(.shellScript): case .some(.shellScript):
let executable = try container.decode(String.self, forKey: .executablePath) let executable = try container.decode(String.self, forKey: .executablePath)
let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? [] let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? []
self = .shellScript(executable: executable, parameters: parameters) self = .shellScript(executable: executable, parameters: parameters)
case .some(.openUrl): case .some(.openUrl):
let url = try container.decode(String.self, forKey: .url) let url = try container.decode(String.self, forKey: .url)
self = .openUrl(url: url) self = .openUrl(url: url)
case .none: case .none:
self = .none self = .none
} }
} }
} }
enum LongActionType: Decodable { enum LongActionType: Decodable {
case none case none
case hidKey(keycode: Int32) case hidKey(keycode: Int32)
case keyPress(keycode: Int) case keyPress(keycode: Int)
case appleScript(source: SourceProtocol) case appleScript(source: SourceProtocol)
case shellScript(executable: String, parameters: [String]) case shellScript(executable: String, parameters: [String])
case custom(closure: ()->()) case custom(closure: () -> Void)
case openUrl(url: String) case openUrl(url: String)
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case longAction case longAction
case longKeycode case longKeycode
@ -407,7 +518,7 @@ enum LongActionType: Decodable {
case longShellArguments case longShellArguments
case longUrl case longUrl
} }
private enum LongActionTypeRaw: String, Decodable { private enum LongActionTypeRaw: String, Decodable {
case hidKey case hidKey
case keyPress case keyPress
@ -415,52 +526,51 @@ enum LongActionType: Decodable {
case shellScript case shellScript
case openUrl case openUrl
} }
init(from decoder: Decoder) throws { init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let longType = try container.decodeIfPresent(LongActionTypeRaw.self, forKey: .longAction) let longType = try container.decodeIfPresent(LongActionTypeRaw.self, forKey: .longAction)
switch longType { switch longType {
case .some(.hidKey): case .some(.hidKey):
let keycode = try container.decode(Int32.self, forKey: .longKeycode) let keycode = try container.decode(Int32.self, forKey: .longKeycode)
self = .hidKey(keycode: keycode) self = .hidKey(keycode: keycode)
case .some(.keyPress): case .some(.keyPress):
let keycode = try container.decode(Int.self, forKey: .longKeycode) let keycode = try container.decode(Int.self, forKey: .longKeycode)
self = .keyPress(keycode: keycode) self = .keyPress(keycode: keycode)
case .some(.appleScript): case .some(.appleScript):
let source = try container.decode(Source.self, forKey: .longActionAppleScript) let source = try container.decode(Source.self, forKey: .longActionAppleScript)
self = .appleScript(source: source) self = .appleScript(source: source)
case .some(.shellScript): case .some(.shellScript):
let executable = try container.decode(String.self, forKey: .longExecutablePath) let executable = try container.decode(String.self, forKey: .longExecutablePath)
let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? [] let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? []
self = .shellScript(executable: executable, parameters: parameters) self = .shellScript(executable: executable, parameters: parameters)
case .some(.openUrl): case .some(.openUrl):
let longUrl = try container.decode(String.self, forKey: .longUrl) let longUrl = try container.decode(String.self, forKey: .longUrl)
self = .openUrl(url: longUrl) self = .openUrl(url: longUrl)
case .none: case .none:
self = .none self = .none
} }
} }
} }
enum GeneralParameter { enum GeneralParameter {
case width(_: CGFloat) case width(_: CGFloat)
case image(source: SourceProtocol) case image(source: SourceProtocol)
case align(_: Align) case align(_: Align)
case bordered(_: Bool) case bordered(_: Bool)
case background(_:NSColor) case background(_: NSColor)
case title(_:String) case title(_: String)
} }
struct GeneralParameters: Decodable { struct GeneralParameters: Decodable {
let parameters: [GeneralParameters.CodingKeys: GeneralParameter] let parameters: [GeneralParameters.CodingKeys: GeneralParameter]
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case width case width
case image case image
@ -469,34 +579,34 @@ struct GeneralParameters: Decodable {
case background case background
case title case title
} }
init(from decoder: Decoder) throws { init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
var result: [GeneralParameters.CodingKeys: GeneralParameter] = [:] var result: [GeneralParameters.CodingKeys: GeneralParameter] = [:]
if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) { if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) {
result[.width] = .width(value) result[.width] = .width(value)
} }
if let imageSource = try container.decodeIfPresent(Source.self, forKey: .image) { if let imageSource = try container.decodeIfPresent(Source.self, forKey: .image) {
result[.image] = .image(source: imageSource) result[.image] = .image(source: imageSource)
} }
let align = try container.decodeIfPresent(Align.self, forKey: .align) ?? .center let align = try container.decodeIfPresent(Align.self, forKey: .align) ?? .center
result[.align] = .align(align) result[.align] = .align(align)
if let borderedFlag = try container.decodeIfPresent(Bool.self, forKey: .bordered) { if let borderedFlag = try container.decodeIfPresent(Bool.self, forKey: .bordered) {
result[.bordered] = .bordered(borderedFlag) result[.bordered] = .bordered(borderedFlag)
} }
if let backgroundColor = try container.decodeIfPresent(String.self, forKey: .background)?.hexColor { if let backgroundColor = try container.decodeIfPresent(String.self, forKey: .background)?.hexColor {
result[.background] = .background(backgroundColor) result[.background] = .background(backgroundColor)
} }
if let title = try container.decodeIfPresent(String.self, forKey: .title) { if let title = try container.decodeIfPresent(String.self, forKey: .title) {
result[.title] = .title(title) result[.title] = .title(title)
} }
parameters = result parameters = result
} }
} }
@ -512,35 +622,35 @@ struct Source: Decodable, SourceProtocol {
let filePath: String? let filePath: String?
let base64: String? let base64: String?
let inline: String? let inline: String?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case filePath case filePath
case base64 case base64
case inline case inline
} }
var data: Data? { var data: Data? {
return base64?.base64Data ?? inline?.data(using: .utf8) ?? filePath?.fileData return base64?.base64Data ?? inline?.data(using: .utf8) ?? filePath?.fileData
} }
var string: String? { var string: String? {
return inline ?? filePath?.fileString return inline ?? filePath?.fileString
} }
var image: NSImage? { var image: NSImage? {
return data?.image return data?.image
} }
var appleScript: NSAppleScript? { var appleScript: NSAppleScript? {
return filePath?.fileURL.appleScript ?? self.string?.appleScript return filePath?.fileURL.appleScript ?? string?.appleScript
} }
private init(filePath: String?, base64: String?, inline: String?) { private init(filePath: String?, base64: String?, inline: String?) {
self.filePath = filePath self.filePath = filePath
self.base64 = base64 self.base64 = base64
self.inline = inline self.inline = inline
} }
init(filePath: String) { init(filePath: String) {
self.init(filePath: filePath, base64: nil, inline: nil) self.init(filePath: filePath, base64: nil, inline: nil)
} }
@ -550,15 +660,15 @@ extension NSImage: SourceProtocol {
var data: Data? { var data: Data? {
return nil return nil
} }
var string: String? { var string: String? {
return nil return nil
} }
var image: NSImage? { var image: NSImage? {
return self return self
} }
var appleScript: NSAppleScript? { var appleScript: NSAppleScript? {
return nil return nil
} }
@ -568,23 +678,22 @@ extension String {
var base64Data: Data? { var base64Data: Data? {
return Data(base64Encoded: self) return Data(base64Encoded: self)
} }
var fileData: Data? { var fileData: Data? {
return try? Data(contentsOf: URL(fileURLWithPath: self)) return try? Data(contentsOf: URL(fileURLWithPath: self))
} }
var fileString: String? { var fileString: String? {
var encoding: String.Encoding = .utf8 var encoding: String.Encoding = .utf8
return try? String(contentsOfFile: self, usedEncoding: &encoding) return try? String(contentsOfFile: self, usedEncoding: &encoding)
} }
} }
extension Data { extension Data {
var utf8string: String? { var utf8string: String? {
return String(data: self, encoding: .utf8) return String(data: self, encoding: .utf8)
} }
var image: NSImage? { var image: NSImage? {
return NSImage(data: self)?.resize(maxSize: NSSize(width: 24, height: 24)) return NSImage(data: self)?.resize(maxSize: NSSize(width: 24, height: 24))
} }
@ -600,7 +709,7 @@ extension String {
var fileURL: URL { var fileURL: URL {
return URL(fileURLWithPath: self) return URL(fileURLWithPath: self)
} }
var appleScript: NSAppleScript? { var appleScript: NSAppleScript? {
return NSAppleScript(source: self) return NSAppleScript(source: self)
} }
@ -608,7 +717,7 @@ extension String {
extension URL { extension URL {
var appleScript: NSAppleScript? { 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) return NSAppleScript(contentsOf: self, error: nil)
} }
} }

View File

@ -18,7 +18,7 @@ struct GenericKeyPress: KeyPress {
} }
extension KeyPress { extension KeyPress {
func send () { func send() {
let src = CGEventSource(stateID: .hidSystemState) let src = CGEventSource(stateID: .hidSystemState)
let keyDown = CGEvent(keyboardEventSource: src, virtualKey: keyCode, keyDown: true) let keyDown = CGEvent(keyboardEventSource: src, virtualKey: keyCode, keyDown: true)
let keyUp = CGEvent(keyboardEventSource: src, virtualKey: keyCode, keyDown: false) let keyUp = CGEvent(keyboardEventSource: src, virtualKey: keyCode, keyDown: false)

View File

@ -3,7 +3,7 @@ import Foundation
class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate { class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
var twofingersPrev: CGFloat = 0.0 var twofingersPrev: CGFloat = 0.0
var threefingersPrev: CGFloat = 0.0 var threefingersPrev: CGFloat = 0.0
init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem]) { init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem]) {
super.init(identifier: identifier) super.init(identifier: identifier)
let views = items.compactMap { $0.view } let views = items.compactMap { $0.view }
@ -12,31 +12,31 @@ class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
stackView.orientation = .horizontal stackView.orientation = .horizontal
let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize)) let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize))
scrollView.documentView = stackView scrollView.documentView = stackView
self.view = scrollView view = scrollView
let twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:))) let twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:)))
twofingers.allowedTouchTypes = .direct twofingers.allowedTouchTypes = .direct
twofingers.numberOfTouchesRequired = 2 twofingers.numberOfTouchesRequired = 2
self.view.addGestureRecognizer(twofingers) view.addGestureRecognizer(twofingers)
let threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:))) let threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:)))
threefingers.allowedTouchTypes = .direct threefingers.allowedTouchTypes = .direct
threefingers.numberOfTouchesRequired = 3 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") fatalError("init(coder:) has not been implemented")
} }
@objc func twofingersHandler(_ sender: NSGestureRecognizer?) { // Volume @objc func twofingersHandler(_ sender: NSGestureRecognizer?) { // Volume
let position = (sender?.location(in: sender?.view).x)! let position = (sender?.location(in: sender?.view).x)!
switch sender!.state { switch sender!.state {
case .began: case .began:
twofingersPrev = position twofingersPrev = position
case .changed: case .changed:
if (((position-twofingersPrev) > 10) || ((twofingersPrev-position) > 10)) { if ((position - twofingersPrev) > 10) || ((twofingersPrev - position) > 10) {
if position > twofingersPrev { if position > twofingersPrev {
HIDPostAuxKey(NX_KEYTYPE_SOUND_UP) HIDPostAuxKey(NX_KEYTYPE_SOUND_UP)
} else if position < twofingersPrev { } else if position < twofingersPrev {
@ -50,15 +50,15 @@ class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
break break
} }
} }
@objc func threefingersHandler(_ sender: NSGestureRecognizer?) { // Brightness @objc func threefingersHandler(_ sender: NSGestureRecognizer?) { // Brightness
let position = (sender?.location(in: sender?.view).x)! let position = (sender?.location(in: sender?.view).x)!
switch sender!.state { switch sender!.state {
case .began: case .began:
threefingersPrev = position threefingersPrev = position
case .changed: case .changed:
if (((position-threefingersPrev) > 15) || ((threefingersPrev-position) > 15)) { if ((position - threefingersPrev) > 15) || ((threefingersPrev - position) > 15) {
if position > threefingersPrev { if position > threefingersPrev {
GenericKeyPress(keyCode: CGKeyCode(144)).send() GenericKeyPress(keyCode: CGKeyCode(144)).send()
} else if position < threefingersPrev { } else if position < threefingersPrev {

View File

@ -13,12 +13,12 @@ extension String {
func trim() -> String { func trim() -> String {
return self.trimmingCharacters(in: NSCharacterSet.whitespaces) return self.trimmingCharacters(in: NSCharacterSet.whitespaces)
} }
func stripComments() -> String { func stripComments() -> String {
// ((\s|,)\/\*[\s\S]*?\*\/)|(( |, ")\/\/.*) // ((\s|,)\/\*[\s\S]*?\*\/)|(( |, ")\/\/.*)
return self.replacingOccurrences(of: "((\\s|,)\\/\\*[\\s\\S]*?\\*\\/)|(( |, \\\")\\/\\/.*)", with: "", options: .regularExpression) return self.replacingOccurrences(of: "((\\s|,)\\/\\*[\\s\\S]*?\\*\\/)|(( |, \\\")\\/\\/.*)", with: "", options: .regularExpression)
} }
var hexColor: NSColor? { var hexColor: NSColor? {
let hex = trimmingCharacters(in: CharacterSet.alphanumerics.inverted) let hex = trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int = UInt32() var int = UInt32()
@ -45,7 +45,7 @@ extension NSImage {
let imageHeight = Float(self.size.height) let imageHeight = Float(self.size.height)
let maxWidth = Float(maxSize.width) let maxWidth = Float(maxSize.width)
let maxHeight = Float(maxSize.height) let maxHeight = Float(maxSize.height)
// Get ratio (landscape or portrait) // Get ratio (landscape or portrait)
if (imageWidth > imageHeight) { if (imageWidth > imageHeight) {
// Landscape // Landscape
@ -55,27 +55,27 @@ extension NSImage {
// Portrait // Portrait
ratio = maxHeight / imageHeight; ratio = maxHeight / imageHeight;
} }
// Calculate new size based on the ratio // Calculate new size based on the ratio
let newWidth = imageWidth * ratio let newWidth = imageWidth * ratio
let newHeight = imageHeight * ratio let newHeight = imageHeight * ratio
// Create a new NSSize object with the newly calculated size // Create a new NSSize object with the newly calculated size
let newSize:NSSize = NSSize(width: Int(newWidth), height: Int(newHeight)) let newSize:NSSize = NSSize(width: Int(newWidth), height: Int(newHeight))
// Cast the NSImage to a CGImage // Cast the NSImage to a CGImage
var imageRect:NSRect = NSMakeRect(0, 0, self.size.width, self.size.height) var imageRect:NSRect = NSMakeRect(0, 0, self.size.width, self.size.height)
let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil) let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)
// Create NSImage from the CGImage using the new size // Create NSImage from the CGImage using the new size
let imageWithNewSize = NSImage(cgImage: imageRef!, size: newSize) let imageWithNewSize = NSImage(cgImage: imageRef!, size: newSize)
// Return the new image // Return the new image
return imageWithNewSize return imageWithNewSize
} }
func rotateByDegreess(degrees:CGFloat) -> NSImage { func rotateByDegreess(degrees:CGFloat) -> NSImage {
var imageBounds = NSZeroRect ; imageBounds.size = self.size var imageBounds = NSZeroRect ; imageBounds.size = self.size
let pathBounds = NSBezierPath(rect: imageBounds) let pathBounds = NSBezierPath(rect: imageBounds)
var transform = NSAffineTransform() var transform = NSAffineTransform()
@ -83,11 +83,11 @@ extension NSImage {
pathBounds.transform(using: transform as AffineTransform) pathBounds.transform(using: transform as AffineTransform)
let rotatedBounds:NSRect = NSMakeRect(NSZeroPoint.x, NSZeroPoint.y , self.size.width, self.size.height ) let rotatedBounds:NSRect = NSMakeRect(NSZeroPoint.x, NSZeroPoint.y , self.size.width, self.size.height )
let rotatedImage = NSImage(size: rotatedBounds.size) let rotatedImage = NSImage(size: rotatedBounds.size)
//Center the image within the rotated bounds //Center the image within the rotated bounds
imageBounds.origin.x = NSMidX(rotatedBounds) - (NSWidth(imageBounds) / 2) imageBounds.origin.x = NSMidX(rotatedBounds) - (NSWidth(imageBounds) / 2)
imageBounds.origin.y = NSMidY(rotatedBounds) - (NSHeight(imageBounds) / 2) imageBounds.origin.y = NSMidY(rotatedBounds) - (NSHeight(imageBounds) / 2)
// Start a new transform // Start a new transform
transform = NSAffineTransform() transform = NSAffineTransform()
// Move coordinate system to the center (since we want to rotate around the center) // Move coordinate system to the center (since we want to rotate around the center)
@ -100,7 +100,7 @@ extension NSImage {
transform.concat() transform.concat()
self.draw(in: imageBounds, from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0) self.draw(in: imageBounds, from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0)
rotatedImage.unlockFocus() rotatedImage.unlockFocus()
return rotatedImage return rotatedImage
} }

View File

@ -6,7 +6,7 @@
// Copyright © 2018 Anton Palgunov. All rights reserved. // 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, *) { if #available(OSX 10.14, *) {
NSTouchBar.presentSystemModalTouchBar(touchBar, systemTrayItemIdentifier: identifier) NSTouchBar.presentSystemModalTouchBar(touchBar, systemTrayItemIdentifier: identifier)
} else { } 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, *) { if #available(OSX 10.14, *) {
NSTouchBar.presentSystemModalTouchBar(touchBar, placement: placement, systemTrayItemIdentifier: identifier) NSTouchBar.presentSystemModalTouchBar(touchBar, placement: placement, systemTrayItemIdentifier: identifier)
} else { } 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, *) { if #available(OSX 10.14, *) {
NSTouchBar.minimizeSystemModalTouchBar(touchBar) NSTouchBar.minimizeSystemModalTouchBar(touchBar)
} else { } else {

View File

@ -8,11 +8,10 @@
import Cocoa import Cocoa
class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrubberDataSource { class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrubberDataSource {
private var scrubber: NSScrubber! private var scrubber: NSScrubber!
private let hf: HapticFeedback = HapticFeedback() private let hf: HapticFeedback = HapticFeedback()
private var timer: Timer! private var timer: Timer!
private var ticks: Int = 0 private var ticks: Int = 0
private let minTicks: Int = 5 private let minTicks: Int = 5
@ -21,24 +20,22 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
private var persistentAppIdentifiers: [String] = [] private var persistentAppIdentifiers: [String] = []
private var runningAppsIdentifiers: [String] = [] private var runningAppsIdentifiers: [String] = []
private var frontmostApplicationIdentifier: String? { private var frontmostApplicationIdentifier: String? {
get { guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil }
guard let frontmostId = NSWorkspace.shared.frontmostApplication?.bundleIdentifier else { return nil } return frontmostId
return frontmostId
}
} }
private var applications: [DockItem] = [] private var applications: [DockItem] = []
override init(identifier: NSTouchBarItem.Identifier) { override init(identifier: NSTouchBarItem.Identifier) {
super.init(identifier: identifier) super.init(identifier: identifier)
scrubber = NSScrubber(); scrubber = NSScrubber()
scrubber.delegate = self scrubber.delegate = self
scrubber.dataSource = self scrubber.dataSource = self
scrubber.mode = .free // .fixed scrubber.mode = .free // .fixed
let layout = NSScrubberFlowLayout(); let layout = NSScrubberFlowLayout()
layout.itemSize = NSSize(width: 36, height: 32) layout.itemSize = NSSize(width: 36, height: 32)
layout.itemSpacing = 2 layout.itemSpacing = 2
scrubber.scrubberLayout = layout scrubber.scrubberLayout = layout
@ -46,35 +43,35 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
scrubber.showsAdditionalContentIndicators = true scrubber.showsAdditionalContentIndicators = true
view = scrubber view = scrubber
scrubber.register(NSScrubberImageItemView.self, forItemIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ScrubberApplicationsItemReuseIdentifier")) 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.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.didTerminateApplicationNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didActivateApplicationNotification, 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") { if let persistent = UserDefaults.standard.stringArray(forKey: "com.toxblh.mtmr.dock.persistent") {
self.persistentAppIdentifiers = persistent persistentAppIdentifiers = persistent
} }
updateRunningApplication() updateRunningApplication()
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@objc func activeApplicationChanged(n: Notification) { @objc func activeApplicationChanged(n _: Notification) {
updateRunningApplication() 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() updateRunningApplication()
} }
func updateRunningApplication() { func updateRunningApplication() {
let newApplications = launchedApplications() let newApplications = launchedApplications()
let index = newApplications.index { let index = newApplications.index {
$0.bundleIdentifier == frontmostApplicationIdentifier $0.bundleIdentifier == frontmostApplicationIdentifier
} }
@ -82,30 +79,30 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
applications = newApplications applications = newApplications
applications += getDockPersistentAppsList() applications += getDockPersistentAppsList()
scrubber.reloadData() scrubber.reloadData()
scrubber.selectedIndex = index ?? 0 scrubber.selectedIndex = index ?? 0
} }
public func numberOfItems(for scrubber: NSScrubber) -> Int { public func numberOfItems(for _: NSScrubber) -> Int {
return applications.count return applications.count
} }
public func scrubber(_ scrubber: NSScrubber, viewForItemAt index: Int) -> NSScrubberItemView { public func scrubber(_ scrubber: NSScrubber, viewForItemAt index: Int) -> NSScrubberItemView {
let item = scrubber.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ScrubberApplicationsItemReuseIdentifier"), owner: self) as? NSScrubberImageItemView ?? NSScrubberImageItemView() let item = scrubber.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ScrubberApplicationsItemReuseIdentifier"), owner: self) as? NSScrubberImageItemView ?? NSScrubberImageItemView()
item.imageView.imageScaling = .scaleProportionallyDown item.imageView.imageScaling = .scaleProportionallyDown
let app = applications[index] let app = applications[index]
if let icon = app.icon { if let icon = app.icon {
item.image = icon item.image = icon
item.image.size = NSSize(width: 26, height: 26) item.image.size = NSSize(width: 26, height: 26)
} }
item.removeFromSuperview() item.removeFromSuperview()
let dotView = NSView(frame: .zero) let dotView = NSView(frame: .zero)
dotView.wantsLayer = true dotView.wantsLayer = true
if self.runningAppsIdentifiers.contains(app.bundleIdentifier!) { if runningAppsIdentifiers.contains(app.bundleIdentifier!) {
dotView.layer?.backgroundColor = NSColor.white.cgColor dotView.layer?.backgroundColor = NSColor.white.cgColor
} else { } else {
dotView.layer?.backgroundColor = NSColor.black.cgColor dotView.layer?.backgroundColor = NSColor.black.cgColor
@ -117,48 +114,48 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
return item return item
} }
public func didBeginInteracting(with scrubber: NSScrubber) { public func didBeginInteracting(with _: NSScrubber) {
stopTimer() stopTimer()
self.ticks = 0 ticks = 0
self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(checkTimer), userInfo: nil, repeats: true) timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(checkTimer), userInfo: nil, repeats: true)
} }
@objc private func checkTimer() { @objc private func checkTimer() {
self.ticks += 1 ticks += 1
if (self.ticks == minTicks) { if ticks == minTicks {
hf.tap(strong: 2) hf.tap(strong: 2)
} }
if (self.ticks > maxTicks) { if ticks > maxTicks {
stopTimer() stopTimer()
hf.tap(strong: 6) hf.tap(strong: 6)
} }
} }
private func stopTimer() { private func stopTimer() {
self.timer?.invalidate() timer?.invalidate()
self.timer = nil timer = nil
self.lastSelected = 0 lastSelected = 0
} }
public func didCancelInteracting(with scrubber: NSScrubber) { public func didCancelInteracting(with _: NSScrubber) {
stopTimer() stopTimer()
} }
public func didFinishInteracting(with scrubber: NSScrubber) { public func didFinishInteracting(with scrubber: NSScrubber) {
stopTimer() stopTimer()
if (ticks == 0) { if ticks == 0 {
return return
} }
if (self.ticks >= minTicks && scrubber.selectedIndex > 0) { if ticks >= minTicks && scrubber.selectedIndex > 0 {
self.longPress(selected: scrubber.selectedIndex) longPress(selected: scrubber.selectedIndex)
return return
} }
let bundleIdentifier = applications[scrubber.selectedIndex].bundleIdentifier let bundleIdentifier = applications[scrubber.selectedIndex].bundleIdentifier
if bundleIdentifier!.contains("file://") { if bundleIdentifier!.contains("file://") {
NSWorkspace.shared.openFile(bundleIdentifier!.replacingOccurrences(of: "file://", with: "")) NSWorkspace.shared.openFile(bundleIdentifier!.replacingOccurrences(of: "file://", with: ""))
@ -167,16 +164,16 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
hf.tap(strong: 6) hf.tap(strong: 6)
} }
updateRunningApplication() updateRunningApplication()
// NB: if you can't open app which on another space, try to check mark // 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" // "When switching to an application, switch to a Space with open windows for the application"
// in Mission control settings // in Mission control settings
} }
private func longPress(selected: Int) { private func longPress(selected: Int) {
let bundleIdentifier = applications[selected].bundleIdentifier let bundleIdentifier = applications[selected].bundleIdentifier
if (self.ticks > maxTicks) { if ticks > maxTicks {
if let processIdentifier = applications[selected].pid { if let processIdentifier = applications[selected].pid {
if !(NSRunningApplication(processIdentifier: processIdentifier)?.terminate())! { if !(NSRunningApplication(processIdentifier: processIdentifier)?.terminate())! {
NSRunningApplication(processIdentifier: processIdentifier)?.forceTerminate() NSRunningApplication(processIdentifier: processIdentifier)?.forceTerminate()
@ -185,34 +182,34 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
} else { } else {
hf.tap(strong: 6) hf.tap(strong: 6)
if let index = self.persistentAppIdentifiers.index(of: bundleIdentifier!) { if let index = self.persistentAppIdentifiers.index(of: bundleIdentifier!) {
self.persistentAppIdentifiers.remove(at: index) persistentAppIdentifiers.remove(at: index)
} else { } 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() UserDefaults.standard.synchronize()
} }
self.ticks = 0 ticks = 0
updateRunningApplication() updateRunningApplication()
} }
private func launchedApplications() -> [DockItem] { private func launchedApplications() -> [DockItem] {
self.runningAppsIdentifiers = [] runningAppsIdentifiers = []
var returnable: [DockItem] = [] var returnable: [DockItem] = []
for app in NSWorkspace.shared.runningApplications { for app in NSWorkspace.shared.runningApplications {
guard app.activationPolicy == NSApplication.ActivationPolicy.regular else { continue } guard app.activationPolicy == NSApplication.ActivationPolicy.regular else { continue }
guard let bundleIdentifier = app.bundleIdentifier 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) let dockItem = DockItem(bundleIdentifier: bundleIdentifier, icon: getIcon(forBundleIdentifier: bundleIdentifier), pid: app.processIdentifier)
returnable.append(dockItem) returnable.append(dockItem)
} }
return returnable 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 bundleIdentifier != nil {
if let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: bundleIdentifier!) { if let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: bundleIdentifier!) {
return NSWorkspace.shared.icon(forFile: appPath) 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") let genericIcon = NSImage(contentsOfFile: "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericDocumentIcon.icns")
return genericIcon ?? NSImage(size: .zero) return genericIcon ?? NSImage(size: .zero)
} }
public func getDockPersistentAppsList() -> [DockItem] { public func getDockPersistentAppsList() -> [DockItem] {
var returnable: [DockItem] = [] var returnable: [DockItem] = []
for bundleIdentifier in persistentAppIdentifiers { for bundleIdentifier in persistentAppIdentifiers {
if !self.runningAppsIdentifiers.contains(bundleIdentifier) { if !runningAppsIdentifiers.contains(bundleIdentifier) {
let dockItem = DockItem(bundleIdentifier: bundleIdentifier, icon: getIcon(forBundleIdentifier: bundleIdentifier)) let dockItem = DockItem(bundleIdentifier: bundleIdentifier, icon: getIcon(forBundleIdentifier: bundleIdentifier))
returnable.append(dockItem) returnable.append(dockItem)
} }

View File

@ -6,29 +6,29 @@
// Copyright © 2018 Anton Palgunov. All rights reserved. // Copyright © 2018 Anton Palgunov. All rights reserved.
// //
import IOKit.ps
import Foundation import Foundation
import IOKit.ps
class BatteryBarItem: CustomButtonTouchBarItem { class BatteryBarItem: CustomButtonTouchBarItem {
private let batteryInfo = BatteryInfo() private let batteryInfo = BatteryInfo()
init(identifier: NSTouchBarItem.Identifier) { init(identifier: NSTouchBarItem.Identifier) {
super.init(identifier: identifier, title: " ") super.init(identifier: identifier, title: " ")
batteryInfo.start { [weak self] in batteryInfo.start { [weak self] in
self?.refresh() self?.refresh()
} }
self.refresh() refresh()
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
func refresh() { func refresh() {
self.attributedTitle = self.batteryInfo.formattedInfo() attributedTitle = batteryInfo.formattedInfo()
} }
deinit { deinit {
batteryInfo.stop() batteryInfo.stop()
} }
@ -42,85 +42,85 @@ class BatteryInfo: NSObject {
var isCharging: Bool = false var isCharging: Bool = false
var ACPower: String = "" var ACPower: String = ""
var timeRemaining: String = "" var timeRemaining: String = ""
var notifyBlock: ()->() = {} var notifyBlock: () -> Void = {}
var loop:CFRunLoopSource? var loop: CFRunLoopSource?
func start(notifyBlock: @escaping ()->()) { func start(notifyBlock: @escaping () -> Void) {
self.notifyBlock = notifyBlock self.notifyBlock = notifyBlock
let opaque = Unmanaged.passRetained(self).toOpaque() let opaque = Unmanaged.passRetained(self).toOpaque()
let context = UnsafeMutableRawPointer(opaque) let context = UnsafeMutableRawPointer(opaque)
loop = IOPSNotificationCreateRunLoopSource({ (context) in loop = IOPSNotificationCreateRunLoopSource({ context in
guard let ctx = context else { guard let ctx = context else {
return return
} }
let watcher = Unmanaged<BatteryInfo>.fromOpaque(ctx).takeUnretainedValue() let watcher = Unmanaged<BatteryInfo>.fromOpaque(ctx).takeUnretainedValue()
watcher.notifyBlock() watcher.notifyBlock()
}, context).takeRetainedValue() as CFRunLoopSource }, context).takeRetainedValue() as CFRunLoopSource
CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode) CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode)
} }
func stop() { func stop() {
self.notifyBlock = {} notifyBlock = {}
guard let loop = self.loop else { guard let loop = self.loop else {
return return
} }
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode) CFRunLoopRemoveSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode)
self.loop = nil self.loop = nil
} }
func getPSInfo() { func getPSInfo() {
let psInfo = IOPSCopyPowerSourcesInfo().takeRetainedValue() let psInfo = IOPSCopyPowerSourcesInfo().takeRetainedValue()
let psList = IOPSCopyPowerSourcesList(psInfo).takeRetainedValue() as [CFTypeRef] let psList = IOPSCopyPowerSourcesList(psInfo).takeRetainedValue() as [CFTypeRef]
for ps in psList { for ps in psList {
if let psDesc = IOPSGetPowerSourceDescription(psInfo, ps).takeUnretainedValue() as? [String: Any] { if let psDesc = IOPSGetPowerSourceDescription(psInfo, ps).takeUnretainedValue() as? [String: Any] {
let current = psDesc[kIOPSCurrentCapacityKey] let current = psDesc[kIOPSCurrentCapacityKey]
if (current != nil) { if current != nil {
self.current = current as! Int self.current = current as! Int
} }
let timeToEmpty = psDesc[kIOPSTimeToEmptyKey] let timeToEmpty = psDesc[kIOPSTimeToEmptyKey]
if (timeToEmpty != nil) { if timeToEmpty != nil {
self.timeToEmpty = timeToEmpty as! Int self.timeToEmpty = timeToEmpty as! Int
} }
let timeToFull = psDesc[kIOPSTimeToFullChargeKey] let timeToFull = psDesc[kIOPSTimeToFullChargeKey]
if (timeToFull != nil) { if timeToFull != nil {
self.timeToFull = timeToFull as! Int self.timeToFull = timeToFull as! Int
} }
let isCharged = psDesc[kIOPSIsChargedKey] let isCharged = psDesc[kIOPSIsChargedKey]
if (isCharged != nil) { if isCharged != nil {
self.isCharged = isCharged as! Bool self.isCharged = isCharged as! Bool
} }
let isCharging = psDesc[kIOPSIsChargingKey] let isCharging = psDesc[kIOPSIsChargingKey]
if (isCharging != nil) { if isCharging != nil {
self.isCharging = isCharging as! Bool self.isCharging = isCharging as! Bool
} }
let ACPower = psDesc[kIOPSPowerSourceStateKey] let ACPower = psDesc[kIOPSPowerSourceStateKey]
if (ACPower != nil) { if ACPower != nil {
self.ACPower = ACPower as! String self.ACPower = ACPower as! String
} }
} }
} }
} }
func getFormattedTime(time: Int) -> String { func getFormattedTime(time: Int) -> String {
if (time > 0) { if time > 0 {
let timeFormatted = NSString(format: " %d:%02d", time / 60, time % 60) as String let timeFormatted = NSString(format: " %d:%02d", time / 60, time % 60) as String
return timeFormatted return timeFormatted
} }
return "" return ""
} }
public func formattedInfo() -> NSAttributedString { public func formattedInfo() -> NSAttributedString {
var title = "" var title = ""
self.getPSInfo() getPSInfo()
if ACPower == "AC Power" { if ACPower == "AC Power" {
if current < 100 { if current < 100 {
title += "⚡️" title += "⚡️"
@ -129,19 +129,18 @@ class BatteryInfo: NSObject {
} else { } else {
timeRemaining = getFormattedTime(time: timeToEmpty) timeRemaining = getFormattedTime(time: timeToEmpty)
} }
title += String(current) + "%" title += String(current) + "%"
var color = NSColor.white var color = NSColor.white
if current <= 10 && ACPower != "AC Power" { if current <= 10 && ACPower != "AC Power" {
color = NSColor.red color = NSColor.red
} }
let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: NSFont.systemFont(ofSize: 15), .baselineOffset: 1]) 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]) 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.append(newTitleSecond)
newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count)) newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
return newTitle return newTitle
} }
} }

View File

@ -1,54 +1,54 @@
import Cocoa
import AppKit import AppKit
import AVFoundation import AVFoundation
import Cocoa
import CoreAudio import CoreAudio
class BrightnessViewController: NSCustomTouchBarItem { class BrightnessViewController: NSCustomTouchBarItem {
private(set) var sliderItem: CustomSlider! private(set) var sliderItem: CustomSlider!
init(identifier: NSTouchBarItem.Identifier, refreshInterval: Double, image: NSImage? = nil) { init(identifier: NSTouchBarItem.Identifier, refreshInterval: Double, image: NSImage? = nil) {
super.init(identifier: identifier) super.init(identifier: identifier)
if (image == nil) { if image == nil {
sliderItem = CustomSlider() sliderItem = CustomSlider()
} else { } else {
sliderItem = CustomSlider(knob: image!) sliderItem = CustomSlider(knob: image!)
} }
sliderItem.target = self sliderItem.target = self
sliderItem.action = #selector(BrightnessViewController.sliderValueChanged(_:)) sliderItem.action = #selector(BrightnessViewController.sliderValueChanged(_:))
sliderItem.minValue = 0.0 sliderItem.minValue = 0.0
sliderItem.maxValue = 100.0 sliderItem.maxValue = 100.0
sliderItem.floatValue = getBrightness() * 100 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) let timer = Timer.scheduledTimer(timeInterval: refreshInterval, target: self, selector: #selector(BrightnessViewController.updateBrightnessSlider), userInfo: nil, repeats: true)
RunLoop.current.add(timer, forMode: RunLoop.Mode.common) RunLoop.current.add(timer, forMode: RunLoop.Mode.common)
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit { deinit {
sliderItem.unbind(NSBindingName.value) sliderItem.unbind(NSBindingName.value)
} }
@objc func updateBrightnessSlider() { @objc func updateBrightnessSlider() {
DispatchQueue.main.async { DispatchQueue.main.async {
self.sliderItem.floatValue = self.getBrightness() * 100 self.sliderItem.floatValue = self.getBrightness() * 100
} }
} }
@objc func sliderValueChanged(_ sender: Any) { @objc func sliderValueChanged(_ sender: Any) {
if let sliderItem = sender as? NSSlider { if let sliderItem = sender as? NSSlider {
setBrightness(level: Float32(sliderItem.intValue)/100.0) setBrightness(level: Float32(sliderItem.intValue) / 100.0)
} }
} }
private func getBrightness() -> Float32 { private func getBrightness() -> Float32 {
if #available(OSX 10.13, *) { if #available(OSX 10.13, *) {
return Float32(CoreDisplay_Display_GetUserBrightness(0)); return Float32(CoreDisplay_Display_GetUserBrightness(0))
} else { } else {
var level: Float32 = 0.5 var level: Float32 = 0.5
let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect")) let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"))
@ -57,16 +57,15 @@ class BrightnessViewController: NSCustomTouchBarItem {
return level return level
} }
} }
private func setBrightness(level: Float) { private func setBrightness(level: Float) {
if #available(OSX 10.13, *) { if #available(OSX 10.13, *) {
CoreDisplay_Display_SetUserBrightness(0, Double(level)); CoreDisplay_Display_SetUserBrightness(0, Double(level))
} else { } else {
let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect")) let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"))
IODisplaySetFloatParameter(service, 1, kIODisplayBrightnessKey as CFString, level) IODisplaySetFloatParameter(service, 1, kIODisplayBrightnessKey as CFString, level)
IOObjectRelease(service) IOObjectRelease(service)
} }
} }
} }

View File

@ -45,7 +45,7 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
if let prefix = currencies[from] { if let prefix = currencies[from] {
self.prefix = prefix self.prefix = prefix
} else { } else {
self.prefix = from prefix = from
} }
super.init(identifier: identifier, title: "") super.init(identifier: identifier, title: "")
@ -59,21 +59,21 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
updateCurrency() updateCurrency()
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@objc func updateCurrency() { @objc func updateCurrency() {
let urlRequest = URLRequest(url: URL(string: "https://api.coinbase.com/v2/exchange-rates?currency=\(from)")!) let urlRequest = URLRequest(url: URL(string: "https://api.coinbase.com/v2/exchange-rates?currency=\(from)")!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in let task = URLSession.shared.dataTask(with: urlRequest) { data, _, error in
if error == nil { if error == nil {
do { 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! var value: Float32!
if let data_array = json["data"] as? [String : AnyObject] { if let data_array = json["data"] as? [String: AnyObject] {
if let rates = data_array["rates"] as? [String : AnyObject] { if let rates = data_array["rates"] as? [String: AnyObject] {
if let item = rates["\(self.to)"] as? String { if let item = rates["\(self.to)"] as? String {
value = Float32(item) value = Float32(item)
} }
@ -103,13 +103,13 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
color = NSColor.red 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]) let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: regularFont])
newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count)) newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
self.attributedTitle = newTitle attributedTitle = newTitle
} }
} }

View File

@ -8,49 +8,49 @@
import Foundation import Foundation
class DnDBarItem : CustomButtonTouchBarItem { class DnDBarItem: CustomButtonTouchBarItem {
private var timer: Timer! private var timer: Timer!
init(identifier: NSTouchBarItem.Identifier) { init(identifier: NSTouchBarItem.Identifier) {
super.init(identifier: identifier, title: "") super.init(identifier: identifier, title: "")
self.isBordered = false isBordered = false
self.setWidth(value: 32) setWidth(value: 32)
self.tapClosure = { [weak self] in self?.DnDToggle() } tapClosure = { [weak self] in self?.DnDToggle() }
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(refresh), userInfo: nil, repeats: true) 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") fatalError("init(coder:) has not been implemented")
} }
func DnDToggle() { func DnDToggle() {
DoNotDisturb.isEnabled = !DoNotDisturb.isEnabled DoNotDisturb.isEnabled = !DoNotDisturb.isEnabled
refresh() refresh()
} }
@objc func 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 { public struct DoNotDisturb {
private static let appId = "com.apple.notificationcenterui" as CFString private static let appId = "com.apple.notificationcenterui" as CFString
private static let dndPref = "com.apple.notificationcenterui.dndprefs_changed" private static let dndPref = "com.apple.notificationcenterui.dndprefs_changed"
private static func set(_ key: String, value: CFPropertyList?) { private static func set(_ key: String, value: CFPropertyList?) {
CFPreferencesSetValue(key as CFString, value, appId, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) CFPreferencesSetValue(key as CFString, value, appId, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost)
} }
private static func commitChanges() { private static func commitChanges() {
CFPreferencesSynchronize(appId, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) CFPreferencesSynchronize(appId, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost)
DistributedNotificationCenter.default().postNotificationName(NSNotification.Name(dndPref), object: nil, userInfo: nil, deliverImmediately: true) DistributedNotificationCenter.default().postNotificationName(NSNotification.Name(dndPref), object: nil, userInfo: nil, deliverImmediately: true)
NSRunningApplication.runningApplications(withBundleIdentifier: appId as String).first?.terminate() NSRunningApplication.runningApplications(withBundleIdentifier: appId as String).first?.terminate()
} }
private static func enable() { private static func enable() {
set("dndStart", value: nil) set("dndStart", value: nil)
set("dndEnd", value: nil) set("dndEnd", value: nil)
@ -58,7 +58,7 @@ public struct DoNotDisturb {
set("doNotDisturbDate", value: Date() as CFPropertyList) set("doNotDisturbDate", value: Date() as CFPropertyList)
commitChanges() commitChanges()
} }
private static func disable() { private static func disable() {
set("dndStart", value: nil) set("dndStart", value: nil)
set("dndEnd", value: nil) set("dndEnd", value: nil)
@ -66,8 +66,8 @@ public struct DoNotDisturb {
set("doNotDisturbDate", value: nil) set("doNotDisturbDate", value: nil)
commitChanges() commitChanges()
} }
static var isEnabled:Bool { static var isEnabled: Bool {
get { get {
return CFPreferencesGetAppBooleanValue("doNotDisturb" as CFString, appId, nil) return CFPreferencesGetAppBooleanValue("doNotDisturb" as CFString, appId, nil)
} }

View File

@ -8,9 +8,8 @@
import Cocoa import Cocoa
class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate { class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate {
var jsonItems: [BarItemDefinition] var jsonItems: [BarItemDefinition]
var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:] var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:] var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
var leftIdentifiers: [NSTouchBarItem.Identifier] = [] var leftIdentifiers: [NSTouchBarItem.Identifier] = []
@ -19,62 +18,60 @@ class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate {
var rightIdentifiers: [NSTouchBarItem.Identifier] = [] var rightIdentifiers: [NSTouchBarItem.Identifier] = []
var scrollArea: NSCustomTouchBarItem? var scrollArea: NSCustomTouchBarItem?
var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
init(identifier: NSTouchBarItem.Identifier, items: [BarItemDefinition]) { init(identifier: NSTouchBarItem.Identifier, items: [BarItemDefinition]) {
jsonItems = items jsonItems = items
super.init(identifier: identifier) 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") fatalError("init(coder:) has not been implemented")
} }
deinit { deinit {}
} @objc override func showPopover(_: Any?) {
itemDefinitions = [:]
@objc override func showPopover(_ sender: Any?) { items = [:]
self.itemDefinitions = [:] leftIdentifiers = []
self.items = [:] centerItems = []
self.leftIdentifiers = [] rightIdentifiers = []
self.centerItems = []
self.rightIdentifiers = [] loadItemDefinitions(jsonItems: jsonItems)
createItems()
self.loadItemDefinitions(jsonItems: jsonItems)
self.createItems()
centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
return items[identifier] items[identifier]
}) })
self.centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
self.scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems) scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
TouchBarController.shared.touchBar.delegate = self TouchBarController.shared.touchBar.delegate = self
TouchBarController.shared.touchBar.defaultItemIdentifiers = [] TouchBarController.shared.touchBar.defaultItemIdentifiers = []
TouchBarController.shared.touchBar.defaultItemIdentifiers = self.leftIdentifiers + [centerScrollArea] + self.rightIdentifiers TouchBarController.shared.touchBar.defaultItemIdentifiers = leftIdentifiers + [centerScrollArea] + rightIdentifiers
if TouchBarController.shared.showControlStripState { if TouchBarController.shared.showControlStripState {
presentSystemModal(TouchBarController.shared.touchBar, systemTrayItemIdentifier: .controlStripItem) presentSystemModal(TouchBarController.shared.touchBar, systemTrayItemIdentifier: .controlStripItem)
} else { } else {
presentSystemModal(TouchBarController.shared.touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem) 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 { if identifier == centerScrollArea {
return self.scrollArea return scrollArea
} }
guard let item = self.items[identifier], guard let item = self.items[identifier],
let definition = self.itemDefinitions[identifier], let definition = self.itemDefinitions[identifier],
definition.align != .center else { definition.align != .center else {
return nil return nil
} }
return item return item
} }
func loadItemDefinitions(jsonItems: [BarItemDefinition]) { func loadItemDefinitions(jsonItems: [BarItemDefinition]) {
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH-mm-ss" dateFormatter.dateFormat = "HH-mm-ss"
@ -94,10 +91,10 @@ class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate {
} }
} }
} }
func createItems() { func createItems() {
for (identifier, definition) in self.itemDefinitions { for (identifier, definition) in itemDefinitions {
self.items[identifier] = TouchBarController.shared.createItem(forIdentifier: identifier, definition: definition) items[identifier] = TouchBarController.shared.createItem(forIdentifier: identifier, definition: definition)
} }
} }
} }

View File

@ -9,33 +9,32 @@
import Cocoa import Cocoa
class InputSourceBarItem: CustomButtonTouchBarItem { class InputSourceBarItem: CustomButtonTouchBarItem {
fileprivate var notificationCenter: CFNotificationCenter fileprivate var notificationCenter: CFNotificationCenter
let buttonSize = NSSize(width: 21, height: 21) let buttonSize = NSSize(width: 21, height: 21)
init(identifier: NSTouchBarItem.Identifier) { init(identifier: NSTouchBarItem.Identifier) {
notificationCenter = CFNotificationCenterGetDistributedCenter(); notificationCenter = CFNotificationCenterGetDistributedCenter()
super.init(identifier: identifier, title: "") super.init(identifier: identifier, title: "")
observeIputSourceChangedNotification(); observeIputSourceChangedNotification()
textInputSourceDidChange() textInputSourceDidChange()
self.tapClosure = { [weak self] in tapClosure = { [weak self] in
self?.switchInputSource() self?.switchInputSource()
} }
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit { deinit {
CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())); CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque()))
} }
@objc public func textInputSourceDidChange() { @objc public func textInputSourceDidChange() {
let currentSource = TISCopyCurrentKeyboardInputSource().takeUnretainedValue() let currentSource = TISCopyCurrentKeyboardInputSource().takeUnretainedValue()
var iconImage: NSImage? = nil var iconImage: NSImage?
if let imageURL = currentSource.iconImageURL, if let imageURL = currentSource.iconImageURL,
let image = NSImage(contentsOf: imageURL) { let image = NSImage(contentsOf: imageURL) {
@ -46,10 +45,10 @@ class InputSourceBarItem: CustomButtonTouchBarItem {
if let iconImage = iconImage { if let iconImage = iconImage {
iconImage.size = buttonSize iconImage.size = buttonSize
self.image = iconImage image = iconImage
self.title = "" title = ""
} else { } else {
self.title = currentSource.name title = currentSource.name
} }
} }
@ -65,15 +64,15 @@ class InputSourceBarItem: CustomButtonTouchBarItem {
}) })
for item in inputSources { for item in inputSources {
if (item.id != currentSource.id) { if item.id != currentSource.id {
TISSelectInputSource(item) TISSelectInputSource(item)
break break
} }
} }
} }
@objc public func observeIputSourceChangedNotification(){ @objc public func observeIputSourceChangedNotification() {
let callback: CFNotificationCallback = { center, observer, name, object, info in let callback: CFNotificationCallback = { _, observer, _, _, _ in
let mySelf = Unmanaged<InputSourceBarItem>.fromOpaque(observer!).takeUnretainedValue() let mySelf = Unmanaged<InputSourceBarItem>.fromOpaque(observer!).takeUnretainedValue()
mySelf.textInputSourceDidChange() mySelf.textInputSourceDidChange()
} }
@ -96,7 +95,7 @@ extension TISInputSource {
private func getProperty(_ key: CFString) -> AnyObject? { private func getProperty(_ key: CFString) -> AnyObject? {
let cfType = TISGetInputSourceProperty(self, key) let cfType = TISGetInputSourceProperty(self, key)
if (cfType != nil) { if cfType != nil {
return Unmanaged<AnyObject>.fromOpaque(cfType!).takeUnretainedValue() return Unmanaged<AnyObject>.fromOpaque(cfType!).takeUnretainedValue()
} else { } else {
return nil return nil
@ -131,4 +130,3 @@ extension TISInputSource {
return OpaquePointer(TISGetInputSourceProperty(self, kTISPropertyIconRef)) as IconRef? return OpaquePointer(TISGetInputSourceProperty(self, kTISPropertyIconRef)) as IconRef?
} }
} }

View File

@ -14,57 +14,57 @@ class MusicBarItem: CustomButtonTouchBarItem {
private var songTitle: String? private var songTitle: String?
private var timer: Timer? private var timer: Timer?
let buttonSize = NSSize(width: 21, height: 21) let buttonSize = NSSize(width: 21, height: 21)
let playerBundleIdentifiers = [ let playerBundleIdentifiers = [
"com.apple.iTunes", "com.apple.iTunes",
"com.spotify.client", "com.spotify.client",
"com.coppertino.Vox", "com.coppertino.Vox",
"com.google.Chrome", "com.google.Chrome",
"com.apple.Safari" "com.apple.Safari",
] ]
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval) { init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval) {
self.interval = interval self.interval = interval
super.init(identifier: identifier, title: "") super.init(identifier: identifier, title: "")
self.isBordered = false isBordered = false
self.tapClosure = { [weak self] in self?.playPause() } tapClosure = { [weak self] in self?.playPause() }
self.longTapClosure = { [weak self] in self?.nextTrack() } longTapClosure = { [weak self] in self?.nextTrack() }
self.refreshAndSchedule() refreshAndSchedule()
} }
@objc func marquee(){ @objc func marquee() {
let str = self.title let str = title
if (str.count > 10) { if str.count > 10 {
let indexFirst = str.index(str.startIndex, offsetBy: 0) let indexFirst = str.index(str.startIndex, offsetBy: 0)
let indexSecond = str.index(str.startIndex, offsetBy: 1) 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") fatalError("init(coder:) has not been implemented")
} }
@objc func playPause() { @objc func playPause() {
for ident in playerBundleIdentifiers { for ident in playerBundleIdentifiers {
if let musicPlayer = SBApplication(bundleIdentifier: ident) { if let musicPlayer = SBApplication(bundleIdentifier: ident) {
if (musicPlayer.isRunning) { if musicPlayer.isRunning {
if (musicPlayer.className == "SpotifyApplication") { if musicPlayer.className == "SpotifyApplication" {
let mp = (musicPlayer as SpotifyApplication) let mp = (musicPlayer as SpotifyApplication)
mp.playpause!() mp.playpause!()
return return
} else if (musicPlayer.className == "ITunesApplication") { } else if musicPlayer.className == "ITunesApplication" {
let mp = (musicPlayer as iTunesApplication) let mp = (musicPlayer as iTunesApplication)
mp.playpause!() mp.playpause!()
return return
} else if (musicPlayer.className == "VOXApplication") { } else if musicPlayer.className == "VOXApplication" {
let mp = (musicPlayer as VoxApplication) let mp = (musicPlayer as VoxApplication)
mp.playpause!() mp.playpause!()
return 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'. // 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 safariApplication = musicPlayer as SafariApplication
let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow }) let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow })
@ -74,7 +74,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
if (tab.URL?.starts(with: "https://music.yandex.ru"))! { if (tab.URL?.starts(with: "https://music.yandex.ru"))! {
_ = safariApplication.doJavaScript!("document.getElementsByClassName('player-controls__btn_play')[0].click()", in: tab) _ = safariApplication.doJavaScript!("document.getElementsByClassName('player-controls__btn_play')[0].click()", in: tab)
return 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) _ = safariApplication.doJavaScript!("document.getElementsByClassName('audio_page_player_play')[0].click()", in: tab)
return return
} else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! { } else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! {
@ -108,27 +108,27 @@ class MusicBarItem: CustomButtonTouchBarItem {
} }
} }
} }
@objc func nextTrack() { @objc func nextTrack() {
for ident in playerBundleIdentifiers { for ident in playerBundleIdentifiers {
if let musicPlayer = SBApplication(bundleIdentifier: ident) { if let musicPlayer = SBApplication(bundleIdentifier: ident) {
if (musicPlayer.isRunning) { if musicPlayer.isRunning {
if (musicPlayer.className == "SpotifyApplication") { if musicPlayer.className == "SpotifyApplication" {
let mp = (musicPlayer as SpotifyApplication) let mp = (musicPlayer as SpotifyApplication)
mp.nextTrack!() mp.nextTrack!()
updatePlayer() updatePlayer()
return return
} else if (musicPlayer.className == "ITunesApplication") { } else if musicPlayer.className == "ITunesApplication" {
let mp = (musicPlayer as iTunesApplication) let mp = (musicPlayer as iTunesApplication)
mp.nextTrack!() mp.nextTrack!()
updatePlayer() updatePlayer()
return return
} else if (musicPlayer.className == "VOXApplication") { } else if musicPlayer.className == "VOXApplication" {
let mp = (musicPlayer as VoxApplication) let mp = (musicPlayer as VoxApplication)
mp.next!() mp.next!()
updatePlayer() updatePlayer()
return 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'. // 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 safariApplication = musicPlayer as SafariApplication
let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow }) 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) _ = safariApplication.doJavaScript!("document.getElementsByClassName('player-controls__btn_next')[0].click()", in: tab)
updatePlayer() updatePlayer()
return 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) _ = safariApplication.doJavaScript!("document.getElementsByClassName('audio_page_player_next')[0].click()", in: tab)
updatePlayer() updatePlayer()
return return
@ -155,7 +155,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
} }
} }
} }
func refreshAndSchedule() { func refreshAndSchedule() {
DispatchQueue.main.async { DispatchQueue.main.async {
self.updatePlayer() self.updatePlayer()
@ -164,22 +164,22 @@ class MusicBarItem: CustomButtonTouchBarItem {
} }
} }
} }
func updatePlayer() { func updatePlayer() {
var iconUpdated = false var iconUpdated = false
var titleUpdated = false var titleUpdated = false
for var ident in playerBundleIdentifiers { for var ident in playerBundleIdentifiers {
if let musicPlayer = SBApplication(bundleIdentifier: ident) { if let musicPlayer = SBApplication(bundleIdentifier: ident) {
if (musicPlayer.isRunning) { if musicPlayer.isRunning {
var tempTitle = "" var tempTitle = ""
if (musicPlayer.className == "SpotifyApplication") { if musicPlayer.className == "SpotifyApplication" {
tempTitle = (musicPlayer as SpotifyApplication).title tempTitle = (musicPlayer as SpotifyApplication).title
} else if (musicPlayer.className == "ITunesApplication") { } else if musicPlayer.className == "ITunesApplication" {
tempTitle = (musicPlayer as iTunesApplication).title tempTitle = (musicPlayer as iTunesApplication).title
} else if (musicPlayer.className == "VOXApplication") { } else if musicPlayer.className == "VOXApplication" {
tempTitle = (musicPlayer as VoxApplication).title tempTitle = (musicPlayer as VoxApplication).title
} else if (musicPlayer.className == "SafariApplication") { } else if musicPlayer.className == "SafariApplication" {
let safariApplication = musicPlayer as SafariApplication let safariApplication = musicPlayer as SafariApplication
let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow }) let safariWindows = safariApplication.windows?().compactMap({ $0 as? SafariWindow })
for window in safariWindows! { for window in safariWindows! {
@ -190,7 +190,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
tempTitle = (tab.name)! tempTitle = (tab.name)!
break 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)! tempTitle = (tab.name)!
break break
} else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! { } else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! {
@ -202,18 +202,18 @@ class MusicBarItem: CustomButtonTouchBarItem {
if tempTitle == "" { if tempTitle == "" {
ident = "" ident = ""
} }
} else if (musicPlayer.className == "GoogleChromeApplication") { } else if musicPlayer.className == "GoogleChromeApplication" {
let chromeApplication = musicPlayer as GoogleChromeApplication let chromeApplication = musicPlayer as GoogleChromeApplication
let chromeWindows = chromeApplication.windows?().compactMap({ $0 as? GoogleChromeWindow }) let chromeWindows = chromeApplication.windows?().compactMap({ $0 as? GoogleChromeWindow })
for window in chromeWindows! { for window in chromeWindows! {
for tab in window.tabs!() { for tab in window.tabs!() {
let tab = tab as! GoogleChromeTab let tab = tab as! GoogleChromeTab
if (tab.URL?.starts(with: "https://music.yandex.ru"))! { if (tab.URL?.starts(with: "https://music.yandex.ru"))! {
if (!(tab.title?.hasSuffix("на Яндекс.Музыке"))!) { if !(tab.title?.hasSuffix("на Яндекс.Музыке"))! {
tempTitle = tab.title! tempTitle = tab.title!
break 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! tempTitle = tab.title!
break break
} else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! { } else if (tab.URL?.starts(with: "https://www.youtube.com/watch"))! {
@ -226,13 +226,13 @@ class MusicBarItem: CustomButtonTouchBarItem {
ident = "" ident = ""
} }
} }
if (tempTitle == self.songTitle) { if tempTitle == self.songTitle {
return return
} else { } else {
self.songTitle = tempTitle self.songTitle = tempTitle
} }
if let songTitle = self.songTitle?.ifNotEmpty { if let songTitle = self.songTitle?.ifNotEmpty {
self.title = " " + songTitle + " " self.title = " " + songTitle + " "
titleUpdated = true titleUpdated = true
@ -251,12 +251,12 @@ class MusicBarItem: CustomButtonTouchBarItem {
} }
} }
} }
DispatchQueue.main.async { DispatchQueue.main.async {
if !iconUpdated { if !iconUpdated {
self.image = nil self.image = nil
} }
if !titleUpdated { if !titleUpdated {
self.title = "" self.title = ""
} }
@ -265,18 +265,20 @@ class MusicBarItem: CustomButtonTouchBarItem {
} }
@objc protocol SpotifyApplication { @objc protocol SpotifyApplication {
@objc optional var currentTrack: SpotifyTrack {get} @objc optional var currentTrack: SpotifyTrack { get }
@objc optional func nextTrack() @objc optional func nextTrack()
@objc optional func previousTrack() @objc optional func previousTrack()
@objc optional func playpause() @objc optional func playpause()
} }
extension SBApplication: SpotifyApplication{}
extension SBApplication: SpotifyApplication {}
@objc protocol SpotifyTrack { @objc protocol SpotifyTrack {
@objc optional var artist: String {get} @objc optional var artist: String { get }
@objc optional var name: String {get} @objc optional var name: String { get }
} }
extension SBObject: SpotifyTrack{}
extension SBObject: SpotifyTrack {}
extension SpotifyApplication { extension SpotifyApplication {
var title: String { var title: String {
@ -285,20 +287,21 @@ extension SpotifyApplication {
} }
} }
@objc protocol iTunesApplication { @objc protocol iTunesApplication {
@objc optional var currentTrack: iTunesTrack {get} @objc optional var currentTrack: iTunesTrack { get }
@objc optional func playpause() @objc optional func playpause()
@objc optional func nextTrack() @objc optional func nextTrack()
@objc optional func previousTrack() @objc optional func previousTrack()
} }
extension SBApplication: iTunesApplication{}
extension SBApplication: iTunesApplication {}
@objc protocol iTunesTrack { @objc protocol iTunesTrack {
@objc optional var artist: String {get} @objc optional var artist: String { get }
@objc optional var name: String {get} @objc optional var name: String { get }
} }
extension SBObject: iTunesTrack{}
extension SBObject: iTunesTrack {}
extension iTunesApplication { extension iTunesApplication {
var title: String { var title: String {
@ -307,16 +310,15 @@ extension iTunesApplication {
} }
} }
@objc protocol VoxApplication { @objc protocol VoxApplication {
@objc optional func playpause() @objc optional func playpause()
@objc optional func next() @objc optional func next()
@objc optional func previous() @objc optional func previous()
@objc optional var track: String {get} @objc optional var track: String { get }
@objc optional var artist: String {get} @objc optional var artist: String { get }
} }
extension SBApplication: VoxApplication{}
extension SBApplication: VoxApplication {}
extension VoxApplication { extension VoxApplication {
var title: String { var title: String {
@ -324,7 +326,6 @@ extension VoxApplication {
} }
} }
@objc public protocol SBObjectProtocol: NSObjectProtocol { @objc public protocol SBObjectProtocol: NSObjectProtocol {
func get() -> Any! func get() -> Any!
} }
@ -338,6 +339,7 @@ extension VoxApplication {
@objc optional func windows() -> SBElementArray @objc optional func windows() -> SBElementArray
@objc optional func doJavaScript(_ x: String!, in in_: Any!) -> Any // Applies a string of JavaScript code to a document. @objc optional func doJavaScript(_ x: String!, in in_: Any!) -> Any // Applies a string of JavaScript code to a document.
} }
extension SBApplication: SafariApplication {} extension SBApplication: SafariApplication {}
@objc public protocol SafariWindow: SBObjectProtocol { @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 var document: SafariDocument { get } // The document whose contents are displayed in the window.
// @objc optional func setCurrentTab(_ currentTab: SafariTab!) // The current tab. // @objc optional func setCurrentTab(_ currentTab: SafariTab!) // The current tab.
} }
extension SBObject: SafariWindow {} extension SBObject: SafariWindow {}
//@objc public protocol SafariDocument: SBObjectProtocol { // @objc public protocol SafariDocument: SBObjectProtocol {
// @objc optional var name: String { get } // Its name. // @objc optional var name: String { get } // Its name.
// @objc optional var URL: String { get } // The current URL of the document. // @objc optional var URL: String { get } // The current URL of the document.
//} // }
//extension SBObject: SafariDocument {} // extension SBObject: SafariDocument {}
@objc public protocol SafariTab: SBObjectProtocol { @objc public protocol SafariTab: SBObjectProtocol {
@objc optional var URL: String { get } // The current URL of the tab. @objc optional var URL: String { get } // The current URL of the tab.
@objc optional var name: String { get } // The name of the tab. @objc optional var name: String { get } // The name of the tab.
} }
extension SBObject: SafariTab {} extension SBObject: SafariTab {}
@objc public protocol GoogleChromeApplication: SBApplicationProtocol { @objc public protocol GoogleChromeApplication: SBApplicationProtocol {
@objc optional func windows() -> SBElementArray @objc optional func windows() -> SBElementArray
@objc optional func executeJavaScript(javascript: String!) -> Any // Applies a string of JavaScript code to a document. //, id: Any! @objc optional func executeJavaScript(javascript: String!) -> Any // Applies a string of JavaScript code to a document. //, id: Any!
} }
extension SBApplication: GoogleChromeApplication {} extension SBApplication: GoogleChromeApplication {}
@objc public protocol GoogleChromeWindow: SBObjectProtocol { @objc public protocol GoogleChromeWindow: SBObjectProtocol {
@objc optional var name: String { get } // The title of the window. @objc optional var name: String { get } // The title of the window.
@objc optional func tabs() -> SBElementArray @objc optional func tabs() -> SBElementArray
} }
extension SBObject: GoogleChromeWindow {} extension SBObject: GoogleChromeWindow {}
@objc public protocol GoogleChromeTab: SBObjectProtocol { @objc public protocol GoogleChromeTab: SBObjectProtocol {
@objc optional var URL: String { get } // The current URL of the tab. @objc optional var URL: String { get } // The current URL of the tab.
@objc optional var title: String { get } // The name of the tab. @objc optional var title: String { get } // The name of the tab.
} }
extension SBObject: GoogleChromeTab {} extension SBObject: GoogleChromeTab {}

View File

@ -11,43 +11,43 @@ import Foundation
class NightShiftBarItem: CustomButtonTouchBarItem { class NightShiftBarItem: CustomButtonTouchBarItem {
private let nsclient = CBBlueLightClient() private let nsclient = CBBlueLightClient()
private var timer: Timer! private var timer: Timer!
private var blueLightStatus: Status { private var blueLightStatus: Status {
var status: Status = Status() var status: Status = Status()
nsclient.getBlueLightStatus(&status) nsclient.getBlueLightStatus(&status)
return status return status
} }
private var isNightShiftEnabled: Bool { private var isNightShiftEnabled: Bool {
return self.blueLightStatus.enabled.boolValue return blueLightStatus.enabled.boolValue
} }
private func setNightShift(state: Bool) { private func setNightShift(state: Bool) {
self.nsclient.setEnabled(state) nsclient.setEnabled(state)
} }
init(identifier: NSTouchBarItem.Identifier) { init(identifier: NSTouchBarItem.Identifier) {
super.init(identifier: identifier, title: "") super.init(identifier: identifier, title: "")
self.isBordered = false isBordered = false
self.setWidth(value: 28) 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) 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") fatalError("init(coder:) has not been implemented")
} }
func nightShiftAction() { func nightShiftAction() {
self.setNightShift(state: !self.isNightShiftEnabled) setNightShift(state: !isNightShiftEnabled)
self.refresh() refresh()
} }
@objc func refresh() { @objc func refresh() {
self.image = isNightShiftEnabled ? #imageLiteral(resourceName: "nightShiftOn") : #imageLiteral(resourceName: "nightShiftOff") image = isNightShiftEnabled ? #imageLiteral(resourceName: "nightShiftOn") : #imageLiteral(resourceName: "nightShiftOff")
} }
} }

View File

@ -3,21 +3,20 @@ import Cocoa
class TimeTouchBarItem: CustomButtonTouchBarItem { class TimeTouchBarItem: CustomButtonTouchBarItem {
private let dateFormatter = DateFormatter() private let dateFormatter = DateFormatter()
private var timer: Timer! private var timer: Timer!
init(identifier: NSTouchBarItem.Identifier, formatTemplate: String) { init(identifier: NSTouchBarItem.Identifier, formatTemplate: String) {
dateFormatter.setLocalizedDateFormatFromTemplate(formatTemplate) dateFormatter.setLocalizedDateFormatFromTemplate(formatTemplate)
super.init(identifier: identifier, title: " ") super.init(identifier: identifier, title: " ")
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true) timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
self.isBordered = false isBordered = false
updateTime() updateTime()
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@objc func updateTime() { @objc func updateTime() {
self.title = self.dateFormatter.string(from: Date()) title = dateFormatter.string(from: Date())
} }
} }

View File

@ -1,55 +1,56 @@
import Cocoa
import AppKit import AppKit
import AVFoundation import AVFoundation
import Cocoa
import CoreAudio import CoreAudio
class VolumeViewController: NSCustomTouchBarItem { class VolumeViewController: NSCustomTouchBarItem {
private(set) var sliderItem: CustomSlider! private(set) var sliderItem: CustomSlider!
init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) { init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) {
super.init(identifier: identifier) super.init(identifier: identifier)
var forPropertyAddress = AudioObjectPropertyAddress( var forPropertyAddress = AudioObjectPropertyAddress(
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume, mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume,
mScope: kAudioDevicePropertyScopeOutput, mScope: kAudioDevicePropertyScopeOutput,
mElement: kAudioObjectPropertyElementMaster) mElement: kAudioObjectPropertyElementMaster
)
AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock) AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock)
if (image == nil) { if image == nil {
sliderItem = CustomSlider() sliderItem = CustomSlider()
} else { } else {
sliderItem = CustomSlider(knob: image!) sliderItem = CustomSlider(knob: image!)
} }
sliderItem.target = self sliderItem.target = self
sliderItem.action = #selector(VolumeViewController.sliderValueChanged(_:)) sliderItem.action = #selector(VolumeViewController.sliderValueChanged(_:))
sliderItem.minValue = 0.0 sliderItem.minValue = 0.0
sliderItem.maxValue = 100.0 sliderItem.maxValue = 100.0
sliderItem.floatValue = getInputGain()*100 sliderItem.floatValue = getInputGain() * 100
self.view = sliderItem view = sliderItem
} }
func audioObjectPropertyListenerBlock (numberAddresses: UInt32, addresses: UnsafePointer<AudioObjectPropertyAddress>) { func audioObjectPropertyListenerBlock(numberAddresses _: UInt32, addresses _: UnsafePointer<AudioObjectPropertyAddress>) {
DispatchQueue.main.async { DispatchQueue.main.async {
self.sliderItem.floatValue = self.getInputGain() * 100 self.sliderItem.floatValue = self.getInputGain() * 100
} }
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit { deinit {
sliderItem.unbind(NSBindingName.value) sliderItem.unbind(NSBindingName.value)
} }
@objc func sliderValueChanged(_ sender: Any) { @objc func sliderValueChanged(_ sender: Any) {
if let sliderItem = sender as? NSSlider { if let sliderItem = sender as? NSSlider {
_ = setInputGain(Float32(sliderItem.intValue)/100.0) _ = setInputGain(Float32(sliderItem.intValue) / 100.0)
} }
} }
private var defaultDeviceID: AudioObjectID { private var defaultDeviceID: AudioObjectID {
var deviceID: AudioObjectID = AudioObjectID(0) var deviceID: AudioObjectID = AudioObjectID(0)
var size: UInt32 = UInt32(MemoryLayout<AudioObjectID>.size) var size: UInt32 = UInt32(MemoryLayout<AudioObjectID>.size)
@ -60,7 +61,7 @@ class VolumeViewController: NSCustomTouchBarItem {
AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &size, &deviceID) AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &size, &deviceID)
return deviceID return deviceID
} }
private func getInputGain() -> Float32 { private func getInputGain() -> Float32 {
var volume: Float32 = 0.5 var volume: Float32 = 0.5
var size: UInt32 = UInt32(MemoryLayout.size(ofValue: volume)) var size: UInt32 = UInt32(MemoryLayout.size(ofValue: volume))
@ -71,16 +72,16 @@ class VolumeViewController: NSCustomTouchBarItem {
AudioObjectGetPropertyData(defaultDeviceID, &address, 0, nil, &size, &volume) AudioObjectGetPropertyData(defaultDeviceID, &address, 0, nil, &size, &volume)
return volume return volume
} }
private func setInputGain(_ volume: Float32) -> OSStatus { private func setInputGain(_ volume: Float32) -> OSStatus {
var inputVolume: Float32 = volume var inputVolume: Float32 = volume
if inputVolume == 0.0 { if inputVolume == 0.0 {
_ = setMute( mute: 1) _ = setMute(mute: 1)
} else { } else {
_ = setMute( mute: 0) _ = setMute(mute: 0)
} }
let size: UInt32 = UInt32(MemoryLayout.size(ofValue: inputVolume)) let size: UInt32 = UInt32(MemoryLayout.size(ofValue: inputVolume))
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress() var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput) address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput)
@ -88,8 +89,8 @@ class VolumeViewController: NSCustomTouchBarItem {
address.mSelector = AudioObjectPropertySelector(kAudioHardwareServiceDeviceProperty_VirtualMasterVolume) address.mSelector = AudioObjectPropertySelector(kAudioHardwareServiceDeviceProperty_VirtualMasterVolume)
return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &inputVolume) 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 muteVal: Int = mute
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress() var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
address.mSelector = AudioObjectPropertySelector(kAudioDevicePropertyMute) address.mSelector = AudioObjectPropertySelector(kAudioDevicePropertyMute)
@ -99,4 +100,3 @@ class VolumeViewController: NSCustomTouchBarItem {
return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &muteVal) return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &muteVal)
} }
} }

View File

@ -16,42 +16,42 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
private var units_str = "°F" private var units_str = "°F"
private var prev_location: CLLocation! private var prev_location: CLLocation!
private var 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 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 iconsText = ["01d": "", "01n": "", "02d": "", "02n": "", "03d": "", "03n": "", "04d": "", "04n": "", "09d": "", "09n": "", "10d": "", "10n": "", "11d": "", "11n": "", "13d": "", "13n": "", "50d": "", "50n": ""]
private var iconsSource: Dictionary<String, String> private var iconsSource: Dictionary<String, String>
private var manager:CLLocationManager! private var manager: CLLocationManager!
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text") { init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text") {
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck") activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
activity.interval = interval activity.interval = interval
self.units = units self.units = units
self.api_key = api_key self.api_key = api_key
if self.units == "metric" { if self.units == "metric" {
units_str = "°C" units_str = "°C"
} }
if self.units == "imperial" { if self.units == "imperial" {
units_str = "°F" units_str = "°F"
} }
if icon_type == "images" { if icon_type == "images" {
iconsSource = iconsImages iconsSource = iconsImages
} else { } else {
iconsSource = iconsText iconsSource = iconsText
} }
super.init(identifier: identifier, title: "") super.init(identifier: identifier, title: "")
let status = CLLocationManager.authorizationStatus() let status = CLLocationManager.authorizationStatus()
if status == .restricted || status == .denied { if status == .restricted || status == .denied {
print("User permission not given") print("User permission not given")
return return
} }
if !CLLocationManager.locationServicesEnabled() { if !CLLocationManager.locationServicesEnabled() {
print("Location services not enabled"); print("Location services not enabled")
return return
} }
@ -62,43 +62,43 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
completion(NSBackgroundActivityScheduler.Result.finished) completion(NSBackgroundActivityScheduler.Result.finished)
} }
updateWeather() updateWeather()
manager = CLLocationManager() manager = CLLocationManager()
manager.delegate = self manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
manager.startUpdatingLocation() manager.startUpdatingLocation()
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@objc func updateWeather() { @objc func updateWeather() {
if self.location != nil { if location != nil {
let urlRequest = URLRequest(url: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)&units=\(self.units)&appid=\(self.api_key)")!) let urlRequest = URLRequest(url: URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)&units=\(units)&appid=\(api_key)")!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in let task = URLSession.shared.dataTask(with: urlRequest) { data, _, error in
if error == nil { if error == nil {
do { 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) // print(json)
var temperature: Int! var temperature: Int!
var condition_icon = "" 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 { if let temp = main["temp"] as? Double {
temperature = Int(temp) temperature = Int(temp)
} }
} }
if let weather = json["weather"] as? NSArray, let item = weather[0] as? NSDictionary { if let weather = json["weather"] as? NSArray, let item = weather[0] as? NSDictionary {
let icon = item["icon"] as! String let icon = item["icon"] as! String
if let test = self.iconsSource[icon] { if let test = self.iconsSource[icon] {
condition_icon = test condition_icon = test
} }
} }
if temperature != nil { if temperature != nil {
DispatchQueue.main.async { DispatchQueue.main.async {
self.setWeather(text: "\(condition_icon) \(temperature!)\(self.units_str)") self.setWeather(text: "\(condition_icon) \(temperature!)\(self.units_str)")
@ -109,31 +109,30 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
} }
} }
} }
task.resume() task.resume()
} }
} }
func setWeather(text: String) { 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! let lastLocation = locations.last!
self.location = lastLocation location = lastLocation
if prev_location == nil { if prev_location == nil {
updateWeather() updateWeather()
} }
prev_location = lastLocation prev_location = lastLocation
} }
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { func locationManager(_: CLLocationManager, didFailWithError error: Error) {
print(error); print(error)
} }
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { func locationManager(_: CLLocationManager, didChangeAuthorization _: CLAuthorizationStatus) {
// print("inside didChangeAuthorization "); // print("inside didChangeAuthorization ");
updateWeather() updateWeather()
} }
} }