Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/video_chroma/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 3 kB image not shown  

SSL SettingsWebViewViewController.swift   Interaktion und
PortierbarkeitJAVA

 

import CocoaLumberjackSwift
import JDStatusBarNotification
import MBProgressHUD
import SafariServices
import ThreemaFramework
import ThreemaMacros
import UIKit
@preconcurrency import WebKit

class SettingsWebViewViewController: ThemedViewController {
    
    // MARK: - Public property

    private(set) lazy var webView: WKWebView = {
        let webPagePreferences = WKWebpagePreferences()
        webPagePreferences.allowsContentJavaScript = allowsContentJavaScript
        
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.defaultWebpagePreferences = webPagePreferences
        let webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.allowsLinkPreview = false
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        webView.isOpaque = false
        
        return webView
    }()
    
    // MARK: - Private properties

    private var url: URL?
    private var isSetupWizard = false
    private var allowsContentJavaScript = false
    private var loadingPresenter: NotificationPresenter?

    // MARK: - Lifecycle
    
    /// Show content of a website in a webView
    /// - Parameters:
    ///   - url: URL of the content
    ///   - title: Title of the controller
    ///   - allowsContentJavaScript: The default value of this property is false. If you change the value to true, the
    ///                              web view execute JavaScript code referenced by the web content.
    ///   - isSetupWizard: If true, it will set all to dark mode
    @objc init(
        url: URL? = nil,
        title: String,
        allowsContentJavaScript: Bool = false,
        isSetupWizard: Bool = false
    ) {
        self.url = url
        self.allowsContentJavaScript = allowsContentJavaScript
        self.isSetupWizard = isSetupWizard
        
        super.init(nibName: nil, bundle: nil)
        
        self.title = title
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.largeTitleDisplayMode = .never
        view.backgroundColor = Colors.backgroundViewController
        webView.navigationDelegate = self
        view = webView
        setupTraitRegistration()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        webView.backgroundColor = isSetupWizard ? Colors.backgroundWizard : Colors.backgroundViewController
        loadURL()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        loadingPresenter?.dismiss(animated: false)
    }

    // MARK: Configurations
    
    override var shouldAutorotate: Bool {
        true
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        .allButUpsideDown
    }
    
    // MARK: - Private functions
    
    /// Begin loading the URL if it has been set. If the loading process takes more than 0.8 seconds, a loading
    /// indicator will be displayed.
    private func loadURL() {
        guard let url,
              let combinedURL = appendQueryItems(to: url) else {
            DDLogError("Can't load url, because url is empty")
            return
        }
        
        Task.detached {
            try? await Task.sleep(seconds: 0.8)
            
            Task { @MainActor in
                if self.webView.isLoading {
                    NotificationPresenterWrapper.shared.presentIndefinitely(type: .loadingWebSite) { presenter in
                        if self.webView.isLoading {
                            self.loadingPresenter = presenter
                        }
                        else {
                            presenter.dismiss()
                        }
                    }
                }
            }
        }
        
        let request = URLRequest(url: combinedURL, cachePolicy: .reloadIgnoringCacheData)
        webView.load(request)
    }
    
    /// Append the query parameters ‘lang’, ‘version’, ‘platform’, and ‘theme’.
    /// If the ‘isSetupWizard’ parameter is true, the dark theme will always be selected.
    /// - Parameter url: URL to append the items
    /// - Returns: URL?
    private func appendQueryItems(to url: URL) -> URL? {
        let theme: String = {
            guard !self.isSetupWizard else {
                return "dark"
            }
            switch Colors.theme {
            case .dark:
                return "dark"
            case .light:
                return "light"
            }
        }()
        
        return url.appending(queryItems: [
            URLQueryItem(name: "lang", value: Bundle.main.preferredLocalizations.first ?? "en"),
            URLQueryItem(name: "version", value: AppVersionInfo.appVersion.version ?? "-"),
            URLQueryItem(name: "platform", value: "ios"),
            URLQueryItem(name: "theme", value: theme),
        ])
    }
    
    /// Check and add SUPPORT as contact and open the chat with it.
    private func addSupportContactAndOpenChat() {
        ContactStore.shared()
            .addContact(
                with: "*SUPPORT",
                verificationLevel: Int32(ContactEntity.VerificationLevel.fullyVerified.rawValue)
            ) { contact, _ in
                let message = "My app version: \(ThreemaUtility.clientVersionWithMDM)"
                let info = [
                    kKeyContact: contact as Any,
                    kKeyForceCompose: NSNumber(value: true),
                    kKeyText: message,
                ] as [String: Any]
                
                DispatchQueue.main.async {
                    NotificationCenter.default.post(
                        name: NSNotification.Name(rawValue: kNotificationShowConversation),
                        object: nil,
                        userInfo: info
                    )
                }
            }
            onError: { error in
                DDLogError("\(error)")
            }
    }
}

// MARK: - Notifications

extension SettingsWebViewViewController {
    private func setupTraitRegistration() {
        let traits: [UITrait] = [UITraitUserInterfaceStyle.self]
        registerForTraitChanges(traits) { [weak self] (_: Self, previous) in
            guard let self else {
                return
            }
            if previous.userInterfaceStyle != traitCollection.userInterfaceStyle {
                loadURL()
            }
        }
    }
}

// MARK: - WKNavigationDelegate

extension SettingsWebViewViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation?) {
        loadingPresenter?.dismiss()
    }
    
    func webView(
        _ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
    ) {
        if navigationAction.navigationType == .linkActivated, let url = navigationAction.request.url {
            // In-page anchor: let WebKit scroll to it natively
            if url.fragment != nil, isSameDocument(url, as: webView.url) {
                decisionHandler(.allow)
                return
            }

            if let scheme = url.scheme, scheme.hasPrefix("http") || scheme.hasPrefix("https") {
                let config = SFSafariViewController.Configuration()
                let safariView = SFSafariViewController(url: url, configuration: config)
                present(safariView, animated: true)
            }
            else if let host = url.host,
                    host == "compose",
                    let query = url.query,
                    query.hasPrefix("id=*SUPPORT") {
                addSupportContactAndOpenChat()
            }
            else {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
            
            decisionHandler(.cancel)
            return
        }
        decisionHandler(.allow)
    }
    
    /// Whether `url` points into the currently loaded document, i.e. only the fragment differs
    private func isSameDocument(_ url: URL, as currentURL: URL?) -> Bool {
        guard let currentURL,
              var target = URLComponents(url: url, resolvingAgainstBaseURL: true),
              var current = URLComponents(url: currentURL, resolvingAgainstBaseURL: true) else {
            return false
        }
        target.fragment = nil
        current.fragment = nil
        return target == current
    }

    func webView(_ webView: WKWebView, didFail navigation: WKNavigation?, withError error: Error) {
        loadingPresenter?.dismiss()
        NotificationPresenterWrapper.shared.present(type: .noConnection)
    }
    
    func webView(
        _ webView: WKWebView,
        didFailProvisionalNavigation navigation: WKNavigation?,
        withError error: any Error
    ) {
        loadingPresenter?.dismiss()
        if (error as NSError).code == URLError.Code.notConnectedToInternet.rawValue {
            NotificationPresenterWrapper.shared.present(type: .noConnection)
        }
    }
}

Messung
CHZG
829610092

¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.1Angebot  (Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-11-04) ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.