mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Fix public chat message sending and Theme switches disappearing
This commit is contained in:
@@ -231,8 +231,7 @@ fun ChatScreen(
|
||||
"newMessage", "messageEdited", "messageDeleted",
|
||||
"dmNew", "dmEdited", "dmDeleted",
|
||||
"typing", "stopTyping", "dmTyping", "stopDmTyping", "suspended", "account_deleted" -> {
|
||||
Logger.d("ChatScreen", "Launching handleWebSocketMessage for ${update.type}")
|
||||
scope.launch {
|
||||
Logger.d("ChatScreen", "handleWebSocketMessage for ${update.type}")
|
||||
try {
|
||||
panel.handleWebSocketMessage(wsMessage)
|
||||
} catch (e: Exception) {
|
||||
@@ -241,7 +240,6 @@ fun ChatScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Logger.e("ChatScreen", "Error parsing updates message: ${e.message}", e)
|
||||
e.printStackTrace()
|
||||
@@ -259,6 +257,11 @@ fun ChatScreen(
|
||||
panel.handleWebSocketMessage(message)
|
||||
}
|
||||
}
|
||||
"sendMessage" -> {
|
||||
scope.launch {
|
||||
panel.handleWebSocketMessage(message)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Logger.d("ChatScreen", "Unhandled top-level WebSocket message type: ${message.type}")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import ru.fromchat.api.ApiClient
|
||||
import ru.fromchat.api.Message
|
||||
import ru.fromchat.api.MessageDeletedData
|
||||
import ru.fromchat.api.ReactionUpdateData
|
||||
import ru.fromchat.api.SendMessageResponse
|
||||
import ru.fromchat.api.TypingUpdateData
|
||||
import ru.fromchat.api.WebSocketMessage
|
||||
import ru.fromchat.api.WebSocketUpdatesData
|
||||
@@ -65,6 +66,42 @@ class PublicChatPanel(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server often omits [Message.client_message_id] on broadcast [newMessage] / [SendMessageResponse.message].
|
||||
* Match the oldest pending optimistic row (same user, text, reply) and replace it; otherwise append.
|
||||
*/
|
||||
private suspend fun confirmIncomingOwnMessageOrAdd(newMsg: Message) {
|
||||
val uid = currentUserId
|
||||
if (uid == null) {
|
||||
addMessage(newMsg)
|
||||
return
|
||||
}
|
||||
if (newMsg.user_id != uid) {
|
||||
addMessage(newMsg)
|
||||
return
|
||||
}
|
||||
if (newMsg.client_message_id != null) {
|
||||
handleMessageConfirmed(newMsg.client_message_id, newMsg)
|
||||
return
|
||||
}
|
||||
if (newMsg.id <= 0) {
|
||||
addMessage(newMsg)
|
||||
return
|
||||
}
|
||||
val pending = _state.messages.firstOrNull { msg ->
|
||||
msg.id < 0 &&
|
||||
msg.user_id == uid &&
|
||||
msg.client_message_id != null &&
|
||||
msg.content == newMsg.content &&
|
||||
msg.reply_to?.id == newMsg.reply_to?.id
|
||||
}
|
||||
if (pending?.client_message_id != null) {
|
||||
handleMessageConfirmed(pending.client_message_id, newMsg)
|
||||
} else {
|
||||
addMessage(newMsg)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sendMessage(content: String, replyToId: Int?, clientMessageId: String?) {
|
||||
ApiClient.sendMessage(content, replyToId, clientMessageId)
|
||||
}
|
||||
@@ -185,12 +222,18 @@ class PublicChatPanel(
|
||||
val data = updateMessage.data ?: return
|
||||
val newMsg = json.decodeFromJsonElement(Message.serializer(), data)
|
||||
Logger.d("PublicChatPanel", "New message received: id=${newMsg.id}, content=${newMsg.content.take(50)}")
|
||||
|
||||
if (newMsg.client_message_id != null && newMsg.user_id == currentUserId) {
|
||||
handleMessageConfirmed(newMsg.client_message_id, newMsg)
|
||||
} else {
|
||||
addMessage(newMsg)
|
||||
confirmIncomingOwnMessageOrAdd(newMsg)
|
||||
}
|
||||
"sendMessage" -> {
|
||||
val data = updateMessage.data ?: return
|
||||
val resp = json.decodeFromJsonElement(SendMessageResponse.serializer(), data)
|
||||
if (!resp.status.equals("success", ignoreCase = true)) return
|
||||
val confirmed = resp.message
|
||||
Logger.d(
|
||||
"PublicChatPanel",
|
||||
"sendMessage ack: id=${confirmed.id}, clientId=${confirmed.client_message_id}"
|
||||
)
|
||||
confirmIncomingOwnMessageOrAdd(confirmed)
|
||||
}
|
||||
"messageEdited" -> {
|
||||
val data = updateMessage.data ?: return
|
||||
|
||||
@@ -111,6 +111,7 @@ fun SettingsTab(
|
||||
Settings.materialYou && materialYouAvailable
|
||||
)
|
||||
}
|
||||
var themeChipIndex by remember { mutableIntStateOf(Settings.theme.ordinal) }
|
||||
|
||||
Category(Modifier.padding(top = 16.dp)) {
|
||||
// Material You
|
||||
@@ -146,7 +147,6 @@ fun SettingsTab(
|
||||
},
|
||||
bottomContent = {
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
var selectedIndex by remember { mutableIntStateOf(Settings.theme.ordinal) }
|
||||
val options = listOf(
|
||||
stringResource(Res.string.as_system),
|
||||
stringResource(Res.string.light),
|
||||
@@ -155,11 +155,11 @@ fun SettingsTab(
|
||||
options.forEachIndexed { index, label ->
|
||||
FilterChip(
|
||||
onClick = {
|
||||
selectedIndex = index
|
||||
themeChipIndex = index
|
||||
Settings.theme = Theme.entries[index]
|
||||
theme = Theme.entries[index]
|
||||
},
|
||||
selected = index == selectedIndex,
|
||||
selected = index == themeChipIndex,
|
||||
leadingIcon = {
|
||||
if (index == 0) {
|
||||
Spacer(Modifier.width(16.dp))
|
||||
|
||||
@@ -111,7 +111,7 @@ fun ListItem(
|
||||
onClick: (() -> Unit)? = null,
|
||||
bodyOnClick: (() -> Unit)? = null,
|
||||
leadingAndBodyShared: Boolean = false,
|
||||
bottomContent: (@Composable ConstraintLayoutScope.() -> Unit)? = null
|
||||
bottomContent: (@Composable () -> Unit)? = null
|
||||
) {
|
||||
Column {
|
||||
@Composable
|
||||
@@ -244,7 +244,7 @@ fun ListItem(
|
||||
)
|
||||
}
|
||||
if (bottomContent != null) {
|
||||
ConstraintLayout(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.constrainAs(btm) {
|
||||
bottom link parent.bottom
|
||||
@@ -252,9 +252,10 @@ fun ListItem(
|
||||
right link parent.right
|
||||
width = Dimension.fillToConstraints
|
||||
}
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp),
|
||||
content = bottomContent
|
||||
)
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
|
||||
) {
|
||||
bottomContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,11 +305,17 @@ inline fun SwitchListItem(
|
||||
supportingText = supportingText,
|
||||
leadingContent = leadingContent,
|
||||
trailingContent = {
|
||||
val (sw) = createRefs()
|
||||
Switch(
|
||||
checked = checked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
interactionSource = interactionSource,
|
||||
enabled = enabled
|
||||
enabled = enabled,
|
||||
modifier = Modifier.constrainAs(sw) {
|
||||
top link parent.top
|
||||
bottom link parent.bottom
|
||||
right link parent.right
|
||||
}
|
||||
)
|
||||
},
|
||||
divider = divider,
|
||||
|
||||
Reference in New Issue
Block a user