fix: close message field after closing a keyboard,

change design
This commit is contained in:
2026-04-23 20:35:29 +03:00
parent f2ab63887a
commit 16fbd40907
@@ -24,17 +24,21 @@ import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.TextView
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.isImeVisible
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@@ -61,12 +65,15 @@ import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.IntOffset
@@ -94,7 +101,6 @@ import de.connect2x.trixnity.core.model.events.m.room.RoomMessageEventContent
import de.connect2x.trixnity.core.model.events.m.room.TopicEventContent
import io.github.rabehx.iconsax.Iconsax
import io.github.rabehx.iconsax.filled.Send2
import io.github.rabehx.iconsax.outline.Send2
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -125,6 +131,7 @@ private const val TIMELINE_BOTTOM_AUTOSCROLL_THRESHOLD = 3
private const val MAX_INITIAL_UNREAD_SEARCH_LIMIT = 500
private val TIMELINE_AVATAR_SIZE = 32.dp
private val MESSAGE_FIELD_TOP_PADDING = 8.dp
private val MESSAGE_FIELD_SIZE = 48.dp
private val simpleHtmlTags = setOf(
"a", "b", "blockquote", "br", "code", "del", "div", "em", "h1", "h2",
@@ -363,29 +370,43 @@ fun Room(modifier: Modifier = Modifier, rid: String) {
}
}
Row(Modifier.fillMaxWidth()) {
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
OutlinedTextField(
modifier = Modifier
.clearFocusOnKeyboardDismiss()
.padding(MESSAGE_FIELD_TOP_PADDING)
.height(MESSAGE_FIELD_SIZE)
.weight(1f),
shape = CircleShape,
value = message,
onValueChange = { message = it },
)
IconButton(
enabled = message.isNotBlank(),
content = { Icon(if (message.isBlank()) Iconsax.Outline.Send2 else Iconsax.Filled.Send2, contentDescription = "Send") },
onClick = {
val payload = message.trim()
if (payload.isBlank()) return@IconButton
CoroutineScope(Dispatchers.IO).launch {
client!!.room.sendMessage(RoomId(rid)) {
text(payload)
AnimatedVisibility(message.isNotBlank()) {
IconButton(
modifier = Modifier
.size(MESSAGE_FIELD_SIZE)
.background(MaterialTheme.colorScheme.primary, CircleShape),
enabled = message.isNotBlank(),
content = {
Icon(Iconsax.Filled.Send2,
contentDescription = "Send",
tint = MaterialTheme.colorScheme.inversePrimary
)
},
onClick = {
val payload = message.trim()
if (payload.isBlank()) return@IconButton
CoroutineScope(Dispatchers.IO).launch {
client!!.room.sendMessage(RoomId(rid)) {
text(payload)
}
}
message = ""
}
message = ""
}
)
)
}
}
}
}
@@ -1727,3 +1748,28 @@ private fun wrapHtml(
private fun colorToCss(color: Color): String {
return String.format("#%06X", 0xFFFFFF and color.toArgb())
}
@OptIn(ExperimentalLayoutApi::class)
fun Modifier.clearFocusOnKeyboardDismiss(): Modifier = composed {
var isFocused by remember { mutableStateOf(false) }
var keyboardAppearedSinceLastFocused by remember { mutableStateOf(false) }
if (isFocused) {
val imeIsVisible = WindowInsets.isImeVisible
val focusManager = LocalFocusManager.current
LaunchedEffect(imeIsVisible) {
if (imeIsVisible) {
keyboardAppearedSinceLastFocused = true
} else if (keyboardAppearedSinceLastFocused) {
focusManager.clearFocus()
}
}
}
onFocusEvent {
if (isFocused != it.isFocused) {
isFocused = it.isFocused
if (isFocused) {
keyboardAppearedSinceLastFocused = false
}
}
}
}