From 2381d4ca0a7d9f6283cc6b8297bef6360305b4ba Mon Sep 17 00:00:00 2001 From: Danil Nikolaev Date: Sat, 30 May 2026 19:54:45 +0300 Subject: [PATCH] refactor(longpoll): move event listeners into LongPollEventsHandler --- .../meloda/fast/presentation/MainActivity.kt | 3 + .../fast/domain/LongPollEventsHandler.kt | 152 ++++++++++++++- .../fast/domain/LongPollUpdatesParser.kt | 179 +----------------- .../meloda/fast/model/LongPollParsedEvent.kt | 2 +- .../dev/meloda/fast/convos/ConvosViewModel.kt | 24 +-- .../dev/meloda/fast/convos/di/ConvosModule.kt | 2 +- .../MessagesHistoryViewModelImpl.kt | 24 +-- 7 files changed, 186 insertions(+), 200 deletions(-) diff --git a/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt b/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt index ba78cfda..68f76bef 100644 --- a/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt +++ b/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt @@ -23,11 +23,13 @@ import dev.meloda.fast.MainViewModel import dev.meloda.fast.MainViewModelImpl import dev.meloda.fast.common.AppConstants import dev.meloda.fast.datastore.AppSettings +import dev.meloda.fast.domain.LongPollEventsHandler import dev.meloda.fast.logger.FastLogger import dev.meloda.fast.service.OnlineService import dev.meloda.fast.service.longpolling.LongPollingService import dev.meloda.fast.ui.R import dev.meloda.fast.ui.common.LocalLogger +import org.koin.android.ext.android.get import org.koin.androidx.compose.koinViewModel import org.koin.compose.koinInject @@ -181,6 +183,7 @@ class MainActivity : AppCompatActivity() { override fun onDestroy() { super.onDestroy() stopServices() + get().onDestroy() } companion object { diff --git a/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventsHandler.kt b/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventsHandler.kt index cb7f4748..8462f284 100644 --- a/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventsHandler.kt +++ b/core/domain/src/main/kotlin/dev/meloda/fast/domain/LongPollEventsHandler.kt @@ -3,13 +3,20 @@ package dev.meloda.fast.domain import dev.meloda.fast.database.dao.ConvoDao import dev.meloda.fast.database.dao.MessageDao import dev.meloda.fast.logger.FastLogger +import dev.meloda.fast.model.InteractionType +import dev.meloda.fast.model.LongPollEvent import dev.meloda.fast.model.LongPollParsedEvent import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import kotlin.coroutines.CoroutineContext +typealias EventListener = (event: LongPollParsedEvent) -> Unit +typealias EventListenerMap = MutableMap> + class LongPollEventsHandler( private val logger: FastLogger, private val convoUseCase: ConvoUseCase, @@ -29,8 +36,15 @@ class LongPollEventsHandler( private val coroutineScope = CoroutineScope(coroutineContext) - suspend fun handleEvents(events: List) { - events.forEach { handleNextEvent(it) } + private val listenersMap: EventListenerMap = mutableMapOf() + + fun handleEvents(events: List) { + coroutineScope.launch { + // TODO: 30.05.2026, Danil Nikolaev: switch to interactors or something else + withContext(Dispatchers.IO) { + events.forEach { handleNextEvent(it) } + } + } } private suspend fun handleNextEvent(event: LongPollParsedEvent) { @@ -88,11 +102,21 @@ class LongPollEventsHandler( } is LongPollParsedEvent.Interaction -> { + val eventType = when (event.interactionType) { + InteractionType.Typing -> LongPollEvent.TYPING + InteractionType.VoiceMessage -> LongPollEvent.AUDIO_MESSAGE_RECORDING + InteractionType.Photo -> LongPollEvent.PHOTO_UPLOADING + InteractionType.Video -> LongPollEvent.VIDEO_UPLOADING + InteractionType.File -> LongPollEvent.FILE_UPLOADING + } + emitEvent(eventType, event) } is LongPollParsedEvent.MessageCacheClear -> { messagesUseCase.storeMessage(event.message) + + emitEvent(LongPollEvent.MESSAGE_CACHE_CLEAR, event) } is LongPollParsedEvent.MessageDeleted -> { @@ -106,10 +130,14 @@ class LongPollEventsHandler( this::class, "markDeleted: updated $affectedRows rows." ) + + emitEvent(LongPollEvent.MESSAGE_DELETED, event) } is LongPollParsedEvent.MessageEdited -> { messagesUseCase.storeMessage(event.message) + + emitEvent(LongPollEvent.MESSAGE_EDITED, event) } is LongPollParsedEvent.MessageMarkedAsImportant -> { @@ -123,10 +151,14 @@ class LongPollEventsHandler( this::class, "markImportant: updated $affectedRows rows." ) + + emitEvent(LongPollEvent.MARKED_AS_IMPORTANT, event) } is LongPollParsedEvent.MessageMarkedAsNotSpam -> { messagesUseCase.storeMessage(event.message) + + emitEvent(LongPollEvent.MARKED_AS_NOT_SPAM, event) } is LongPollParsedEvent.MessageMarkedAsSpam -> { @@ -140,18 +172,26 @@ class LongPollEventsHandler( this::class, "markSpam: updated $affectedRows rows." ) + + emitEvent(LongPollEvent.MARKED_AS_SPAM, event) } is LongPollParsedEvent.MessageRestored -> { messagesUseCase.storeMessage(event.message) + + emitEvent(LongPollEvent.MESSAGE_RESTORED, event) } is LongPollParsedEvent.MessageUpdated -> { messagesUseCase.storeMessage(event.message) + + emitEvent(LongPollEvent.MESSAGE_UPDATED, event) } - is LongPollParsedEvent.NewMessage -> { + is LongPollParsedEvent.MessageNew -> { messagesUseCase.storeMessage(event.message) + + emitEvent(LongPollEvent.MESSAGE_NEW, event) } is LongPollParsedEvent.IncomingMessageRead -> { @@ -165,6 +205,8 @@ class LongPollEventsHandler( this::class, "inMessageRead: updated $affectedRows rows." ) + + emitEvent(LongPollEvent.INCOMING_MESSAGE_READ, event) } is LongPollParsedEvent.OutgoingMessageRead -> { @@ -178,11 +220,113 @@ class LongPollEventsHandler( this::class, "outMessageRead: updated $affectedRows rows." ) + + emitEvent(LongPollEvent.OUTGOING_MESSAGE_READ, event) } is LongPollParsedEvent.UnreadCounter -> { - + emitEvent(LongPollEvent.UNREAD_COUNTER_UPDATE, event) } } } + + private fun emitEvent(eventType: LongPollEvent, event: T) { + listenersMap[eventType]?.forEach { it(event) } + } + + private fun registerListener( + eventType: LongPollEvent, + listener: (T) -> Unit + ) { + if (listenersMap[eventType] == null) { + listenersMap[eventType] = mutableListOf() + } + + @Suppress("UNCHECKED_CAST") + listenersMap[eventType]?.add(listener as EventListener) + } + + private fun registerListeners( + eventTypes: List, + listener: (T) -> Unit + ) { + eventTypes.forEach { eventType -> registerListener(eventType, listener) } + } + + fun onMessageSetFlags(block: (LongPollParsedEvent) -> Unit) { + registerListener(LongPollEvent.MESSAGE_SET_FLAGS, block) + } + + fun onMessageMarkAsImportant(block: (LongPollParsedEvent.MessageMarkedAsImportant) -> Unit) { + registerListener(LongPollEvent.MARKED_AS_IMPORTANT, block) + } + + fun onMessageMarkAsSpam(block: (LongPollParsedEvent.MessageMarkedAsSpam) -> Unit) { + registerListener(LongPollEvent.MARKED_AS_SPAM, block) + } + + fun onMessageDelete(block: (LongPollParsedEvent.MessageDeleted) -> Unit) { + registerListener(LongPollEvent.MESSAGE_DELETED, block) + } + + fun onMessageClearFlags(block: (LongPollParsedEvent) -> Unit) { + registerListener(LongPollEvent.MESSAGE_CLEAR_FLAGS, block) + } + + fun onMessageMarkAsNotSpam(block: (LongPollParsedEvent.MessageMarkedAsNotSpam) -> Unit) { + registerListener(LongPollEvent.MARKED_AS_NOT_SPAM, block) + } + + fun onMessageRestore(block: (LongPollParsedEvent.MessageRestored) -> Unit) { + registerListener(LongPollEvent.MESSAGE_RESTORED, block) + } + + fun onMessageNew(block: (LongPollParsedEvent.MessageNew) -> Unit) { + registerListener(LongPollEvent.MESSAGE_NEW, block) + } + + fun onMessageEdit(block: (LongPollParsedEvent.MessageEdited) -> Unit) { + registerListener(LongPollEvent.MESSAGE_EDITED, block) + } + + fun onMessageIncomingRead(block: (LongPollParsedEvent.IncomingMessageRead) -> Unit) { + registerListener(LongPollEvent.INCOMING_MESSAGE_READ, block) + } + + fun onMessageOutgoingRead(block: (LongPollParsedEvent.OutgoingMessageRead) -> Unit) { + registerListener(LongPollEvent.OUTGOING_MESSAGE_READ, block) + } + + fun onChatClear(block: (LongPollParsedEvent.ChatCleared) -> Unit) { + registerListener(LongPollEvent.CHAT_CLEARED, block) + } + + fun onChatMajorChange(block: (LongPollParsedEvent.ChatMajorChanged) -> Unit) { + registerListener(LongPollEvent.CHAT_MAJOR_CHANGED, block) + } + + fun onChatMinorChange(block: (LongPollParsedEvent.ChatMinorChanged) -> Unit) { + registerListener(LongPollEvent.CHAT_MINOR_CHANGED, block) + } + + fun onChatArchive(block: (LongPollParsedEvent.ChatArchived) -> Unit) { + registerListener(LongPollEvent.CHAT_ARCHIVED, block) + } + + fun onInteraction(block: (LongPollParsedEvent.Interaction) -> Unit) { + registerListeners( + eventTypes = listOf( + LongPollEvent.TYPING, + LongPollEvent.AUDIO_MESSAGE_RECORDING, + LongPollEvent.PHOTO_UPLOADING, + LongPollEvent.VIDEO_UPLOADING, + LongPollEvent.FILE_UPLOADING + ), + listener = block + ) + } + + fun onDestroy() { + listenersMap.clear() + } } 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 3f6ebe18..6d3d1f2c 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 @@ -11,7 +11,6 @@ import dev.meloda.fast.logger.FastLogger import dev.meloda.fast.model.ApiEvent import dev.meloda.fast.model.ConvoFlags import dev.meloda.fast.model.InteractionType -import dev.meloda.fast.model.LongPollEvent import dev.meloda.fast.model.LongPollParsedEvent import dev.meloda.fast.model.MessageFlags import dev.meloda.fast.model.api.domain.VkConvo @@ -43,9 +42,6 @@ class LongPollUpdatesParser( private val coroutineScope = CoroutineScope(coroutineContext) - private val listenersMap: MutableMap>> = - mutableMapOf() - suspend fun parseNextUpdate(event: List): List { val eventId = event.first().asInt() @@ -101,9 +97,6 @@ class LongPollUpdatesParser( marked = true ) eventsToSend += eventToSend - - listenersMap[LongPollEvent.MARKED_AS_IMPORTANT] - ?.forEach { it.onEvent(eventToSend) } } MessageFlags.SPAM -> { @@ -112,7 +105,6 @@ class LongPollUpdatesParser( cmId = cmId ) eventsToSend += eventToSend - listenersMap[LongPollEvent.MARKED_AS_SPAM]?.forEach { it.onEvent(eventToSend) } } MessageFlags.DELETED -> { @@ -131,7 +123,6 @@ class LongPollUpdatesParser( ) } eventsToSend += eventToSend - listenersMap[LongPollEvent.MESSAGE_DELETED]?.forEach { it.onEvent(eventToSend) } } MessageFlags.AUDIO_LISTENED -> { @@ -140,9 +131,6 @@ class LongPollUpdatesParser( cmId = cmId ) eventsToSend += eventToSend - - listenersMap[LongPollEvent.AUDIO_MESSAGE_LISTENED] - ?.forEach { it.onEvent(eventToSend) } } MessageFlags.UNREAD -> Unit @@ -156,14 +144,6 @@ class LongPollUpdatesParser( } } - eventsToSend.forEach { eventToSend -> - listenersMap[LongPollEvent.MESSAGE_SET_FLAGS]?.let { listeners -> - listeners.forEach { vkEventCallback -> - vkEventCallback.onEvent(eventToSend) - } - } - } - return eventsToSend } @@ -193,9 +173,6 @@ class LongPollUpdatesParser( marked = false ) eventsToSend += eventToSend - - listenersMap[LongPollEvent.MARKED_AS_IMPORTANT] - ?.forEach { it.onEvent(eventToSend) } } MessageFlags.SPAM -> { @@ -204,9 +181,6 @@ class LongPollUpdatesParser( val eventToSend = LongPollParsedEvent.MessageMarkedAsNotSpam(message = message) eventsToSend += eventToSend - - listenersMap[LongPollEvent.MARKED_AS_NOT_SPAM] - ?.forEach { it.onEvent(eventToSend) } } } } @@ -216,9 +190,6 @@ class LongPollUpdatesParser( val eventToSend = LongPollParsedEvent.MessageRestored(message = message) eventsToSend += eventToSend - - listenersMap[LongPollEvent.MESSAGE_RESTORED] - ?.forEach { it.onEvent(eventToSend) } } } @@ -234,10 +205,6 @@ class LongPollUpdatesParser( } } - listenersMap[LongPollEvent.MESSAGE_CLEAR_FLAGS]?.forEach { listener -> - eventsToSend.forEach { listener.onEvent(it) } - } - continuation.resume(eventsToSend) } } @@ -264,7 +231,7 @@ class LongPollUpdatesParser( }.await() if (message != null) { - val event = LongPollParsedEvent.NewMessage( + val event = LongPollParsedEvent.MessageNew( message = message, inArchive = convo?.isArchived == true // TODO: 03-Apr-25, Danil Nikolaev: @@ -272,7 +239,6 @@ class LongPollUpdatesParser( // enabled notifications from archive ) - listenersMap[LongPollEvent.MESSAGE_NEW]?.forEach { it.onEvent(event) } continuation.resume(listOf(event)) } else { continuation.resume(emptyList()) @@ -293,7 +259,6 @@ class LongPollUpdatesParser( val message = loadMessage(peerId = peerId, cmId = cmId) if (message != null) { val event = LongPollParsedEvent.MessageEdited(message) - listenersMap[LongPollEvent.MESSAGE_EDITED]?.forEach { it.onEvent(event) } continuation.resume(listOf(event)) } else { continuation.resume(emptyList()) @@ -316,7 +281,6 @@ class LongPollUpdatesParser( cmId = cmId, unreadCount = unreadCount ) - listenersMap[LongPollEvent.INCOMING_MESSAGE_READ]?.forEach { it.onEvent(event) } return listOf(event) } @@ -336,7 +300,6 @@ class LongPollUpdatesParser( unreadCount = unreadCount ) - listenersMap[LongPollEvent.OUTGOING_MESSAGE_READ]?.forEach { it.onEvent(event) } return listOf(event) } @@ -373,8 +336,6 @@ class LongPollUpdatesParser( archived = false ) eventsToSend += eventToSend - - listenersMap[LongPollEvent.CHAT_ARCHIVED]?.forEach { it.onEvent(eventToSend) } } ConvoFlags.DISABLE_PUSH -> Unit @@ -392,10 +353,6 @@ class LongPollUpdatesParser( } } - listenersMap[LongPollEvent.CHAT_CLEAR_FLAGS]?.forEach { listener -> - eventsToSend.forEach { listener.onEvent(it) } - } - continuation.resume(eventsToSend) } } @@ -433,8 +390,6 @@ class LongPollUpdatesParser( archived = true ) eventsToSend += eventToSend - - listenersMap[LongPollEvent.CHAT_ARCHIVED]?.forEach { it.onEvent(eventToSend) } } ConvoFlags.DISABLE_PUSH -> Unit @@ -452,10 +407,6 @@ class LongPollUpdatesParser( } } - listenersMap[LongPollEvent.CHAT_SET_FLAGS]?.forEach { listener -> - eventsToSend.forEach { listener.onEvent(it) } - } - continuation.resume(eventsToSend) } } @@ -473,7 +424,6 @@ class LongPollUpdatesParser( peerId = peerId, toCmId = cmId ) - listenersMap[LongPollEvent.CHAT_CLEARED]?.forEach { it.onEvent(event) } return listOf(event) } @@ -490,7 +440,6 @@ class LongPollUpdatesParser( peerId = peerId, majorId = majorId, ) - listenersMap[LongPollEvent.CHAT_MAJOR_CHANGED]?.forEach { it.onEvent(event) } return listOf(event) } @@ -507,7 +456,6 @@ class LongPollUpdatesParser( peerId = peerId, minorId = minorId, ) - listenersMap[LongPollEvent.CHAT_MINOR_CHANGED]?.forEach { it.onEvent(event) } return listOf(event) } @@ -526,14 +474,6 @@ class LongPollUpdatesParser( else -> return emptyList() } - val longPollEvent: LongPollEvent = when (eventType) { - ApiEvent.TYPING -> LongPollEvent.TYPING - ApiEvent.AUDIO_MESSAGE_RECORDING -> LongPollEvent.AUDIO_MESSAGE_RECORDING - ApiEvent.PHOTO_UPLOADING -> LongPollEvent.PHOTO_UPLOADING - ApiEvent.VIDEO_UPLOADING -> LongPollEvent.VIDEO_UPLOADING - ApiEvent.FILE_UPLOADING -> LongPollEvent.FILE_UPLOADING - } - val peerId = event[1].asLong() val userIds = event[2].toList(Any::asLong).filter { it != UserConfig.userId } val totalCount = event[3].asInt() @@ -550,7 +490,6 @@ class LongPollUpdatesParser( timestamp = timestamp ) - listenersMap[longPollEvent]?.forEach { it.onEvent(event) } return listOf(event) } @@ -577,7 +516,6 @@ class LongPollUpdatesParser( archiveUnmuted = archiveUnreadUnmutedCount, archiveMentions = archiveMentionsCount ) - listenersMap[LongPollEvent.UNREAD_COUNTER_UPDATE]?.forEach { it.onEvent(event) } return listOf(event) } @@ -595,7 +533,6 @@ class LongPollUpdatesParser( if (message != null) { val event = LongPollParsedEvent.MessageUpdated(message) - listenersMap[LongPollEvent.MESSAGE_UPDATED]?.forEach { it.onEvent(event) } continuation.resume(listOf(event)) } else { continuation.resume(emptyList()) @@ -615,7 +552,6 @@ class LongPollUpdatesParser( val message = loadMessage(messageId = messageId) if (message != null) { val event = LongPollParsedEvent.MessageCacheClear(message) - listenersMap[LongPollEvent.MESSAGE_CACHE_CLEAR]?.forEach { it.onEvent(event) } continuation.resume(listOf(event)) } else { continuation.resume(emptyList()) @@ -641,7 +577,10 @@ class LongPollUpdatesParser( ).listenValue(this) { state -> state.processState( error = { error -> - logger.error(this@LongPollUpdatesParser::class, "loadMessage(): ERROR: $error") + logger.error( + this@LongPollUpdatesParser::class, + "loadMessage(): ERROR: $error" + ) continuation.resume(null) }, success = { response -> @@ -670,7 +609,10 @@ class LongPollUpdatesParser( ).listenValue(coroutineScope) { state -> state.processState( error = { error -> - logger.error(this@LongPollUpdatesParser::class, "loadConvo(): ERROR: $error") + logger.error( + this@LongPollUpdatesParser::class, + "loadConvo(): ERROR: $error" + ) continuation.resume(null) }, success = { response -> @@ -685,107 +627,4 @@ 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)) - } - - fun onMessageMarkedAsImportant(block: (LongPollParsedEvent.MessageMarkedAsImportant) -> Unit) { - registerListener(LongPollEvent.MARKED_AS_IMPORTANT, assembleEventCallback(block)) - } - - fun onMessageMarkedAsSpam(block: (LongPollParsedEvent.MessageMarkedAsSpam) -> Unit) { - registerListener(LongPollEvent.MARKED_AS_SPAM, assembleEventCallback(block)) - } - - fun onMessageDeleted(block: (LongPollParsedEvent.MessageDeleted) -> Unit) { - registerListener(LongPollEvent.MESSAGE_DELETED, assembleEventCallback(block)) - } - - fun onMessageClearFlags(block: (LongPollParsedEvent) -> Unit) { - registerListener(LongPollEvent.MESSAGE_CLEAR_FLAGS, assembleEventCallback(block)) - } - - fun onMessageMarkedAsNotSpam(block: (LongPollParsedEvent.MessageMarkedAsNotSpam) -> Unit) { - registerListener(LongPollEvent.MARKED_AS_NOT_SPAM, assembleEventCallback(block)) - } - - fun onMessageRestored(block: (LongPollParsedEvent.MessageRestored) -> Unit) { - registerListener(LongPollEvent.MESSAGE_RESTORED, assembleEventCallback(block)) - } - - fun onNewMessage(block: (LongPollParsedEvent.NewMessage) -> Unit) { - registerListener(LongPollEvent.MESSAGE_NEW, assembleEventCallback(block)) - } - - fun onMessageEdited(block: (LongPollParsedEvent.MessageEdited) -> Unit) { - registerListener(LongPollEvent.MESSAGE_EDITED, assembleEventCallback(block)) - } - - fun onMessageIncomingRead(block: (LongPollParsedEvent.IncomingMessageRead) -> Unit) { - registerListener(LongPollEvent.INCOMING_MESSAGE_READ, assembleEventCallback(block)) - } - - fun onMessageOutgoingRead(block: (LongPollParsedEvent.OutgoingMessageRead) -> Unit) { - registerListener(LongPollEvent.OUTGOING_MESSAGE_READ, assembleEventCallback(block)) - } - - fun onChatCleared(block: (LongPollParsedEvent.ChatCleared) -> Unit) { - registerListener(LongPollEvent.CHAT_CLEARED, assembleEventCallback(block)) - } - - fun onChatMajorChanged(block: (LongPollParsedEvent.ChatMajorChanged) -> Unit) { - registerListener(LongPollEvent.CHAT_MAJOR_CHANGED, assembleEventCallback(block)) - } - - fun onChatMinorChanged(block: (LongPollParsedEvent.ChatMinorChanged) -> Unit) { - registerListener(LongPollEvent.CHAT_MINOR_CHANGED, assembleEventCallback(block)) - } - - fun onChatArchived(block: (LongPollParsedEvent.ChatArchived) -> Unit) { - registerListener(LongPollEvent.CHAT_ARCHIVED, assembleEventCallback(block)) - } - - fun onInteractions(block: (LongPollParsedEvent.Interaction) -> Unit) { - registerListeners( - eventTypes = listOf( - LongPollEvent.TYPING, - LongPollEvent.AUDIO_MESSAGE_RECORDING, - LongPollEvent.PHOTO_UPLOADING, - LongPollEvent.VIDEO_UPLOADING, - LongPollEvent.FILE_UPLOADING - ), - listener = assembleEventCallback(block) - ) - } -} - -internal inline fun assembleEventCallback( - crossinline block: (R) -> Unit, -): VkEventCallback { - return VkEventCallback { event -> block.invoke(event) } -} - -fun interface VkEventCallback { - fun onEvent(event: T) } diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/LongPollParsedEvent.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/LongPollParsedEvent.kt index c1729d2e..668d4991 100644 --- a/core/model/src/main/kotlin/dev/meloda/fast/model/LongPollParsedEvent.kt +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/LongPollParsedEvent.kt @@ -5,7 +5,7 @@ import dev.meloda.fast.model.api.domain.VkMessage sealed interface LongPollParsedEvent { - data class NewMessage( + data class MessageNew( val message: VkMessage, val inArchive: Boolean ) : LongPollParsedEvent diff --git a/feature/convos/src/main/kotlin/dev/meloda/fast/convos/ConvosViewModel.kt b/feature/convos/src/main/kotlin/dev/meloda/fast/convos/ConvosViewModel.kt index 1fc02457..68c148b8 100644 --- a/feature/convos/src/main/kotlin/dev/meloda/fast/convos/ConvosViewModel.kt +++ b/feature/convos/src/main/kotlin/dev/meloda/fast/convos/ConvosViewModel.kt @@ -27,7 +27,7 @@ import dev.meloda.fast.data.processState import dev.meloda.fast.datastore.UserSettings import dev.meloda.fast.domain.ConvoUseCase import dev.meloda.fast.domain.LoadConvosByIdUseCase -import dev.meloda.fast.domain.LongPollUpdatesParser +import dev.meloda.fast.domain.LongPollEventsHandler import dev.meloda.fast.domain.MessagesUseCase import dev.meloda.fast.domain.util.asPresentation import dev.meloda.fast.domain.util.extractAvatar @@ -46,7 +46,7 @@ import kotlinx.coroutines.flow.launchIn @Immutable class ConvosViewModel( - updatesParser: LongPollUpdatesParser, + eventsHandler: LongPollEventsHandler, val filter: ConvosFilter, private val convoUseCase: ConvoUseCase, private val messagesUseCase: MessagesUseCase, @@ -74,15 +74,15 @@ class ConvosViewModel( init { loadConvos() - updatesParser.onNewMessage(::handleNewMessage) - updatesParser.onMessageEdited(::handleEditedMessage) - updatesParser.onMessageIncomingRead(::handleReadIncomingMessage) - updatesParser.onMessageOutgoingRead(::handleReadOutgoingMessage) - updatesParser.onInteractions(::handleInteraction) - updatesParser.onChatMajorChanged(::handleChatMajorChanged) - updatesParser.onChatMinorChanged(::handleChatMinorChanged) - updatesParser.onChatCleared(::handleChatClearing) - updatesParser.onChatArchived(::handleChatArchived) + eventsHandler.onMessageNew(::handleNewMessage) + eventsHandler.onMessageEdit(::handleEditedMessage) + eventsHandler.onMessageIncomingRead(::handleReadIncomingMessage) + eventsHandler.onMessageOutgoingRead(::handleReadOutgoingMessage) + eventsHandler.onInteraction(::handleInteraction) + eventsHandler.onChatMajorChange(::handleChatMajorChanged) + eventsHandler.onChatMinorChange(::handleChatMinorChanged) + eventsHandler.onChatClear(::handleChatClearing) + eventsHandler.onChatArchive(::handleChatArchived) userSettings.useContactNames.listenValue(viewModelScope) { syncUiConvos() @@ -382,7 +382,7 @@ class ConvosViewModel( } // TODO: 03-Apr-25, Danil Nikolaev: handle business messages - private fun handleNewMessage(event: LongPollParsedEvent.NewMessage) { + private fun handleNewMessage(event: LongPollParsedEvent.MessageNew) { val message = event.message val newConvos = convos.toMutableList() diff --git a/feature/convos/src/main/kotlin/dev/meloda/fast/convos/di/ConvosModule.kt b/feature/convos/src/main/kotlin/dev/meloda/fast/convos/di/ConvosModule.kt index b54191ef..32d8ebaa 100644 --- a/feature/convos/src/main/kotlin/dev/meloda/fast/convos/di/ConvosModule.kt +++ b/feature/convos/src/main/kotlin/dev/meloda/fast/convos/di/ConvosModule.kt @@ -25,7 +25,7 @@ val convosModule = module { private fun Scope.createConvosViewModel(filter: ConvosFilter): ConvosViewModel { return ConvosViewModel( filter = filter, - updatesParser = get(), + eventsHandler = get(), convoUseCase = get(), messagesUseCase = get(), resources = get(), 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 5d714aae..b7be9a22 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 @@ -39,7 +39,7 @@ import dev.meloda.fast.datastore.UserSettings import dev.meloda.fast.domain.ConvoUseCase import dev.meloda.fast.domain.GetMessageReadPeersUseCase import dev.meloda.fast.domain.LoadConvosByIdUseCase -import dev.meloda.fast.domain.LongPollUpdatesParser +import dev.meloda.fast.domain.LongPollEventsHandler import dev.meloda.fast.domain.MessagesUseCase import dev.meloda.fast.domain.util.asPresentation import dev.meloda.fast.domain.util.extractAvatar @@ -84,7 +84,7 @@ class MessagesHistoryViewModelImpl( private val userSettings: UserSettings, private val loadConvosByIdUseCase: LoadConvosByIdUseCase, private val getMessageReadPeersUseCase: GetMessageReadPeersUseCase, - updatesParser: LongPollUpdatesParser, + eventsHandler: LongPollEventsHandler, savedStateHandle: SavedStateHandle ) : MessagesHistoryViewModel, ViewModel() { @@ -124,15 +124,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) + eventsHandler.onMessageNew(::handleNewMessage) + eventsHandler.onMessageEdit(::handleEditedMessage) + eventsHandler.onMessageIncomingRead(::handleReadIncomingEvent) + eventsHandler.onMessageOutgoingRead(::handleReadOutgoingEvent) + eventsHandler.onMessageDelete(::handleMessageDeleted) + eventsHandler.onMessageRestore(::handleMessageRestored) + eventsHandler.onMessageMarkAsImportant(::handleMessageMarkedAsImportant) + eventsHandler.onMessageMarkAsSpam(::handleMessageMarkedAsSpam) + eventsHandler.onMessageMarkAsNotSpam(::handleMessageMarkedAsNotSpam) } override fun onNavigationConsumed() { @@ -681,7 +681,7 @@ class MessagesHistoryViewModelImpl( } } - private fun handleNewMessage(event: LongPollParsedEvent.NewMessage) { + private fun handleNewMessage(event: LongPollParsedEvent.MessageNew) { val message = event.message if (message.peerId != screenState.value.convoId) return