core, ios: advanced server config (#1371)
* ios: advanced server config * simplify UI * core: ServerCfg * commit migration, update schema * add preset servers to response * return default servers if none saved * fix test
This commit is contained in:
committed by
GitHub
parent
f8302e2030
commit
491fe4a9bf
@@ -319,6 +319,17 @@ func setUserSMPServers(smpServers: [String]) async throws {
|
||||
try await sendCommandOkResp(.setUserSMPServers(smpServers: smpServers))
|
||||
}
|
||||
|
||||
func testSMPServer(smpServer: String) async throws -> Result<(), SMPTestFailure> {
|
||||
let r = await chatSendCmd(.testSMPServer(smpServer: smpServer))
|
||||
if case let .sMPTestResult(testFailure) = r {
|
||||
if let t = testFailure {
|
||||
return .failure(t)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
throw r
|
||||
}
|
||||
|
||||
func getChatItemTTL() throws -> ChatItemTTL {
|
||||
let r = chatSendCmdSync(.apiGetChatItemTTL)
|
||||
if case let .chatItemTTL(chatItemTTL) = r { return ChatItemTTL(chatItemTTL) }
|
||||
|
||||
@@ -40,6 +40,13 @@ struct NetworkAndServers: View {
|
||||
Text("SMP servers")
|
||||
}
|
||||
|
||||
NavigationLink {
|
||||
SMPServersView()
|
||||
.navigationTitle("Your SMP servers")
|
||||
} label: {
|
||||
Text("SMP servers (new)")
|
||||
}
|
||||
|
||||
Picker("Use .onion hosts", selection: $onionHosts) {
|
||||
ForEach(OnionHosts.values, id: \.self) { Text($0.text) }
|
||||
}
|
||||
|
||||
105
apps/ios/Shared/Views/UserSettings/SMPServerView.swift
Normal file
105
apps/ios/Shared/Views/UserSettings/SMPServerView.swift
Normal file
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// SMPServerView.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Evgeny on 15/11/2022.
|
||||
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
struct SMPServerView: View {
|
||||
@State var server: ServerCfg
|
||||
|
||||
var body: some View {
|
||||
if server.preset {
|
||||
presetServer()
|
||||
} else {
|
||||
customServer()
|
||||
}
|
||||
}
|
||||
|
||||
private func presetServer() -> some View {
|
||||
return VStack {
|
||||
List {
|
||||
Section("Preset server address") {
|
||||
Text(server.server)
|
||||
}
|
||||
useServerSection()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func customServer() -> some View {
|
||||
VStack {
|
||||
List {
|
||||
Section("Your server address") {
|
||||
TextEditor(text: $server.server)
|
||||
.multilineTextAlignment(.leading)
|
||||
.autocorrectionDisabled(true)
|
||||
.autocapitalization(.none)
|
||||
.lineLimit(10)
|
||||
.frame(height: 108)
|
||||
.padding(-6)
|
||||
}
|
||||
useServerSection()
|
||||
Section("Add to another device") {
|
||||
QRCode(uri: server.server)
|
||||
.listRowInsets(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func useServerSection() -> some View {
|
||||
Section("Use server") {
|
||||
HStack {
|
||||
Button("Test server") {
|
||||
Task { await testServerConnection(server: $server) }
|
||||
}
|
||||
Spacer()
|
||||
showTestStatus(server: server)
|
||||
}
|
||||
Toggle("Enabled", isOn: $server.enabled)
|
||||
Button("Remove server", role: .destructive) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder func showTestStatus(server: ServerCfg) -> some View {
|
||||
switch server.tested {
|
||||
case .some(true):
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.green)
|
||||
case .some(false):
|
||||
Image(systemName: "multiply")
|
||||
.foregroundColor(.red)
|
||||
case .none:
|
||||
Color.clear
|
||||
}
|
||||
}
|
||||
|
||||
func testServerConnection(server: Binding<ServerCfg>) async {
|
||||
do {
|
||||
let r = try await testSMPServer(smpServer: server.wrappedValue.server)
|
||||
await MainActor.run {
|
||||
switch r {
|
||||
case .success: server.wrappedValue.tested = true
|
||||
case .failure: server.wrappedValue.tested = false
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
await MainActor.run {
|
||||
server.wrappedValue.tested = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SMPServerView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SMPServerView(server: ServerCfg.sampleData.custom)
|
||||
}
|
||||
}
|
||||
106
apps/ios/Shared/Views/UserSettings/SMPServersView.swift
Normal file
106
apps/ios/Shared/Views/UserSettings/SMPServersView.swift
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// SMPServersView.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Evgeny on 15/11/2022.
|
||||
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
struct SMPServersView: View {
|
||||
@Environment(\.editMode) var editMode
|
||||
@State var servers: [ServerCfg] = [
|
||||
ServerCfg.sampleData.preset,
|
||||
ServerCfg.sampleData.custom,
|
||||
ServerCfg.sampleData.untested,
|
||||
]
|
||||
@State var showAddServer = false
|
||||
@State var showSaveAlert = false
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section("SMP servers") {
|
||||
ForEach(servers) { srv in
|
||||
smpServerView(srv)
|
||||
}
|
||||
.onMove { indexSet, offset in
|
||||
servers.move(fromOffsets: indexSet, toOffset: offset)
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
servers.remove(atOffsets: indexSet)
|
||||
}
|
||||
if isEditing {
|
||||
Button("Add server…") {
|
||||
showAddServer = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: isEditing) { value in
|
||||
if value == false {
|
||||
showSaveAlert = true
|
||||
}
|
||||
}
|
||||
.toolbar { EditButton() }
|
||||
.confirmationDialog("Add server…", isPresented: $showAddServer, titleVisibility: .hidden) {
|
||||
Button("Scan server QR code") {
|
||||
}
|
||||
Button("Add preset servers") {
|
||||
}
|
||||
Button("Enter server manually") {
|
||||
servers.append(ServerCfg.empty)
|
||||
}
|
||||
}
|
||||
.confirmationDialog("Save servers?", isPresented: $showSaveAlert, titleVisibility: .visible) {
|
||||
Button("Test & save servers") {
|
||||
for i in 0..<servers.count {
|
||||
servers[i].tested = nil
|
||||
}
|
||||
Task {
|
||||
for i in 0..<servers.count {
|
||||
await testServerConnection(server: $servers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
Button("Save servers") {
|
||||
}
|
||||
Button("Revert changes") {
|
||||
}
|
||||
Button("Cancel", role: .cancel) {
|
||||
editMode?.wrappedValue = .active
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var isEditing: Bool {
|
||||
editMode?.wrappedValue.isEditing == true
|
||||
}
|
||||
|
||||
private func smpServerView(_ srv: ServerCfg) -> some View {
|
||||
NavigationLink {
|
||||
SMPServerView(server: srv)
|
||||
.navigationBarTitle("Server")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
let v = Text(srv.server)
|
||||
HStack {
|
||||
showTestStatus(server: srv)
|
||||
.frame(width: 16, alignment: .center)
|
||||
.padding(.trailing, 4)
|
||||
if srv.enabled {
|
||||
v
|
||||
} else {
|
||||
(v + Text(" (disabled)")).foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SMPServersView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SMPServersView()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user