mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-11 18:28:52 +00:00
new server view wip
This commit is contained in:
+4
@@ -241,6 +241,10 @@ fun ModalData.NetworkAndServersView(close: () -> Unit) {
|
||||
SectionCustomFooter {
|
||||
ServersErrorFooter(serversErr)
|
||||
}
|
||||
} else if (serverErrors.value.isNotEmpty()) {
|
||||
SectionCustomFooter {
|
||||
ServersErrorFooter(generalGetString(MR.strings.errors_in_servers_configuration))
|
||||
}
|
||||
}
|
||||
|
||||
SectionDividerSpaced()
|
||||
|
||||
+32
-134
@@ -1,43 +1,30 @@
|
||||
package chat.simplex.common.views.usersettings.networkAndServers
|
||||
|
||||
import SectionBottomSpacer
|
||||
import SectionDividerSpaced
|
||||
import SectionItemView
|
||||
import SectionItemViewSpaceBetween
|
||||
import SectionView
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.model.ServerAddress.Companion.parseServerAddress
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.newchat.QRCode
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.usersettings.PreferenceToggle
|
||||
import chat.simplex.res.MR
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
||||
@Composable
|
||||
fun ModalData.NewServerView(
|
||||
userServers: MutableState<List<UserOperatorServers>>,
|
||||
serverErrors: MutableState<List<UserServersError>>,
|
||||
operatorIndex: Int,
|
||||
rhId: Long?,
|
||||
close: () -> Unit
|
||||
) {
|
||||
val newServer = remember { mutableStateOf(UserServer.empty) }
|
||||
val testing = remember { mutableStateOf(false) }
|
||||
val scope = rememberCoroutineScope()
|
||||
val newServer = remember { mutableStateOf(UserServer.empty) }
|
||||
|
||||
ModalView(close = {
|
||||
addServer(
|
||||
scope,
|
||||
newServer.value,
|
||||
userServers,
|
||||
serverErrors,
|
||||
@@ -45,104 +32,42 @@ fun ModalData.NewServerView(
|
||||
close = close
|
||||
)
|
||||
}) {
|
||||
NewServerLayout(
|
||||
userServers,
|
||||
serverErrors,
|
||||
operatorIndex,
|
||||
rhId,
|
||||
newServer,
|
||||
testing
|
||||
// testServer = {
|
||||
// testing = true
|
||||
// withLongRunningApi {
|
||||
// val res = testServerConnection(server, m)
|
||||
// if (isActive) {
|
||||
// onUpdate(res.first)
|
||||
// testing = false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
)
|
||||
}
|
||||
if (testing.value) {
|
||||
Box(
|
||||
Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
Modifier
|
||||
.padding(horizontal = 2.dp)
|
||||
.size(30.dp),
|
||||
color = MaterialTheme.colors.secondary,
|
||||
strokeWidth = 2.5.dp
|
||||
Box {
|
||||
NewServerLayout(
|
||||
newServer,
|
||||
testing.value,
|
||||
testServer = {
|
||||
testing.value = true
|
||||
withLongRunningApi {
|
||||
val res = testServerConnection(newServer.value, chatModel)
|
||||
if (isActive) {
|
||||
newServer.value = res.first
|
||||
testing.value = false
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
if (testing.value) {
|
||||
DefaultProgressView(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NewServerLayout(
|
||||
userServers: MutableState<List<UserOperatorServers>>,
|
||||
serverErrors: MutableState<List<UserServersError>>,
|
||||
operatorIndex: Int,
|
||||
rhId: Long?,
|
||||
server: MutableState<UserServer>,
|
||||
testing: MutableState<Boolean>
|
||||
testing: Boolean,
|
||||
testServer: () -> Unit,
|
||||
) {
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.smp_servers_new_server))
|
||||
CustomServer(userServers, serverErrors, operatorIndex, rhId, server, testing)
|
||||
CustomServer(server, testing, testServer, onDelete = null)
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomServer(
|
||||
userServers: MutableState<List<UserOperatorServers>>,
|
||||
serverErrors: MutableState<List<UserServersError>>,
|
||||
operatorIndex: Int,
|
||||
rhId: Long?,
|
||||
server: MutableState<UserServer>,
|
||||
testing: MutableState<Boolean>
|
||||
) {
|
||||
val serverAddress = remember { mutableStateOf(server.value.server) }
|
||||
val valid = remember {
|
||||
derivedStateOf {
|
||||
with(parseServerAddress(serverAddress.value)) {
|
||||
this?.valid == true
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionView(
|
||||
stringResource(MR.strings.smp_servers_your_server_address).uppercase(),
|
||||
icon = painterResource(MR.images.ic_error),
|
||||
iconTint = if (!valid.value) MaterialTheme.colors.error else Color.Transparent,
|
||||
) {
|
||||
val testedPreviously = remember { mutableMapOf<String, Boolean?>() }
|
||||
TextEditor(
|
||||
serverAddress,
|
||||
Modifier.height(144.dp)
|
||||
)
|
||||
LaunchedEffect(Unit) {
|
||||
snapshotFlow { serverAddress.value }
|
||||
.distinctUntilChanged()
|
||||
.collect {
|
||||
testedPreviously[server.value.server] = server.value.tested
|
||||
server.value = server.value.copy(server = it, tested = testedPreviously[serverAddress.value])
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionDividerSpaced(maxTopPadding = true)
|
||||
// UseServerSection(valid.value, testing, server, testServer, onUpdate, onDelete)
|
||||
|
||||
if (valid.value) {
|
||||
SectionDividerSpaced()
|
||||
SectionView(stringResource(MR.strings.smp_servers_add_to_another_device).uppercase()) {
|
||||
QRCode(serverAddress.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun serverProtocolAndOperator(
|
||||
server: UserServer,
|
||||
userServers: List<UserOperatorServers>
|
||||
@@ -165,6 +90,7 @@ fun serverProtocolAndOperator(
|
||||
}
|
||||
|
||||
fun addServer(
|
||||
scope: CoroutineScope,
|
||||
server: UserServer,
|
||||
userServers: MutableState<List<UserOperatorServers>>,
|
||||
serverErrors: MutableState<List<UserServersError>>,
|
||||
@@ -179,7 +105,6 @@ fun addServer(
|
||||
// Create a mutable copy of the userServers list
|
||||
val updatedUserServers = userServers.value.toMutableList()
|
||||
val operatorServers = updatedUserServers[operatorIndex]
|
||||
|
||||
// Create a mutable copy of the smpServers or xftpServers and add the server
|
||||
when (serverProtocol) {
|
||||
ServerProtocol.SMP -> {
|
||||
@@ -187,6 +112,7 @@ fun addServer(
|
||||
updatedSMPServers.add(server)
|
||||
updatedUserServers[operatorIndex] = operatorServers.copy(smpServers = updatedSMPServers)
|
||||
}
|
||||
|
||||
ServerProtocol.XFTP -> {
|
||||
val updatedXFTPServers = operatorServers.xftpServers.toMutableList()
|
||||
updatedXFTPServers.add(server)
|
||||
@@ -195,53 +121,25 @@ fun addServer(
|
||||
}
|
||||
|
||||
userServers.value = updatedUserServers
|
||||
// TODO
|
||||
// validateServers(rhId, userServers, serverErrors)
|
||||
close()
|
||||
scope.launch { validateServers(rhId, userServers, serverErrors) }
|
||||
matchingOperator?.let { op ->
|
||||
AlertManager.shared.showAlertMsg(
|
||||
title = "Operator server",
|
||||
text = "Server added to operator ${op.tradeName}."
|
||||
title = generalGetString(MR.strings.operator_server_alert_title),
|
||||
text = String.format(generalGetString(MR.strings.server_added_to_operator__name), op.tradeName)
|
||||
)
|
||||
}
|
||||
} else { // Shouldn't happen
|
||||
close()
|
||||
AlertManager.shared.showAlertMsg(title = "Error adding server")
|
||||
AlertManager.shared.showAlertMsg(title = generalGetString(MR.strings.error_adding_server))
|
||||
}
|
||||
} else {
|
||||
close()
|
||||
if (server.server.trim().isNotEmpty()) {
|
||||
AlertManager.shared.showAlertMsg(
|
||||
title = "Invalid server address!",
|
||||
text = "Check server address and try again."
|
||||
title = generalGetString(MR.strings.smp_servers_invalid_address),
|
||||
text = generalGetString(MR.strings.smp_servers_check_address)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@Composable
|
||||
//private fun UseServerSection(
|
||||
// valid: Boolean,
|
||||
// testing: MutableState<Boolean>,
|
||||
// server: UserServer
|
||||
//) {
|
||||
// SectionView(stringResource(MR.strings.smp_servers_use_server).uppercase()) {
|
||||
// SectionItemViewSpaceBetween(testServer, disabled = !valid || testing.value) {
|
||||
// Text(stringResource(MR.strings.smp_servers_test_server), color = if (valid && !testing.value) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary)
|
||||
// ShowTestStatus(server)
|
||||
// }
|
||||
//
|
||||
// val enabled = rememberUpdatedState(server.enabled)
|
||||
// PreferenceToggle(
|
||||
// stringResource(MR.strings.smp_servers_use_server_for_new_conn),
|
||||
// disabled = server.tested != true && !server.preset,
|
||||
// checked = enabled.value
|
||||
// ) {
|
||||
// onUpdate(server.copy(enabled = it))
|
||||
// }
|
||||
//
|
||||
// SectionItemView(onDelete, disabled = testing) {
|
||||
// Text(stringResource(MR.strings.smp_servers_delete_server), color = if (testing) MaterialTheme.colors.secondary else MaterialTheme.colors.error)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
+44
-60
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
@@ -42,7 +41,7 @@ fun ProtocolServerView(
|
||||
close: () -> Unit,
|
||||
rhId: Long?
|
||||
) {
|
||||
var testing by remember { mutableStateOf(false) }
|
||||
val testing = remember { mutableStateOf(false) }
|
||||
val scope = rememberCoroutineScope()
|
||||
val draftServer = remember { mutableStateOf(server) }
|
||||
|
||||
@@ -70,8 +69,8 @@ fun ProtocolServerView(
|
||||
)
|
||||
} else {
|
||||
onUpdate(draftServer.value)
|
||||
validateServers(rhId, userServers, serverErrors)
|
||||
close()
|
||||
validateServers(rhId, userServers, serverErrors)
|
||||
}
|
||||
} else {
|
||||
close()
|
||||
@@ -83,37 +82,26 @@ fun ProtocolServerView(
|
||||
}
|
||||
}
|
||||
) {
|
||||
ProtocolServerLayout(
|
||||
testing,
|
||||
draftServer.value,
|
||||
serverProtocol,
|
||||
testServer = {
|
||||
testing = true
|
||||
withLongRunningApi {
|
||||
val res = testServerConnection(draftServer.value, m)
|
||||
if (isActive) {
|
||||
draftServer.value = res.first
|
||||
testing = false
|
||||
Box {
|
||||
ProtocolServerLayout(
|
||||
draftServer,
|
||||
serverProtocol,
|
||||
testing.value,
|
||||
testServer = {
|
||||
testing.value = true
|
||||
withLongRunningApi {
|
||||
val res = testServerConnection(draftServer.value, m)
|
||||
if (isActive) {
|
||||
draftServer.value = res.first
|
||||
testing.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onUpdate = {
|
||||
draftServer.value = it
|
||||
},
|
||||
onDelete
|
||||
)
|
||||
if (testing) {
|
||||
Box(
|
||||
Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
Modifier
|
||||
.padding(horizontal = 2.dp)
|
||||
.size(30.dp),
|
||||
color = MaterialTheme.colors.secondary,
|
||||
strokeWidth = 2.5.dp
|
||||
)
|
||||
},
|
||||
onDelete
|
||||
)
|
||||
|
||||
if (testing.value) {
|
||||
DefaultProgressView(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,20 +109,19 @@ fun ProtocolServerView(
|
||||
|
||||
@Composable
|
||||
private fun ProtocolServerLayout(
|
||||
testing: Boolean,
|
||||
server: UserServer,
|
||||
server: MutableState<UserServer>,
|
||||
serverProtocol: ServerProtocol,
|
||||
testing: Boolean,
|
||||
testServer: () -> Unit,
|
||||
onUpdate: (UserServer) -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
) {
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(if (serverProtocol == ServerProtocol.XFTP) MR.strings.xftp_server else MR.strings.smp_server))
|
||||
|
||||
if (server.preset) {
|
||||
PresetServer(testing, server, testServer, onUpdate)
|
||||
if (server.value.preset) {
|
||||
PresetServer(server, testing, testServer)
|
||||
} else {
|
||||
CustomServer(testing, server, serverProtocol, testServer, onUpdate, onDelete)
|
||||
CustomServer(server, testing, testServer, onDelete)
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
@@ -142,15 +129,14 @@ private fun ProtocolServerLayout(
|
||||
|
||||
@Composable
|
||||
private fun PresetServer(
|
||||
server: MutableState<UserServer>,
|
||||
testing: Boolean,
|
||||
server: UserServer,
|
||||
testServer: () -> Unit,
|
||||
onUpdate: (UserServer) -> Unit,
|
||||
testServer: () -> Unit
|
||||
) {
|
||||
SectionView(stringResource(MR.strings.smp_servers_preset_address).uppercase()) {
|
||||
SelectionContainer {
|
||||
Text(
|
||||
server.server,
|
||||
server.value.server,
|
||||
Modifier.padding(start = DEFAULT_PADDING, top = 5.dp, end = DEFAULT_PADDING, bottom = 10.dp),
|
||||
style = TextStyle(
|
||||
fontFamily = FontFamily.Monospace, fontSize = 16.sp,
|
||||
@@ -160,23 +146,21 @@ private fun PresetServer(
|
||||
}
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
UseServerSection(true, testing, server, testServer, onUpdate)
|
||||
UseServerSection(server, true, testing, testServer)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomServer(
|
||||
fun CustomServer(
|
||||
server: MutableState<UserServer>,
|
||||
testing: Boolean,
|
||||
server: UserServer,
|
||||
serverProtocol: ServerProtocol,
|
||||
testServer: () -> Unit,
|
||||
onUpdate: (UserServer) -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
onDelete: (() -> Unit)?,
|
||||
) {
|
||||
val serverAddress = remember { mutableStateOf(server.server) }
|
||||
val serverAddress = remember { mutableStateOf(server.value.server) }
|
||||
val valid = remember {
|
||||
derivedStateOf {
|
||||
with(parseServerAddress(serverAddress.value)) {
|
||||
this?.valid == true && this.serverProtocol == serverProtocol
|
||||
this?.valid == true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,13 +178,14 @@ private fun CustomServer(
|
||||
snapshotFlow { serverAddress.value }
|
||||
.distinctUntilChanged()
|
||||
.collect {
|
||||
testedPreviously[server.server] = server.tested
|
||||
onUpdate(server.copy(server = it, tested = testedPreviously[serverAddress.value]))
|
||||
testedPreviously[server.value.server] = server.value.tested
|
||||
server.value = server.value.copy(server = it, tested = testedPreviously[serverAddress.value])
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionDividerSpaced(maxTopPadding = true)
|
||||
UseServerSection(valid.value, testing, server, testServer, onUpdate, onDelete)
|
||||
|
||||
UseServerSection(server, valid.value, testing, testServer, onDelete)
|
||||
|
||||
if (valid.value) {
|
||||
SectionDividerSpaced()
|
||||
@@ -212,26 +197,25 @@ private fun CustomServer(
|
||||
|
||||
@Composable
|
||||
private fun UseServerSection(
|
||||
server: MutableState<UserServer>,
|
||||
valid: Boolean,
|
||||
testing: Boolean,
|
||||
server: UserServer,
|
||||
testServer: () -> Unit,
|
||||
onUpdate: (UserServer) -> Unit,
|
||||
onDelete: (() -> Unit)? = null,
|
||||
) {
|
||||
SectionView(stringResource(MR.strings.smp_servers_use_server).uppercase()) {
|
||||
SectionItemViewSpaceBetween(testServer, disabled = !valid || testing) {
|
||||
Text(stringResource(MR.strings.smp_servers_test_server), color = if (valid && !testing) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary)
|
||||
ShowTestStatus(server)
|
||||
ShowTestStatus(server.value)
|
||||
}
|
||||
|
||||
val enabled = rememberUpdatedState(server.enabled)
|
||||
val enabled = rememberUpdatedState(server.value.enabled)
|
||||
PreferenceToggle(
|
||||
stringResource(MR.strings.smp_servers_use_server_for_new_conn),
|
||||
// disabled = server.tested != true && !server.preset,
|
||||
disabled = testing,
|
||||
checked = enabled.value
|
||||
) {
|
||||
onUpdate(server.copy(enabled = it))
|
||||
server.value = server.value.copy(enabled = it)
|
||||
}
|
||||
|
||||
if (onDelete != null) {
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
<string name="no_media_servers_configured_for_sending">No media & file servers configured for sending.</string>
|
||||
<string name="no_media_servers_configured_for_private_routing">No media & file servers configured for private routing.</string>
|
||||
<string name="for_chat_profile">For chat profile %s:</string>
|
||||
<string name="errors_in_servers_configuration">Errors in servers configuration.</string>
|
||||
<string name="error_accepting_operator_conditions">Error accepting conditions</string>
|
||||
|
||||
<!-- API Error Responses - SimpleXAPI.kt -->
|
||||
@@ -1735,6 +1736,11 @@
|
||||
<string name="error_server_protocol_changed">Server protocol changed.</string>
|
||||
<string name="error_server_operator_changed">Server operator changed.</string>
|
||||
|
||||
<!-- NewServerView.kt -->
|
||||
<string name="operator_server_alert_title">Operator server</string>
|
||||
<string name="server_added_to_operator__name">Server added to operator %s.</string>
|
||||
<string name="error_adding_server">Error adding server</string>
|
||||
|
||||
<!-- AdvancedNetworkSettings.kt -->
|
||||
<string name="network_option_tcp_connection">TCP connection</string>
|
||||
<string name="network_options_reset_to_defaults">Reset to defaults</string>
|
||||
|
||||
Reference in New Issue
Block a user