mirror of
https://github.com/home-assistant/iOS.git
synced 2026-02-04 02:46:35 -06: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. --> ## 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 <175728472+Copilot@users.noreply.github.com>
135 lines
4.4 KiB
Swift
135 lines
4.4 KiB
Swift
import Shared
|
|
import SwiftUI
|
|
import UIKit
|
|
|
|
struct WebViewEmptyStateView: View {
|
|
@Environment(\.safeAreaInsets) private var safeAreaInsets
|
|
|
|
@State private var showCloseButton = false
|
|
let server: Server
|
|
let retryAction: (() -> Void)?
|
|
let settingsAction: (() -> Void)?
|
|
let dismissAction: (() -> Void)?
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .topTrailing) {
|
|
content
|
|
header
|
|
}
|
|
.ignoresSafeArea()
|
|
}
|
|
|
|
private var header: some View {
|
|
Group {
|
|
serverSelection
|
|
ModalCloseButton {
|
|
dismissAction?()
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
}
|
|
.padding()
|
|
// This is needed alongside with the ignores safe area below because
|
|
// this view is added as a subview to the WebView
|
|
.offset(x: 0, y: safeAreaInsets.top)
|
|
}
|
|
|
|
private var content: some View {
|
|
VStack(spacing: DesignSystem.Spaces.two) {
|
|
Image(.logo)
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(width: 80, height: 80)
|
|
.foregroundColor(.accentColor)
|
|
Text(L10n.WebView.EmptyState.title)
|
|
.font(.title2)
|
|
.fontWeight(.semibold)
|
|
Text(L10n.WebView.EmptyState.body)
|
|
.font(.callout)
|
|
.foregroundColor(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
.padding(.horizontal, DesignSystem.Spaces.two)
|
|
VStack(spacing: DesignSystem.Spaces.one) {
|
|
Button(action: {
|
|
retryAction?()
|
|
}) {
|
|
Text(L10n.WebView.EmptyState.retryButton)
|
|
}
|
|
.buttonStyle(.primaryButton)
|
|
Button(action: {
|
|
settingsAction?()
|
|
}) {
|
|
Text(L10n.WebView.EmptyState.openSettingsButton)
|
|
}
|
|
.buttonStyle(.secondaryButton)
|
|
}
|
|
.frame(maxWidth: Sizes.maxWidthForLargerScreens)
|
|
.padding(.horizontal, DesignSystem.Spaces.two)
|
|
.padding(.top)
|
|
}
|
|
.padding(DesignSystem.Spaces.three)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.background(Color(uiColor: .systemBackground))
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var serverSelection: some View {
|
|
if Current.servers.all.count > 1 {
|
|
HStack {
|
|
Spacer()
|
|
ServerPickerView(server: server)
|
|
#if targetEnvironment(macCatalyst)
|
|
.padding()
|
|
#endif
|
|
// Using .secondarySystemBackground to visually distinguish the server selection view
|
|
.background(Color(uiColor: .secondarySystemBackground))
|
|
.clipShape(Capsule())
|
|
Spacer()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
WebViewEmptyStateView(server: ServerFixture.standard) {} settingsAction: {} dismissAction: {}
|
|
}
|
|
|
|
final class WebViewEmptyStateWrapperView: UIView {
|
|
private let hostingController: UIHostingController<WebViewEmptyStateView>
|
|
private let server: Server
|
|
|
|
init(
|
|
server: Server,
|
|
retryAction: (() -> Void)? = nil,
|
|
settingsAction: (() -> Void)? = nil,
|
|
dismissAction: (() -> Void)? = nil
|
|
) {
|
|
self.server = server
|
|
let swiftUIView = WebViewEmptyStateView(
|
|
server: server,
|
|
retryAction: retryAction,
|
|
settingsAction: settingsAction,
|
|
dismissAction: dismissAction
|
|
)
|
|
self.hostingController = UIHostingController(rootView: swiftUIView)
|
|
super.init(frame: .zero)
|
|
setup()
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private func setup() {
|
|
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
|
|
addSubview(hostingController.view)
|
|
NSLayoutConstraint.activate([
|
|
hostingController.view.topAnchor.constraint(equalTo: topAnchor),
|
|
hostingController.view.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
hostingController.view.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
hostingController.view.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
])
|
|
backgroundColor = .clear
|
|
}
|
|
}
|