Skip to content

Commit 7aa3f81

Browse files
authored
Merge pull request #50 from johnste/finicky-2
Finicky 2
2 parents ceb32e4 + 81cb5b1 commit 7aa3f81

16 files changed

+476
-289
lines changed

Finicky/Finicky.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
543EC33F21DE54EA004789DF /* validateConfig.js in Resources */ = {isa = PBXBuildFile; fileRef = 543EC33E21DE54E9004789DF /* validateConfig.js */; };
1212
544B57891B28B87900812908 /* statusitem.png in Resources */ = {isa = PBXBuildFile; fileRef = 544B57871B28B87900812908 /* statusitem.png */; };
1313
544B578A1B28B87900812908 /* statusitem@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 544B57881B28B87900812908 /* statusitem@2x.png */; };
14+
546F1678228B487F006C5375 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546F1677228B487F006C5375 /* Utilities.swift */; };
1415
5479FDD421655A3400D15A3C /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5479FDD321655A3400D15A3C /* Notifications.swift */; };
1516
548479A22278ADB40003D51C /* validate.js in Resources */ = {isa = PBXBuildFile; fileRef = 548479A12278ADB40003D51C /* validate.js */; };
1617
54899CD61B20D5BC00647101 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54899CD51B20D5BC00647101 /* AppDelegate.swift */; };
@@ -45,6 +46,7 @@
4546
543EC33E21DE54E9004789DF /* validateConfig.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = validateConfig.js; sourceTree = "<group>"; };
4647
544B57871B28B87900812908 /* statusitem.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = statusitem.png; sourceTree = "<group>"; };
4748
544B57881B28B87900812908 /* statusitem@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "statusitem@2x.png"; sourceTree = "<group>"; };
49+
546F1677228B487F006C5375 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
4850
5479FDD321655A3400D15A3C /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
4951
548479A12278ADB40003D51C /* validate.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = validate.js; sourceTree = "<group>"; };
5052
54899CD01B20D5BC00647101 /* Finicky.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Finicky.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -121,6 +123,7 @@
121123
54B0E7021B4678CE003F8AEE /* ShortUrlResolver.swift */,
122124
5479FDD321655A3400D15A3C /* Notifications.swift */,
123125
54B5771522860D0B0016BF77 /* Credits.rtf */,
126+
546F1677228B487F006C5375 /* Utilities.swift */,
124127
);
125128
path = Finicky;
126129
sourceTree = "<group>";
@@ -278,6 +281,7 @@
278281
isa = PBXSourcesBuildPhase;
279282
buildActionMask = 2147483647;
280283
files = (
284+
546F1678228B487F006C5375 /* Utilities.swift in Sources */,
281285
5479FDD421655A3400D15A3C /* Notifications.swift in Sources */,
282286
54E33FD71B24E27000998E13 /* Config.swift in Sources */,
283287
54899CD61B20D5BC00647101 /* AppDelegate.swift in Sources */,

Finicky/Finicky/API.swift

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import JavaScriptCore
44
@objc protocol FinickyAPIExports : JSExport {
55
static func log(_ message: String?) -> Void
66
static func notify(_ title: JSValue, _ subtitle: JSValue) -> Void
7-
static func matchDomains(_ domains: [String]) -> ((_ url: String) -> JSValue)
87
static func getUrlParts(_ url: String) -> Dictionary<String, Any>
98
}
109

@@ -38,33 +37,19 @@ import JavaScriptCore
3837
self.logToConsole = logToConsole
3938
}
4039

41-
@objc class func matchDomains(_ domains: [String]) -> ((_ url: String) -> JSValue) {
42-
func matchDomain(url: String) -> JSValue {
43-
for domain in domains {
44-
let urlParts = getUrlParts(url);
45-
if( urlParts["host"] as! String == domain) {
46-
return JSValue(bool: true, in: context)
47-
}
48-
}
49-
return JSValue(bool: false, in: context)
50-
}
51-
52-
return matchDomain;
53-
}
54-
5540
@objc public class func getUrlParts(_ urlString: String) -> Dictionary<String, Any> {
5641
let url: URL! = URL.init(string: urlString)
5742

5843
guard url != nil else { return [:] }
5944

60-
let _protocol = url.scheme ?? nil
61-
let username = url.user ?? nil
62-
let password = url.password ?? nil
63-
let host = url.host ?? nil
45+
let _protocol = url.scheme ?? ""
46+
let username = url.user ?? ""
47+
let password = url.password ?? ""
48+
let host = url.host ?? ""
6449
let port = url.port ?? nil
6550
let pathname = url.path
66-
let search = url.query ?? nil
67-
let hash = url.fragment ?? nil
51+
let search = url.query ?? ""
52+
let hash = url.fragment ?? ""
6853

6954
let urlDict = [
7055
"hash": hash as Any,
@@ -79,5 +64,4 @@ import JavaScriptCore
7964

8065
return urlDict
8166
}
82-
8367
}

