Skip to content

Commit 45713f4

Browse files
authored
Move remote assets code into individual files (#176)
1 parent 4058a64 commit 45713f4

File tree

4 files changed

+138
-133
lines changed

4 files changed

+138
-133
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import Foundation
2+
import WebKit
3+
4+
class CachedAssetSchemeHandler: NSObject, WKURLSchemeHandler {
5+
nonisolated static let cachedURLSchemePrefix = "gbk-cache-"
6+
nonisolated static let supportedURLSchemes = ["gbk-cache-http", "gbk-cache-https"]
7+
8+
nonisolated static func originalHTTPURL(from url: URL) -> URL? {
9+
guard let scheme = url.scheme, supportedURLSchemes.contains(scheme) else { return nil }
10+
11+
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
12+
return nil
13+
}
14+
15+
components.scheme = String(scheme.suffix(from: scheme.index(scheme.startIndex, offsetBy: cachedURLSchemePrefix.count)))
16+
return components.url
17+
}
18+
19+
nonisolated static func cachedURL(forWebLink link: String) -> String? {
20+
if link.starts(with: "http://") || link.starts(with: "https://") {
21+
return cachedURLSchemePrefix + link
22+
}
23+
return nil
24+
}
25+
26+
let worker: Worker
27+
28+
init(library: EditorAssetsLibrary) {
29+
self.worker = .init(library: library)
30+
}
31+
32+
func webView(_ webView: WKWebView, start urlSchemeTask: any WKURLSchemeTask) {
33+
Task {
34+
await worker.start(urlSchemeTask)
35+
}
36+
}
37+
38+
func webView(_ webView: WKWebView, stop urlSchemeTask: any WKURLSchemeTask) {
39+
Task {
40+
await worker.stop(urlSchemeTask)
41+
}
42+
}
43+
44+
actor Worker {
45+
struct TaskInfo {
46+
var webViewTask: WKURLSchemeTask
47+
var fetchAssetTask: Task<Void, Never>
48+
49+
func cancel() {
50+
fetchAssetTask.cancel()
51+
}
52+
}
53+
54+
let library: EditorAssetsLibrary
55+
var tasks: [ObjectIdentifier: TaskInfo] = [:]
56+
57+
init(library: EditorAssetsLibrary) {
58+
self.library = library
59+
}
60+
61+
deinit {
62+
for (_, task) in tasks {
63+
task.cancel()
64+
}
65+
}
66+
67+
func start(_ task: WKURLSchemeTask) {
68+
guard let url = task.request.url, let httpURL = CachedAssetSchemeHandler.originalHTTPURL(from: url) else {
69+
task.didFailWithError(URLError(.badURL))
70+
return
71+
}
72+
73+
let taskKey = ObjectIdentifier(task)
74+
75+
let fetchAssetTask = Task { [library, weak self] in
76+
do {
77+
let (response, content) = try await library.cacheAsset(from: httpURL, webViewURL: url)
78+
79+
await self?.tasks[taskKey]?.webViewTask.didReceive(response)
80+
await self?.tasks[taskKey]?.webViewTask.didReceive(content)
81+
82+
await self?.finish(with: nil, taskKey: taskKey)
83+
} catch {
84+
await self?.finish(with: error, taskKey: taskKey)
85+
}
86+
}
87+
tasks[taskKey] = .init(webViewTask: task, fetchAssetTask: fetchAssetTask)
88+
}
89+
90+
func stop(_ task: WKURLSchemeTask) {
91+
let taskKey = ObjectIdentifier(task)
92+
tasks[taskKey]?.cancel()
93+
tasks[taskKey] = nil
94+
}
95+
96+
private func finish(with error: Error?, taskKey: ObjectIdentifier) {
97+
guard let task = tasks[taskKey] else { return }
98+
99+
if let error {
100+
task.webViewTask.didFailWithError(error)
101+
} else {
102+
task.webViewTask.didFinish()
103+
}
104+
tasks[taskKey] = nil
105+
}
106+
}
107+
}
108+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Foundation
2+
import WebKit
3+
4+
class EditorAssetsProvider: NSObject, WKScriptMessageHandlerWithReply {
5+
let library: EditorAssetsLibrary
6+
7+
init(library: EditorAssetsLibrary) {
8+
self.library = library
9+
}
10+
11+
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping @MainActor @Sendable (Any?, String?) -> Void) {
12+
guard let payload = message.body as? NSDictionary,
13+
let asset = payload.object(forKey: "asset") as? String,
14+
asset == "manifest"
15+
else {
16+
replyHandler(nil, "Unexpected message")
17+
return
18+
}
19+
20+
Task.detached { [library] in
21+
do {
22+
let data = try await library.manifestContentForEditor()
23+
let dict = try JSONSerialization.jsonObject(with: data)
24+
await replyHandler(dict, nil)
25+
} catch {
26+
await replyHandler(nil, error.localizedDescription)
27+
}
28+
}
29+
}
30+
}

