Attempt an iOS layout with DisclosureGroup
Also fix missing initial filters based on selection. Fixes #746
This commit is contained in:
parent
2455c5397e
commit
48dc31a1f1
|
@ -130,6 +130,7 @@ private extension OpenVPNView {
|
||||||
VPNProviderServerView(
|
VPNProviderServerView(
|
||||||
providerId: $0,
|
providerId: $0,
|
||||||
configurationType: OpenVPN.Configuration.self,
|
configurationType: OpenVPN.Configuration.self,
|
||||||
|
selectedEntity: providerEntity.wrappedValue,
|
||||||
onSelect: onSelectServer
|
onSelect: onSelectServer
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct VPNProviderServerView<Configuration>: View where Configuration: ProviderC
|
||||||
|
|
||||||
let configurationType: Configuration.Type
|
let configurationType: Configuration.Type
|
||||||
|
|
||||||
var selectedEntity: VPNEntity<Configuration>?
|
let selectedEntity: VPNEntity<Configuration>?
|
||||||
|
|
||||||
let onSelect: (_ server: VPNServer, _ preset: VPNPreset<Configuration>) -> Void
|
let onSelect: (_ server: VPNServer, _ preset: VPNPreset<Configuration>) -> Void
|
||||||
|
|
||||||
|
@ -119,9 +119,10 @@ extension VPNProviderServerView {
|
||||||
VPNProviderServerView(
|
VPNProviderServerView(
|
||||||
apis: [API.bundled],
|
apis: [API.bundled],
|
||||||
providerId: .protonvpn,
|
providerId: .protonvpn,
|
||||||
configurationType: OpenVPN.Configuration.self
|
configurationType: OpenVPN.Configuration.self,
|
||||||
) { _, _ in
|
selectedEntity: nil,
|
||||||
}
|
onSelect: { _, _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.withMockEnvironment()
|
.withMockEnvironment()
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,20 +55,54 @@ extension VPNProviderServerView {
|
||||||
private extension VPNProviderServerView.Subview {
|
private extension VPNProviderServerView.Subview {
|
||||||
var listView: some View {
|
var listView: some View {
|
||||||
List {
|
List {
|
||||||
// FIXME: #746, providers UI, iOS server rows + country flags
|
|
||||||
if manager.isFiltering {
|
if manager.isFiltering {
|
||||||
ProgressView()
|
ProgressView()
|
||||||
} else {
|
} else {
|
||||||
ForEach(manager.filteredServers, id: \.id) { server in
|
ForEach(countryCodes, id: \.self, content: countryView)
|
||||||
Button("\(server.hostname ?? server.id) \(server.provider.countryCode)") {
|
|
||||||
onSelect(server)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.themeAnimation(on: manager.isFiltering, category: .providers)
|
.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 {
|
var filtersItem: some ToolbarContent {
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
Button {
|
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
|
#endif
|
||||||
|
|
|
@ -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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue