SPB Git

spb/admin-ka-ios

Public
4.3 KB · 112 lines swift
1import SwiftUI2import WebKit3import UIKit45// État partagé entre le WKWebView et l'interface SwiftUI6final class WebModel: ObservableObject {7    @Published var progress: Double = 08    @Published var loaded = false9    @Published var failed = false10    var reloadRequested = false11    var webView: WKWebView?1213    func reload() {14        failed = false15        loaded = false16        progress = 017        if let wv = webView {18            if wv.url == nil { wv.load(URLRequest(url: Ka.url)) } else { wv.reload() }19        }20    }21}2223struct WebView: UIViewRepresentable {24    @ObservedObject var model: WebModel2526    func makeCoordinator() -> Coordinator { Coordinator(model: model) }2728    func makeUIView(context: Context) -> WKWebView {29        let cfg = WKWebViewConfiguration()30        cfg.websiteDataStore = .default() // persiste le cookie de session (reste connecté)31        cfg.allowsInlineMediaPlayback = true32        cfg.defaultWebpagePreferences.allowsContentJavaScript = true3334        let wv = WKWebView(frame: .zero, configuration: cfg)35        wv.navigationDelegate = context.coordinator36        wv.uiDelegate = context.coordinator37        wv.allowsBackForwardNavigationGestures = false38        wv.scrollView.bounces = true39        wv.scrollView.contentInsetAdjustmentBehavior = .never40        wv.isOpaque = false41        wv.backgroundColor = UIColor(Ka.bg)42        wv.scrollView.backgroundColor = UIColor(Ka.bg)43        wv.customUserAgent = "AdminKa-iOS/1.0 (Groupe KA console)"4445        // pull-to-refresh natif46        let rc = UIRefreshControl()47        rc.tintColor = UIColor(Ka.orange)48        rc.addTarget(context.coordinator, action: #selector(Coordinator.onRefresh(_:)), for: .valueChanged)49        wv.scrollView.refreshControl = rc5051        context.coordinator.observe(wv)52        model.webView = wv53        wv.load(URLRequest(url: Ka.url))54        return wv55    }5657    func updateUIView(_ uiView: WKWebView, context: Context) {}5859    final class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {60        let model: WebModel61        private var obs: NSKeyValueObservation?62        init(model: WebModel) { self.model = model }6364        func observe(_ wv: WKWebView) {65            obs = wv.observe(\.estimatedProgress, options: [.new]) { [weak self] wv, _ in66                DispatchQueue.main.async { self?.model.progress = wv.estimatedProgress }67            }68        }6970        @objc func onRefresh(_ sender: UIRefreshControl) {71            model.webView?.reload()72        }7374        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {75            webView.scrollView.refreshControl?.endRefreshing()76            DispatchQueue.main.async {77                withAnimation(.easeOut(duration: 0.35)) { self.model.loaded = true }78                self.model.failed = false79            }80        }8182        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { fail(error) }83        func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { fail(error) }84        private func fail(_ error: Error) {85            let ns = error as NSError86            if ns.code == NSURLErrorCancelled { return }87            DispatchQueue.main.async {88                self.model.webView?.scrollView.refreshControl?.endRefreshing()89                self.model.failed = true90            }91        }9293        // liens externes (target=_blank / http externes) → Safari94        func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration,95                     for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {96            if let url = navigationAction.request.url { UIApplication.shared.open(url) }97            return nil98        }99        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,100                     decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {101            if let url = navigationAction.request.url, let host = url.host,102               navigationAction.navigationType == .linkActivated,103               host != Ka.url.host {104                UIApplication.shared.open(url)105                decisionHandler(.cancel)106                return107            }108            decisionHandler(.allow)109        }110    }111}112
Files · 6a53e8c71829f5f8190598eda7a85d925d970a90
Menu

Theme