Skip to content

Commit

Permalink
refactor(app): update loading of ios app webview
Browse files Browse the repository at this point in the history
  • Loading branch information
ACTCD committed Oct 17, 2023
1 parent ba8d8b6 commit 69bb257
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 61 deletions.
4 changes: 2 additions & 2 deletions entry-app-webview.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'"> -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="color-scheme" content="dark">
<title>Userscripts App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/app/main.js"></script>
<script inline src="/src/app/scripts.js"></script>
</body>
</html>
37 changes: 33 additions & 4 deletions src/app/App.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,43 @@
<script>
import icon from "./img/icon.png";
import logo from "./img/logo.svg?raw";
let version = "v0.0.0";
let build = "(0)";
let directory = "init";
window.APP = {
printVersion: (v, b) => {
version = v;
build = b;
},
printDirectory: d => {
directory = d;
}
};
function changeDirectory() {
window.webkit?.messageHandlers.controller.postMessage("CHANGE_DIRECTORY");
}
</script>
<main>
<img class="icon" inline src={icon} alt="Userscripts App Icon">
<img class="icon" src={icon} alt="Userscripts App Icon" draggable="false">
<div class="logo">
{@html logo}
<span><span id="version">v0.1</span>&nbsp;<span id="build">(0)</span></span>
<span>
<span>{version}</span>
<span>{build}</span>
</span>
</div>
<p>You can turn on the Userscripts iOS Safari extension in Settings.
<a href="https://github.com/quoid/userscripts#userscripts-safari">Read the docs.</a>
</p>
<button id="set_directory">Change Userscripts Directory</button>
<button id="set_directory" on:click={changeDirectory}>
Change Userscripts Directory
</button>
<div class="current">CURRENT DIRECTORY:</div>
<div id="directory">init</div>
<div id="directory">{directory}</div>
</main>
<style>
Expand All @@ -26,6 +49,8 @@
justify-content: center;
padding: 0 1rem;
text-align: center;
-webkit-touch-callout: none;
user-select: none;
}
a {
Expand All @@ -48,6 +73,8 @@
}
.logo > span {
text-align: left;
min-width: 3.5rem;
margin-left: 0.5rem;
}
Expand Down Expand Up @@ -81,5 +108,7 @@
font-size: 0.875rem;
font-weight: 400;
word-break: break-all;
min-height: 7rem;
max-height: 10rem;
}
</style>
15 changes: 0 additions & 15 deletions src/app/scripts.js

This file was deleted.

1 change: 0 additions & 1 deletion xcode/App-Shared/Base.lproj/Main.html

This file was deleted.

Binary file removed xcode/App-Shared/Resources/Icon.png
Binary file not shown.
57 changes: 57 additions & 0 deletions xcode/App-Shared/USchemeHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import WebKit
import UniformTypeIdentifiers

private let logger = USLogger(#fileID)
let AppWebViewUrlScheme = "userscriptsapp"
let AppWebViewEntryPage = "entry-app-webview.html"

// https://developer.apple.com/documentation/webkit/wkurlschemehandler
// https://developer.apple.com/documentation/webkit/wkurlschemetask
class USchemeHandler: NSObject, WKURLSchemeHandler {

func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
// https://developer.apple.com/documentation/dispatch/dispatchqueue
DispatchQueue.global(qos: .userInteractive).async {
guard let url = urlSchemeTask.request.url else {
logger?.error("\(#function, privacy: .public) - failed to get request url")
return
}
guard url.scheme == AppWebViewUrlScheme else {
logger?.error("\(#function, privacy: .public) - unexpected url scheme: \(url, privacy: .public)")
return
}
print(url)
var name: String
if #available(macOS 13.0, iOS 16.0, *) {
name = url.path(percentEncoded: false)
} else {
name = url.path
}
if ["", "/"].contains(name) {
name = AppWebViewEntryPage
}
guard let file = Bundle.main.url(forResource: name, withExtension: nil, subdirectory: "dist") else {
logger?.error("\(#function, privacy: .public) - file not found: \(url, privacy: .public)")
return
}
guard let data = try? Data(contentsOf: file) else {
logger?.error("\(#function, privacy: .public) - faild to get data from: \(url, privacy: .public)")
return
}

// https://developer.apple.com/documentation/uniformtypeidentifiers
//let mime = UTType.init(filenameExtension: file.pathExtension)?.preferredMIMEType ?? "application/octet-stream"
let mime = UTTypeReference.init(filenameExtension: file.pathExtension)?.preferredMIMEType ?? "application/octet-stream"

let response = URLResponse(url: url, mimeType: mime, expectedContentLength: data.count, textEncodingName: nil)
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()
}
}

