From 514b8859c77ccbdb97071b25fca8bf8dd9b69092 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 18 May 2026 20:46:18 +0300 Subject: [PATCH] refactor: trim message history orchestration --- .../MessagesHistoryViewModelImpl.kt | 22 +++++++++++-------- .../presentation/MessagesList.kt | 6 ++--- .../presentation/attachments/Attachments.kt | 12 +++++----- .../presentation/attachments/Link.kt | 3 ++- .../meloda/fast/profile/ProfileViewModel.kt | 19 +++++++++++++--- 5 files changed, 40 insertions(+), 22 deletions(-) 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 c848f89e..d008668b 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 @@ -139,15 +139,7 @@ class MessagesHistoryViewModelImpl( loaders.loadConvo() loaders.loadMessagesHistory(currentOffset.value) - updatesReducer.newMessages.onEach(longPollEventHandler::onNewMessage).launchIn(viewModelScope) - updatesReducer.messageEdited.onEach(longPollEventHandler::onMessageEdited).launchIn(viewModelScope) - updatesReducer.messageIncomingRead.onEach(longPollEventHandler::onReadIncoming).launchIn(viewModelScope) - updatesReducer.messageOutgoingRead.onEach(longPollEventHandler::onReadOutgoing).launchIn(viewModelScope) - updatesReducer.messageDeleted.onEach(longPollEventHandler::onMessageDeleted).launchIn(viewModelScope) - updatesReducer.messageRestored.onEach(longPollEventHandler::onMessageRestored).launchIn(viewModelScope) - updatesReducer.messageMarkedAsImportant.onEach(longPollEventHandler::onMessageMarkedAsImportant).launchIn(viewModelScope) - updatesReducer.messageMarkedAsSpam.onEach(longPollEventHandler::onMessageMarkedAsSpam).launchIn(viewModelScope) - updatesReducer.messageMarkedAsNotSpam.onEach(longPollEventHandler::onMessageMarkedAsNotSpam).launchIn(viewModelScope) + observeLongPollUpdates() } override fun onNavigationConsumed() { @@ -239,6 +231,18 @@ class MessagesHistoryViewModelImpl( override fun onKeyboardShown() = messageActions.onKeyboardShown() + private fun observeLongPollUpdates() { + updatesReducer.newMessages.onEach(longPollEventHandler::onNewMessage).launchIn(viewModelScope) + updatesReducer.messageEdited.onEach(longPollEventHandler::onMessageEdited).launchIn(viewModelScope) + updatesReducer.messageIncomingRead.onEach(longPollEventHandler::onReadIncoming).launchIn(viewModelScope) + updatesReducer.messageOutgoingRead.onEach(longPollEventHandler::onReadOutgoing).launchIn(viewModelScope) + updatesReducer.messageDeleted.onEach(longPollEventHandler::onMessageDeleted).launchIn(viewModelScope) + updatesReducer.messageRestored.onEach(longPollEventHandler::onMessageRestored).launchIn(viewModelScope) + updatesReducer.messageMarkedAsImportant.onEach(longPollEventHandler::onMessageMarkedAsImportant).launchIn(viewModelScope) + updatesReducer.messageMarkedAsSpam.onEach(longPollEventHandler::onMessageMarkedAsSpam).launchIn(viewModelScope) + updatesReducer.messageMarkedAsNotSpam.onEach(longPollEventHandler::onMessageMarkedAsNotSpam).launchIn(viewModelScope) + } + override suspend fun loadMessageReadPeers(peerId: Long, cmId: Long): Int = readPeersLoader.loadMessageReadPeers(peerId = peerId, cmId = cmId) diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt index 979c2533..aa123fa7 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt @@ -182,7 +182,7 @@ fun MessagesList( item = item, onClick = { if (item.actionCmId != null) { - onRequestScrollToCmId(item.actionCmId!!) + onRequestScrollToCmId(item.actionCmId) } } ) @@ -301,7 +301,7 @@ fun MessagesList( }, onReplyClick = { if (item.replyCmId != null) { - onRequestScrollToCmId(item.replyCmId!!) + onRequestScrollToCmId(item.replyCmId) } }, offsetX = offsetAnimatable.value @@ -328,7 +328,7 @@ fun MessagesList( }, onReplyClick = { if (item.replyCmId != null) { - onRequestScrollToCmId(item.replyCmId!!) + onRequestScrollToCmId(item.replyCmId) } }, offsetX = offsetAnimatable.value diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt index cdc47fef..31166fc1 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt @@ -214,10 +214,10 @@ fun Attachments( } } -fun VkAttachment.asUiPhoto(): UiPreview { +fun VkAttachment.asUiPhoto(): UiPreview? { return when (this) { is VkPhotoDomain -> { - val size = this.getDefault()!! + val size = this.getDefault() ?: return null UiPreview( id = this.id, url = size.url, @@ -247,7 +247,7 @@ fun VkAttachment.asUiPhoto(): UiPreview { is VkFileDomain -> { when { this.preview?.video != null -> { - val video = this.preview?.video!! + val video = this.preview?.video ?: return null UiPreview( id = id, @@ -259,7 +259,7 @@ fun VkAttachment.asUiPhoto(): UiPreview { } this.preview?.photo != null -> { - val photoSize = this.preview?.photo?.sizes?.first()!! + val photoSize = this.preview?.photo?.sizes?.firstOrNull() ?: return null UiPreview( id = id, @@ -270,11 +270,11 @@ fun VkAttachment.asUiPhoto(): UiPreview { ) } - else -> error("Unsupported type: $this") + else -> null } } - else -> error("Unsupported type: $this") + else -> null } } diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Link.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Link.kt index aa0fc9e4..1f0f7447 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Link.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Link.kt @@ -108,8 +108,9 @@ fun Link( Column(modifier = Modifier.weight(1f)) { if (item.title != null) { + val title = item.title Text( - text = item.title!!, + text = title, style = MaterialTheme.typography.bodyLarge, maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt index 427b674d..3766c6e7 100644 --- a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt +++ b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt @@ -69,9 +69,22 @@ class ProfileViewModelImpl( nomCase = null ).listenValue(viewModelScope) { state -> state.processState( - error = { error -> - // TODO: 12/07/2024, Danil Nikolaev: if local info is null then show error view - }, + error = { error -> + VkUtils.parseError(error)?.let { newBaseError -> + baseError.setValue { newBaseError } + } + + if (baseError.value == null) { + baseError.setValue { BaseError.InternalError } + } + + screenState.setValue { old -> + old.copy( + avatarUrl = null, + fullName = null + ) + } + }, success = { response -> val user = requireNotNull(response)