From 5cb2ff13e5098a7ad55eb7f02a5f1d4680c6e35e Mon Sep 17 00:00:00 2001 From: John Sterling Date: Wed, 10 Apr 2019 00:06:29 +0200 Subject: [PATCH] Add option to hide status bar icon --- Finicky/Finicky/AppDelegate.swift | 11 ++++++-- Finicky/Finicky/Config.swift | 27 +++++++++++++++----- Finicky/Finicky/Notifications.swift | 3 ++- Finicky/Finicky/validateConfig.js | 39 +++++++++++++++++++++++------ 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/Finicky/Finicky/AppDelegate.swift b/Finicky/Finicky/AppDelegate.swift index 9dbde22..aa65086 100644 --- a/Finicky/Finicky/AppDelegate.swift +++ b/Finicky/Finicky/AppDelegate.swift @@ -33,6 +33,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele statusItem.highlightMode = true statusItem.image = img _ = toggleDockIcon(showIcon: false) + + func toggleIconCallback(show: Bool) { + guard statusItem != nil else { return } + statusItem.isVisible = !show + } + + configLoader = FinickyConfig(toggleIconCallback: toggleIconCallback) + configLoader.reload(showSuccess: false) + } @IBAction func reloadConfig(_ sender: NSMenuItem) { @@ -170,8 +179,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele func applicationWillFinishLaunching(_ aNotification: Notification) { - configLoader = FinickyConfig() - configLoader.reload(showSuccess: false) shortUrlResolver = FNShortUrlResolver() let appleEventManager:NSAppleEventManager = NSAppleEventManager.shared() appleEventManager.setEventHandler(self, andSelector: #selector(AppDelegate.handleGetURLEvent(_:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) diff --git a/Finicky/Finicky/Config.swift b/Finicky/Finicky/Config.swift index ab3ecc1..733e63f 100644 --- a/Finicky/Finicky/Config.swift +++ b/Finicky/Finicky/Config.swift @@ -34,15 +34,16 @@ open class FinickyConfig { var ctx: JSContext! var validateConfigJS : String?; var processUrlJS : String?; - var hasError: Bool; + var hasError: Bool = false; var dispatchSource: DispatchSourceFileSystemObject? var fileDescriptor: Int32 = -1 var fileManager = FileManager.init(); var lastModificationDate: Date? = nil; + var toggleIconCallback:(_ hide: Bool) -> Void; - public init() { - self.hasError = false; + public init(toggleIconCallback: @escaping (_ hide: Bool) -> Void ) { + self.toggleIconCallback = toggleIconCallback listenToChanges(); if let path = Bundle.main.path(forResource: "validateConfig.js", ofType: nil ) { @@ -134,18 +135,20 @@ open class FinickyConfig { } let validConfig = ctx.evaluateScript(validateConfigJS!)?.call(withArguments: []) + if let isBoolean = validConfig?.isBoolean { if (isBoolean) { - let result = validConfig?.toBool() - if (!result!) { + if (!(validConfig?.toBool())!) { print("Invalid config") showNotification(title: "Invalid config") return false; + } else { + return true; } } } - return true; + return false; } func reload(showSuccess: Bool) { @@ -174,9 +177,21 @@ open class FinickyConfig { if config != nil { let success = parseConfig(config!) if (success && showSuccess) { + toggleIconCallback(getHideIcon()) showNotification(title: "Reloaded config successfully") } } + + + } + + open func getHideIcon() -> Bool { + let hideIcon = ctx.evaluateScript("module.exports.options && module.exports.options.hideIcon")?.toBool() + + if hideIcon == nil { + return false + } + return hideIcon!; } open func determineOpeningApp(url: URL) -> AppDescriptor? { diff --git a/Finicky/Finicky/Notifications.swift b/Finicky/Finicky/Notifications.swift index a6c7a59..5051626 100644 --- a/Finicky/Finicky/Notifications.swift +++ b/Finicky/Finicky/Notifications.swift @@ -1,7 +1,7 @@ import Foundation import AppKit -func showNotification(title: String, subtitle: String? = nil, informativeText: String? = nil) -> Void { +func showNotification(title: String, subtitle: String? = nil, informativeText: String? = nil, error: Bool = false) -> Void { let notification = NSUserNotification() notification.title = title @@ -14,5 +14,6 @@ func showNotification(title: String, subtitle: String? = nil, informativeText: S } notification.soundName = NSUserNotificationDefaultSoundName + NSUserNotificationCenter.default.deliver(notification) } diff --git a/Finicky/Finicky/validateConfig.js b/Finicky/Finicky/validateConfig.js index 18824c2..f674b42 100644 --- a/Finicky/Finicky/validateConfig.js +++ b/Finicky/Finicky/validateConfig.js @@ -1,4 +1,13 @@ (function() { + + + function isOfType(value, type = []) { + const types = Array.isArray(type) ? type : [type]; + return types.includes(typeof value); + } + + const isBool = (value) => [isOfType(value, "boolean"), "boolean", typeof value]; + return function validateConfig() { if (!module || !module.exports) { throw new Error("module.exports is not defined"); @@ -9,6 +18,25 @@ } module.exports.handlers.forEach(validateHandler); + + const options = module.exports.options; + if (options && typeof options === "object") { + + const validateOptions = { hideIcon: isBool }; + + Object.keys(options).forEach(key => { + if (!validateOptions[key]) { + throw new Error("module.exports.options contained an invalid option: " + key); + } + + const [valid, expectedType, actualType] = validateOptions[key](options[key]); + if (!valid) { + throw new Error(`module.exports.options.${key} expected to be type ${expectedType}, but was ${actualType}`); + } + }); + } + + return true; }; function validateHandler(handler, index) { @@ -48,14 +76,9 @@ } if (typeof value === "object" && typeof value.value !== "string") { - throw new Error( - `Handler #${handlerNum} value: expected object to have string property ${typeof value.value}` - ); + throw new Error( + `Handler #${handlerNum} value: expected object to have string property ${typeof value.value}` + ); } } - - function isOfType(value, type = []) { - const types = Array.isArray(type) ? type : [type]; - return types.includes(typeof value); - } })();