From c380c1a73d0b37567924543c8bbfebced0ecde84 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 14 May 2026 18:06:54 +0300 Subject: [PATCH] refactor: split message event handlers --- .../fast/domain/LongPollEventDispatcher.kt | 36 ++++ .../fast/domain/LongPollUpdatesParser.kt | 115 ++++------- .../MessagesHistoryLongPollEventHandler.kt | 158 ++++++++++++++++ .../MessagesHistoryViewModelImpl.kt | 178 ++---------------- 4 files changed, 251 insertions(+), 236 deletions(-) create mode 100644 core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventDispatcher.kt create mode 100644 feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryLongPollEventHandler.kt diff --git a/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventDispatcher.kt b/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventDispatcher.kt new file mode 100644 index 00000000..b3b5af56 --- /dev/null +++ b/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventDispatcher.kt @@ -0,0 +1,36 @@ +package dev.meloda.fast.domain + +import dev.meloda.fast.model.LongPollEvent +import dev.meloda.fast.model.LongPollParsedEvent + +internal class LongPollEventDispatcher { + private val listenersMap: MutableMap>> = + mutableMapOf() + + @Suppress("UNCHECKED_CAST") + fun dispatch(eventType: LongPollEvent, event: T) { + listenersMap[eventType]?.forEach { callback -> + (callback as? VkEventCallback)?.onEvent(event) + } + } + + fun dispatchAll(eventType: LongPollEvent, events: List) { + events.forEach { event -> dispatch(eventType, event) } + } + + @Suppress("UNCHECKED_CAST") + fun registerListener( + eventType: LongPollEvent, + listener: VkEventCallback + ) { + listenersMap[eventType] = (listenersMap[eventType] ?: mutableListOf()) + .also { it.add(listener as VkEventCallback) } + } + + fun registerListeners( + eventTypes: List, + listener: VkEventCallback + ) { + eventTypes.forEach { eventType -> registerListener(eventType, listener) } + } +} diff --git a/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollUpdatesParser.kt b/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollUpdatesParser.kt index ea7dc5c6..4cf085f9 100644 --- a/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollUpdatesParser.kt +++ b/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollUpdatesParser.kt @@ -43,20 +43,7 @@ class LongPollUpdatesParser( get() = Dispatchers.Default + job + exceptionHandler private val coroutineScope = CoroutineScope(coroutineContext) - - private val listenersMap: MutableMap>> = - mutableMapOf() - - @Suppress("UNCHECKED_CAST") - private fun dispatch(eventType: LongPollEvent, event: T) { - listenersMap[eventType]?.forEach { callback -> - (callback as? VkEventCallback)?.onEvent(event) - } - } - - private fun dispatchAll(eventType: LongPollEvent, events: List) { - events.forEach { event -> dispatch(eventType, event) } - } + private val eventDispatcher = LongPollEventDispatcher() fun parseNextUpdate(event: List) { val eventId = event.first().asInt() @@ -107,7 +94,7 @@ class LongPollUpdatesParser( marked = true ) eventsToSend += eventToSend - dispatch(LongPollEvent.MARKED_AS_IMPORTANT, eventToSend) + eventDispatcher.dispatch(LongPollEvent.MARKED_AS_IMPORTANT, eventToSend) } MessageFlags.SPAM -> { @@ -116,7 +103,7 @@ class LongPollUpdatesParser( cmId = cmId ) eventsToSend += eventToSend - dispatch(LongPollEvent.MARKED_AS_SPAM, eventToSend) + eventDispatcher.dispatch(LongPollEvent.MARKED_AS_SPAM, eventToSend) } MessageFlags.DELETED -> { @@ -135,7 +122,7 @@ class LongPollUpdatesParser( ) } eventsToSend += eventToSend - dispatch(LongPollEvent.MESSAGE_DELETED, eventToSend) + eventDispatcher.dispatch(LongPollEvent.MESSAGE_DELETED, eventToSend) } MessageFlags.AUDIO_LISTENED -> { @@ -144,14 +131,14 @@ class LongPollUpdatesParser( cmId = cmId ) eventsToSend += eventToSend - dispatch(LongPollEvent.AUDIO_MESSAGE_LISTENED, eventToSend) + eventDispatcher.dispatch(LongPollEvent.AUDIO_MESSAGE_LISTENED, eventToSend) } else -> Unit } } - dispatchAll(LongPollEvent.MESSAGE_SET_FLAGS, eventsToSend) + eventDispatcher.dispatchAll(LongPollEvent.MESSAGE_SET_FLAGS, eventsToSend) } private fun parseMessageClearFlags(eventType: ApiEvent, event: List) { @@ -175,7 +162,7 @@ class LongPollUpdatesParser( marked = false ) eventsToSend += eventToSend - dispatch(LongPollEvent.MARKED_AS_IMPORTANT, eventToSend) + eventDispatcher.dispatch(LongPollEvent.MARKED_AS_IMPORTANT, eventToSend) } MessageFlags.SPAM -> { @@ -189,7 +176,7 @@ class LongPollUpdatesParser( val eventToSend = LongPollParsedEvent.MessageMarkedAsNotSpam(message = message) eventsToSend += eventToSend - dispatch(LongPollEvent.MARKED_AS_NOT_SPAM, eventToSend) + eventDispatcher.dispatch(LongPollEvent.MARKED_AS_NOT_SPAM, eventToSend) } } } @@ -205,7 +192,7 @@ class LongPollUpdatesParser( val eventToSend = LongPollParsedEvent.MessageRestored(message = message) eventsToSend += eventToSend - dispatch(LongPollEvent.MESSAGE_RESTORED, eventToSend) + eventDispatcher.dispatch(LongPollEvent.MESSAGE_RESTORED, eventToSend) } } } @@ -214,7 +201,7 @@ class LongPollUpdatesParser( } } - dispatchAll(LongPollEvent.MESSAGE_CLEAR_FLAGS, eventsToSend) + eventDispatcher.dispatchAll(LongPollEvent.MESSAGE_CLEAR_FLAGS, eventsToSend) } } @@ -238,7 +225,7 @@ class LongPollUpdatesParser( }.await() message?.let { - dispatch( + eventDispatcher.dispatch( LongPollEvent.MESSAGE_NEW, LongPollParsedEvent.NewMessage( message = message, @@ -263,7 +250,7 @@ class LongPollUpdatesParser( peerId = peerId, cmId = cmId )?.let { message -> - dispatch(LongPollEvent.MESSAGE_EDITED, LongPollParsedEvent.MessageEdited(message)) + eventDispatcher.dispatch(LongPollEvent.MESSAGE_EDITED, LongPollParsedEvent.MessageEdited(message)) } } } @@ -274,7 +261,7 @@ class LongPollUpdatesParser( val cmId = event[2].asLong() val unreadCount = event[3].asInt() - dispatch( + eventDispatcher.dispatch( LongPollEvent.INCOMING_MESSAGE_READ, LongPollParsedEvent.IncomingMessageRead( peerId = peerId, @@ -290,7 +277,7 @@ class LongPollUpdatesParser( val cmId = event[2].asLong() val unreadCount = event[3].asInt() - dispatch( + eventDispatcher.dispatch( LongPollEvent.OUTGOING_MESSAGE_READ, LongPollParsedEvent.OutgoingMessageRead( peerId = peerId, @@ -330,14 +317,14 @@ class LongPollUpdatesParser( archived = false ) eventsToSend += eventToSend - dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend) + eventDispatcher.dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend) } else -> Unit } } - dispatchAll(LongPollEvent.CHAT_CLEAR_FLAGS, eventsToSend) + eventDispatcher.dispatchAll(LongPollEvent.CHAT_CLEAR_FLAGS, eventsToSend) } } @@ -371,14 +358,14 @@ class LongPollUpdatesParser( archived = true ) eventsToSend += eventToSend - dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend) + eventDispatcher.dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend) } else -> Unit } } - dispatchAll(LongPollEvent.CHAT_SET_FLAGS, eventsToSend) + eventDispatcher.dispatchAll(LongPollEvent.CHAT_SET_FLAGS, eventsToSend) } } @@ -388,7 +375,7 @@ class LongPollUpdatesParser( val peerId = event[1].asLong() val cmId = event[2].asLong() - dispatch( + eventDispatcher.dispatch( LongPollEvent.CHAT_CLEARED, LongPollParsedEvent.ChatCleared( peerId = peerId, @@ -403,7 +390,7 @@ class LongPollUpdatesParser( val peerId = event[1].asLong() val majorId = event[2].asInt() - dispatch( + eventDispatcher.dispatch( LongPollEvent.CHAT_MAJOR_CHANGED, LongPollParsedEvent.ChatMajorChanged( peerId = peerId, @@ -418,7 +405,7 @@ class LongPollUpdatesParser( val peerId = event[1].asLong() val minorId = event[2].asInt() - dispatch( + eventDispatcher.dispatch( LongPollEvent.CHAT_MINOR_CHANGED, LongPollParsedEvent.ChatMinorChanged( peerId = peerId, @@ -456,7 +443,7 @@ class LongPollUpdatesParser( // if userIds contains only account's id, then we don't need to show our status if (userIds.isEmpty()) return - dispatch( + eventDispatcher.dispatch( longPollEvent, LongPollParsedEvent.Interaction( interactionType = interactionType, @@ -479,7 +466,7 @@ class LongPollUpdatesParser( val archiveUnreadUnmutedCount = event[8].asInt() val archiveMentionsCount = event[9].asInt() - dispatch( + eventDispatcher.dispatch( LongPollEvent.UNREAD_COUNTER_UPDATE, LongPollParsedEvent.UnreadCounter( unread = unreadCount, @@ -504,7 +491,7 @@ class LongPollUpdatesParser( peerId = peerId, cmId = cmId )?.let { message -> - dispatch(LongPollEvent.MESSAGE_UPDATED, LongPollParsedEvent.MessageUpdated(message)) + eventDispatcher.dispatch(LongPollEvent.MESSAGE_UPDATED, LongPollParsedEvent.MessageUpdated(message)) } } } @@ -516,7 +503,7 @@ class LongPollUpdatesParser( coroutineScope.launch(Dispatchers.IO) { loadMessage(messageId = messageId)?.let { message -> - dispatch( + eventDispatcher.dispatch( LongPollEvent.MESSAGE_CACHE_CLEAR, LongPollParsedEvent.MessageCacheClear(message) ) @@ -587,88 +574,68 @@ class LongPollUpdatesParser( } } - @Suppress("UNCHECKED_CAST") - private fun registerListener( - eventType: LongPollEvent, - listener: VkEventCallback - ) { - listenersMap.let { map -> - map[eventType] = (map[eventType] ?: mutableListOf()) - .also { - it.add(listener as VkEventCallback) - } - } - } - - private fun registerListeners( - eventTypes: List, - listener: VkEventCallback - ) { - eventTypes.forEach { eventType -> registerListener(eventType, listener) } - } - fun onMessageSetFlags(block: (LongPollParsedEvent) -> Unit) { - registerListener(LongPollEvent.MESSAGE_SET_FLAGS, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MESSAGE_SET_FLAGS, assembleEventCallback(block)) } fun onMessageMarkedAsImportant(block: (LongPollParsedEvent.MessageMarkedAsImportant) -> Unit) { - registerListener(LongPollEvent.MARKED_AS_IMPORTANT, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MARKED_AS_IMPORTANT, assembleEventCallback(block)) } fun onMessageMarkedAsSpam(block: (LongPollParsedEvent.MessageMarkedAsSpam) -> Unit) { - registerListener(LongPollEvent.MARKED_AS_SPAM, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MARKED_AS_SPAM, assembleEventCallback(block)) } fun onMessageDeleted(block: (LongPollParsedEvent.MessageDeleted) -> Unit) { - registerListener(LongPollEvent.MESSAGE_DELETED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MESSAGE_DELETED, assembleEventCallback(block)) } fun onMessageClearFlags(block: (LongPollParsedEvent) -> Unit) { - registerListener(LongPollEvent.MESSAGE_CLEAR_FLAGS, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MESSAGE_CLEAR_FLAGS, assembleEventCallback(block)) } fun onMessageMarkedAsNotSpam(block: (LongPollParsedEvent.MessageMarkedAsNotSpam) -> Unit) { - registerListener(LongPollEvent.MARKED_AS_NOT_SPAM, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MARKED_AS_NOT_SPAM, assembleEventCallback(block)) } fun onMessageRestored(block: (LongPollParsedEvent.MessageRestored) -> Unit) { - registerListener(LongPollEvent.MESSAGE_RESTORED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MESSAGE_RESTORED, assembleEventCallback(block)) } fun onNewMessage(block: (LongPollParsedEvent.NewMessage) -> Unit) { - registerListener(LongPollEvent.MESSAGE_NEW, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MESSAGE_NEW, assembleEventCallback(block)) } fun onMessageEdited(block: (LongPollParsedEvent.MessageEdited) -> Unit) { - registerListener(LongPollEvent.MESSAGE_EDITED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.MESSAGE_EDITED, assembleEventCallback(block)) } fun onMessageIncomingRead(block: (LongPollParsedEvent.IncomingMessageRead) -> Unit) { - registerListener(LongPollEvent.INCOMING_MESSAGE_READ, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.INCOMING_MESSAGE_READ, assembleEventCallback(block)) } fun onMessageOutgoingRead(block: (LongPollParsedEvent.OutgoingMessageRead) -> Unit) { - registerListener(LongPollEvent.OUTGOING_MESSAGE_READ, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.OUTGOING_MESSAGE_READ, assembleEventCallback(block)) } fun onChatCleared(block: (LongPollParsedEvent.ChatCleared) -> Unit) { - registerListener(LongPollEvent.CHAT_CLEARED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.CHAT_CLEARED, assembleEventCallback(block)) } fun onChatMajorChanged(block: (LongPollParsedEvent.ChatMajorChanged) -> Unit) { - registerListener(LongPollEvent.CHAT_MAJOR_CHANGED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.CHAT_MAJOR_CHANGED, assembleEventCallback(block)) } fun onChatMinorChanged(block: (LongPollParsedEvent.ChatMinorChanged) -> Unit) { - registerListener(LongPollEvent.CHAT_MINOR_CHANGED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.CHAT_MINOR_CHANGED, assembleEventCallback(block)) } fun onChatArchived(block: (LongPollParsedEvent.ChatArchived) -> Unit) { - registerListener(LongPollEvent.CHAT_ARCHIVED, assembleEventCallback(block)) + eventDispatcher.registerListener(LongPollEvent.CHAT_ARCHIVED, assembleEventCallback(block)) } fun onInteractions(block: (LongPollParsedEvent.Interaction) -> Unit) { - registerListeners( + eventDispatcher.registerListeners( eventTypes = listOf( LongPollEvent.TYPING, LongPollEvent.AUDIO_MESSAGE_RECORDING, diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryLongPollEventHandler.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryLongPollEventHandler.kt new file mode 100644 index 00000000..b8020390 --- /dev/null +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryLongPollEventHandler.kt @@ -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, + private val messages: MutableStateFlow>, + 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.sorted(): List { + return sortedWith { m1, m2 -> + val dateDiff = m2.date - m1.date + if (dateDiff != 0) { + dateDiff + } else { + val idDiff = m2.id - m1.id + idDiff.toInt() + } + } + } +} diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModelImpl.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModelImpl.kt index ea853850..7382324a 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModelImpl.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModelImpl.kt @@ -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()")