From 182cb3d1c2793502eeb6b092c30b4cd39a3a1015 Mon Sep 17 00:00:00 2001 From: Fedor Zaitsev Date: Fri, 28 Feb 2020 02:10:32 -0800 Subject: [PATCH 1/3] Updated README Added explanation for missing parameters (background, title and image) --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index e985d68..7cff707 100644 --- a/README.md +++ b/README.md @@ -375,6 +375,31 @@ If you want to longPress for some operations, it is similar to the configuration "bordered": "false" // "true" or "false" ``` +- `background` allow to specify you button background color + +```js + "background": "#FF0000", +``` +by using background with color "#000000" and bordered == false you can create button without gray background but with background when the button is pressed + +- `title` specify button title + +```js + "title": "hello" +``` + +- `image` specify button icon + +```js + "image": { + //Can be either of those + "base64": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAABGdB...." + //or + "filePath": "~/img.png" + } +``` + + ### Roadmap - [x] Create the first prototype with TouchBar in Storyboard From 4ad39af148264af4dfb1befb1d2f18cf02ba17b3 Mon Sep 17 00:00:00 2001 From: Fedor Zaitsev Date: Fri, 28 Feb 2020 02:44:19 -0800 Subject: [PATCH 2/3] Implemented changable icons for AppleScriptTouchBarItem AppleScriptTouchBarItem now allow to specify any number of icons which can be changed from the script. You cannot change icon from touch event. To change icon, you need to return array from your script with 2 values - title and icn name. More info in readme --- MTMR/AppleScriptTouchBarItem.swift | 26 +++++++++++++++++++++++++- MTMR/ItemsParsing.swift | 6 ++++-- MTMR/TouchBarController.swift | 4 ++-- README.md | 29 ++++++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/MTMR/AppleScriptTouchBarItem.swift b/MTMR/AppleScriptTouchBarItem.swift index 33d89cf..1ee67a7 100644 --- a/MTMR/AppleScriptTouchBarItem.swift +++ b/MTMR/AppleScriptTouchBarItem.swift @@ -4,9 +4,11 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { private var script: NSAppleScript! private let interval: TimeInterval private var forceHideConstraint: NSLayoutConstraint! + private let alternativeImages: [String: SourceProtocol] - init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) { + init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, alternativeImages: [String: SourceProtocol]) { self.interval = interval + self.alternativeImages = alternativeImages super.init(identifier: identifier, title: "⏳") forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0) title = "scheduled" @@ -57,6 +59,16 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { } } + func updateIcon(iconLabel: String) { + if alternativeImages[iconLabel] != nil { + DispatchQueue.main.async { + self.image = self.alternativeImages[iconLabel]!.image + } + } else { + print("Cannot find icon with label \"\(iconLabel)\"") + } + } + func execute() -> String { var error: NSDictionary? let output = script.executeAndReturnError(&error) @@ -64,6 +76,18 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem { 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 ?? "" } } diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 062409b..5248a2c 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -208,7 +208,7 @@ class SupportedTypesHolder { enum ItemType: Decodable { case staticButton(title: String) - case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double) + case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double, alternativeImages: [String: SourceProtocol]) case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double) case timeButton(formatTemplate: String, timeZone: String?, locale: String?) case battery @@ -251,6 +251,7 @@ enum ItemType: Decodable { case autoResize case filter case disableMarquee + case alternativeImages } enum ItemTypeRaw: String, Decodable { @@ -282,7 +283,8 @@ enum ItemType: Decodable { case .appleScriptTitledButton: let source = try container.decode(Source.self, forKey: .source) let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 - self = .appleScriptTitledButton(source: source, refreshInterval: interval) + let alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:] + self = .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages) case .shellScriptTitledButton: let source = try container.decode(Source.self, forKey: .source) diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 7c7b559..e28598c 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -240,8 +240,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { switch item.type { case let .staticButton(title: title): barItem = CustomButtonTouchBarItem(identifier: identifier, title: title) - case let .appleScriptTitledButton(source: source, refreshInterval: interval): - barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval) + case let .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages): + barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, alternativeImages: alternativeImages) case let .shellScriptTitledButton(source: source, refreshInterval: interval): barItem = ShellScriptTouchBarItem(identifier: identifier, source: source, interval: interval) case let .timeButton(formatTemplate: template, timeZone: timeZone, locale: locale): diff --git a/README.md b/README.md index 7cff707..93d21e8 100644 --- a/README.md +++ b/README.md @@ -133,10 +133,37 @@ The pre-installed configuration contains less or more than you'll probably want, "inline": "tell application \"Finder\"\rif not (exists window 1) then\rmake new Finder window\rset target of front window to path to home folder as string\rend if\ractivate\rend tell", // or "base64": "StringInbase64" - } + }, } ``` +> Note: appleScriptTitledButton can change its icon. To do it, you need to do the following things: +1. Declarate dictionary of icons in `alternativeImages` field +2. Make you script return array of two values - `{"TITLE", "IMAGE_LABEL"}` +3. Make sure that your `IMAGE_LABEL` is declared in `alternativeImages` field + +Example: +```js + { + "type": "appleScriptTitledButton", + "source": { + "inline": "if (random number from 1 to 2) = 1 then\n\tset val to {\"title\", \"play\"}\nelse\n\tset val to {\"title\", \"pause\"}\nend if\nreturn val" + }, + "refreshInterval": 1, + "image": { + "base64": "iVBORw0KGgoAAAANSUhEUgA..." + }, + "alternativeImages": { + "play": { + "base64": "iVBORw0KGgoAAAANSUhEUgAAAAAA..." + }, + "pause": { + "base64": "iVBORw0KGgoAAAANSUhEUgAAAIAA..." + } + } + }, +``` + #### `shellScriptTitledButton` > Note: script may return also colors using escape sequences (read more here https://misc.flogisoft.com/bash/tip_colors_and_formatting) > Only "16 Colors" mode supported atm. If background color returned, button will pick it up as own background color. From 542f70d1898cf065949a4dd84322d5ec491a760c Mon Sep 17 00:00:00 2001 From: Fedor Zaitsev Date: Fri, 17 Apr 2020 16:21:53 -0700 Subject: [PATCH 3/3] Fixed error related to ShellButton When you execute Process from swift you cannot relay solely on pipe.fileHandleForReading.readDataToEndOfFile() Sometimes when I close notebook I get exception saying that you cannot access process.terminationStatus variable while process is running. Apparently it seems that this call can be finished when OS X put disks into sleep mode(?) What I did: 1. Added Process.waitUntilExit() call 2. Added timeout (equal to the update interval) --- MTMR/ShellScriptTouchBarItem.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MTMR/ShellScriptTouchBarItem.swift b/MTMR/ShellScriptTouchBarItem.swift index 94d51ec..4fd51f3 100644 --- a/MTMR/ShellScriptTouchBarItem.swift +++ b/MTMR/ShellScriptTouchBarItem.swift @@ -62,11 +62,19 @@ class ShellScriptTouchBarItem: CustomButtonTouchBarItem { let pipe = Pipe() task.standardOutput = pipe + + // kill process if it is over update interval + DispatchQueue.main.asyncAfter(deadline: .now() + interval) { [weak task] in + task?.terminate() + } + task.launch() let data = pipe.fileHandleForReading.readDataToEndOfFile() var output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String? ?? "" + //always wait until task end or you can catch "task still running" error while accessing task.terminationStatus variable + task.waitUntilExit() if (output == "" && task.terminationStatus != 0) { output = "error" }