mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-11 01:18:39 +00:00
Merge branch 'tries/button-image'
# Conflicts: # MTMR.xcodeproj/project.pbxproj
This commit is contained in:
commit
9afa9d7470
@ -15,6 +15,7 @@
|
|||||||
36C2ECE0207CB1B0003CDA33 /* defaultPreset.json in Resources */ = {isa = PBXBuildFile; fileRef = 36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */; };
|
36C2ECE0207CB1B0003CDA33 /* defaultPreset.json in Resources */ = {isa = PBXBuildFile; fileRef = 36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */; };
|
||||||
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */; };
|
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */; };
|
||||||
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; };
|
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; };
|
||||||
|
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; };
|
||||||
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
|
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
|
||||||
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
|
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
|
||||||
@ -57,6 +58,7 @@
|
|||||||
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = defaultPreset.json; sourceTree = "<group>"; };
|
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = defaultPreset.json; sourceTree = "<group>"; };
|
||||||
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrightnessViewController.swift; sourceTree = "<group>"; };
|
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrightnessViewController.swift; sourceTree = "<group>"; };
|
||||||
6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VolumeViewController.swift; sourceTree = "<group>"; };
|
6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VolumeViewController.swift; sourceTree = "<group>"; };
|
||||||
|
B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = "<group>"; };
|
||||||
B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = "<group>"; };
|
B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = "<group>"; };
|
||||||
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButtonTouchBarItem.swift; sourceTree = "<group>"; };
|
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButtonTouchBarItem.swift; sourceTree = "<group>"; };
|
||||||
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = "<group>"; };
|
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = "<group>"; };
|
||||||
@ -150,6 +152,7 @@
|
|||||||
36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */,
|
36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */,
|
||||||
B059D621205E03F5006E6B86 /* TouchBarController.swift */,
|
B059D621205E03F5006E6B86 /* TouchBarController.swift */,
|
||||||
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */,
|
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */,
|
||||||
|
B0008E542080286C003AD4DD /* SupportHelpers.swift */,
|
||||||
B082B258205C7D8000BC04DC /* Main.storyboard */,
|
B082B258205C7D8000BC04DC /* Main.storyboard */,
|
||||||
B082B25B205C7D8000BC04DC /* Info.plist */,
|
B082B25B205C7D8000BC04DC /* Info.plist */,
|
||||||
B082B25C205C7D8000BC04DC /* MTMR.entitlements */,
|
B082B25C205C7D8000BC04DC /* MTMR.entitlements */,
|
||||||
@ -317,6 +320,7 @@
|
|||||||
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
|
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
|
||||||
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
||||||
|
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
||||||
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
||||||
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */,
|
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
private let interval: TimeInterval
|
private let interval: TimeInterval
|
||||||
private var forceHideConstraint: NSLayoutConstraint!
|
private var forceHideConstraint: NSLayoutConstraint!
|
||||||
|
|
||||||
init?(identifier: NSTouchBarItem.Identifier, source: Source, interval: TimeInterval, onTap: @escaping ()->()) {
|
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, onTap: @escaping ()->()) {
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
super.init(identifier: identifier, title: "compile", onTap: onTap)
|
super.init(identifier: identifier, title: "compile", onTap: onTap)
|
||||||
self.forceHideConstraint = self.view.widthAnchor.constraint(equalToConstant: 0)
|
self.forceHideConstraint = self.view.widthAnchor.constraint(equalToConstant: 0)
|
||||||
@ -56,7 +56,7 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Source {
|
extension SourceProtocol {
|
||||||
var appleScript: NSAppleScript? {
|
var appleScript: NSAppleScript? {
|
||||||
guard let source = self.string else { return nil }
|
guard let source = self.string else { return nil }
|
||||||
return NSAppleScript(source: source)
|
return NSAppleScript(source: source)
|
||||||
|
|||||||
@ -12,15 +12,10 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem {
|
|||||||
let tapClosure: () -> ()
|
let tapClosure: () -> ()
|
||||||
private(set) var button: NSButton!
|
private(set) var button: NSButton!
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, title: String, onTap callback: @escaping () -> (), image: NSImage? = nil) {
|
init(identifier: NSTouchBarItem.Identifier, title: String, onTap callback: @escaping () -> ()) {
|
||||||
self.tapClosure = callback
|
self.tapClosure = callback
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
if let image = image {
|
button = NSButton(title: title, target: self, action: #selector(didTapped))
|
||||||
button = NSButton(title: title, image: image, target: self, action: #selector(didTapped))
|
|
||||||
button.bezelColor = .clear
|
|
||||||
} else {
|
|
||||||
button = NSButton(title: title, target: self, action: #selector(didTapped))
|
|
||||||
}
|
|
||||||
self.view = button
|
self.view = button
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,8 +30,8 @@ struct BarItemDefinition: Decodable {
|
|||||||
let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type)
|
let parametersDecoder = SupportedTypesHolder.sharedInstance.lookup(by: type)
|
||||||
let additionalParameters = try GeneralParameters(from: decoder).parameters
|
let additionalParameters = try GeneralParameters(from: decoder).parameters
|
||||||
if let result = try? parametersDecoder(decoder),
|
if let result = try? parametersDecoder(decoder),
|
||||||
case let (itemType, action) = result {
|
case let (itemType, action, parameters) = result {
|
||||||
self.init(type: itemType, action: action, additionalParameters: additionalParameters)
|
self.init(type: itemType, action: action, additionalParameters: additionalParameters + parameters)
|
||||||
} else {
|
} else {
|
||||||
self.init(type: .staticButton(title: "unknown"), action: .none, additionalParameters: additionalParameters)
|
self.init(type: .staticButton(title: "unknown"), action: .none, additionalParameters: additionalParameters)
|
||||||
}
|
}
|
||||||
@ -40,23 +40,38 @@ struct BarItemDefinition: Decodable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SupportedTypesHolder {
|
class SupportedTypesHolder {
|
||||||
typealias ParametersDecoder = (Decoder) throws ->(item: ItemType, action: ActionType)
|
typealias ParametersDecoder = (Decoder) throws ->(item: ItemType, action: ActionType, parameters: [GeneralParameter])
|
||||||
private var supportedTypes: [String: ParametersDecoder] = [
|
private var supportedTypes: [String: ParametersDecoder] = [
|
||||||
"escape": { _ in return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53)) },
|
"escape": { _ in return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53), parameters: []) },
|
||||||
"brightnessUp": { _ in return (item: .staticButton(title: "🔆"), action: .keyPress(keycode: 113)) },
|
"brightnessUp": { _ in return (item: .staticButton(title: "🔆"), action: .keyPress(keycode: 113), parameters: []) },
|
||||||
"brightnessDown": { _ in return (item: .staticButton(title: "🔅"), action: .keyPress(keycode: 107)) },
|
"brightnessDown": { _ in return (item: .staticButton(title: "🔅"), action: .keyPress(keycode: 107), parameters: []) },
|
||||||
"volumeDown": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarVolumeDownTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN)) },
|
"volumeDown": { _ in
|
||||||
"volumeUp": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarVolumeUpTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP)) },
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeDownTemplate)!)
|
||||||
"previous": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarRewindTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS)) },
|
return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_DOWN), parameters: [imageParameter])
|
||||||
"play": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarPlayPauseTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_PLAY)) },
|
},
|
||||||
"next": { _ in return (item: .staticImageButton(title: "", image: NSImage(named: .touchBarFastForwardTemplate)!), action: .hidKey(keycode: NX_KEYTYPE_NEXT)) },
|
"volumeUp": { _ in
|
||||||
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeUpTemplate)!)
|
||||||
|
return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_SOUND_UP), parameters: [imageParameter])
|
||||||
|
},
|
||||||
|
"previous": { _ in
|
||||||
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarRewindTemplate)!)
|
||||||
|
return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PREVIOUS), parameters: [imageParameter])
|
||||||
|
},
|
||||||
|
"play": { _ in
|
||||||
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarPlayPauseTemplate)!)
|
||||||
|
return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_PLAY), parameters: [imageParameter])
|
||||||
|
},
|
||||||
|
"next": { _ in
|
||||||
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarFastForwardTemplate)!)
|
||||||
|
return (item: .staticButton(title: ""), action: .hidKey(keycode: NX_KEYTYPE_NEXT), parameters: [imageParameter])
|
||||||
|
},
|
||||||
"weather": { decoder in
|
"weather": { 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)
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
|
||||||
let scriptPath = Bundle.main.path(forResource: "Weather", ofType: "scpt")!
|
let scriptPath = Bundle.main.path(forResource: "Weather", ofType: "scpt")!
|
||||||
let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0)
|
let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0)
|
||||||
return (item: item, action: .none)
|
return (item: item, action: .none, parameters: [])
|
||||||
},
|
},
|
||||||
"battery": { decoder in
|
"battery": { decoder in
|
||||||
enum CodingKeys: String, CodingKey { case refreshInterval }
|
enum CodingKeys: String, CodingKey { case refreshInterval }
|
||||||
@ -64,17 +79,17 @@ class SupportedTypesHolder {
|
|||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
|
||||||
let scriptPath = Bundle.main.path(forResource: "Battery", ofType: "scpt")!
|
let scriptPath = Bundle.main.path(forResource: "Battery", ofType: "scpt")!
|
||||||
let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0)
|
let item = ItemType.appleScriptTitledButton(source: Source(filePath: scriptPath), refreshInterval: interval ?? 1800.0)
|
||||||
return (item: item, action: .none)
|
return (item: item, action: .none, parameters: [])
|
||||||
},
|
},
|
||||||
"sleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]) ) },
|
"sleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]), parameters: []) },
|
||||||
"displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]) ) },
|
"displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), 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))
|
return (item: try ItemType(from: decoder), action: try ActionType(from: decoder), parameters: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,15 +99,14 @@ class SupportedTypesHolder {
|
|||||||
|
|
||||||
func register(typename: String, item: ItemType, action: ActionType) {
|
func register(typename: String, item: ItemType, action: ActionType) {
|
||||||
register(typename: typename) { _ in
|
register(typename: typename) { _ in
|
||||||
return (item: item, action: action)
|
return (item: item, action: action, parameters: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ItemType: Decodable {
|
enum ItemType: Decodable {
|
||||||
case staticButton(title: String)
|
case staticButton(title: String)
|
||||||
case staticImageButton(title: String, image: NSImage)
|
case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
||||||
case appleScriptTitledButton(source: Source, refreshInterval: Double)
|
|
||||||
case timeButton(formatTemplate: String)
|
case timeButton(formatTemplate: String)
|
||||||
case flexSpace()
|
case flexSpace()
|
||||||
case volume()
|
case volume()
|
||||||
@ -109,7 +123,6 @@ enum ItemType: Decodable {
|
|||||||
|
|
||||||
enum ItemTypeRaw: String, Decodable {
|
enum ItemTypeRaw: String, Decodable {
|
||||||
case staticButton
|
case staticButton
|
||||||
case staticImageButton
|
|
||||||
case appleScriptTitledButton
|
case appleScriptTitledButton
|
||||||
case timeButton
|
case timeButton
|
||||||
case flexSpace
|
case flexSpace
|
||||||
@ -125,15 +138,6 @@ enum ItemType: Decodable {
|
|||||||
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 .staticImageButton:
|
|
||||||
let title = try container.decode(String.self, forKey: .title)
|
|
||||||
let imageRaw = try container.decode(String.self, forKey: .image)
|
|
||||||
if let decodedImageData = Data(base64Encoded: imageRaw, options: .ignoreUnknownCharacters) {
|
|
||||||
let decImage = NSImage(data: decodedImageData)!
|
|
||||||
self = .staticImageButton(title: title, image: decImage)
|
|
||||||
} else {
|
|
||||||
self = .staticButton(title: title)
|
|
||||||
}
|
|
||||||
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)
|
||||||
@ -154,7 +158,7 @@ enum ActionType: Decodable {
|
|||||||
case none
|
case none
|
||||||
case hidKey(keycode: Int)
|
case hidKey(keycode: Int)
|
||||||
case keyPress(keycode: Int)
|
case keyPress(keycode: Int)
|
||||||
case appleSctipt(source: Source)
|
case appleSctipt(source: SourceProtocol)
|
||||||
case shellScript(executable: String, parameters: [String])
|
case shellScript(executable: String, parameters: [String])
|
||||||
case custom(closure: ()->())
|
case custom(closure: ()->())
|
||||||
|
|
||||||
@ -230,6 +234,7 @@ func ==(lhs: ActionType, rhs: ActionType) -> Bool {
|
|||||||
|
|
||||||
enum GeneralParameter {
|
enum GeneralParameter {
|
||||||
case width(_: CGFloat)
|
case width(_: CGFloat)
|
||||||
|
case image(source: SourceProtocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GeneralParameters: Decodable {
|
struct GeneralParameters: Decodable {
|
||||||
@ -237,6 +242,7 @@ struct GeneralParameters: Decodable {
|
|||||||
|
|
||||||
fileprivate enum CodingKeys: String, CodingKey {
|
fileprivate enum CodingKeys: String, CodingKey {
|
||||||
case width
|
case width
|
||||||
|
case image
|
||||||
}
|
}
|
||||||
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)
|
||||||
@ -244,20 +250,36 @@ struct GeneralParameters: Decodable {
|
|||||||
if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) {
|
if let value = try container.decodeIfPresent(CGFloat.self, forKey: .width) {
|
||||||
result.append(.width(value))
|
result.append(.width(value))
|
||||||
}
|
}
|
||||||
|
if let imageSource = try container.decodeIfPresent(Source.self, forKey: .image) {
|
||||||
|
result.append(.image(source: imageSource))
|
||||||
|
}
|
||||||
parameters = result
|
parameters = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protocol SourceProtocol {
|
||||||
struct Source: Decodable {
|
var data: Data? { get }
|
||||||
|
var string: String? { get }
|
||||||
|
var image: NSImage? { get }
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
case filePath
|
||||||
|
case base64
|
||||||
|
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 ?? self.data?.base64Content
|
return inline ?? self.data?.utf8string
|
||||||
|
}
|
||||||
|
var image: NSImage? {
|
||||||
|
return data?.image
|
||||||
}
|
}
|
||||||
|
|
||||||
private init(filePath: String?, base64: String?, inline: String?) {
|
private init(filePath: String?, base64: String?, inline: String?) {
|
||||||
@ -269,8 +291,19 @@ struct Source: Decodable {
|
|||||||
self.init(filePath: filePath, base64: nil, inline: nil)
|
self.init(filePath: filePath, base64: nil, inline: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extension Source: Equatable {}
|
extension NSImage: SourceProtocol {
|
||||||
func ==(left: Source, right: Source) -> Bool {
|
var data: Data? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var string: String? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var image: NSImage? {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extension SourceProtocol where Self: Equatable {}
|
||||||
|
func ==(left: SourceProtocol, right: SourceProtocol) -> Bool {
|
||||||
return left.data == right.data
|
return left.data == right.data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +316,10 @@ extension String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
extension Data {
|
extension Data {
|
||||||
var base64Content: String? {
|
var utf8string: String? {
|
||||||
return String(data: self, encoding: .utf8)
|
return String(data: self, encoding: .utf8)
|
||||||
}
|
}
|
||||||
|
var image: NSImage? {
|
||||||
|
return NSImage(data: self)?.resize(maxSize: NSSize(width: 24, height: 24))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
MTMR/SupportHelpers.swift
Normal file
52
MTMR/SupportHelpers.swift
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// SupportHelpers.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Anton Palgunov on 13/04/2018.
|
||||||
|
// Copyright © 2018 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
func trim() -> String {
|
||||||
|
return self.trimmingCharacters(in: NSCharacterSet.whitespaces)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NSImage {
|
||||||
|
func resize(maxSize:NSSize) -> NSImage {
|
||||||
|
var ratio:Float = 0.0
|
||||||
|
let imageWidth = Float(self.size.width)
|
||||||
|
let imageHeight = Float(self.size.height)
|
||||||
|
let maxWidth = Float(maxSize.width)
|
||||||
|
let maxHeight = Float(maxSize.height)
|
||||||
|
|
||||||
|
// Get ratio (landscape or portrait)
|
||||||
|
if (imageWidth > imageHeight) {
|
||||||
|
// Landscape
|
||||||
|
ratio = maxWidth / imageWidth;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Portrait
|
||||||
|
ratio = maxHeight / imageHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate new size based on the ratio
|
||||||
|
let newWidth = imageWidth * ratio
|
||||||
|
let newHeight = imageHeight * ratio
|
||||||
|
|
||||||
|
// Create a new NSSize object with the newly calculated size
|
||||||
|
let newSize:NSSize = NSSize(width: Int(newWidth), height: Int(newHeight))
|
||||||
|
|
||||||
|
// Cast the NSImage to a CGImage
|
||||||
|
var imageRect:NSRect = NSMakeRect(0, 0, self.size.width, self.size.height)
|
||||||
|
let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)
|
||||||
|
|
||||||
|
// Create NSImage from the CGImage using the new size
|
||||||
|
let imageWithNewSize = NSImage(cgImage: imageRef!, size: newSize)
|
||||||
|
|
||||||
|
// Return the new image
|
||||||
|
return imageWithNewSize
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,13 +14,11 @@ struct ExactItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension ItemType {
|
extension ItemType {
|
||||||
|
|
||||||
var identifierBase: String {
|
var identifierBase: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .staticButton(title: _):
|
case .staticButton(title: _):
|
||||||
return "com.toxblh.mtmr.staticButton."
|
return "com.toxblh.mtmr.staticButton."
|
||||||
case .staticImageButton(title: _):
|
|
||||||
return "com.toxblh.mtmr.staticImageButton."
|
|
||||||
case .appleScriptTitledButton(source: _):
|
case .appleScriptTitledButton(source: _):
|
||||||
return "com.toxblh.mtmr.appleScriptButton."
|
return "com.toxblh.mtmr.appleScriptButton."
|
||||||
case .timeButton(formatTemplate: _):
|
case .timeButton(formatTemplate: _):
|
||||||
@ -33,7 +31,7 @@ extension ItemType {
|
|||||||
return "com.toxblh.mtmr.brightness"
|
return "com.toxblh.mtmr.brightness"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NSTouchBarItem.Identifier {
|
extension NSTouchBarItem.Identifier {
|
||||||
@ -43,23 +41,23 @@ extension NSTouchBarItem.Identifier {
|
|||||||
class TouchBarController: NSObject, NSTouchBarDelegate {
|
class TouchBarController: NSObject, NSTouchBarDelegate {
|
||||||
|
|
||||||
static let shared = TouchBarController()
|
static let shared = TouchBarController()
|
||||||
|
|
||||||
let touchBar = NSTouchBar()
|
let touchBar = NSTouchBar()
|
||||||
|
|
||||||
var items: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
|
var items: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
|
||||||
|
|
||||||
private override init() {
|
private override init() {
|
||||||
super.init()
|
super.init()
|
||||||
SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in
|
SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in
|
||||||
self?.dismissTouchBar()
|
self?.dismissTouchBar()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
loadItems()
|
loadItems()
|
||||||
|
|
||||||
touchBar.delegate = self
|
touchBar.delegate = self
|
||||||
self.presentTouchBar()
|
self.presentTouchBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadItems() {
|
func loadItems() {
|
||||||
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")
|
||||||
@ -70,7 +68,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
}
|
}
|
||||||
let jsonData = presetPath.fileData
|
let jsonData = presetPath.fileData
|
||||||
let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [])]
|
let jsonItems = jsonData?.barItemDefinitions() ?? [BarItemDefinition(type: .staticButton(title: "bad preset"), action: .none, additionalParameters: [])]
|
||||||
|
|
||||||
for item in jsonItems {
|
for item in jsonItems {
|
||||||
let identifierString = item.type.identifierBase.appending(UUID().uuidString)
|
let identifierString = item.type.identifierBase.appending(UUID().uuidString)
|
||||||
let identifier = item.type == ItemType.flexSpace()
|
let identifier = item.type == ItemType.flexSpace()
|
||||||
@ -88,30 +86,29 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
NSTouchBarItem.addSystemTrayItem(item)
|
NSTouchBarItem.addSystemTrayItem(item)
|
||||||
DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true)
|
DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateControlStripPresence() {
|
func updateControlStripPresence() {
|
||||||
DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true)
|
DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func presentTouchBar() {
|
@objc private func presentTouchBar() {
|
||||||
NSTouchBar.presentSystemModalFunctionBar(touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem)
|
NSTouchBar.presentSystemModalFunctionBar(touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func dismissTouchBar() {
|
@objc private func dismissTouchBar() {
|
||||||
NSTouchBar.minimizeSystemModalFunctionBar(touchBar)
|
NSTouchBar.minimizeSystemModalFunctionBar(touchBar)
|
||||||
}
|
}
|
||||||
|
|
||||||
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
|
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
|
||||||
guard let item = self.items[identifier] else {
|
guard let item = self.items[identifier] else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let action = self.action(forItem: item)
|
let action = self.action(forItem: item)
|
||||||
|
|
||||||
var barItem: NSTouchBarItem!
|
var barItem: NSTouchBarItem!
|
||||||
switch item.type {
|
switch item.type {
|
||||||
case .staticButton(title: let title):
|
case .staticButton(title: let title):
|
||||||
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action)
|
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action)
|
||||||
case .staticImageButton(title: let title, image: let image):
|
|
||||||
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title, onTap: action, image: image)
|
|
||||||
case .appleScriptTitledButton(source: let source, refreshInterval: let interval):
|
case .appleScriptTitledButton(source: let source, refreshInterval: let interval):
|
||||||
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, onTap: action)
|
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, onTap: action)
|
||||||
case .timeButton(formatTemplate: let template):
|
case .timeButton(formatTemplate: let template):
|
||||||
@ -127,11 +124,17 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
if case .width(let value) = parameter, let widthBarItem = barItem as? CanSetWidth {
|
if case .width(let value) = parameter, let widthBarItem = barItem as? CanSetWidth {
|
||||||
widthBarItem.setWidth(value: value)
|
widthBarItem.setWidth(value: value)
|
||||||
}
|
}
|
||||||
|
if case .image(let source) = parameter, let item = barItem as? CustomButtonTouchBarItem {
|
||||||
|
let button = item.button!
|
||||||
|
button.image = source.image
|
||||||
|
button.imagePosition = .imageLeading
|
||||||
|
button.imageHugsTitle = true
|
||||||
|
button.bezelColor = .clear
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return barItem
|
return barItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func action(forItem item: BarItemDefinition) -> ()->() {
|
func action(forItem item: BarItemDefinition) -> ()->() {
|
||||||
switch item.action {
|
switch item.action {
|
||||||
case .hidKey(keycode: let keycode):
|
case .hidKey(keycode: let keycode):
|
||||||
|
|||||||
12
README.md
12
README.md
@ -82,13 +82,6 @@ File for customize your preset for MTMR: `open ~/Library/Application Support/MTM
|
|||||||
"title": "esc",
|
"title": "esc",
|
||||||
```
|
```
|
||||||
|
|
||||||
- `staticImageButton`
|
|
||||||
```json
|
|
||||||
"type": "staticImageButton",
|
|
||||||
"image": "StringInbase64"
|
|
||||||
"title": "Finder",
|
|
||||||
```
|
|
||||||
|
|
||||||
- `appleScriptTitledButton`
|
- `appleScriptTitledButton`
|
||||||
```js
|
```js
|
||||||
"type": "appleScriptTitledButton",
|
"type": "appleScriptTitledButton",
|
||||||
@ -175,9 +168,8 @@ File for customize your preset for MTMR: `open ~/Library/Application Support/MTM
|
|||||||
"refreshInterval": 1
|
"refreshInterval": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "staticImageButton",
|
"type": "staticButton",
|
||||||
"title": "Finder",
|
"image": { "base64" : "%base64Finder%"},
|
||||||
"image": "%base64Finder%",
|
|
||||||
"action": "appleScript",
|
"action": "appleScript",
|
||||||
"actionAppleScript": {
|
"actionAppleScript": {
|
||||||
"inline": "tell application \"Finder\"\rmake new Finder window\rset target of front window to path to home folder as string\ractivate\rend tell"
|
"inline": "tell application \"Finder\"\rmake new Finder window\rset target of front window to path to home folder as string\ractivate\rend tell"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user