Files

69 lines
2.5 KiB
Swift

// SPDX-FileCopyrightText: 2026 Kaede Akino
// SPDX-License-Identifier: GPL-3.0-only
import SwiftUI
import TermindApplication
import TermindDomain
public struct LocalDiscoveryView: View {
private let model: LocalDiscoveryModel
@Environment(\.scenePhase) private var scenePhase
private let select: (DiscoveredLocalHost) -> Void
public init(model: LocalDiscoveryModel, select: @escaping (DiscoveredLocalHost) -> Void) {
self.model = model
self.select = select
}
public var body: some View {
VStack(spacing: 0) {
if model.phase == .scanning {
VStack(spacing: 16) {
ProgressView()
Text(scanning).foregroundStyle(.secondary)
}.frame(maxWidth: .infinity, maxHeight: .infinity)
} else if model.hosts.isEmpty {
ContentUnavailableView {
Label(AppStrings.LocalNetwork.discovery.swiftUIKey, systemImage: "dot.radiowaves.left.and.right")
} description: {
Text(status)
}
} else {
List(model.hosts) { host in
Button {
select(host)
} label: {
VStack(alignment: .leading, spacing: 6) {
Text(host.name).font(.headline)
Text("\(host.address):\(host.port)").font(.callout.monospaced())
}.padding(.vertical, 4)
}.buttonStyle(.plain)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.task { model.scan() }
.onDisappear { model.cancel() }
.onChange(of: scenePhase) { _, phase in
if phase == .background { model.cancel() }
}
}
private var scanning: LocalizedStringResource {
model.connectionProtocol == .telnet
? AppStrings.LocalNetwork.scanningTelnet : AppStrings.LocalNetwork.scanning
}
private var status: LocalizedStringResource {
switch model.phase {
case .permissionDenied: AppStrings.LocalNetwork.permissionDenied
case .unavailable, .idle: AppStrings.LocalNetwork.unavailable
case .failed: AppStrings.LocalNetwork.scanFailed
case .scanning: scanning
case .finished:
model.connectionProtocol == .telnet
? AppStrings.LocalNetwork.noTelnetServers : AppStrings.LocalNetwork.noServers
}
}
}