mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-11 09:28:38 +00:00
Rewrote presets parsing. Instead of parsing presets in a separate file using bunch of huge enums it is now parsed inside each object. To implement a new class: 1. Derive your class from CustomTouchBarItem (for static) or CustomButtonTouchBarItem (for buttons) 2. Override class var typeIdentifier with your object identificator 3. Override init(from decoder: Decoder) and read all custom json params you need 4. Don't forget to call super.init(identifier: CustomTouchBarItem.createIdentifier(type)) in the init() function 5. Add your new class to BarItemDefinition.types in ItemParsing.swift Good example is PomodoroBarItem If you want to inherid from some other NS class (NSSlider or NSPopoverTouchBarItem or other) then look into GroupBarItem and BrightnessViewController
126 lines
4.1 KiB
Swift
126 lines
4.1 KiB
Swift
import Foundation
|
|
|
|
class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|
private var script: NSAppleScript!
|
|
private let interval: TimeInterval
|
|
private var forceHideConstraint: NSLayoutConstraint!
|
|
private let alternativeImages: [String: SourceProtocol]
|
|
|
|
private enum CodingKeys: String, CodingKey {
|
|
case source
|
|
case alternativeImages
|
|
case refreshInterval
|
|
}
|
|
|
|
override class var typeIdentifier: String {
|
|
return "appleScriptTitledButton"
|
|
}
|
|
|
|
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, alternativeImages: [String: SourceProtocol]) {
|
|
self.interval = interval
|
|
self.alternativeImages = alternativeImages
|
|
super.init(identifier: identifier, title: "⏳")
|
|
|
|
initScripts(source: source)
|
|
}
|
|
|
|
required init?(coder _: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
required init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
let source = try container.decode(Source.self, forKey: .source)
|
|
self.interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
|
self.alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
|
|
|
|
print("AppleScriptTouchBarItem.init(from decoder)")
|
|
try super.init(from: decoder)
|
|
self.title = "⏳"
|
|
|
|
initScripts(source: source)
|
|
}
|
|
|
|
func initScripts(source: SourceProtocol) {
|
|
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
|
title = "scheduled"
|
|
DispatchQueue.appleScriptQueue.async {
|
|
guard let script = source.appleScript else {
|
|
DispatchQueue.main.async {
|
|
self.title = "no script"
|
|
}
|
|
return
|
|
}
|
|
self.script = script
|
|
DispatchQueue.main.async {
|
|
self.isBordered = false
|
|
}
|
|
|
|
var error: NSDictionary?
|
|
guard script.compileAndReturnError(&error) else {
|
|
#if DEBUG
|
|
print(error?.description ?? "unknown error")
|
|
#endif
|
|
DispatchQueue.main.async {
|
|
self.title = "error"
|
|
}
|
|
return
|
|
}
|
|
self.refreshAndSchedule()
|
|
}
|
|
}
|
|
|
|
func refreshAndSchedule() {
|
|
#if DEBUG
|
|
print("refresh happened (interval \(interval)), self \(identifier.rawValue))")
|
|
#endif
|
|
let scriptResult = execute()
|
|
DispatchQueue.main.async {
|
|
self.title = scriptResult
|
|
self.forceHideConstraint.isActive = scriptResult == ""
|
|
#if DEBUG
|
|
print("did set new script result title \(scriptResult)")
|
|
#endif
|
|
}
|
|
DispatchQueue.appleScriptQueue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
|
self?.refreshAndSchedule()
|
|
}
|
|
}
|
|
|
|
func updateIcon(iconLabel: String) {
|
|
if alternativeImages[iconLabel] != nil {
|
|
DispatchQueue.main.async {
|
|
self.setImage(self.alternativeImages[iconLabel]!.image)
|
|
}
|
|
} else {
|
|
print("Cannot find icon with label \"\(iconLabel)\"")
|
|
}
|
|
}
|
|
|
|
func execute() -> String {
|
|
var error: NSDictionary?
|
|
let output = script.executeAndReturnError(&error)
|
|
if let error = error {
|
|
print(error)
|
|
return "error"
|
|
}
|
|
if output.descriptorType == typeAEList {
|
|
let arr = Array(1...output.numberOfItems).compactMap({ output.atIndex($0)!.stringValue ?? "" })
|
|
|
|
if arr.count <= 0 {
|
|
return ""
|
|
} else if arr.count == 1 {
|
|
return arr[0]
|
|
} else {
|
|
updateIcon(iconLabel: arr[1])
|
|
return arr[0]
|
|
}
|
|
}
|
|
return output.stringValue ?? ""
|
|
}
|
|
}
|
|
|
|
extension DispatchQueue {
|
|
static let appleScriptQueue = DispatchQueue(label: "mtmr.applescript")
|
|
}
|