92 lines
2.4 KiB
Swift
92 lines
2.4 KiB
Swift
//
|
|
// WebViewManager.swift
|
|
// FollowNative
|
|
//
|
|
// Created by Innei on 2025/1/31.
|
|
//
|
|
import Combine
|
|
import ExpoModulesCore
|
|
import SafariServices
|
|
import SwiftUI
|
|
@preconcurrency import WebKit
|
|
|
|
private var pendingJavaScripts: [String] = []
|
|
|
|
// Add protocol for handling link clicks
|
|
protocol WebViewLinkDelegate: AnyObject {
|
|
func webView(_ webView: WKWebView, shouldOpenURL url: URL)
|
|
}
|
|
|
|
enum WebViewManager {
|
|
static var state = WebViewState()
|
|
|
|
public static func evaluateJavaScript(_ js: String) {
|
|
DispatchQueue.main.async {
|
|
guard let webView = SharedWebViewModule.sharedWebView else {
|
|
pendingJavaScripts.append(js)
|
|
return
|
|
}
|
|
guard webView.url != nil else {
|
|
pendingJavaScripts.append(js)
|
|
return
|
|
}
|
|
|
|
if webView.isLoading {
|
|
pendingJavaScripts.append(js)
|
|
} else {
|
|
webView.evaluateJavaScript(js)
|
|
}
|
|
}
|
|
}
|
|
|
|
static private(set) var shared: WKWebView = {
|
|
FOWebView(frame: .zero, state: state)
|
|
}()
|
|
|
|
static func resetWebView() {
|
|
self.state = WebViewState()
|
|
self.shared = FOWebView(frame: .zero, state: state)
|
|
}
|
|
|
|
static func presentModalWebView(url: URL, from viewController: UIViewController, onDismiss: (() -> Void)? = nil) {
|
|
let safariVC = SafariViewController(url: url)
|
|
safariVC.view.tintColor = Utils.accentColor
|
|
safariVC.preferredControlTintColor = Utils.accentColor
|
|
|
|
if let onDismiss = onDismiss { safariVC.setOnDismiss(onDismiss) }
|
|
viewController.present(safariVC, animated: true)
|
|
}
|
|
}
|
|
|
|
// SwiftUI wrapper for the shared WKWebView
|
|
struct SharedWebViewUI: UIViewRepresentable {
|
|
func makeUIView(context: Context) -> WKWebView {
|
|
return WebViewManager.shared
|
|
}
|
|
|
|
func updateUIView(_ uiView: WKWebView, context: Context) {
|
|
|
|
}
|
|
}
|
|
|
|
extension WebViewManager {
|
|
static var swiftUIView: some View {
|
|
SharedWebViewUI()
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
}
|
|
}
|
|
|
|
fileprivate class SafariViewController: SFSafariViewController {
|
|
|
|
private var onDismiss: (() -> Void)?
|
|
|
|
public func setOnDismiss(_ onDismiss: @escaping () -> Void) {
|
|
self.onDismiss = onDismiss
|
|
}
|
|
|
|
override func viewDidDisappear(_ animated: Bool) {
|
|
super.viewDidDisappear(animated)
|
|
onDismiss?()
|
|
}
|
|
}
|