From 3ae3011c7c7dad7b0fa7894ba690149394c02a8f Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:30:14 +0400 Subject: [PATCH] wip --- .../NetworkAndServers/OperatorView.swift | 106 +++++++++++++++++- .../ProtocolServersView.swift | 3 +- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift index 91b5316424..d9601b434a 100644 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift @@ -14,10 +14,14 @@ import SimpleXChat struct OperatorView: View { @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject var theme: AppTheme + @Environment(\.editMode) private var editMode let serverProtocol: ServerProtocol - @Binding var serverOperator: ServerOperator // Binding + @Binding var serverOperator: ServerOperator @State var serverOperatorToEdit: ServerOperator - var servers: [ServerCfg] // State / Binding + @State var currServers: [ServerCfg] + @State var servers: [ServerCfg] = [] + @State private var selectedServer: String? = nil + @State private var justOpened = true var proto: String { serverProtocol.rawValue.uppercased() } @@ -30,12 +34,30 @@ struct OperatorView: View { } useOperatorSection() + + serversSection() + + Section { + Button("Reset") { servers = currServers } + .disabled(Set(servers) == Set(currServers)) + Button("Test servers") {} + Button("Save servers") {} + .disabled(true) + } } } .modifier(BackButton(disabled: Binding.constant(false)) { serverOperator = serverOperatorToEdit dismiss() }) + .toolbar { EditButton() } + .onAppear { + // this condition is needed to prevent re-setting the servers when exiting single server view + if justOpened { + servers = currServers + justOpened = false + } + } } private func infoViewLink() -> some View { @@ -82,13 +104,89 @@ struct OperatorView: View { .modifier(ThemedBackground(grouped: true)) .navigationBarTitleDisplayMode(.large) } label: { - if case .accepted = serverOperator.latestConditionsAcceptance { + if case .accepted = serverOperatorToEdit.latestConditionsAcceptance { Text("Conditions accepted") } else { Text("Review conditions") } } } + + private func serversSection() -> some View { + Section { + ForEach($servers) { srv in + protocolServerView(srv) + } + .onMove { indexSet, offset in + servers.move(fromOffsets: indexSet, toOffset: offset) + } + .onDelete { indexSet in + servers.remove(atOffsets: indexSet) + } + } header: { + Text("\(serverOperator.name) \(proto) servers") + .foregroundColor(theme.colors.secondary) + } footer: { + Text("The servers for new connections of your current chat profile **\(ChatModel.shared.currentUser?.displayName ?? "")**.") + .foregroundColor(theme.colors.secondary) + .lineLimit(10) + } + } + + private func protocolServerView(_ server: Binding) -> some View { + let srv = server.wrappedValue + return NavigationLink(tag: srv.id, selection: $selectedServer) { + ProtocolServerView( + serverProtocol: serverProtocol, + server: server, + serverToEdit: srv + ) + .navigationBarTitle(srv.preset ? "Preset server" : "Your server") + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + } label: { + let address = parseServerAddress(srv.server) + HStack { + Group { + if let address = address { + if !address.valid || address.serverProtocol != serverProtocol { + invalidServer() + } else if !uniqueAddress(srv, address) { + Image(systemName: "exclamationmark.circle").foregroundColor(.red) + } else if !srv.enabled { + Image(systemName: "slash.circle").foregroundColor(theme.colors.secondary) + } else { + showTestStatus(server: srv) + } + } else { + invalidServer() + } + } + .frame(width: 16, alignment: .center) + .padding(.trailing, 4) + + let v = Text(address?.hostnames.first ?? srv.server).lineLimit(1) + if srv.enabled { + v + } else { + v.foregroundColor(theme.colors.secondary) + } + } + } + } + + private func invalidServer() -> some View { + Image(systemName: "exclamationmark.circle").foregroundColor(.red) + } + + // TODO all servers across all operators + private func uniqueAddress(_ s: ServerCfg, _ address: ServerAddress) -> Bool { + servers.allSatisfy { srv in + address.hostnames.allSatisfy { host in + srv.id == s.id || !srv.server.contains(host) + } + } + } } struct OperatorInfoView: View { @@ -159,6 +257,6 @@ struct UsageConditionsView: View { serverProtocol: .smp, serverOperator: Binding.constant(ServerOperator.sampleData1), serverOperatorToEdit: ServerOperator.sampleData1, - servers: [ServerCfg.sampleData.preset] + currServers: [ServerCfg.sampleData.preset] ) } diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift index f75879ed2f..e8490a783b 100644 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift @@ -198,7 +198,7 @@ struct ProtocolServersView: View { serverProtocol: .smp, serverOperator: serverOperator, serverOperatorToEdit: srvOperator, - servers: servers + currServers: servers ) .navigationBarTitle("\(srvOperator.name) servers") .modifier(ThemedBackground(grouped: true)) @@ -234,6 +234,7 @@ struct ProtocolServersView: View { allServers.allSatisfy { !$0.enabled } } + // TODO remove private func protocolServerView(_ server: Binding) -> some View { let srv = server.wrappedValue return NavigationLink(tag: srv.id, selection: $selectedServer) {