mirror of
https://github.com/home-assistant/iOS.git
synced 2026-06-16 13:26:27 -05:00
<!-- 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 --> ## Screenshots <!-- If this is a user-facing change not in the frontend, please include screenshots in light and dark mode. --> <img width="1206" height="2622" alt="Simulator Screenshot - Daily tester 2 - 2026-04-22 at 14 43 08" src="https://github.com/user-attachments/assets/66e0e557-5b69-4f8d-82c1-53dbf7fb4b9b" /> ## 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. --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
136 lines
4.2 KiB
Swift
136 lines
4.2 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
|
|
latestLoadError = nil
|
|
|
|
let requestedState = FrontEndConnectionState(rawValue: state) ?? .unknown
|
|
let resolvedState: FrontEndConnectionState = if connectionState == .authInvalid, requestedState != .connected {
|
|
.authInvalid
|
|
} else {
|
|
requestedState
|
|
}
|
|
isConnected = resolvedState == .connected
|
|
connectionState = resolvedState
|
|
|
|
// Possible values: connected, disconnected, auth-invalid
|
|
switch resolvedState {
|
|
case .connected:
|
|
hideEmptyState()
|
|
case .authInvalid:
|
|
showEmptyState()
|
|
case .disconnected, .unknown:
|
|
// 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 showBanner(request: BannerRequest) {
|
|
bannerPresenter.show(on: self, request: request)
|
|
}
|
|
|
|
func hideBanner(id: String) {
|
|
bannerPresenter.hide(id: id)
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
@objc func refreshIfDisconnected() {
|
|
guard connectionState != .connected else { return }
|
|
refresh()
|
|
}
|
|
}
|