Simplified implementation of new chat text

This commit is contained in:
Juha Heinanen
2025-10-10 11:34:53 +03:00
parent 17db3e9572
commit 7f0f858033
2 changed files with 33 additions and 31 deletions

View File

@ -48,11 +48,11 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -124,8 +124,6 @@ private fun ChatScreen(
val aor = account.aor
var chatMessages by remember(aor, peerUri) { mutableStateOf<List<Message>>(emptyList()) }
val allDrafts by viewModel.aorPeerMessage.collectAsState()
val currentDraft = allDrafts.getOrDefault(AorPeer(aor, peerUri), TextFieldValue(""))
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
@ -190,12 +188,9 @@ private fun ChatScreen(
bottomBar = {
NewMessage(
ctx = ctx,
viewModel,
account = account,
peerUri = peerUri,
newMessage = currentDraft,
onNewMessageChange = { newTextFieldValue ->
viewModel.updateAorPeerMessage(aor, peerUri, newTextFieldValue)
},
addMessage = addMessage
)
},
@ -481,16 +476,19 @@ private fun Messages(
@Composable
private fun NewMessage(
ctx: Context,
viewModel: ViewModel,
account: Account,
peerUri: String,
newMessage: TextFieldValue,
onNewMessageChange: (TextFieldValue) -> Unit,
addMessage: (message: Message) -> Unit
) {
val aor = account.aor
val ua = UserAgent.ofAor(aor)!!
val newMessage = rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue(viewModel.getAorPeerMessage(aor, peerUri)))
}
var textFieldLoaded by remember { mutableStateOf(false) }
val focusRequester = remember { FocusRequester() }
@ -512,10 +510,11 @@ private fun NewMessage(
) {
val keyboardController = LocalSoftwareKeyboardController.current
OutlinedTextField(
value = newMessage,
value = newMessage.value,
placeholder = { Text(stringResource(R.string.new_message)) },
onValueChange = { newValue ->
onNewMessageChange(newValue)
onValueChange = {
newMessage.value = it
viewModel.updateAorPeerMessage(aor, peerUri, it.text)
},
modifier = Modifier
.weight(1f)
@ -528,12 +527,13 @@ private fun NewMessage(
},
singleLine = false,
trailingIcon = {
if (newMessage.text.isNotEmpty()) {
if (newMessage.value.text.isNotEmpty()) {
Icon(
Icons.Outlined.Clear,
contentDescription = "Clear",
modifier = Modifier.clickable {
onNewMessageChange(TextFieldValue(""))
newMessage.value = TextFieldValue("")
viewModel.updateAorPeerMessage(aor, peerUri, "")
}
)
} },
@ -546,7 +546,7 @@ private fun NewMessage(
)
)
LaunchedEffect(Unit) {
if (newMessage.text.isNotEmpty())
if (newMessage.value.text.isNotEmpty())
focusRequester.requestFocus()
}
Image(
@ -556,7 +556,7 @@ private fun NewMessage(
modifier = Modifier
.size(36.dp)
.clickable {
val msgText = newMessage.text
val msgText = newMessage.value.text
if (msgText.isNotEmpty()) {
keyboardController?.hide()
val time = System.currentTimeMillis()
@ -595,7 +595,8 @@ private fun NewMessage(
msg.direction = MESSAGE_UP_FAIL
msg.responseReason = ctx.getString(R.string.message_failed)
} else {
onNewMessageChange(TextFieldValue(""))
newMessage.value = TextFieldValue("")
viewModel.updateAorPeerMessage(aor, peerUri, "")
keyboardController?.hide()
}
}

View File

@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import androidx.compose.runtime.State
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
@ -31,32 +31,33 @@ class ViewModel(application: Application) : AndroidViewModel(application) {
_selectedAor.value = newValue
}
private val _aorPeerMessage = MutableStateFlow(mutableMapOf<AorPeer, TextFieldValue>())
val aorPeerMessage: StateFlow<Map<AorPeer, TextFieldValue>> = _aorPeerMessage.asStateFlow()
private val _aorPeerMessage = MutableStateFlow(mutableMapOf<AorPeer, String>())
fun updateAorPeerMessage(aor: String, peerUri: String, value: TextFieldValue) {
fun updateAorPeerMessage(aor: String, peerUri: String, message: String) {
val key = AorPeer(aor, peerUri)
val newMap = _aorPeerMessage.value.toMutableMap()
if (value.text.isEmpty())
newMap.remove(key)
if (message == "")
_aorPeerMessage.value.remove(key)
else
newMap[key] = value
_aorPeerMessage.value = newMap
_aorPeerMessage.value[key] = message
}
private val _showKeyboard = mutableStateOf(0)
fun getAorPeerMessage(aor: String, peerUri: String): String {
val key = AorPeer(aor, peerUri)
return _aorPeerMessage.value.getOrDefault(key, "")
}
private val _showKeyboard = mutableIntStateOf(0)
val showKeyboard: State<Int> = _showKeyboard
fun requestShowKeyboard() {
_showKeyboard.value++
_showKeyboard.intValue++
}
private val _hideKeyboard = mutableStateOf(0)
private val _hideKeyboard = mutableIntStateOf(0)
val hideKeyboard: State<Int> = _hideKeyboard
fun requestHideKeyboard() {
_hideKeyboard.value++
_hideKeyboard.intValue++
}
private val _speakerIcon = MutableStateFlow(R.drawable.speaker_off)