Skip to content

chore: loading state blinking (WPB-23296)#4597

Merged
sbakhtiarov merged 2 commits intodevelopfrom
chore/loading-state-blinking
Feb 17, 2026
Merged

chore: loading state blinking (WPB-23296)#4597
sbakhtiarov merged 2 commits intodevelopfrom
chore/loading-state-blinking

Conversation

@sbakhtiarov
Copy link
Copy Markdown
Contributor

@sbakhtiarov sbakhtiarov commented Feb 12, 2026

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.

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (dba2398) to head (c8325da).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files
@@       Coverage Diff       @@
##   develop   #4597   +/-   ##
===============================
===============================

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dba2398...c8325da. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sonarqubecloud
Copy link
Copy Markdown

@sbakhtiarov sbakhtiarov added this pull request to the merge queue Feb 17, 2026
Merged via the queue into develop with commit 61338db Feb 17, 2026
18 of 19 checks passed
@sbakhtiarov sbakhtiarov deleted the chore/loading-state-blinking branch February 17, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants