Use cursor-based pagination for search messages#6179
Use cursor-based pagination for search messages#6179VelikovPetar wants to merge 5 commits intodevelopfrom
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
…ion_for_search_messages
WalkthroughThe changes replace offset-based pagination with cursor-based (next-token) pagination across message search functionality in the compose and UI components modules. State models are updated to store and propagate the next cursor, API calls adjusted to use next instead of offset, and test coverage added for new search flows. Changes
Poem
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt (1)
160-167: Error recovery allows retry — confirm this is intentional.On failure,
canLoadMoreandnextare preserved (not reset). This means the user can retry the same page by callingloadMore()again, which seems like a reasonable recovery path. Just flagging for confirmation since the old offset-based behavior may have differed here.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt` around lines 160 - 167, The error handler handleSearchMessagesError currently preserves pagination state (canLoadMore and next), allowing loadMore() retries; if that is not intended, update handleSearchMessagesError to reset pagination by copying _state.value with isLoading=false, isLoadingMore=false, canLoadMore=false and next=null so a failed search does not permit an immediate retry of the same page; reference handleSearchMessagesError, _state, canLoadMore, next and loadMore() when making the change.stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt (1)
416-426: Optional: useargumentCaptor<String?>()for the nullablenextparameter.
argumentCaptor<String>()works here at runtime (wideningString→Any?beforeassertNullsuppresses the null check), butString?matches the actual parameter type ofnextand makes the captor usage type-safe.🛠️ Suggested change
-val captor = argumentCaptor<String>() +val captor = argumentCaptor<String?>()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt` around lines 416 - 426, The test uses argumentCaptor<String>() for the nullable next parameter in searchMessages which is type-unsafe; replace it with argumentCaptor<String?>() so the captor's generic matches the actual nullable parameter type (update the captor declaration and subsequent captor.firstValue / captor.secondValue assertions to use that captor), referencing the existing captor variable used in the verify(...) call for searchMessages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt`:
- Around line 529-531: The helper function givenRepositorySelectChannels is
unnecessarily marked suspend even though it only performs synchronous Mockito
stubbing; remove the suspend modifier from its declaration so it becomes a
regular function (match style of other helpers like givenSearchMessagesResult)
and keep the same body that calls
whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn channels
to stub the repository.
---
Nitpick comments:
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt`:
- Around line 416-426: The test uses argumentCaptor<String>() for the nullable
next parameter in searchMessages which is type-unsafe; replace it with
argumentCaptor<String?>() so the captor's generic matches the actual nullable
parameter type (update the captor declaration and subsequent captor.firstValue /
captor.secondValue assertions to use that captor), referencing the existing
captor variable used in the verify(...) call for searchMessages.
In
`@stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt`:
- Around line 160-167: The error handler handleSearchMessagesError currently
preserves pagination state (canLoadMore and next), allowing loadMore() retries;
if that is not intended, update handleSearchMessagesError to reset pagination by
copying _state.value with isLoading=false, isLoadingMore=false,
canLoadMore=false and next=null so a failed search does not permit an immediate
retry of the same page; reference handleSearchMessagesError, _state,
canLoadMore, next and loadMore() when making the change.
ℹ️ Review info
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.ktstream-chat-android-ui-components/api/stream-chat-android-ui-components.apistream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.ktstream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/viewmodels/search/SearchViewModelTest.kt
| suspend fun givenRepositorySelectChannels(channels: List<Channel> = emptyList()) = apply { | ||
| whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn channels | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
rg -n "fun selectChannels" --type=kt -A 2Repository: GetStream/stream-chat-android
Length of output: 99
🏁 Script executed:
rg -n "fun selectChannels" -A 2Repository: GetStream/stream-chat-android
Length of output: 6182
Remove the unnecessary suspend modifier from givenRepositorySelectChannels.
Although RepositoryFacade.selectChannels is a suspend function, the fixture helper only performs mockito-kotlin stubbing via whenever(...) doReturn ..., which is synchronous and does not require a coroutine context. The suspend modifier adds noise and is inconsistent with other fixture helpers like givenSearchMessagesResult. Remove it:
fun givenRepositorySelectChannels(channels: List<Channel> = emptyList()) = apply {
whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn channels
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt`
around lines 529 - 531, The helper function givenRepositorySelectChannels is
unnecessarily marked suspend even though it only performs synchronous Mockito
stubbing; remove the suspend modifier from its declaration so it becomes a
regular function (match style of other helpers like givenSearchMessagesResult)
and keep the same body that calls
whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn channels
to stub the repository.
…ion_for_search_messages
…ion_for_search_messages
|



Goal
Replace offset-based pagination with cursor-based pagination for message search to improve reliability and performance.
Resolves: https://linear.app/stream/issue/AND-1088/use-cursor-based-pagination-instead-of-offset-based-pagination-in
Implementation
SearchViewModel(UI Components) to usenextcursor instead of offsetChannelListViewModel(Compose) message search to usenextcursor instead of offsetcanLoadMorelogic to check for non-emptynexttoken instead of comparing message count to limitnextfield to state classes to track the pagination cursorSearchViewModelChannelListViewModelmessage searchUI Changes
No UI changes.
Testing
./gradlew :stream-chat-android-ui-components:testDebugUnitTest --tests "*.SearchViewModelTest"./gradlew :stream-chat-android-compose:testDebugUnitTest --tests "*.ChannelListViewModelTest"Summary by CodeRabbit
Release Notes
New Features
Tests