import AppKit import SwiftUI import WebKit /// Embeds the Feishu record page inside the app. Uses the default persistent /// data store, so the Feishu login survives app restarts. Workflow (流程) /// fields can't be reached via the API — this is the in-app way to advance them. struct FeishuWebView: NSViewRepresentable { let url: URL func makeNSView(context: Context) -> WKWebView { let configuration = WKWebViewConfiguration() configuration.websiteDataStore = .default() let webView = WKWebView(frame: .zero, configuration: configuration) webView.navigationDelegate = context.coordinator webView.allowsBackForwardNavigationGestures = true webView.load(URLRequest(url: url)) return webView } func updateNSView(_ webView: WKWebView, context: Context) { if webView.url?.absoluteString != url.absoluteString { webView.load(URLRequest(url: url)) } } func makeCoordinator() -> Coordinator { Coordinator() } final class Coordinator: NSObject, WKNavigationDelegate { // Only http(s) navigates inside the webview. Custom schemes the page // may try (e.g. feishu:// to hand off to the desktop client) are // routed to the system instead of failing silently. func webView( _ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction ) async -> WKNavigationActionPolicy { guard let url = navigationAction.request.url, let scheme = url.scheme else { return .allow } if scheme == "http" || scheme == "https" { return .allow } NSWorkspace.shared.open(url) return .cancel } } } /// Window content wrapper: WKWebView has no intrinsic size, so a bare hosting /// controller collapses the window to ~1px — pin a minimum size here. struct FeishuWebWindowContent: View { let url: URL var body: some View { FeishuWebView(url: url) .frame(minWidth: 900, minHeight: 600) } }