diff --git a/CHANGELOG.md b/CHANGELOG.md index 52a9da11657..225eed7e4d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ ## stream-chat-android-state ### 🐞 Fixed +- Prevent duplicate `GetOrCreateChannel` calls when paginating messages. [#6016](https://github.com/GetStream/stream-chat-android/pull/6016) ### ⬆️ Improved diff --git a/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt b/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt index 67994d6928b..e392d8c2f66 100644 --- a/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt +++ b/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt @@ -237,7 +237,12 @@ internal class ChannelLogic( val offlineChannel = runChannelQueryOffline(request) val onlineResult = runChannelQueryOnline(request) - .onSuccess { fillTheGap(request.messagesLimit(), loadedMessages, it.messages) } + .onSuccess { + // Fill the missing messages gap only if loading around ID + if (request.isFilteringAroundIdMessages()) { + fillTheGap(request.messagesLimit(), loadedMessages, it.messages) + } + } return when { onlineResult is Result.Success -> onlineResult @@ -480,15 +485,6 @@ internal class ChannelLogic( channelStateLogic.removeMessagesBefore(date, systemMessage) } - /** - * Hides the messages created before the given date. - * - * @param date The date used for generating result. - */ - internal fun hideMessagesBefore(date: Date) { - channelStateLogic.hideMessagesBefore(date) - } - private fun upsertReminder(messageId: String, reminder: MessageReminder) { val message = reminder.message ?: mutableState.getMessageById(messageId) ?: return upsertEventMessage(message.copy(reminder = reminder.toMessageReminderInfo())) diff --git a/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogic.kt b/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogic.kt index 9607fa7ef7e..588993202c6 100644 --- a/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogic.kt +++ b/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogic.kt @@ -784,6 +784,8 @@ internal class ChannelStateLogic( } mutableState.recoveryNeeded = true } + mutableState.setLoadingOlderMessages(false) + mutableState.setLoadingNewerMessages(false) } /** diff --git a/stream-chat-android-state/src/test/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogicTest.kt b/stream-chat-android-state/src/test/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogicTest.kt index 0d8a40271a1..f19948e857b 100644 --- a/stream-chat-android-state/src/test/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogicTest.kt +++ b/stream-chat-android-state/src/test/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelStateLogicTest.kt @@ -51,6 +51,7 @@ import io.getstream.chat.android.state.model.querychannels.pagination.internal.Q import io.getstream.chat.android.state.plugin.state.channel.internal.ChannelMutableState import io.getstream.chat.android.state.plugin.state.global.internal.MutableGlobalState import io.getstream.chat.android.test.TestCoroutineExtension +import io.getstream.result.Error import kotlinx.coroutines.flow.MutableStateFlow import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should not be equal to` @@ -65,6 +66,7 @@ import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock +import org.mockito.kotlin.never import org.mockito.kotlin.spy import org.mockito.kotlin.times import org.mockito.kotlin.verify @@ -789,6 +791,28 @@ internal class ChannelStateLogicTest { ) } + @Test + fun `When propagateQueryError is called for recoverable error, Then channel is marked for recovery and loading is reset`() { + // when + channelStateLogic.propagateQueryError(Error.GenericError("Test error")) + + // then + verify(mutableState).recoveryNeeded = true + verify(mutableState).setLoadingOlderMessages(false) + verify(mutableState).setLoadingNewerMessages(false) + } + + @Test + fun `When propagateQueryError is called for unrecoverable error, Then channel is not marked for recovery and loading is reset`() { + // when + channelStateLogic.propagateQueryError(Error.NetworkError("Test network error", 500)) + + // then + verify(mutableState, never()).recoveryNeeded = any() + verify(mutableState).setLoadingOlderMessages(false) + verify(mutableState).setLoadingNewerMessages(false) + } + companion object { @JvmField diff --git a/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt b/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt index 07e9edc4322..eb0a60b9ac8 100644 --- a/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt +++ b/stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt @@ -1210,15 +1210,14 @@ public class MessageListController( logger.d { "[loadOlderMessages] messageLimit: $messageLimit" } if (clientState.isOffline) return - _mode.value.run { - when (this) { - is MessageMode.Normal -> { - if (channelState.value?.endOfOlderMessages?.value == true) return - chatClient.loadOlderMessages(cid, messageLimit).enqueue() - } - - is MessageMode.MessageThread -> threadLoadMore(this) + when (val mode = _mode.value) { + is MessageMode.Normal -> { + val endOfOlderMessages = channelState.value?.endOfOlderMessages?.value == true + val loadingOlderMessages = channelState.value?.loadingOlderMessages?.value == true + if (endOfOlderMessages || loadingOlderMessages) return + chatClient.loadOlderMessages(cid, messageLimit).enqueue() } + is MessageMode.MessageThread -> threadLoadMore(mode) } }