Split MAX bot loops and make chats cache-first
This commit is contained in:
@@ -80,7 +80,7 @@ class QMaxApi {
|
||||
}
|
||||
|
||||
suspend fun messages(sessionServerUrl: String, token: String, chatId: String): List<MessageDto> {
|
||||
return get(sessionServerUrl, "/api/chats/$chatId/messages", token)
|
||||
return get(sessionServerUrl, "/api/chats/$chatId/messages?sync=false", token)
|
||||
}
|
||||
|
||||
suspend fun markChatRead(sessionServerUrl: String, token: String, chatId: String) {
|
||||
|
||||
@@ -23,6 +23,8 @@ import xyz.kusoft.qmax.core.model.QMaxSession
|
||||
import xyz.kusoft.qmax.core.network.QMaxHttpException
|
||||
import xyz.kusoft.qmax.core.realtime.QMaxRealtimeClient
|
||||
import java.io.File
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
|
||||
data class QMaxUiState(
|
||||
val serverUrl: String = BuildConfig.QMAX_DEFAULT_SERVER_URL,
|
||||
@@ -328,7 +330,7 @@ class QMaxViewModel(private val repository: QMaxRepository) : ViewModel() {
|
||||
}
|
||||
realtime.joinChat(chat.id)
|
||||
}
|
||||
loadMessages(showLoading = true)
|
||||
loadMessages(showLoading = false)
|
||||
presencePollJob?.cancel()
|
||||
presencePollJob = viewModelScope.launch {
|
||||
while (state.value.selectedChat?.id == chat.id) {
|
||||
@@ -574,7 +576,45 @@ class QMaxViewModel(private val repository: QMaxRepository) : ViewModel() {
|
||||
val sentMessages = mutableListOf<MessageDto>()
|
||||
|
||||
if (attachmentUris.isEmpty()) {
|
||||
sentMessages += repository.sendMessage(session, chat.id, text, replyToMessageId)
|
||||
val pending = pendingTextMessage(chat.id, text, replyToMessageId)
|
||||
repository.cacheRealtimeMessage(session, pending)
|
||||
repository.clearDraft(chat.id)
|
||||
val current = state.value
|
||||
if (current.selectedChat?.id == chat.id) {
|
||||
state.value = current.copy(
|
||||
composerText = "",
|
||||
replyTarget = null,
|
||||
messages = upsertMessage(current.messages, pending)
|
||||
)
|
||||
}
|
||||
onSuccess()
|
||||
|
||||
try {
|
||||
val sent = repository.sendMessage(session, chat.id, text, replyToMessageId)
|
||||
repository.deleteCachedMessage(session, chat.id, pending.id)
|
||||
repository.cacheRealtimeMessage(session, sent)
|
||||
val afterSend = state.value
|
||||
if (afterSend.selectedChat?.id == chat.id) {
|
||||
state.value = afterSend.copy(
|
||||
messages = replaceMessage(afterSend.messages, pending.id, sent)
|
||||
)
|
||||
}
|
||||
loadChats()
|
||||
} catch (error: Throwable) {
|
||||
val failed = pending.copy(
|
||||
deliveryState = "Failed",
|
||||
error = error.message ?: "\u041e\u0448\u0438\u0431\u043a\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438"
|
||||
)
|
||||
repository.cacheRealtimeMessage(session, failed)
|
||||
val afterFailure = state.value
|
||||
if (afterFailure.selectedChat?.id == chat.id) {
|
||||
state.value = afterFailure.copy(
|
||||
messages = replaceMessage(afterFailure.messages, pending.id, failed)
|
||||
)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
return@launchLoading
|
||||
} else {
|
||||
attachmentUris.forEachIndexed { index, uri ->
|
||||
val caption = text.takeIf { index == 0 && it.isNotBlank() }
|
||||
@@ -1101,6 +1141,23 @@ class QMaxViewModel(private val repository: QMaxRepository) : ViewModel() {
|
||||
return (messages.filterNot { it.id == message.id } + message).sortedBy { it.sentAt }
|
||||
}
|
||||
|
||||
private fun replaceMessage(messages: List<MessageDto>, oldMessageId: String, message: MessageDto): List<MessageDto> {
|
||||
return (messages.filterNot { it.id == oldMessageId || it.id == message.id } + message).sortedBy { it.sentAt }
|
||||
}
|
||||
|
||||
private fun pendingTextMessage(chatId: String, text: String, replyToMessageId: String?): MessageDto {
|
||||
return MessageDto(
|
||||
id = "local-${UUID.randomUUID()}",
|
||||
chatId = chatId,
|
||||
senderName = "You",
|
||||
direction = "Outgoing",
|
||||
text = text,
|
||||
sentAt = OffsetDateTime.now().toString(),
|
||||
replyToMessageId = replyToMessageId,
|
||||
deliveryState = "Sending"
|
||||
)
|
||||
}
|
||||
|
||||
private fun normalizeChats(
|
||||
chats: List<ChatDto>,
|
||||
selectedChatId: String? = state.value.selectedChat?.id
|
||||
|
||||
Reference in New Issue
Block a user