From 6816e1a1ff1c4a71f8fbc428aead68deee5facf9 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 29 Jun 2026 08:48:00 +0000 Subject: [PATCH] desktop, android: improve custom relay and user address text fields design (#7155) --- .../simplex/common/views/helpers/Section.kt | 10 ++-- .../common/views/helpers/TextEditor.kt | 3 +- .../views/usersettings/UserAddressView.kt | 9 +++- .../networkAndServers/ChatRelayView.kt | 51 ++++++++----------- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt index 9afcdd0b94..5196a144b1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt @@ -1,4 +1,5 @@ import androidx.compose.foundation.* +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* @@ -27,7 +28,7 @@ import chat.simplex.common.views.onboarding.SelectableCard import chat.simplex.common.views.usersettings.SettingsActionItemWithContent import chat.simplex.res.MR -private val SectionCardShape = RoundedCornerShape(16.dp) +val SectionCardShape = RoundedCornerShape(16.dp) val CARD_PADDING = 18.dp val ICON_TEXT_SPACING = 8.dp @@ -113,15 +114,18 @@ fun SectionView( iconTint: Color = MaterialTheme.colors.secondary, leadingIcon: Boolean = false, padding: PaddingValues = PaddingValues(), + onIconClick: (() -> Unit)? = null, content: (@Composable ColumnScope.() -> Unit) ) { val card = LocalCardScreen.current Column { val iconSize = with(LocalDensity.current) { 21.sp.toDp() } + val interactionSource = remember { MutableInteractionSource() } + val iconClickable = if (onIconClick != null) Modifier.clickable(interactionSource = interactionSource, indication = ripple(bounded = false, radius = iconSize * 0.75f), onClick = onIconClick) else Modifier Row(Modifier.padding(start = if (card) DEFAULT_PADDING + DEFAULT_PADDING_HALF else DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) { - if (leadingIcon) Icon(icon, null, Modifier.padding(end = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) + if (leadingIcon) Icon(icon, null, Modifier.padding(end = DEFAULT_PADDING_HALF).size(iconSize).then(iconClickable), tint = iconTint) Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = if (card) 14.sp else 12.sp, fontWeight = if (card) FontWeight.Medium else FontWeight.Normal) - if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) + if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize).then(iconClickable), tint = iconTint) } CardColumn(padding) { content() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/TextEditor.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/TextEditor.kt index cd40585cad..833f53f2af 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/TextEditor.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/TextEditor.kt @@ -31,6 +31,7 @@ fun TextEditor( modifier: Modifier, placeholder: String? = null, contentPadding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING), + shape: Shape = RoundedCornerShape(14.dp), isValid: (String) -> Boolean = { true }, focusRequester: FocusRequester? = null, enabled: Boolean = true @@ -53,7 +54,7 @@ fun TextEditor( .fillMaxWidth() .padding(contentPadding) .heightIn(min = 52.dp) - .border(border = BorderStroke(1.dp, strokeColor), shape = RoundedCornerShape(14.dp)), + .border(border = BorderStroke(1.dp, strokeColor), shape = shape), contentAlignment = Alignment.Center, ) { val textFieldModifier = modifier diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt index c55eaf6c10..36c74cceb6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt @@ -1,6 +1,7 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer +import SectionCardShape import SectionDividerSpaced import SectionItemView import SectionTextFooter @@ -699,7 +700,13 @@ private fun AcceptIncognitoToggle(addressSettingsState: MutableState) { val autoReply = rememberSaveable { mutableStateOf(addressSettingsState.value.autoReply) } - TextEditor(autoReply, Modifier.height(100.dp), placeholder = stringResource(MR.strings.enter_welcome_message_optional)) + TextEditor( + autoReply, + Modifier.height(100.dp), + placeholder = stringResource(MR.strings.enter_welcome_message_optional), + contentPadding = PaddingValues(), + shape = SectionCardShape + ) LaunchedEffect(autoReply.value) { if (autoReply.value != addressSettingsState.value.autoReply) { addressSettingsState.value = AddressSettingsState( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt index ab63067226..9a2d7f8e61 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt @@ -1,6 +1,7 @@ package chat.simplex.common.views.usersettings.networkAndServers import SectionBottomSpacer +import SectionCardShape import SectionDividerSpaced import SectionItemView import SectionItemViewSpaceBetween @@ -10,9 +11,7 @@ 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.platform.LocalDensity import androidx.compose.ui.unit.sp import androidx.compose.ui.graphics.Color import dev.icerock.moko.resources.compose.painterResource @@ -230,43 +229,35 @@ private fun CustomRelay( } SectionView( - stringResource(MR.strings.your_relay_address).uppercase(), + stringResource(MR.strings.your_relay_address), icon = painterResource(MR.images.ic_error), iconTint = if (!validAddress.value) MaterialTheme.colors.error else Color.Transparent, ) { TextEditor( relayAddress, - Modifier.height(144.dp) + Modifier.height(144.dp), + contentPadding = PaddingValues(), + shape = SectionCardShape ) } SectionDividerSpaced(maxTopPadding = true) - Column { - val iconSize = with(LocalDensity.current) { 21.sp.toDp() } - Row(Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) { - Text( - stringResource(MR.strings.your_relay_name).uppercase(), - color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp - ) - IconButton( - onClick = { if (!validName.value) showInvalidRelayNameAlert(relayName) }, - enabled = !validName.value, - modifier = Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize) - ) { - Icon( - painterResource(MR.images.ic_error), null, - tint = if (!validName.value) MaterialTheme.colors.error else Color.Transparent - ) - } - } - Column(Modifier.fillMaxWidth()) { - TextEditor( - relayName, - Modifier, - placeholder = generalGetString(MR.strings.enter_relay_name), - enabled = relay.value.tested != true - ) - } + SectionView( + stringResource(MR.strings.your_relay_name), + icon = painterResource(MR.images.ic_error), + iconTint = if (!validName.value) MaterialTheme.colors.error else Color.Transparent, + onIconClick = if (!validName.value) { + { showInvalidRelayNameAlert(relayName) } + } else null + ) { + TextEditor( + relayName, + Modifier, + placeholder = generalGetString(MR.strings.enter_relay_name), + contentPadding = PaddingValues(), + shape = SectionCardShape, + enabled = relay.value.tested != true + ) } if (relay.value.tested != true) { SectionTextFooter(annotatedStringResource(MR.strings.test_relay_to_retrieve_name))