mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-10 00:58:37 +00:00
longActions
This commit is contained in:
parent
e95c707009
commit
1f764d539a
@ -3,7 +3,7 @@ import AppKit
|
|||||||
|
|
||||||
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: self.utf8string!.stripComments().data(using: .utf8)!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,23 +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 }
|
||||||
@ -37,46 +38,56 @@ 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 return (item: .staticButton(title: "esc"), action: .keyPress(keycode: 53), longAction: .none, parameters: [.align: .align(.left)]) },
|
||||||
|
|
||||||
"delete": { _ in return (item: .staticButton(title: "del"), action: .keyPress(keycode: 117), longAction: .none, parameters: [:])},
|
"delete": { _ in return (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])
|
||||||
},
|
},
|
||||||
|
|
||||||
"volumeDown": { _ in
|
"volumeDown": { _ in
|
||||||
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeDownTemplate)!)
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeDownTemplate)!)
|
||||||
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: .touchBarVolumeUpTemplate)!)
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarVolumeUpTemplate)!)
|
||||||
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: .touchBarAudioOutputMuteTemplate)!)
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarAudioOutputMuteTemplate)!)
|
||||||
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: .touchBarRewindTemplate)!)
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarRewindTemplate)!)
|
||||||
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: .touchBarPlayPauseTemplate)!)
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarPlayPauseTemplate)!)
|
||||||
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: .touchBarFastForwardTemplate)!)
|
let imageParameter = GeneralParameter.image(source: NSImage(named: .touchBarFastForwardTemplate)!)
|
||||||
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)
|
||||||
@ -88,6 +99,7 @@ class SupportedTypesHolder {
|
|||||||
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: action, longAction: 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)
|
||||||
@ -98,12 +110,15 @@ class SupportedTypesHolder {
|
|||||||
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: action, longAction: longAction, parameters: [:])
|
||||||
},
|
},
|
||||||
|
|
||||||
"dock": { decoder in
|
"dock": { decoder in
|
||||||
return (item: .dock(), action: .none, longAction: .none, parameters: [:])
|
return (item: .dock(), action: .none, longAction: .none, parameters: [:])
|
||||||
},
|
},
|
||||||
|
|
||||||
"inputsource": { decoder in
|
"inputsource": { decoder in
|
||||||
return (item: .inputsource(), action: .none, longAction: .none, parameters: [:])
|
return (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)
|
||||||
@ -113,6 +128,7 @@ class SupportedTypesHolder {
|
|||||||
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)
|
||||||
@ -123,8 +139,11 @@ class SupportedTypesHolder {
|
|||||||
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 return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["sleepnow"]), longAction: .none, parameters: [:]) },
|
||||||
|
|
||||||
"displaySleep": { _ in return (item: .staticButton(title: "☕️"), action: .shellScript(executable: "/usr/bin/pmset", parameters: ["displaysleepnow"]), longAction: .none, parameters: [:])},
|
"displaySleep": { _ in return (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)
|
||||||
@ -136,6 +155,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)
|
||||||
@ -147,20 +167,20 @@ class SupportedTypesHolder {
|
|||||||
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: [:])
|
return (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: [:])
|
return (item: item, action: action, longAction: longAction, parameters: [:])
|
||||||
@ -181,7 +201,7 @@ enum ItemType: Decodable {
|
|||||||
case inputsource()
|
case inputsource()
|
||||||
case music(interval: Double)
|
case music(interval: Double)
|
||||||
case groupBar(items: [BarItemDefinition])
|
case groupBar(items: [BarItemDefinition])
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
case title
|
case title
|
||||||
@ -198,7 +218,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
|
||||||
@ -213,46 +233,58 @@ enum ItemType: Decodable {
|
|||||||
case music
|
case music
|
||||||
case groupBar
|
case groupBar
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@ -264,11 +296,11 @@ enum ActionType: Decodable {
|
|||||||
case none
|
case none
|
||||||
case hidKey(keycode: Int32)
|
case hidKey(keycode: Int32)
|
||||||
case keyPress(keycode: Int)
|
case keyPress(keycode: Int)
|
||||||
case appleSctipt(source: SourceProtocol)
|
case appleScript(source: SourceProtocol)
|
||||||
case shellScript(executable: String, parameters: [String])
|
case shellScript(executable: String, parameters: [String])
|
||||||
case custom(closure: ()->())
|
case custom(closure: ()->())
|
||||||
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
|
||||||
@ -277,7 +309,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
|
||||||
@ -285,29 +317,35 @@ 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):
|
|
||||||
let keycode = try container.decode(Int.self, forKey: .keycode)
|
case .some(.keyPress):
|
||||||
self = .keyPress(keycode: keycode)
|
let keycode = try container.decode(Int.self, forKey: .keycode)
|
||||||
case .some(.appleScript):
|
self = .keyPress(keycode: keycode)
|
||||||
let source = try container.decode(Source.self, forKey: .actionAppleScript)
|
|
||||||
self = .appleSctipt(source: source)
|
case .some(.appleScript):
|
||||||
case .some(.shellScript):
|
let source = try container.decode(Source.self, forKey: .actionAppleScript)
|
||||||
let executable = try container.decode(String.self, forKey: .executablePath)
|
self = .appleScript(source: source)
|
||||||
let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? []
|
|
||||||
self = .shellScript(executable: executable, parameters: parameters)
|
case .some(.shellScript):
|
||||||
case .some(.openUrl):
|
let executable = try container.decode(String.self, forKey: .executablePath)
|
||||||
let url = try container.decode(String.self, forKey: .url)
|
let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? []
|
||||||
self = .openUrl(url: url)
|
self = .shellScript(executable: executable, parameters: parameters)
|
||||||
case .none:
|
|
||||||
self = .none
|
case .some(.openUrl):
|
||||||
|
let url = try container.decode(String.self, forKey: .url)
|
||||||
|
self = .openUrl(url: url)
|
||||||
|
|
||||||
|
case .none:
|
||||||
|
self = .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,17 +355,17 @@ enum LongActionType: Decodable {
|
|||||||
case none
|
case none
|
||||||
case hidKey(keycode: Int32)
|
case hidKey(keycode: Int32)
|
||||||
case keyPress(keycode: Int)
|
case keyPress(keycode: Int)
|
||||||
case appleSctipt(source: SourceProtocol)
|
case appleScript(source: SourceProtocol)
|
||||||
case shellScript(executable: String, parameters: [String])
|
case shellScript(executable: String, parameters: [String])
|
||||||
case custom(closure: ()->())
|
case custom(closure: ()->())
|
||||||
case openUrl(url: String)
|
case openUrl(url: String)
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case longAction
|
case longAction
|
||||||
case keycode
|
case longKeycode
|
||||||
case actionAppleScript
|
case longActionAppleScript
|
||||||
case executablePath
|
case longExecutablePath
|
||||||
case shellArguments
|
case longShellArguments
|
||||||
case longUrl
|
case longUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,25 +380,31 @@ enum LongActionType: Decodable {
|
|||||||
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: .keycode)
|
let keycode = try container.decode(Int32.self, forKey: .longKeycode)
|
||||||
self = .hidKey(keycode: keycode)
|
self = .hidKey(keycode: keycode)
|
||||||
case .some(.keyPress):
|
|
||||||
let keycode = try container.decode(Int.self, forKey: .keycode)
|
case .some(.keyPress):
|
||||||
self = .keyPress(keycode: keycode)
|
let keycode = try container.decode(Int.self, forKey: .longKeycode)
|
||||||
case .some(.appleScript):
|
self = .keyPress(keycode: keycode)
|
||||||
let source = try container.decode(Source.self, forKey: .actionAppleScript)
|
|
||||||
self = .appleSctipt(source: source)
|
case .some(.appleScript):
|
||||||
case .some(.shellScript):
|
let source = try container.decode(Source.self, forKey: .longActionAppleScript)
|
||||||
let executable = try container.decode(String.self, forKey: .executablePath)
|
self = .appleScript(source: source)
|
||||||
let parameters = try container.decodeIfPresent([String].self, forKey: .shellArguments) ?? []
|
|
||||||
self = .shellScript(executable: executable, parameters: parameters)
|
case .some(.shellScript):
|
||||||
case .some(.openUrl):
|
let executable = try container.decode(String.self, forKey: .longExecutablePath)
|
||||||
let longUrl = try container.decode(String.self, forKey: .longUrl)
|
let parameters = try container.decodeIfPresent([String].self, forKey: .longShellArguments) ?? []
|
||||||
self = .openUrl(url: longUrl)
|
self = .shellScript(executable: executable, parameters: parameters)
|
||||||
case .none:
|
|
||||||
self = .none
|
case .some(.openUrl):
|
||||||
|
let longUrl = try container.decode(String.self, forKey: .longUrl)
|
||||||
|
self = .openUrl(url: longUrl)
|
||||||
|
|
||||||
|
case .none:
|
||||||
|
self = .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,7 +421,7 @@ enum GeneralParameter {
|
|||||||
|
|
||||||
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
|
||||||
@ -386,35 +430,45 @@ 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol SourceProtocol {
|
protocol SourceProtocol {
|
||||||
var data: Data? { get }
|
var data: Data? { get }
|
||||||
var string: String? { get }
|
var string: String? { get }
|
||||||
var image: NSImage? { get }
|
var image: NSImage? { get }
|
||||||
var appleScript: NSAppleScript? { get }
|
var appleScript: NSAppleScript? { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Source: Decodable, SourceProtocol {
|
struct Source: Decodable, SourceProtocol {
|
||||||
let filePath: String?
|
let filePath: String?
|
||||||
let base64: String?
|
let base64: String?
|
||||||
@ -429,35 +483,43 @@ struct Source: Decodable, SourceProtocol {
|
|||||||
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 ?? self.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NSImage: SourceProtocol {
|
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
|
||||||
}
|
}
|
||||||
@ -467,6 +529,7 @@ 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))
|
||||||
}
|
}
|
||||||
@ -477,10 +540,12 @@ extension String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
||||||
}
|
}
|
||||||
@ -496,6 +561,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -315,7 +315,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
return { HIDPostAuxKey(keycode) }
|
return { HIDPostAuxKey(keycode) }
|
||||||
case .keyPress(keycode: let keycode):
|
case .keyPress(keycode: let keycode):
|
||||||
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
|
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
|
||||||
case .appleSctipt(source: let source):
|
case .appleScript(source: let source):
|
||||||
guard let appleScript = source.appleScript else {
|
guard let appleScript = source.appleScript else {
|
||||||
print("cannot create apple script for item \(item)")
|
print("cannot create apple script for item \(item)")
|
||||||
return {}
|
return {}
|
||||||
@ -360,7 +360,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
return { HIDPostAuxKey(keycode) }
|
return { HIDPostAuxKey(keycode) }
|
||||||
case .keyPress(keycode: let keycode):
|
case .keyPress(keycode: let keycode):
|
||||||
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
|
return { GenericKeyPress(keyCode: CGKeyCode(keycode)).send() }
|
||||||
case .appleSctipt(source: let source):
|
case .appleScript(source: let source):
|
||||||
guard let appleScript = source.appleScript else {
|
guard let appleScript = source.appleScript else {
|
||||||
print("cannot create apple script for item \(item)")
|
print("cannot create apple script for item \(item)")
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
14
README.md
14
README.md
@ -202,6 +202,20 @@ File for customize your preset for MTMR: `open ~/Library/Application\ Support/MT
|
|||||||
"url": "https://google.com",
|
"url": "https://google.com",
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## LongActions
|
||||||
|
This then you want to use longPress for some operations is will the same values like for Actions but different additional parameters, example:
|
||||||
|
```js
|
||||||
|
"longAction": "hidKey",
|
||||||
|
"longKeycode": 53,
|
||||||
|
```
|
||||||
|
|
||||||
|
- longAction
|
||||||
|
- longKeycode
|
||||||
|
- longActionAppleScript
|
||||||
|
- longExecutablePath
|
||||||
|
- longShellArguments
|
||||||
|
- longUrl
|
||||||
|
|
||||||
## Additional parameters:
|
## Additional parameters:
|
||||||
|
|
||||||
- `width` allow to restrict how much room a particular button will take
|
- `width` allow to restrict how much room a particular button will take
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user