mirror of
https://github.com/home-assistant/iOS.git
synced 2026-06-25 06:22:24 -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 --> This PR is a massive refactor of how the app handles UI presentation and navigation, goin from the UIKit based apps style to SwiftUI. ## 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: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
83 lines
2.5 KiB
Swift
83 lines
2.5 KiB
Swift
import Shared
|
|
import SwiftUI
|
|
|
|
struct ServerPickerView: View {
|
|
private let preSelectedServer: Server?
|
|
private let onSelect: ((Server) -> Void)?
|
|
|
|
/// The selected server id.
|
|
@State private var selection: String
|
|
@State private var isSynchronizingSelection = false
|
|
|
|
/// Initializes with server to pre-select it.
|
|
init(server: Server? = nil, onSelect: ((Server) -> Void)? = nil) {
|
|
self.preSelectedServer = server
|
|
self.onSelect = onSelect
|
|
self
|
|
._selection = State(
|
|
initialValue: server?.identifier.rawValue ?? Current.servers.all.first?.identifier
|
|
.rawValue ?? ""
|
|
)
|
|
}
|
|
|
|
var body: some View {
|
|
Picker(selection: $selection) {
|
|
ForEach(Current.servers.all, id: \.identifier) { server in
|
|
Text(server.info.name)
|
|
.tag(server.identifier.rawValue)
|
|
}
|
|
} label: {
|
|
Text(L10n.ServersSelection.title)
|
|
}
|
|
.pickerStyle(.menu)
|
|
.frame(minWidth: 100)
|
|
.onAppear {
|
|
synchronizeSelectionIfNeeded()
|
|
}
|
|
.onChange(of: preSelectedServer?.identifier.rawValue) { _ in
|
|
synchronizeSelectionIfNeeded()
|
|
}
|
|
.onChange(of: selection) { newValue in
|
|
guard !isSynchronizingSelection else { return }
|
|
|
|
guard let server = Current.servers.all.first(where: { $0.identifier.rawValue == newValue }) else {
|
|
Current.Log
|
|
.error(
|
|
"Failed to find server with id: \(newValue) so server picker view could open server"
|
|
)
|
|
return
|
|
}
|
|
|
|
if let onSelect {
|
|
onSelect(server)
|
|
} else {
|
|
Current.sceneManager.appCoordinator.done { coordinator in
|
|
coordinator.open(server: server)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func synchronizeSelectionIfNeeded() {
|
|
let validServerIDs = Set(Current.servers.all.map(\.identifier.rawValue))
|
|
let preferredSelection = preSelectedServer?.identifier.rawValue
|
|
?? Current.servers.all.first?.identifier.rawValue
|
|
?? ""
|
|
|
|
let targetSelection = validServerIDs.contains(selection) ? selection : preferredSelection
|
|
|
|
guard selection != targetSelection else { return }
|
|
|
|
isSynchronizingSelection = true
|
|
selection = targetSelection
|
|
|
|
DispatchQueue.main.async {
|
|
isSynchronizingSelection = false
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
ServerPickerView()
|
|
}
|