chore: loading state blinking (WPB-23296)#4597
Open
sbakhtiarov wants to merge 1 commit intodevelopfrom
Open
Conversation
|
saleniuk
approved these changes
Feb 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



https://wearezeta.atlassian.net/browse/WPB-23296
https://wearezeta.atlassian.net/browse/WPB-23296
What's new in this PR?
Issues
When a user has no conversations and opens the app, the conversations screen blinks between the loading shimmer and the empty state one or two times before settling on the empty state.
Causes (Optional)
The conversation list uses Paging 3 with SQLDelight's QueryPagingSource, which automatically invalidates whenever the underlying database tables are written to. At app startup, sync operations (WebSocket connection, background sync) write to conversation-related tables — even when no new conversations arrive (e.g. metadata, members, user info updates).
Each table write invalidates the PagingSource, causing the Pager to emit a fresh PagingData. When LazyPagingItems receives a new PagingData, it resets loadState.refresh to Loading and itemCount to 0. The loading condition in ConversationsScreenContent:
val showLoading = lazyPagingItems.loadState.refresh == LoadState.Loading && lazyPagingItems.itemCount == 0
becomes true again, briefly switching from the empty content back to the loading shimmer. When the re-query completes (still 0 items), it switches back to empty — producing a visible blink. This repeats for each sync-triggered invalidation.
Users with conversations are unaffected because enablePlaceholders = true keeps itemCount > 0 during refresh, so the showLoading guard never fires after the initial load.
Solution
Track whether the initial paging load has completed. After the first successful load (LoadState.NotLoading), never show the loading indicator again for the same composition — show the empty state directly instead.
The flag is scoped to remember, so it correctly resets when the composition is recreated (e.g. switching conversation filters via Crossfade). Error states don't set the flag, so a retry after a failed initial load still shows the loading indicator as expected.