From c7a646ae7303edc959ce66a7a7beda0d50b73126 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Thu, 9 Jul 2026 03:48:42 +0000 Subject: [PATCH] chore: improve line break handling (#39) Reviewed-on: https://git.reya.su/reya/coop-mobile/pulls/39 --- .../kotlin/su/reya/coop/screens/chat/ChatInput.kt | 8 ++++++++ .../src/commonMain/kotlin/su/reya/coop/Extensions.kt | 10 +++++----- shared/src/commonMain/kotlin/su/reya/coop/Profile.kt | 4 ++-- shared/src/commonMain/kotlin/su/reya/coop/Room.kt | 6 ++++-- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatInput.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatInput.kt index 7f09365..e1300a5 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatInput.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/chat/ChatInput.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -23,6 +24,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.unit.dp import coop.composeapp.generated.resources.Res import coop.composeapp.generated.resources.ic_add_circle @@ -52,6 +55,11 @@ fun ChatInput( value = value, onValueChange = onValueChange, placeholder = { Text("Message") }, + maxLines = 5, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Sentences, + imeAction = ImeAction.Default + ), leadingIcon = { IconButton(onClick = onUpload) { Icon( diff --git a/shared/src/commonMain/kotlin/su/reya/coop/Extensions.kt b/shared/src/commonMain/kotlin/su/reya/coop/Extensions.kt index 7b78f79..5d5151e 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/Extensions.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/Extensions.kt @@ -10,17 +10,17 @@ fun PublicKey.short(): String { val URL_REGEX = Regex("(https?://\\S+)", RegexOption.IGNORE_CASE) private val imageExtensions = setOf("jpg", "jpeg", "png", "gif", "webp", "bmp") -fun String.extractUrls(): List { - return URL_REGEX.findAll(this).map { it.value }.toList() -} - fun String.removeImageUrls(): String { return URL_REGEX.replace(this) { result -> if (result.value.isImageUrl()) "" else result.value - }.replace(Regex("\\s+"), " ").trim() + }.trim() } fun String.isImageUrl(): Boolean { val extension = this.substringAfterLast('.', "").lowercase() return extension in imageExtensions } + +fun String.sanitizeName(): String { + return this.replace("\n", " ").replace("\r", " ").trim() +} diff --git a/shared/src/commonMain/kotlin/su/reya/coop/Profile.kt b/shared/src/commonMain/kotlin/su/reya/coop/Profile.kt index 8b40cd1..9dde03c 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/Profile.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/Profile.kt @@ -10,8 +10,8 @@ data class Profile( private val record by lazy { metadata.asRecord() } val name: String - get() = record.displayName ?: record.name ?: publicKey.short() - + get() = record.displayName?.sanitizeName() ?: record.name ?: publicKey.short() + val picture: String? get() = record.picture diff --git a/shared/src/commonMain/kotlin/su/reya/coop/Room.kt b/shared/src/commonMain/kotlin/su/reya/coop/Room.kt index 5b7d8eb..e61a691 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/Room.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/Room.kt @@ -99,11 +99,13 @@ fun Room.uiStateFlow( val displayMembers = if (isGroup()) members.take(2) else members.take(1) if (!subject.isNullOrBlank()) { - return flowOf(RoomUiState(name = subject, isGroup = isGroup())) + return flowOf(RoomUiState(name = subject.sanitizeName(), isGroup = isGroup())) } return combine(displayMembers.map { nostrViewModel.getMetadata(it) }) { profiles -> - val names = profiles.mapIndexed { i, profile -> profile?.name ?: displayMembers[i].short() } + val names = profiles.mapIndexed { i, profile -> + profile?.name?.sanitizeName() ?: displayMembers[i].short() + } val name = when { isGroup() -> {