ios/Sources/GutenbergKit/Sources/EditorViewController.swift

Lines changed: 0 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -423,136 +423,3 @@ private final class GutenbergEditorController: NSObject, WKNavigationDelegate, W
423423
}
424424
}
425425
}
426-
427-
private class EditorAssetsProvider: NSObject, WKScriptMessageHandlerWithReply {
428-
let library: EditorAssetsLibrary
429-
430-
init(library: EditorAssetsLibrary) {
431-
self.library = library
432-
}
433-
434-
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping @MainActor @Sendable (Any?, String?) -> Void) {
435-
guard let payload = message.body as? NSDictionary,
436-
let asset = payload.object(forKey: "asset") as? String,
437-
asset == "manifest"
438-
else {
439-
replyHandler(nil, "Unexpected message")
440-
return
441-
}
442-
443-
Task.detached { [library] in
444-
do {
445-
let data = try await library.manifestContentForEditor()
446-
let dict = try JSONSerialization.jsonObject(with: data)
447-
await replyHandler(dict, nil)
448-
} catch {
449-
await replyHandler(nil, error.localizedDescription)
450-
}
451-
}
452-
}
453-
}
454-
455-
class CachedAssetSchemeHandler: NSObject, WKURLSchemeHandler {
456-
nonisolated static let cachedURLSchemePrefix = "gbk-cache-"
457-
nonisolated static let supportedURLSchemes = ["gbk-cache-http", "gbk-cache-https"]
458-
459-
nonisolated static func originalHTTPURL(from url: URL) -> URL? {
460-
guard let scheme = url.scheme, supportedURLSchemes.contains(scheme) else { return nil }
461-
462-
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
463-
return nil
464-
}
465-
466-
components.scheme = String(scheme.suffix(from: scheme.index(scheme.startIndex, offsetBy: cachedURLSchemePrefix.count)))
467-
return components.url
468-
}
469-
470-
nonisolated static func cachedURL(forWebLink link: String) -> String? {
471-
if link.starts(with: "http://") || link.starts(with: "https://") {
472-
return cachedURLSchemePrefix + link
473-
}
474-
return nil
475-
}
476-
477-
let worker: Worker
478-
479-
init(library: EditorAssetsLibrary) {
480-
self.worker = .init(library: library)
481-
}
482-
483-
func webView(_ webView: WKWebView, start urlSchemeTask: any WKURLSchemeTask) {
484-
Task {
485-
await worker.start(urlSchemeTask)
486-
}
487-
}
488-
489-
func webView(_ webView: WKWebView, stop urlSchemeTask: any WKURLSchemeTask) {
490-
Task {
491-
await worker.stop(urlSchemeTask)
492-
}
493-
}
494-
495-
actor Worker {
496-
struct TaskInfo {
497-
var webViewTask: WKURLSchemeTask
498-
var fetchAssetTask: Task<Void, Never>
499-
500-
func cancel() {
501-
fetchAssetTask.cancel()
502-
}
503-
}
504-
505-
let library: EditorAssetsLibrary
506-
var tasks: [ObjectIdentifier: TaskInfo] = [:]
507-
508-
init(library: EditorAssetsLibrary) {
509-
self.library = library
510-
}
511-
512-
deinit {
513-
for (_, task) in tasks {
514-
task.cancel()
515-
}
516-
}
517-
518-
func start(_ task: WKURLSchemeTask) {
519-
guard let url = task.request.url, let httpURL = CachedAssetSchemeHandler.originalHTTPURL(from: url) else {
520-
task.didFailWithError(URLError(.badURL))
521-
return
522-
}
523-
524-
let taskKey = ObjectIdentifier(task)
525-
526-
let fetchAssetTask = Task { [library, weak self] in
527-
do {
528-
let (response, content) = try await library.cacheAsset(from: httpURL, webViewURL: url)
529-
530-
await self?.tasks[taskKey]?.webViewTask.didReceive(response)
531-
await self?.tasks[taskKey]?.webViewTask.didReceive(content)
532-
533-
await self?.finish(with: nil, taskKey: taskKey)
534-
} catch {
535-
await self?.finish(with: error, taskKey: taskKey)
536-
}
537-
}
538-
tasks[taskKey] = .init(webViewTask: task, fetchAssetTask: fetchAssetTask)
539-
}
540-
541-
func stop(_ task: WKURLSchemeTask) {
542-
let taskKey = ObjectIdentifier(task)
543-
tasks[taskKey]?.cancel()
544-
tasks[taskKey] = nil
545-
}
546-
547-
private func finish(with error: Error?, taskKey: ObjectIdentifier) {
548-
guard let task = tasks[taskKey] else { return }
549-
550-
if let error {
551-
task.webViewTask.didFailWithError(error)
552-
} else {
553-
task.webViewTask.didFinish()
554-
}
555-
tasks[taskKey] = nil
556-
}
557-
}
558-
}

0 commit comments

Comments
 (0)