mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-10 05:41:56 +00:00
Merge branch 'server-operators' into dc/android-desktop-server-operators
This commit is contained in:
@@ -31,14 +31,22 @@ enum UserPickerSheet: Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
class SaveableSettings: ObservableObject {
|
||||
@Published var servers: ServerSettings = ServerSettings(currUserServers: [], userServers: [], serverErrors: [])
|
||||
}
|
||||
|
||||
struct ServerSettings {
|
||||
public var currUserServers: [UserOperatorServers]
|
||||
public var userServers: [UserOperatorServers]
|
||||
public var serverErrors: [UserServersError]
|
||||
}
|
||||
|
||||
struct UserPickerSheetView: View {
|
||||
let sheet: UserPickerSheet
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@State private var loaded = false
|
||||
@StateObject private var ss = SaveableSettings()
|
||||
|
||||
@State private var currUserServers: [UserOperatorServers] = []
|
||||
@State private var userServers: [UserOperatorServers] = []
|
||||
@State private var serverErrors: [UserServersError] = []
|
||||
@State private var loaded = false
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
@@ -60,11 +68,7 @@ struct UserPickerSheetView: View {
|
||||
case .useFromDesktop:
|
||||
ConnectDesktopView()
|
||||
case .settings:
|
||||
SettingsView(
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors
|
||||
)
|
||||
SettingsView()
|
||||
}
|
||||
}
|
||||
Color.clear // Required for list background to be rendered during loading
|
||||
@@ -85,15 +89,20 @@ struct UserPickerSheetView: View {
|
||||
)
|
||||
}
|
||||
.onDisappear {
|
||||
if serversCanBeSaved(currUserServers, userServers, serverErrors) {
|
||||
if serversCanBeSaved(
|
||||
ss.servers.currUserServers,
|
||||
ss.servers.userServers,
|
||||
ss.servers.serverErrors
|
||||
) {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Save servers?", comment: "alert title"),
|
||||
buttonTitle: NSLocalizedString("Save", comment: "alert button"),
|
||||
buttonAction: { saveServers($currUserServers, $userServers) },
|
||||
buttonAction: { saveServers($ss.servers.currUserServers, $ss.servers.userServers) },
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
}
|
||||
.environmentObject(ss)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@ struct ServersSummaryView: View {
|
||||
@State private var timer: Timer? = nil
|
||||
@State private var alert: SomeAlert?
|
||||
|
||||
@State private var currUserServers: [UserOperatorServers] = []
|
||||
@State private var userServers: [UserOperatorServers] = []
|
||||
@State private var serverErrors: [UserServersError] = []
|
||||
|
||||
@AppStorage(DEFAULT_SHOW_SUBSCRIPTION_PERCENTAGE) private var showSubscriptionPercentage = false
|
||||
|
||||
enum PresentedUserCategory {
|
||||
@@ -57,15 +53,6 @@ struct ServersSummaryView: View {
|
||||
}
|
||||
.onDisappear {
|
||||
stopTimer()
|
||||
|
||||
if serversCanBeSaved(currUserServers, userServers, serverErrors) {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Save servers?", comment: "alert title"),
|
||||
buttonTitle: NSLocalizedString("Save", comment: "alert button"),
|
||||
buttonAction: { saveServers($currUserServers, $userServers) },
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
}
|
||||
.alert(item: $alert) { $0.alert }
|
||||
}
|
||||
@@ -288,10 +275,7 @@ struct ServersSummaryView: View {
|
||||
NavigationLink(tag: srvSumm.id, selection: $selectedSMPServer) {
|
||||
SMPServerSummaryView(
|
||||
summary: srvSumm,
|
||||
statsStartedAt: statsStartedAt,
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors
|
||||
statsStartedAt: statsStartedAt
|
||||
)
|
||||
.navigationBarTitle("SMP server")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
@@ -360,10 +344,7 @@ struct ServersSummaryView: View {
|
||||
NavigationLink(tag: srvSumm.id, selection: $selectedXFTPServer) {
|
||||
XFTPServerSummaryView(
|
||||
summary: srvSumm,
|
||||
statsStartedAt: statsStartedAt,
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors
|
||||
statsStartedAt: statsStartedAt
|
||||
)
|
||||
.navigationBarTitle("XFTP server")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
@@ -505,28 +486,11 @@ struct SMPServerSummaryView: View {
|
||||
|
||||
@AppStorage(DEFAULT_SHOW_SUBSCRIPTION_PERCENTAGE) private var showSubscriptionPercentage = false
|
||||
|
||||
@Binding var currUserServers: [UserOperatorServers]
|
||||
@Binding var userServers: [UserOperatorServers]
|
||||
@Binding var serverErrors: [UserServersError]
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section("Server address") {
|
||||
Text(summary.smpServer)
|
||||
.textSelection(.enabled)
|
||||
if summary.known == true {
|
||||
NavigationLink {
|
||||
NetworkAndServers(
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors
|
||||
)
|
||||
.navigationTitle("Network & servers")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
} label: {
|
||||
Text("Open server settings")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let stats = summary.stats {
|
||||
@@ -701,28 +665,11 @@ struct XFTPServerSummaryView: View {
|
||||
var summary: XFTPServerSummary
|
||||
var statsStartedAt: Date
|
||||
|
||||
@Binding var currUserServers: [UserOperatorServers]
|
||||
@Binding var userServers: [UserOperatorServers]
|
||||
@Binding var serverErrors: [UserServersError]
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section("Server address") {
|
||||
Text(summary.xftpServer)
|
||||
.textSelection(.enabled)
|
||||
if summary.known == true {
|
||||
NavigationLink {
|
||||
NetworkAndServers(
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors
|
||||
)
|
||||
.navigationTitle("Network & servers")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
} label: {
|
||||
Text("Open server settings")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let stats = summary.stats {
|
||||
|
||||
@@ -34,9 +34,7 @@ struct NetworkAndServers: View {
|
||||
@EnvironmentObject var m: ChatModel
|
||||
@Environment(\.colorScheme) var colorScheme: ColorScheme
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@Binding var currUserServers: [UserOperatorServers]
|
||||
@Binding var userServers: [UserOperatorServers]
|
||||
@Binding var serverErrors: [UserServersError]
|
||||
@EnvironmentObject var ss: SaveableSettings
|
||||
@State private var sheetItem: NetworkAndServersSheet? = nil
|
||||
@State private var justOpened = true
|
||||
@State private var showSaveDialog = false
|
||||
@@ -45,9 +43,9 @@ struct NetworkAndServers: View {
|
||||
VStack {
|
||||
List {
|
||||
let conditionsAction = m.conditions.conditionsAction
|
||||
let anyOperatorEnabled = userServers.contains(where: { $0.operator?.enabled ?? false })
|
||||
let anyOperatorEnabled = ss.servers.userServers.contains(where: { $0.operator?.enabled ?? false })
|
||||
Section {
|
||||
ForEach(userServers.enumerated().map { $0 }, id: \.element.id) { idx, userOperatorServers in
|
||||
ForEach(ss.servers.userServers.enumerated().map { $0 }, id: \.element.id) { idx, userOperatorServers in
|
||||
if let serverOperator = userOperatorServers.operator {
|
||||
serverOperatorView(idx, serverOperator)
|
||||
} else {
|
||||
@@ -74,11 +72,11 @@ struct NetworkAndServers: View {
|
||||
}
|
||||
|
||||
Section {
|
||||
if let idx = userServers.firstIndex(where: { $0.operator == nil }) {
|
||||
if let idx = ss.servers.userServers.firstIndex(where: { $0.operator == nil }) {
|
||||
NavigationLink {
|
||||
YourServersView(
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors,
|
||||
userServers: $ss.servers.userServers,
|
||||
serverErrors: $ss.servers.serverErrors,
|
||||
operatorIndex: idx
|
||||
)
|
||||
.navigationTitle("Your servers")
|
||||
@@ -87,7 +85,7 @@ struct NetworkAndServers: View {
|
||||
HStack {
|
||||
Text("Your servers")
|
||||
|
||||
if userServers[idx] != currUserServers[idx] {
|
||||
if ss.servers.userServers[idx] != ss.servers.currUserServers[idx] {
|
||||
Spacer()
|
||||
unsavedChangesIndicator()
|
||||
}
|
||||
@@ -108,12 +106,12 @@ struct NetworkAndServers: View {
|
||||
}
|
||||
|
||||
Section {
|
||||
Button("Save servers", action: { saveServers($currUserServers, $userServers) })
|
||||
.disabled(!serversCanBeSaved(currUserServers, userServers, serverErrors))
|
||||
Button("Save servers", action: { saveServers($ss.servers.currUserServers, $ss.servers.userServers) })
|
||||
.disabled(!serversCanBeSaved(ss.servers.currUserServers, ss.servers.userServers, ss.servers.serverErrors))
|
||||
} footer: {
|
||||
if let errStr = globalServersError(serverErrors) {
|
||||
if let errStr = globalServersError(ss.servers.serverErrors) {
|
||||
ServersErrorView(errStr: errStr)
|
||||
} else if !serverErrors.isEmpty {
|
||||
} else if !ss.servers.serverErrors.isEmpty {
|
||||
ServersErrorView(errStr: NSLocalizedString("Errors in servers configuration.", comment: "servers error"))
|
||||
}
|
||||
}
|
||||
@@ -141,9 +139,9 @@ struct NetworkAndServers: View {
|
||||
// this condition is needed to prevent re-setting the servers when exiting single server view
|
||||
if justOpened {
|
||||
do {
|
||||
currUserServers = try await getUserServers()
|
||||
userServers = currUserServers
|
||||
serverErrors = []
|
||||
ss.servers.currUserServers = try await getUserServers()
|
||||
ss.servers.userServers = ss.servers.currUserServers
|
||||
ss.servers.serverErrors = []
|
||||
} catch let error {
|
||||
await MainActor.run {
|
||||
showAlert(
|
||||
@@ -156,7 +154,7 @@ struct NetworkAndServers: View {
|
||||
}
|
||||
}
|
||||
.modifier(BackButton(disabled: Binding.constant(false)) {
|
||||
if serversCanBeSaved(currUserServers, userServers, serverErrors) {
|
||||
if serversCanBeSaved(ss.servers.currUserServers, ss.servers.userServers, ss.servers.serverErrors) {
|
||||
showSaveDialog = true
|
||||
} else {
|
||||
dismiss()
|
||||
@@ -164,7 +162,7 @@ struct NetworkAndServers: View {
|
||||
})
|
||||
.confirmationDialog("Save servers?", isPresented: $showSaveDialog, titleVisibility: .visible) {
|
||||
Button("Save") {
|
||||
saveServers($currUserServers, $userServers)
|
||||
saveServers($ss.servers.currUserServers, $ss.servers.userServers)
|
||||
dismiss()
|
||||
}
|
||||
Button("Exit without saving") { dismiss() }
|
||||
@@ -173,8 +171,8 @@ struct NetworkAndServers: View {
|
||||
switch item {
|
||||
case .showConditions:
|
||||
UsageConditionsView(
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers
|
||||
currUserServers: $ss.servers.currUserServers,
|
||||
userServers: $ss.servers.userServers
|
||||
)
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
}
|
||||
@@ -184,9 +182,9 @@ struct NetworkAndServers: View {
|
||||
private func serverOperatorView(_ operatorIndex: Int, _ serverOperator: ServerOperator) -> some View {
|
||||
NavigationLink() {
|
||||
OperatorView(
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors,
|
||||
currUserServers: $ss.servers.currUserServers,
|
||||
userServers: $ss.servers.userServers,
|
||||
serverErrors: $ss.servers.serverErrors,
|
||||
operatorIndex: operatorIndex,
|
||||
useOperator: serverOperator.enabled
|
||||
)
|
||||
@@ -203,7 +201,7 @@ struct NetworkAndServers: View {
|
||||
Text(serverOperator.tradeName)
|
||||
.foregroundColor(serverOperator.enabled ? theme.colors.onBackground : theme.colors.secondary)
|
||||
|
||||
if userServers[operatorIndex] != currUserServers[operatorIndex] {
|
||||
if ss.servers.userServers[operatorIndex] != ss.servers.currUserServers[operatorIndex] {
|
||||
Spacer()
|
||||
unsavedChangesIndicator()
|
||||
}
|
||||
@@ -427,10 +425,6 @@ func updateOperatorsConditionsAcceptance(_ usvs: Binding<[UserOperatorServers]>,
|
||||
|
||||
struct NetworkServersView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NetworkAndServers(
|
||||
currUserServers: Binding.constant([UserOperatorServers.sampleData1, UserOperatorServers.sampleDataNilOperator]),
|
||||
userServers: Binding.constant([UserOperatorServers.sampleData1, UserOperatorServers.sampleDataNilOperator]),
|
||||
serverErrors: Binding.constant([])
|
||||
)
|
||||
NetworkAndServers()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,10 +266,6 @@ struct SettingsView: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@State private var showProgress: Bool = false
|
||||
|
||||
@Binding var currUserServers: [UserOperatorServers]
|
||||
@Binding var userServers: [UserOperatorServers]
|
||||
@Binding var serverErrors: [UserServersError]
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
settingsView()
|
||||
@@ -296,13 +292,9 @@ struct SettingsView: View {
|
||||
.disabled(chatModel.chatRunning != true)
|
||||
|
||||
NavigationLink {
|
||||
NetworkAndServers(
|
||||
currUserServers: $currUserServers,
|
||||
userServers: $userServers,
|
||||
serverErrors: $serverErrors
|
||||
)
|
||||
.navigationTitle("Network & servers")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
NetworkAndServers()
|
||||
.navigationTitle("Network & servers")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
} label: {
|
||||
settingsRow("externaldrive.connected.to.line.below", color: theme.colors.secondary) { Text("Network & servers") }
|
||||
}
|
||||
@@ -536,11 +528,7 @@ struct SettingsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let chatModel = ChatModel()
|
||||
chatModel.currentUser = User.sampleData
|
||||
return SettingsView(
|
||||
currUserServers: Binding.constant([UserOperatorServers.sampleData1, UserOperatorServers.sampleDataNilOperator]),
|
||||
userServers: Binding.constant([UserOperatorServers.sampleData1, UserOperatorServers.sampleDataNilOperator]),
|
||||
serverErrors: Binding.constant([])
|
||||
)
|
||||
.environmentObject(chatModel)
|
||||
return SettingsView()
|
||||
.environmentObject(chatModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,7 +1456,6 @@ public enum UserServersError: Decodable {
|
||||
case noServers(protocol: ServerProtocol, user: UserRef?)
|
||||
case storageMissing(protocol: ServerProtocol, user: UserRef?)
|
||||
case proxyMissing(protocol: ServerProtocol, user: UserRef?)
|
||||
case invalidServer(protocol: ServerProtocol, invalidServer: String)
|
||||
case duplicateServer(protocol: ServerProtocol, duplicateServer: String, duplicateHost: String)
|
||||
|
||||
public var globalError: String? {
|
||||
|
||||
Reference in New Issue
Block a user