refactor: split message event handlers

This commit is contained in:
Codex
2026-05-14 18:06:54 +03:00
parent 2bf81c60d6
commit c380c1a73d
4 changed files with 251 additions and 236 deletions
@@ -0,0 +1,158 @@
package dev.meloda.fast.messageshistory
import android.util.Log
import com.conena.nanokt.collections.indexOfFirstOrNull
import dev.meloda.fast.common.extensions.setValue
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
import dev.meloda.fast.model.LongPollParsedEvent
import dev.meloda.fast.model.api.domain.VkMessage
import kotlinx.coroutines.flow.MutableStateFlow
import kotlin.math.abs
internal class MessagesHistoryLongPollEventHandler(
private val screenState: MutableStateFlow<MessagesHistoryScreenState>,
private val messages: MutableStateFlow<List<VkMessage>>,
private val syncUiMessages: () -> Unit
) {
fun onNewMessage(event: LongPollParsedEvent.NewMessage) {
val message = event.message
Log.d("MessagesHistoryViewModel", "handleNewMessage: $message")
if (message.peerId != screenState.value.convoId) return
if (messages.value.indexOfFirstOrNull { it.id == message.id } != null) return
val randomIds = messages.value.map(VkMessage::randomId)
if (message.randomId != 0L && message.randomId in randomIds) return
val newMessages = messages.value.toMutableList()
newMessages.add(0, message)
messages.setValue { newMessages }
syncUiMessages()
}
fun onMessageEdited(event: LongPollParsedEvent.MessageEdited) {
val message = event.message
if (message.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.id == message.id }
if (index == null) {
return
}
newMessages[index] = message
messages.setValue { newMessages }
syncUiMessages()
}
fun onReadIncoming(event: LongPollParsedEvent.IncomingMessageRead) {
if (event.peerId != screenState.value.convoId) return
val index = messages.value.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) return
val newConvo = screenState.value.convo.copy(
inReadCmId = event.cmId
)
screenState.setValue { old ->
old.copy(convo = newConvo)
}
syncUiMessages()
}
fun onReadOutgoing(event: LongPollParsedEvent.OutgoingMessageRead) {
if (event.peerId != screenState.value.convoId) return
val index = messages.value.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) return
val newConvo = screenState.value.convo.copy(
outReadCmId = event.cmId
)
screenState.setValue { old ->
old.copy(convo = newConvo)
}
syncUiMessages()
}
fun onMessageDeleted(event: LongPollParsedEvent.MessageDeleted) {
if (event.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) return
newMessages.removeAt(index)
messages.setValue { newMessages }
syncUiMessages()
}
fun onMessageRestored(event: LongPollParsedEvent.MessageRestored) {
if (event.message.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val minDate = newMessages.minOf(VkMessage::date)
if (event.message.date < minDate) return
newMessages.add(event.message)
messages.setValue { newMessages.sorted() }
syncUiMessages()
}
fun onMessageMarkedAsImportant(event: LongPollParsedEvent.MessageMarkedAsImportant) {
if (event.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) return
newMessages[index] = newMessages[index].copy(isImportant = event.marked)
messages.setValue { newMessages }
syncUiMessages()
}
fun onMessageMarkedAsSpam(event: LongPollParsedEvent.MessageMarkedAsSpam) {
if (event.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) return
newMessages.removeAt(index)
messages.setValue { newMessages }
syncUiMessages()
}
fun onMessageMarkedAsNotSpam(event: LongPollParsedEvent.MessageMarkedAsNotSpam) {
if (event.message.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val maxDate = newMessages.maxOf(VkMessage::date)
val minDate = newMessages.minOf(VkMessage::date)
if (event.message.date !in minDate..maxDate) return
newMessages.add(event.message)
messages.setValue { newMessages.sorted() }
syncUiMessages()
}
private fun List<VkMessage>.sorted(): List<VkMessage> {
return sortedWith { m1, m2 ->
val dateDiff = m2.date - m1.date
if (dateDiff != 0) {
dateDiff
} else {
val idDiff = m2.id - m1.id
idDiff.toInt()
}
}
}
}
@@ -58,7 +58,6 @@ import dev.meloda.fast.messageshistory.model.MessageOption
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
import dev.meloda.fast.messageshistory.navigation.MessagesHistory
import dev.meloda.fast.model.BaseError
import dev.meloda.fast.model.LongPollParsedEvent
import dev.meloda.fast.model.api.domain.FormatDataType
import dev.meloda.fast.model.api.domain.VkMessage
import dev.meloda.fast.model.api.domain.VkPhotoDomain
@@ -120,6 +119,13 @@ class MessagesHistoryViewModelImpl(
private var editMessage: VkMessage? = null
private val longPollEventHandler = MessagesHistoryLongPollEventHandler(
screenState = screenState,
messages = messages
) {
syncUiMessages()
}
init {
val arguments = MessagesHistory.from(savedStateHandle).arguments
@@ -128,15 +134,15 @@ class MessagesHistoryViewModelImpl(
loadConvo()
loadMessagesHistory()
updatesParser.onNewMessage(::handleNewMessage)
updatesParser.onMessageEdited(::handleEditedMessage)
updatesParser.onMessageIncomingRead(::handleReadIncomingEvent)
updatesParser.onMessageOutgoingRead(::handleReadOutgoingEvent)
updatesParser.onMessageDeleted(::handleMessageDeleted)
updatesParser.onMessageRestored(::handleMessageRestored)
updatesParser.onMessageMarkedAsImportant(::handleMessageMarkedAsImportant)
updatesParser.onMessageMarkedAsSpam(::handleMessageMarkedAsSpam)
updatesParser.onMessageMarkedAsNotSpam(::handleMessageMarkedAsNotSpam)
updatesParser.onNewMessage(longPollEventHandler::onNewMessage)
updatesParser.onMessageEdited(longPollEventHandler::onMessageEdited)
updatesParser.onMessageIncomingRead(longPollEventHandler::onReadIncoming)
updatesParser.onMessageOutgoingRead(longPollEventHandler::onReadOutgoing)
updatesParser.onMessageDeleted(longPollEventHandler::onMessageDeleted)
updatesParser.onMessageRestored(longPollEventHandler::onMessageRestored)
updatesParser.onMessageMarkedAsImportant(longPollEventHandler::onMessageMarkedAsImportant)
updatesParser.onMessageMarkedAsSpam(longPollEventHandler::onMessageMarkedAsSpam)
updatesParser.onMessageMarkedAsNotSpam(longPollEventHandler::onMessageMarkedAsNotSpam)
}
override fun onNavigationConsumed() {
@@ -685,158 +691,6 @@ class MessagesHistoryViewModelImpl(
}
}
private fun handleNewMessage(event: LongPollParsedEvent.NewMessage) {
val message = event.message
Log.d("MessagesHistoryViewModel", "handleNewMessage: $message")
if (message.peerId != screenState.value.convoId) return
if (messages.value.indexOfFirstOrNull { it.id == message.id } != null) return
val randomIds = messages.value.map(VkMessage::randomId)
if (message.randomId != 0L && message.randomId in randomIds) return
val newMessages = messages.value.toMutableList()
newMessages.add(0, message)
messages.setValue { newMessages }
syncUiMessages()
}
private fun handleEditedMessage(event: LongPollParsedEvent.MessageEdited) {
val message = event.message
if (message.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.id == message.id }
if (index == null) { // сообщения нет в списке
// pizdets
} else {
newMessages[index] = message
messages.setValue { newMessages }
syncUiMessages()
}
}
private fun handleReadIncomingEvent(event: LongPollParsedEvent.IncomingMessageRead) {
if (event.peerId != screenState.value.convoId) return
val messages = messages.value
val index = messages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) { // диалога нет в списке
// pizdets
} else {
val newConvo = screenState.value.convo.copy(
inReadCmId = event.cmId
)
screenState.setValue { old ->
old.copy(convo = newConvo)
}
syncUiMessages()
}
}
private fun handleReadOutgoingEvent(event: LongPollParsedEvent.OutgoingMessageRead) {
if (event.peerId != screenState.value.convoId) return
val messages = messages.value
val index = messages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) { // сообщения нет в списке
// pizdets
} else {
val newConvo = screenState.value.convo.copy(
outReadCmId = event.cmId
)
screenState.setValue { old ->
old.copy(convo = newConvo)
}
syncUiMessages()
}
}
private fun handleMessageDeleted(event: LongPollParsedEvent.MessageDeleted) {
if (event.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) { // сообщения нет в списке
// pizdets
} else {
newMessages.removeAt(index)
messages.setValue { newMessages }
syncUiMessages()
}
}
private fun handleMessageRestored(event: LongPollParsedEvent.MessageRestored) {
if (event.message.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val minDate = newMessages.minOf(VkMessage::date)
if (event.message.date < minDate) { // сообщения не должно быть в списке
// pizdets
return
}
newMessages.add(event.message)
messages.setValue { newMessages.sorted() }
syncUiMessages()
}
private fun handleMessageMarkedAsImportant(event: LongPollParsedEvent.MessageMarkedAsImportant) {
if (event.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) { // сообщения нет в списке
// pizdets
} else {
val newMessage = newMessages[index].copy(isImportant = event.marked)
newMessages[index] = newMessage
messages.setValue { newMessages }
syncUiMessages()
}
}
private fun handleMessageMarkedAsSpam(event: LongPollParsedEvent.MessageMarkedAsSpam) {
if (event.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val index = newMessages.indexOfFirstOrNull { it.cmId == event.cmId }
if (index == null) { // сообщения нет в списке
// pizdets
} else {
newMessages.removeAt(index)
messages.setValue { newMessages }
syncUiMessages()
}
}
private fun handleMessageMarkedAsNotSpam(event: LongPollParsedEvent.MessageMarkedAsNotSpam) {
if (event.message.peerId != screenState.value.convoId) return
val newMessages = messages.value.toMutableList()
val maxDate = newMessages.maxOf(VkMessage::date)
val minDate = newMessages.minOf(VkMessage::date)
if (event.message.date !in minDate..maxDate) return
newMessages.add(event.message)
messages.setValue { newMessages.sorted() }
syncUiMessages()
}
private fun loadConvo() {
Log.d("MessagesHistoryViewModelImpl", "loadConvo()")