diff --git a/Finicky/Finicky/AppDelegate.swift b/Finicky/Finicky/AppDelegate.swift index 8f50021..169157c 100644 --- a/Finicky/Finicky/AppDelegate.swift +++ b/Finicky/Finicky/AppDelegate.swift @@ -112,7 +112,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele LSSetDefaultHandlerForURLScheme("http" as CFString, bundleId as CFString) LSSetDefaultHandlerForURLScheme("https" as CFString, bundleId as CFString) LSSetDefaultHandlerForURLScheme("finicky" as CFString, bundleId as CFString) - LSSetDefaultHandlerForURLScheme("finickys" as CFString, bundleId as CFString) } @IBAction func reloadConfig(_: NSMenuItem? = nil) { @@ -231,17 +230,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele } @IBAction func testUrl(_ sender: NSTextField) { - guard var value = sender.stringValue.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { + guard let value = sender.stringValue.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { logToConsole("Could not parse URL") return } - if value.starts(with: "finickys://") || value.starts(with: "finicky://") { - logToConsole("Finicky will convert finickys:// and finicky:// urls to https:// and http:// respectively") - value = value.replacingOccurrences(of: "finicky://", with: "http://", options: .literal, range: nil) - value = value.replacingOccurrences(of: "finickys://", with: "https://", options: .literal, range: nil) - } - if !value.starts(with: "https://"), !value.starts(with: "http://") { logToConsole("Finicky only understands https:// and http:// urls") return @@ -299,21 +292,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele let pid = event!.attributeDescriptor(forKeyword: AEKeyword(keySenderPIDAttr))!.int32Value let opener = Application(pid: pid) - var url = URL(string: event!.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))!.stringValue!)! - - if url.scheme == "finicky" || url.scheme == "finickys" { - if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) { - if url.scheme == "finicky" { - urlComponents.scheme = "http" - } - - if url.scheme == "finickys" { - urlComponents.scheme = "https" - } - - url = urlComponents.url! - } + + var rawUrl = event!.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))!.stringValue! + + if rawUrl.hasPrefix("finicky://") { + rawUrl.removeFirst("finicky://".count) } + + let url = URL(string: rawUrl)! + shortUrlResolver.resolveUrl(url, callback: { (URL) -> Void in self.callUrlHandlers(opener: opener, url: URL) }) diff --git a/Finicky/Finicky/Info.plist b/Finicky/Finicky/Info.plist index 6f4efa8..a5cea0b 100644 --- a/Finicky/Finicky/Info.plist +++ b/Finicky/Finicky/Info.plist @@ -88,9 +88,19 @@ https + + CFBundleTypeRole + Viewer + CFBundleURLName + FinickyHttpRewrite + CFBundleURLSchemes + + finicky + + CFBundleVersion - 310 + 311 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/browser-extension/background.js b/browser-extension/background.js new file mode 100644 index 0000000..050dbc6 --- /dev/null +++ b/browser-extension/background.js @@ -0,0 +1,20 @@ +const menuItemId = "finicky-open-url"; + +let browser = typeof window !== "undefined" && typeof window.browser !== "undefined" ? window.browser : chrome; + + +browser.contextMenus.onClicked.addListener((info, tab) => { + if (info.menuItemId !== menuItemId) { + return; + } + + browser.tabs.update(tab.id, { url: "finicky://" + info.linkUrl }); +}); + +try { + chrome.contextMenus.create({ + id: menuItemId, + title: "Open with Finicky", + contexts: ["link"], + }); +} catch (ex) {} diff --git a/browser-extension/contentScript.js b/browser-extension/contentScript.js new file mode 100644 index 0000000..2543afd --- /dev/null +++ b/browser-extension/contentScript.js @@ -0,0 +1,71 @@ +let isIntercepting = false; + +window.addEventListener("keydown", (event) => { + if (event.key.toLowerCase() === "alt") { + isIntercepting = true; + } +}); + +window.addEventListener("keyup", (event) => { + if (event.key.toLowerCase() === "alt") { + isIntercepting = false; + } +}); + +window.addEventListener("blur", (event) => { + isIntercepting = false; +}); + +function getAnchor(element) { + do { + if (element.tagName?.toLowerCase() === "a") { + return element; + } + + element = element.parentNode; + } while (element.parentNode); + + return undefined; +} + +window.addEventListener( + "mousedown", + function (event) { + const anchor = getAnchor(event.target); + if (!anchor) return; + + console.log("mousedowned something", anchor, isIntercepting); + } +); + +window.addEventListener( + "click", + function (event) { + const anchor = capture(event); + if (!anchor) return; + + console.log("clicked something", anchor, isIntercepting); + + try { + const url = new URL(anchor.href, document.baseURI).href; + console.log("opening url in finicky", url); + window.location = "finicky://" + url; + } catch (ex) { + console.error("Finicky Browser Extension Error", ex); + } + }, + true +); + +function capture(event) { + if (!isIntercepting) return; + + const anchor = getAnchor(event.target); + + if (!anchor?.hasAttribute("href")) return; + + event.preventDefault(); + event.stopImmediatePropagation(); + + return anchor; +} \ No newline at end of file diff --git a/browser-extension/icon128.png b/browser-extension/icon128.png new file mode 100644 index 0000000..8707d5a Binary files /dev/null and b/browser-extension/icon128.png differ diff --git a/browser-extension/icon16.png b/browser-extension/icon16.png new file mode 100644 index 0000000..8d2a872 Binary files /dev/null and b/browser-extension/icon16.png differ diff --git a/browser-extension/icon48.png b/browser-extension/icon48.png new file mode 100644 index 0000000..7a2ade8 Binary files /dev/null and b/browser-extension/icon48.png differ diff --git a/browser-extension/manifest.json b/browser-extension/manifest.json new file mode 100644 index 0000000..181bb85 --- /dev/null +++ b/browser-extension/manifest.json @@ -0,0 +1,22 @@ +{ + "name": "Finicky", + "description": "The Official Finicky Browser Extension. Requires Finicky (macOS only)", + "version": "0.1", + "manifest_version": 2, + "homepage_url": "https://github.com/johnste/finicky", + "background": { + "scripts": ["background.js"] + }, + "content_scripts": [ + { + "matches": [""], + "js": ["contentScript.js"] + } + ], + "icons": { + "16": "icon16.png", + "48": "icon48.png", + "128": "icon128.png" + }, + "permissions": ["contextMenus", ""] +}