Finicky/Finicky/AppDelegate.swift

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
3232
statusItem.menu = statusItemMenu
3333
statusItem.highlightMode = true
3434
statusItem.image = img
35-
_ = toggleDockIcon(showIcon: false)
35+
toggleDockIcon(showIcon: false)
3636

3737
func toggleIconCallback(show: Bool) {
3838
guard statusItem != nil else { return }
@@ -45,7 +45,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
4545

4646
configLoader = FinickyConfig(toggleIconCallback: toggleIconCallback, logToConsoleCallback: logToConsole, setShortUrlProviders: setShortUrlProviders)
4747
configLoader.reload(showSuccess: false)
48-
4948
}
5049

5150
@IBAction func reloadConfig(_ sender: NSMenuItem) {
@@ -79,23 +78,30 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
7978
return
8079
}
8180
if let url = URL.init(string: value) {
82-
if let appDescriptor = configLoader.determineOpeningApp(url: url, sourceBundleIdentifier: "net.kassett.finicky") {
83-
var description = ""
84-
85-
if let openInBackground = appDescriptor.openInBackground {
86-
description = """
87-
Would open \(AppDescriptorType.bundleId == appDescriptor.appType ? "bundleId" : "") "\(appDescriptor.name)" \(openInBackground ? "application in the background" : "") URL: "\(appDescriptor.url)"
88-
"""
89-
} else {
90-
description = """
91-
Would open \(AppDescriptorType.bundleId == appDescriptor.appType ? "bundleId" : "") "\(appDescriptor.name)" URL: "\(appDescriptor.url)"
92-
"""
93-
}
94-
logToConsole(description)
81+
shortUrlResolver.resolveUrl(url, callback: {(URL) -> Void in
82+
self.performTest(url: URL)
83+
})
84+
}
85+
}
86+
87+
func performTest(url: URL) {
88+
if let appDescriptor = configLoader.determineOpeningApp(url: url, sourceBundleIdentifier: "net.kassett.finicky") {
89+
var description = ""
90+
91+
if let openInBackground = appDescriptor.openInBackground {
92+
description = """
93+
Would open \(AppDescriptorType.bundleId == appDescriptor.appType ? "bundleId" : "")\(appDescriptor.name) \(openInBackground ? "application in the background" : "") URL: \(appDescriptor.url)
94+
"""
95+
} else {
96+
description = """
97+
Would open \(AppDescriptorType.bundleId == appDescriptor.appType ? "bundleId" : "")\(appDescriptor.name) URL: \(appDescriptor.url)
98+
"""
9599
}
100+
logToConsole(description)
96101
}
97102
}
98103

