Attempt an iOS layout with DisclosureGroup

Also fix missing initial filters based on selection.

Fixes #746
This commit is contained in:
Davide 2024-10-23 17:58:04 +02:00
parent 2455c5397e
commit 48dc31a1f1
No known key found for this signature in database
GPG Key ID: A48836171C759F5E
4 changed files with 76 additions and 10 deletions

View File

@ -130,6 +130,7 @@ private extension OpenVPNView {
VPNProviderServerView(
providerId: $0,
configurationType: OpenVPN.Configuration.self,
selectedEntity: providerEntity.wrappedValue,
onSelect: onSelectServer
)
}

View File

@ -39,7 +39,7 @@ struct VPNProviderServerView<Configuration>: View where Configuration: ProviderC
let configurationType: Configuration.Type
var selectedEntity: VPNEntity<Configuration>?
let selectedEntity: VPNEntity<Configuration>?
let onSelect: (_ server: VPNServer, _ preset: VPNPreset<Configuration>) -> Void
@ -119,9 +119,10 @@ extension VPNProviderServerView {
VPNProviderServerView(
apis: [API.bundled],
providerId: .protonvpn,
configurationType: OpenVPN.Configuration.self
) { _, _ in
}
configurationType: OpenVPN.Configuration.self,
selectedEntity: nil,
onSelect: { _, _ in }
)
}
.withMockEnvironment()
}

View File

@ -55,20 +55,54 @@ extension VPNProviderServerView {
private extension VPNProviderServerView.Subview {
var listView: some View {
List {
// FIXME: #746, providers UI, iOS server rows + country flags
if manager.isFiltering {
ProgressView()
} else {
ForEach(manager.filteredServers, id: \.id) { server in
Button("\(server.hostname ?? server.id) \(server.provider.countryCode)") {
onSelect(server)
}
}
ForEach(countryCodes, id: \.self, content: countryView)
}
}
.themeAnimation(on: manager.isFiltering, category: .providers)
}
var countryCodes: [String] {
manager
.allCountryCodes
.sorted {
$0.localizedAsRegionCode! < $1.localizedAsRegionCode!
}
}
func countryServers(for code: String) -> [VPNServer]? {
manager
.filteredServers
.filter {
$0.provider.countryCode == code
}
.nilIfEmpty
}
func countryView(for code: String) -> some View {
countryServers(for: code)
.map { servers in
DisclosureGroup {
ForEach(servers, id: \.serverId, content: serverView)
} label: {
HStack {
ThemeCountryFlag(code: code)
Text(code.localizedAsRegionCode!)
}
}
}
}
func serverView(for server: VPNServer) -> some View {
Button {
onSelect(server)
} label: {
Text(server.hostname ?? server.id)
}
}
var filtersItem: some ToolbarContent {
ToolbarItem {
Button {
@ -93,4 +127,19 @@ private extension VPNProviderServerView.Subview {
}
}
// MARK: - Preview
#Preview {
NavigationStack {
VPNProviderServerView(
apis: [API.bundled],
providerId: .tunnelbear,
configurationType: OpenVPN.Configuration.self,
selectedEntity: nil,
onSelect: { _, _ in }
)
}
.withMockEnvironment()
}
#endif

View File

@ -82,4 +82,19 @@ private extension VPNProviderServerView.Subview {
}
}
// MARK: - Preview
#Preview {
NavigationStack {
VPNProviderServerView(
apis: [API.bundled],
providerId: .tunnelbear,
configurationType: OpenVPN.Configuration.self,
selectedEntity: nil,
onSelect: { _, _ in }
)
}
.withMockEnvironment()
}
#endif