169 lines
5.1 KiB
Swift
169 lines
5.1 KiB
Swift
import SwiftUI
|
|
|
|
#if canImport(WebKit)
|
|
import WebKit
|
|
|
|
struct WebLoginView: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
@State private var isLoading = true
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
ZStack {
|
|
WebLoginRepresentable(
|
|
url: URL(string: "https://ddys.io")!,
|
|
isLoading: $isLoading,
|
|
onCookiesExtracted: { cookies in
|
|
CookieManager.shared.cookieString = cookies
|
|
dismiss()
|
|
}
|
|
)
|
|
|
|
if isLoading {
|
|
ProgressView("加载中...")
|
|
}
|
|
}
|
|
.navigationTitle("登录 DDYS")
|
|
#if os(iOS)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
#endif
|
|
.toolbar {
|
|
ToolbarItem(placement: .cancellationAction) {
|
|
Button("取消") { dismiss() }
|
|
}
|
|
ToolbarItem(placement: .confirmationAction) {
|
|
Button("提取 Cookie") {
|
|
// 通知 WebView 提取 cookies
|
|
NotificationCenter.default.post(name: .extractCookies, object: nil)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Notification.Name {
|
|
static let extractCookies = Notification.Name("extractCookies")
|
|
}
|
|
|
|
#if os(iOS)
|
|
struct WebLoginRepresentable: UIViewRepresentable {
|
|
let url: URL
|
|
@Binding var isLoading: Bool
|
|
let onCookiesExtracted: (String) -> Void
|
|
|
|
func makeUIView(context: Context) -> WKWebView {
|
|
let config = WKWebViewConfiguration()
|
|
let webView = WKWebView(frame: .zero, configuration: config)
|
|
webView.navigationDelegate = context.coordinator
|
|
webView.load(URLRequest(url: url))
|
|
|
|
NotificationCenter.default.addObserver(
|
|
context.coordinator,
|
|
selector: #selector(Coordinator.extractCookies),
|
|
name: .extractCookies,
|
|
object: nil
|
|
)
|
|
return webView
|
|
}
|
|
|
|
func updateUIView(_ uiView: WKWebView, context: Context) {}
|
|
|
|
func makeCoordinator() -> Coordinator {
|
|
Coordinator(parent: self)
|
|
}
|
|
|
|
class Coordinator: NSObject, WKNavigationDelegate {
|
|
let parent: WebLoginRepresentable
|
|
weak var webView: WKWebView?
|
|
|
|
init(parent: WebLoginRepresentable) {
|
|
self.parent = parent
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
|
self.webView = webView
|
|
parent.isLoading = true
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
parent.isLoading = false
|
|
}
|
|
|
|
@objc func extractCookies() {
|
|
guard let webView else { return }
|
|
webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
|
|
let ddysCookies = cookies
|
|
.filter { $0.domain.contains("ddys") }
|
|
.map { "\($0.name)=\($0.value)" }
|
|
.joined(separator: "; ")
|
|
|
|
DispatchQueue.main.async {
|
|
self.parent.onCookiesExtracted(ddysCookies)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
struct WebLoginRepresentable: NSViewRepresentable {
|
|
let url: URL
|
|
@Binding var isLoading: Bool
|
|
let onCookiesExtracted: (String) -> Void
|
|
|
|
func makeNSView(context: Context) -> WKWebView {
|
|
let config = WKWebViewConfiguration()
|
|
let webView = WKWebView(frame: .zero, configuration: config)
|
|
webView.navigationDelegate = context.coordinator
|
|
webView.load(URLRequest(url: url))
|
|
|
|
NotificationCenter.default.addObserver(
|
|
context.coordinator,
|
|
selector: #selector(Coordinator.extractCookies),
|
|
name: .extractCookies,
|
|
object: nil
|
|
)
|
|
return webView
|
|
}
|
|
|
|
func updateNSView(_ nsView: WKWebView, context: Context) {}
|
|
|
|
func makeCoordinator() -> Coordinator {
|
|
Coordinator(parent: self)
|
|
}
|
|
|
|
class Coordinator: NSObject, WKNavigationDelegate {
|
|
let parent: WebLoginRepresentable
|
|
weak var webView: WKWebView?
|
|
|
|
init(parent: WebLoginRepresentable) {
|
|
self.parent = parent
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
|
self.webView = webView
|
|
parent.isLoading = true
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
parent.isLoading = false
|
|
}
|
|
|
|
@objc func extractCookies() {
|
|
guard let webView else { return }
|
|
webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
|
|
let ddysCookies = cookies
|
|
.filter { $0.domain.contains("ddys") }
|
|
.map { "\($0.name)=\($0.value)" }
|
|
.joined(separator: "; ")
|
|
|
|
DispatchQueue.main.async {
|
|
self.parent.onCookiesExtracted(ddysCookies)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|