From 24c304b1c6347dabf1fdc4f071839acbaa5cb745 Mon Sep 17 00:00:00 2001 From: Diogo Date: Wed, 20 Nov 2024 13:07:54 +0000 Subject: [PATCH] more servers --- .../chat/simplex/common/model/SimpleXAPI.kt | 4 +- .../networkAndServers/NetworkAndServers.kt | 1 + .../networkAndServers/OperatorView.kt | 86 ++++++++++++++++++- .../networkAndServers/ProtocolServersView.kt | 49 ++++++++++- .../commonMain/resources/MR/base/strings.xml | 3 + 5 files changed, 134 insertions(+), 9 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 61a1b8b0fe..7115fa6a10 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -3812,8 +3812,8 @@ data class ServerOperator( @Serializable data class ServerRoles( - val storage: Boolean, - val proxy: Boolean + var storage: Boolean, + var proxy: Boolean ) @Serializable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt index 5a3e9db51c..f076a91bbb 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt @@ -679,6 +679,7 @@ fun ServerErrorsView(errStr: String) { .size(19.sp.toDp()) .offset(x = 2.sp.toDp()) ) + TextIconSpaced() Text(errStr, color = MaterialTheme.colors.secondary) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt index 2e45c9d518..11ceef121c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt @@ -1,5 +1,6 @@ package chat.simplex.common.views.usersettings.networkAndServers +import SectionCustomFooter import SectionDividerSpaced import SectionItemView import SectionTextFooter @@ -32,6 +33,7 @@ import chat.simplex.res.MR import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.launch +import kotlin.random.Random @Composable fun ModalData.OperatorView( @@ -61,7 +63,9 @@ fun OperatorViewLayout( operatorIndex: Int, rhId: Long? ) { - val operator = remember { userServers.value[operatorIndex].operator_ } + val operator by remember { derivedStateOf { userServers.value[operatorIndex].operator_ } } + val scope = rememberCoroutineScope() + val duplicateHosts = findDuplicateHosts(serverErrors.value) Column { SectionView(generalGetString(MR.strings.operator).uppercase()) { @@ -92,8 +96,82 @@ fun OperatorViewLayout( } if (operator.enabled) { - if (userServers.value[operatorIndex].smpServers.filter { !it.deleted }.isNotEmpty()) { + if (userServers.value[operatorIndex].smpServers.any { !it.deleted }) { + SectionDividerSpaced() + SectionView(generalGetString(MR.strings.operator_use_for_messages).uppercase()) { + SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) { + Text( + stringResource(MR.strings.operator_use_for_messages_receiving), + Modifier.padding(end = 24.dp), + color = Color.Unspecified + ) + Spacer(Modifier.fillMaxWidth().weight(1f)) + DefaultSwitch( + checked = userServers.value[operatorIndex].operator_.smpRoles.storage, + onCheckedChange = { enabled -> + userServers.value = userServers.value.toMutableList().apply { + this[operatorIndex] = this[operatorIndex].copy( + operator = this[operatorIndex].operator?.copy( + smpRoles = this[operatorIndex].operator?.smpRoles?.copy(storage = enabled) ?: ServerRoles(storage = enabled, proxy = false) + ) + ) + } + scope.launch { + validateServers(rhId, userServers, serverErrors) + } + } + ) + } + SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) { + Text( + stringResource(MR.strings.operator_use_for_messages_private_routing), + Modifier.padding(end = 24.dp), + color = Color.Unspecified + ) + Spacer(Modifier.fillMaxWidth().weight(1f)) + DefaultSwitch( + checked = userServers.value[operatorIndex].operator_.smpRoles.proxy, + onCheckedChange = { enabled -> + userServers.value = userServers.value.toMutableList().apply { + this[operatorIndex] = this[operatorIndex].copy( + operator = this[operatorIndex].operator?.copy( + smpRoles = this[operatorIndex].operator?.smpRoles?.copy(proxy = enabled) ?: ServerRoles(storage = false, proxy = enabled) + ) + ) + } + scope.launch { + validateServers(rhId, userServers, serverErrors) + } + } + ) + } + } + val smpErrors = globalSMPServersError(serverErrors.value) + if (smpErrors != null) { + SectionCustomFooter { + ServerErrorsView(smpErrors) + } + } + } + + // Preset servers can't be deleted + if (userServers.value[operatorIndex].smpServers.any { it.preset }) { + SectionDividerSpaced() + SectionView(generalGetString(MR.strings.message_servers).uppercase()) { + userServers.value[operatorIndex].smpServers.forEach { server -> + SectionItemView { + ProtocolServerViewLink( + userServers = userServers, + serverErrors = serverErrors, + server = server, + serverProtocol = ServerProtocol.SMP, + rhId = rhId, + duplicateHosts = duplicateHosts + ) + } + } + } } } } @@ -128,7 +206,7 @@ private fun UseOperatorToggle( operatorIndex: Int, rhId: Long? ) { - SectionItemView { + SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) { Text( stringResource(MR.strings.operator_use_operator_toggle_description), Modifier.padding(end = 24.dp), @@ -306,7 +384,7 @@ private fun NonScrollableTitle(title: String) { } @Composable -private fun ConditionsTextView( +fun ConditionsTextView( rhId: Long? ) { val conditionsData = remember { mutableStateOf?>(null) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt index cd74ff639e..83201413cc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt @@ -1,11 +1,18 @@ package chat.simplex.common.views.usersettings.networkAndServers -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import chat.simplex.common.model.UserOperatorServers +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import chat.simplex.common.model.* +import chat.simplex.common.model.ServerAddress.Companion.parseServerAddress import chat.simplex.common.platform.ColumnWithScrollBar import chat.simplex.common.views.helpers.* import chat.simplex.res.MR +import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @Composable @@ -13,4 +20,40 @@ fun ModalData.YourServersView(userServers: MutableState>, + serverErrors: MutableState>, + server: UserServer, + serverProtocol: ServerProtocol, + duplicateHosts: Set, + rhId: Long?, +) { + val address = parseServerAddress(server.server) + when { + address == null || !address.valid || address.serverProtocol != serverProtocol || address.hostnames.any { it in duplicateHosts } -> InvalidServer() + !server.enabled -> Icon(painterResource(MR.images.ic_do_not_disturb_on), null, tint = MaterialTheme.colors.secondary) + else -> ShowTestStatus(server) + } + Spacer(Modifier.padding(horizontal = 4.dp)) + val text = address?.hostnames?.firstOrNull() ?: server.server + if (server.enabled) { + Text(text, color = MaterialTheme.colors.onBackground, maxLines = 1) + } else { + Text(text, maxLines = 1, color = MaterialTheme.colors.secondary) + } +} + +@Composable +private fun InvalidServer() { + Icon( + painterResource(MR.images.ic_error), + contentDescription = stringResource(MR.strings.server_error), + tint = Color.Red, + modifier = Modifier + .size(19.sp.toDp()) + .offset(x = 2.sp.toDp()) + ) } \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index 60ea048e26..cac01f127d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1700,6 +1700,9 @@ Accept conditions Conditions of use In order to use operator %s, accept conditions of use. + Use for messages + For receiving + For private routing TCP connection