func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {

}

}
55 changes: 32 additions & 23 deletions xcode/App-Shared/ViewController.swift
Original file line number Diff line number Diff line change
@@ -1,40 +1,49 @@
//
// ViewController.swift
// Userscripts-iOS
//
// Created by Justin Wasack on 10/3/21.
// Copyright © 2021 Justin Wasack. All rights reserved.
//

import UIKit
import WebKit
import UniformTypeIdentifiers
import os

private let logger = USLogger(#fileID)

class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, UIDocumentPickerDelegate {

@IBOutlet var webView: WKWebView!

override func viewDidLoad() {
super.viewDidLoad()

// https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview
override func loadView() {
// https://developer.apple.com/documentation/webkit/wkwebviewconfiguration
let configuration = WKWebViewConfiguration()
// https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/2875766-seturlschemehandler
configuration.setURLSchemeHandler(USchemeHandler(), forURLScheme: AppWebViewUrlScheme)
// https://developer.apple.com/documentation/webkit/wkusercontentcontroller
configuration.userContentController.add(self, name: "controller")
// https://developer.apple.com/documentation/webkit/wkwebview
self.webView = WKWebView(frame: .zero, configuration: configuration)
// https://developer.apple.com/documentation/webkit/wknavigationdelegate
self.webView.navigationDelegate = self
#if DEBUG
// https://webkit.org/blog/13936/enabling-the-inspection-of-web-content-in-apps/
if #available(macOS 13.3, iOS 16.4, tvOS 16.4, *) {
// https://developer.apple.com/documentation/webkit/wkwebview/4111163-inspectable/
self.webView.isInspectable = true
}
#endif
view = webView
self.webView.scrollView.isScrollEnabled = false
self.webView.isOpaque = false
let backgroundColor = UIColor.init(red: (47/255.0), green: (51/255.0), blue: (55/255.0), alpha: 1.0)
view.setValue(backgroundColor, forKey: "backgroundColor")
self.webView.isOpaque = false
self.webView.backgroundColor = backgroundColor
self.webView.navigationDelegate = self
self.webView.scrollView.isScrollEnabled = false
self.webView.configuration.userContentController.add(self, name: "controller")
}

self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!)
// https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload
override func viewDidLoad() {
super.viewDidLoad()
webView.load(URLRequest(url: URL(string: "\(AppWebViewUrlScheme):///")!))
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "??"
let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "??"
webView.evaluateJavaScript("printDirectory('\(Preferences.scriptsDirectoryUrl.absoluteString)')")
webView.evaluateJavaScript("printVersion('v\(appVersion)', '(\(buildNumber))')")
webView.evaluateJavaScript("APP.printVersion('v\(appVersion)', '(\(buildNumber))')")
webView.evaluateJavaScript("APP.printDirectory('\(getCurrentScriptsDirectoryString())')")
}

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
Expand All @@ -57,7 +66,7 @@ class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHan
logger?.error("\(#function, privacy: .public) - Userscripts iOS received a message without a name")
return
}
if name == "SET_READ_LOCATION" {
if name == "CHANGE_DIRECTORY" {
// https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories
logger?.info("\(#function, privacy: .public) - Userscripts iOS has requested to set the readLocation")
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.folder])
Expand All @@ -69,6 +78,6 @@ class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHan

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
Preferences.scriptsDirectoryUrl = url
webView.evaluateJavaScript("printDirectory('\(Preferences.scriptsDirectoryUrl.absoluteString)')")
webView.evaluateJavaScript("APP.printDirectory('\(getCurrentScriptsDirectoryString())')")
}
}
24 changes: 8 additions & 16 deletions xcode/Userscripts.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
030C64FC2AD0B24C00548FBD /* Initialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030C64FB2AD0B24C00548FBD /* Initialization.swift */; };
0336619F294DF7C900CFE179 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0336619E294DF7C900CFE179 /* Functions.swift */; };
033661A529510B7900CFE179 /* View.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 033661A329510B7900CFE179 /* View.storyboard */; };
039F59532AD9591C002E9977 /* dist in Resources */ = {isa = PBXBuildFile; fileRef = 039F59522AD9591C002E9977 /* dist */; };
039F59562ADA2FE2002E9977 /* USchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039F59552ADA2FE2002E9977 /* USchemeHandler.swift */; };
03C24F972ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; };
03C24F982ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; };
03C24F992ABD2CBB00F130F9 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C24F962ABD2CBB00F130F9 /* Preferences.swift */; };
Expand All @@ -28,8 +30,6 @@
4A36A61A268266B30018536B /* images in Resources */ = {isa = PBXBuildFile; fileRef = 4A36A616268266B30018536B /* images */; };
4A36A61B268266B30018536B /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 4A36A617268266B30018536B /* _locales */; };
4A4CF6DE270A38BD00111584 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6DD270A38BD00111584 /* AppDelegate.swift */; };
4A4CF6E2270A38BD00111584 /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E0270A38BD00111584 /* Main.html */; };
4A4CF6E4270A38BD00111584 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E3270A38BD00111584 /* Icon.png */; };
4A4CF6E8270A38BD00111584 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E7270A38BD00111584 /* SceneDelegate.swift */; };
4A4CF6EA270A38BD00111584 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4CF6E9270A38BD00111584 /* ViewController.swift */; };
4A4CF6ED270A38BD00111584 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CF6EB270A38BD00111584 /* LaunchScreen.storyboard */; };
Expand Down Expand Up @@ -106,6 +106,8 @@
030C64FB2AD0B24C00548FBD /* Initialization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Initialization.swift; sourceTree = "<group>"; };
0336619E294DF7C900CFE179 /* Functions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Functions.swift; sourceTree = "<group>"; };
033661A429510B7900CFE179 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/View.storyboard; sourceTree = "<group>"; };
039F59522AD9591C002E9977 /* dist */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dist; sourceTree = "<group>"; };
039F59552ADA2FE2002E9977 /* USchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USchemeHandler.swift; sourceTree = "<group>"; };
03C24F962ABD2CBB00F130F9 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
03E20D05291E170000B4F692 /* dist */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dist; sourceTree = "<group>"; };
4A143AA9279DE6FF0029BFD0 /* Mac-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Mac-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -114,8 +116,6 @@
4A36A617268266B30018536B /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = "<group>"; };
4A4CF6DB270A38BD00111584 /* Userscripts-iOS-App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Userscripts-iOS-App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
4A4CF6DD270A38BD00111584 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
4A4CF6E1270A38BD00111584 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = ../Base.lproj/Main.html; sourceTree = "<group>"; };
4A4CF6E3270A38BD00111584 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
4A4CF6E7270A38BD00111584 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
4A4CF6E9270A38BD00111584 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
4A4CF6EC270A38BD00111584 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
Expand Down Expand Up @@ -192,15 +192,15 @@
children = (
039F59512AD95485002E9977 /* Resources */,
4A4CF6E9270A38BD00111584 /* ViewController.swift */,
039F59552ADA2FE2002E9977 /* USchemeHandler.swift */,
);
path = "App-Shared";
sourceTree = "<group>";
};
039F59512AD95485002E9977 /* Resources */ = {
isa = PBXGroup;
children = (
4A4CF6E3270A38BD00111584 /* Icon.png */,
4A4CF6E0270A38BD00111584 /* Main.html */,
039F59522AD9591C002E9977 /* dist */,
);
path = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -478,12 +478,11 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4A4CF6E4270A38BD00111584 /* Icon.png in Resources */,
4A4CF6F0270A38BD00111584 /* Main.storyboard in Resources */,
4A4CF6ED270A38BD00111584 /* LaunchScreen.storyboard in Resources */,
4A4CF6E2270A38BD00111584 /* Main.html in Resources */,
030C64F62AC62CC900548FBD /* Settings.bundle in Resources */,
4A4CF710270A38BF00111584 /* Assets.xcassets in Resources */,
039F59532AD9591C002E9977 /* dist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -568,6 +567,7 @@
030C64FC2AD0B24C00548FBD /* Initialization.swift in Sources */,
78B25585299D4C27000B2E9B /* Utilities.swift in Sources */,
4A4CF6E8270A38BD00111584 /* SceneDelegate.swift in Sources */,
039F59562ADA2FE2002E9977 /* USchemeHandler.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -634,14 +634,6 @@
name = View.storyboard;
sourceTree = "<group>";
};
4A4CF6E0270A38BD00111584 /* Main.html */ = {
isa = PBXVariantGroup;
children = (
4A4CF6E1270A38BD00111584 /* Base */,
);
name = Main.html;
sourceTree = "<group>";
};
4A4CF6EB270A38BD00111584 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
Expand Down

0 comments on commit 69bb257

Please sign in to comment.