iOS/Sources/App/Frontend/WebView/WebViewController+ProtocolConformance.swift
Bruno Pantaleão Gonçalves 120df2a204
Skip sync on Catalyst for load/refresh (#4325)
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->

## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Extracted load/refresh blocks and conditionally invoke
Current.connectivity.syncNetworkInformation only on non-Catalyst
targets. On Catalyst the closures are executed immediately to avoid
unnecessary async network syncs and ensure immediate UI behavior.
Applied to WebViewController and its protocol conformance refresh
handling.

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#

## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
2026-02-08 15:07:54 +00:00

113 lines
3.5 KiB
Swift

import Foundation
import Shared
import UIKit
import WebKit
extension WebViewController: WebViewControllerProtocol {
var canGoBack: Bool {
webView.canGoBack
}
var canGoForward: Bool {
webView.canGoForward
}
@objc func goBack() {
webView.goBack()
}
@objc func goForward() {
webView.goForward()
}
var overlayedController: UIViewController? {
presentedViewController
}
func presentOverlayController(controller: UIViewController, animated: Bool) {
DispatchQueue.main.async { [weak self] in
self?.dismissOverlayController(animated: false, completion: { [weak self] in
self?.present(controller, animated: animated, completion: nil)
})
}
}
func presentAlertController(controller: UIViewController, animated: Bool) {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
if let overlayedController {
overlayedController.present(controller, animated: animated, completion: nil)
} else {
present(controller, animated: animated, completion: nil)
}
}
}
func evaluateJavaScript(_ script: String, completion: ((Any?, (any Error)?) -> Void)?) {
webView.evaluateJavaScript(script, completionHandler: completion)
}
func dismissOverlayController(animated: Bool, completion: (() -> Void)?) {
dismissAllViewControllersAbove(completion: completion)
}
func dismissControllerAboveOverlayController() {
overlayedController?.dismissAllViewControllersAbove()
}
func updateFrontendConnectionState(state: String) {
emptyStateTimer?.invalidate()
emptyStateTimer = nil
let state = FrontEndConnectionState(rawValue: state) ?? .unknown
isConnected = state == .connected
// Possible values: connected, disconnected, auth-invalid
if state == .connected {
hideEmptyState()
} else {
// Start a 10-second timer. If not interrupted by a 'connected' state, set alpha to 1.
emptyStateTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { [weak self] _ in
self?.showEmptyState()
}
}
}
func navigateToPath(path: String) {
if let activeURL = server.info.connection.activeURL(), let url = URL(string: activeURL.absoluteString + path) {
load(request: URLRequest(url: url))
}
}
func load(request: URLRequest) {
Current.Log.verbose("Requesting webView navigation to \(String(describing: request.url?.absoluteString))")
webView.load(request)
}
@objc func refresh() {
let refreshBlock: () -> Void = { [weak self] in
guard let self else { return }
// called via menu/keyboard shortcut too
if let webviewURL = server.info.connection.webviewURL() {
if webView.url?.baseIsEqual(to: webviewURL) == true, !lastNavigationWasServerError {
reload()
} else {
load(request: URLRequest(url: webviewURL))
}
hideNoActiveURLError()
} else {
showNoActiveURLError()
}
}
if Current.isCatalyst {
refreshBlock()
} else {
Current.connectivity.syncNetworkInformation {
refreshBlock()
}
}
updateDatabaseAndPanels()
}
}