104+
@discardableResult
99105
@objc func toggleDockIcon(showIcon state: Bool) -> Bool {
100106
var result: Bool
101107
if state {
@@ -112,13 +118,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
112118
let pid = event!.attributeDescriptor(forKeyword: AEKeyword(keySenderPIDAttr))!.int32Value
113119
let sourceBundleIdentifier = NSRunningApplication(processIdentifier: pid)?.bundleIdentifier
114120

115-
if shortUrlResolver.isShortUrl(url) {
116-
shortUrlResolver.resolveUrl(url, callback: {(URL) -> Void in
117-
self.callUrlHandlers(sourceBundleIdentifier, url: url)
118-
})
119-
} else {
120-
self.callUrlHandlers(sourceBundleIdentifier, url: url)
121-
}
121+
shortUrlResolver.resolveUrl(url, callback: {(URL) -> Void in
122+
self.callUrlHandlers(sourceBundleIdentifier, url: URL)
123+
})
122124
}
123125

124126
@objc func callUrlHandlers(_ sourceBundleIdentifier: String?, url: URL) {
@@ -138,7 +140,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
138140
if bundleId != nil {
139141
openUrlWithBrowser(appDescriptor.url, bundleIdentifier:bundleId!, openInBackground: appDescriptor.openInBackground )
140142
} else {
141-
print ("Finicky was unable to find the application \"" + appDescriptor.name + "\"")
143+
let description = "Finicky was unable to find the application \"" + appDescriptor.name + "\"";
144+
print(description)
145+
logToConsole(description)
142146
showNotification(title: "Unable to find application", informativeText: "Finicky was unable to find the application \"" + appDescriptor.name + "\"", error: true)
143147
}
144148
}
@@ -154,27 +158,16 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
154158

155159

156160
func openUrlWithBrowser(_ url: URL, bundleIdentifier: String, openInBackground: Bool?) {
157-
let urls = [url]
158-
159-
// Launch in background by default if finicky isn't active to avoid something..
161+
// Launch in background by default if finicky isn't active to avoid something that causes some bug to happen...
162+
// Too long ago to remember what actually happened
160163
let openInBackground = openInBackground ?? !isActive
161164

162-
if !openInBackground {
163-
NSWorkspace.shared.launchApplication(
164-
withBundleIdentifier: bundleIdentifier,
165-
options: NSWorkspace.LaunchOptions.default,
166-
additionalEventParamDescriptor: nil,
167-
launchIdentifier: nil
168-
)
165+
print("opening " + url.absoluteString)
166+
if (openInBackground) {
167+
shell("open", url.absoluteString , "-b", bundleIdentifier, "-g")
168+
} else {
169+
shell("open",url.absoluteString , "-b", bundleIdentifier)
169170
}
170-
171-
NSWorkspace.shared.open(
172-
urls,
173-
withAppBundleIdentifier: bundleIdentifier,
174-
options: openInBackground ? NSWorkspace.LaunchOptions.withoutActivation : NSWorkspace.LaunchOptions.default,
175-
additionalEventParamDescriptor: nil,
176-
launchIdentifiers: nil
177-
)
178171
}
179172

180173
func application(_ sender: NSApplication, openFiles filenames: [String]) {
@@ -183,7 +176,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
183176
}
184177
}
185178

186-
187179
func applicationWillFinishLaunching(_ aNotification: Notification) {
188180
let appleEventManager:NSAppleEventManager = NSAppleEventManager.shared()
189181
appleEventManager.setEventHandler(self, andSelector: #selector(AppDelegate.handleGetURLEvent(_:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))

Finicky/Finicky/Config.swift

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,17 @@ open class FinickyConfig {
109109
dispatchSource?.resume()
110110
}
111111

112+
@discardableResult
112113
open func createContext() -> JSContext {
113114
ctx = JSContext()
114115

115116
ctx.exceptionHandler = {
116-
context, exception in
117+
(context: JSContext!, exception: JSValue!) in
117118
self.hasError = true;
119+
//let stacktrace = exception.objectForKeyedSubscript("stack").toString()
120+
//let lineNumber = exception.objectForKeyedSubscript("line").toString()
121+
//let columnNumber = exception.objectForKeyedSubscript("column").toString()
122+
//let message = "Error parsing config: \"\(String(describing: exception!))\" \nStack: \(stacktrace!):\(lineNumber!):\(columnNumber!)";
118123
let message = "Error parsing config: \"\(String(describing: exception!))\"";
119124
print(message)
120125
showNotification(title: "Error parsing config", informativeText: String(describing: exception!), error: true)
@@ -131,6 +136,7 @@ open class FinickyConfig {
131136
return ctx
132137
}
133138

139+
@discardableResult
134140
open func parseConfig(_ config: String) -> Bool {
135141
ctx.evaluateScript(config)
136142

@@ -173,18 +179,19 @@ open class FinickyConfig {
173179

174180
if config == nil {
175181
let message = "Config file could not be read or found"
176-
showNotification(title: message, subtitle: "Click here to show example config file", error: true)
182+
showNotification(title: message, subtitle: "Click here for assistance", error: true)
177183
print(message)
178184
if (self.logToConsole != nil) {
179185
self.logToConsole!(message + "\n\n" + """
180186
// --------------------------------------------------------------
181187
// Example config, save as ~/.finicky.js
188+
// For more examples, see the Finicky github page https://github.com/johnste/finicky
182189
module.exports = {
183190
defaultBrowser: "Safari",
184191
handlers: [
185192
{
186-
match: /^https?:\\/\\/(youtube|facebook|twitter|linkedin|keep\\.google)\\.com/,
187-
app: "Google Chrome"
193+
match: finicky.matchDomains(["youtube.com", "facebook.com", "twitter.com", "linkedin.com"]),
194+
browser: "Google Chrome"
188195
}
189196
]
190197
};
@@ -230,12 +237,16 @@ open class FinickyConfig {
230237

231238
open func getShortUrlProviders() -> [String]? {
232239
let urlShorteners = ctx.evaluateScript("module.exports.options && module.exports.options.urlShorteners || []")?.toArray()
233-
return urlShorteners as! [String]?;
240+
let list = urlShorteners as! [String]?;
241+
if (list?.count == 0) {
242+
return nil;
243+
}
244+
return list;
234245
}
235246

236247
open func determineOpeningApp(url: URL, sourceBundleIdentifier: String? = nil) -> AppDescriptor? {
237248
let appValue = getConfiguredAppValue(url: url, sourceBundleIdentifier: sourceBundleIdentifier)
238-
249+
239250
if ((appValue?.isObject)!) {
240251
let dict = appValue?.toDictionary()
241252
let appType = AppDescriptorType(rawValue: dict!["appType"] as! String)
@@ -268,8 +279,10 @@ open class FinickyConfig {
268279
func getConfiguredAppValue(url: URL, sourceBundleIdentifier: String?) -> JSValue? {
269280
let optionsDict = [
270281
"sourceBundleIdentifier": sourceBundleIdentifier as Any,
282+
"urlString": url.absoluteString,
283+
"url": FinickyAPI.getUrlParts(url.absoluteString),
271284
] as [AnyHashable : Any]
272-
let result = ctx.evaluateScript(processUrlJS!)?.call(withArguments: [url.absoluteString, optionsDict])
285+
let result = ctx.evaluateScript(processUrlJS!)?.call(withArguments: [optionsDict])
273286
return result
274287
}
275288

@@ -279,5 +292,37 @@ open class FinickyConfig {
279292
}
280293
FinickyAPI.setContext(ctx)
281294
ctx.setObject(FinickyAPI.self, forKeyedSubscript: "finicky" as NSCopying & NSObjectProtocol)
295+
296+
ctx.evaluateScript("""
297+
finicky.matchDomains = function(matchers) {
298+
if (!Array.isArray(matchers)) {
299+
matchers = [matchers];
300+
}
301+
302+
return function({ url }) {
303+
const domain = url.host;
304+
return matchers.some(matcher => {
305+
if (matcher instanceof RegExp) {
306+
return matcher.test(domain);
307+
} else if (typeof matcher === "string") {
308+
return matcher === domain;
309+
}
310+
311+
return false;
312+
});
313+
}
314+
}
315+
316+
// Warn when using deprecated API methods
317+
finicky.onUrl = function() {
318+
finicky.log("finicky.onUrl is no longer supported in this version of Finicky, please go to https://github.com/johnste/finicky for updated documentation");
319+
finicky.notify("finicky.onUrl is no longer supported", "Check the Finicky website for updated documentation");
320+
}
321+
322+
finicky.setDefaultBrowser = function() {
323+
finicky.log("finicky.setDefaultBrowser is no longer supported in this version of Finicky, please go to https://github.com/johnste/finicky for updated documentation");
324+
finicky.notify("finicky.setDefaultBrowser is no longer supported", "Check the Finicky website for updated documentation");
325+
}
326+
""")
282327
}
283328
}

Finicky/Finicky/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<key>CFBundlePackageType</key>
4141
<string>APPL</string>
4242
<key>CFBundleShortVersionString</key>
43-
<string>2.0-alpha</string>
43+
<string>2.0-beta</string>
4444
<key>CFBundleSignature</key>
4545
<string>????</string>
4646
<key>CFBundleURLTypes</key>

0 commit comments

Comments
 (0)