diff options
| author | Ruben Beltran del Rio <ruben@unlimited.pizza> | 2023-09-13 18:39:01 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <ruben@unlimited.pizza> | 2023-09-13 18:39:01 +0200 |
| commit | 4a191e8036581893bf5f4cfb284770d1bfe9a807 (patch) | |
| tree | abbf7be12b65b56c9b6a11861fd96ad406ad4590 /safari/Junction | |
| parent | 06b7617a863d00dbcc91d1e46f09942c6aad366e (diff) | |
Add safari code
Diffstat (limited to 'safari/Junction')
22 files changed, 405 insertions, 0 deletions
diff --git a/safari/Junction/AppDelegate.swift b/safari/Junction/AppDelegate.swift new file mode 100644 index 0000000..0e990a0 --- /dev/null +++ b/safari/Junction/AppDelegate.swift @@ -0,0 +1,21 @@ +// +// AppDelegate.swift +// Junction +// +// Created by Ruben Beltran del Rio on 9/13/23. +// + +import Cocoa + +@main +class AppDelegate: NSObject, NSApplicationDelegate { + + func applicationDidFinishLaunching(_ notification: Notification) { + // Override point for customization after application launch. + } + + func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + +} diff --git a/safari/Junction/Assets.xcassets/AccentColor.colorset/Contents.json b/safari/Junction/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/Contents.json b/safari/Junction/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..64dc11e --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "filename" : "icon_16x16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "icon_16x16@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "icon_32x32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "icon_32x32@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "icon_128x128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "icon_128x128@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "icon_256x256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "icon_256x256@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "icon_512x512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "icon_512x512@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_128x128.png Binary files differnew file mode 100644 index 0000000..0bcb999 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_128x128.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png Binary files differnew file mode 100644 index 0000000..a45aa17 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_16x16.png Binary files differnew file mode 100644 index 0000000..737d986 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_16x16.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png Binary files differnew file mode 100644 index 0000000..b748f7b --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_256x256.png Binary files differnew file mode 100644 index 0000000..59d8be3 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_256x256.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png Binary files differnew file mode 100644 index 0000000..2f37b07 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_32x32.png Binary files differnew file mode 100644 index 0000000..b748f7b --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_32x32.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png Binary files differnew file mode 100644 index 0000000..b0cf195 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_512x512.png Binary files differnew file mode 100644 index 0000000..2f37b07 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_512x512.png diff --git a/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png Binary files differnew file mode 100644 index 0000000..f056447 --- /dev/null +++ b/safari/Junction/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png diff --git a/safari/Junction/Assets.xcassets/Contents.json b/safari/Junction/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/safari/Junction/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/safari/Junction/Assets.xcassets/LargeIcon.imageset/Contents.json b/safari/Junction/Assets.xcassets/LargeIcon.imageset/Contents.json new file mode 100644 index 0000000..a19a549 --- /dev/null +++ b/safari/Junction/Assets.xcassets/LargeIcon.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/safari/Junction/Base.lproj/Main.html b/safari/Junction/Base.lproj/Main.html new file mode 100644 index 0000000..081cc41 --- /dev/null +++ b/safari/Junction/Base.lproj/Main.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta http-equiv="Content-Security-Policy" content="default-src 'self'"> + + <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> + + <link rel="stylesheet" href="../Style.css"> + <script src="../Script.js" defer></script> +</head> +<body> + <img src="../Icon.png" width="128" height="128" alt="Junction Icon"> + <p class="state-unknown">You can turn on Junction’s extension in Safari Extensions preferences.</p> + <p class="state-on">Junction’s extension is currently on. You can turn it off in Safari Extensions preferences.</p> + <p class="state-off">Junction’s extension is currently off. You can turn it on in Safari Extensions preferences.</p> + <button class="open-preferences">Quit and Open Safari Extensions Preferences…</button> +</body> +</html> diff --git a/safari/Junction/Base.lproj/Main.storyboard b/safari/Junction/Base.lproj/Main.storyboard new file mode 100644 index 0000000..6de6cf1 --- /dev/null +++ b/safari/Junction/Base.lproj/Main.storyboard @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19085" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS"> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19085"/> + <plugIn identifier="com.apple.WebKit2IBPlugin" version="19085"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--Application--> + <scene sceneID="JPo-4y-FX3"> + <objects> + <application id="hnw-xV-0zn" sceneMemberID="viewController"> + <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6"> + <items> + <menuItem title="Junction" id="1Xt-HY-uBw"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Junction" systemMenu="apple" id="uQy-DD-JDr"> + <items> + <menuItem title="About Junction" id="5kV-Vb-QxS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/> + <menuItem title="Hide Junction" keyEquivalent="h" id="Olw-nP-bQN"> + <connections> + <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/> + </connections> + </menuItem> + <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/> + </connections> + </menuItem> + <menuItem title="Show All" id="Kd2-mp-pUS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/> + <menuItem title="Quit Junction" keyEquivalent="q" id="4sb-4s-VLi"> + <connections> + <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Help" id="wpr-3q-Mcd"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ"> + <items> + <menuItem title="Junction Help" keyEquivalent="?" id="FKE-Sm-Kum"> + <connections> + <action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + <connections> + <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/> + </connections> + </application> + <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target"/> + <customObject id="YLy-65-1bz" customClass="NSFontManager"/> + <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="76" y="-134"/> + </scene> + <!--Window Controller--> + <scene sceneID="R2V-B0-nI4"> + <objects> + <windowController showSeguePresentationStyle="single" id="B8D-0N-5wS" sceneMemberID="viewController"> + <window key="window" title="Junction" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" animationBehavior="default" id="IQv-IB-iLA"> + <windowStyleMask key="styleMask" titled="YES" closable="YES"/> + <windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/> + <rect key="contentRect" x="196" y="240" width="425" height="325"/> + <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/> + <connections> + <outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/> + </connections> + </window> + <connections> + <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/> + </connections> + </windowController> + <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="75" y="250"/> + </scene> + <!--View Controller--> + <scene sceneID="hIz-AP-VOD"> + <objects> + <viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController"> + <view key="view" id="m2S-Jp-Qdl"> + <rect key="frame" x="0.0" y="0.0" width="425" height="325"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <wkWebView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eOr-cG-IQY"> + <rect key="frame" x="0.0" y="0.0" width="425" height="325"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <wkWebViewConfiguration key="configuration"> + <audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/> + <wkPreferences key="preferences"/> + </wkWebViewConfiguration> + </wkWebView> + </subviews> + </view> + <connections> + <outlet property="webView" destination="eOr-cG-IQY" id="GFe-mU-dBY"/> + </connections> + </viewController> + <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="75" y="655"/> + </scene> + </scenes> +</document> diff --git a/safari/Junction/Junction.entitlements b/safari/Junction/Junction.entitlements new file mode 100644 index 0000000..625af03 --- /dev/null +++ b/safari/Junction/Junction.entitlements @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.app-sandbox</key> + <true/> + <key>com.apple.security.files.user-selected.read-only</key> + <true/> + <key>com.apple.security.network.client</key> + <true/> +</dict> +</plist> diff --git a/safari/Junction/Resources/Icon.png b/safari/Junction/Resources/Icon.png Binary files differnew file mode 100644 index 0000000..f056447 --- /dev/null +++ b/safari/Junction/Resources/Icon.png diff --git a/safari/Junction/Resources/Script.js b/safari/Junction/Resources/Script.js new file mode 100644 index 0000000..f551e6b --- /dev/null +++ b/safari/Junction/Resources/Script.js @@ -0,0 +1,22 @@ +function show(enabled, useSettingsInsteadOfPreferences) { + if (useSettingsInsteadOfPreferences) { + document.getElementsByClassName('state-on')[0].innerText = "Junction’s extension is currently on. You can turn it off in the Extensions section of Safari Settings."; + document.getElementsByClassName('state-off')[0].innerText = "Junction’s extension is currently off. You can turn it on in the Extensions section of Safari Settings."; + document.getElementsByClassName('state-unknown')[0].innerText = "You can turn on Junction’s extension in the Extensions section of Safari Settings."; + document.getElementsByClassName('open-preferences')[0].innerText = "Quit and Open Safari Settings…"; + } + + if (typeof enabled === "boolean") { + document.body.classList.toggle(`state-on`, enabled); + document.body.classList.toggle(`state-off`, !enabled); + } else { + document.body.classList.remove(`state-on`); + document.body.classList.remove(`state-off`); + } +} + +function openPreferences() { + webkit.messageHandlers.controller.postMessage("open-preferences"); +} + +document.querySelector("button.open-preferences").addEventListener("click", openPreferences); diff --git a/safari/Junction/Resources/Style.css b/safari/Junction/Resources/Style.css new file mode 100644 index 0000000..cbde9e6 --- /dev/null +++ b/safari/Junction/Resources/Style.css @@ -0,0 +1,45 @@ +* { + -webkit-user-select: none; + -webkit-user-drag: none; + cursor: default; +} + +:root { + color-scheme: light dark; + + --spacing: 20px; +} + +html { + height: 100%; +} + +body { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + + gap: var(--spacing); + margin: 0 calc(var(--spacing) * 2); + height: 100%; + + font: -apple-system-short-body; + text-align: center; +} + +body:not(.state-on, .state-off) :is(.state-on, .state-off) { + display: none; +} + +body.state-on :is(.state-off, .state-unknown) { + display: none; +} + +body.state-off :is(.state-on, .state-unknown) { + display: none; +} + +button { + font-size: 1em; +} diff --git a/safari/Junction/ViewController.swift b/safari/Junction/ViewController.swift new file mode 100644 index 0000000..91f4596 --- /dev/null +++ b/safari/Junction/ViewController.swift @@ -0,0 +1,57 @@ +// +// ViewController.swift +// Junction +// +// Created by Ruben Beltran del Rio on 9/13/23. +// + +import Cocoa +import SafariServices +import WebKit + +let extensionBundleIdentifier = "systems.tranquil.Junction.Extension" + +class ViewController: NSViewController, WKNavigationDelegate, WKScriptMessageHandler { + + @IBOutlet var webView: WKWebView! + + override func viewDidLoad() { + super.viewDidLoad() + + self.webView.navigationDelegate = self + + self.webView.configuration.userContentController.add(self, name: "controller") + + self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!) + } + + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in + guard let state = state, error == nil else { + // Insert code to inform the user that something went wrong. + return + } + + DispatchQueue.main.async { + if #available(macOS 13, *) { + webView.evaluateJavaScript("show(\(state.isEnabled), true)") + } else { + webView.evaluateJavaScript("show(\(state.isEnabled), false)") + } + } + } + } + + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { + if (message.body as! String != "open-preferences") { + return; + } + + SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in + DispatchQueue.main.async { + NSApplication.shared.terminate(nil) + } + } + } + +} |