Skip to content

compose: Align Channel List feedback states with Figma (loading error, action failure, deletion)#6492

Open
andremion wants to merge 4 commits into
developfrom
andrerego/and-1215-channel-list-feedback-states
Open

compose: Align Channel List feedback states with Figma (loading error, action failure, deletion)#6492
andremion wants to merge 4 commits into
developfrom
andrerego/and-1215-channel-list-feedback-states

Conversation

@andremion

@andremion andremion commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Goal

The Channel List in the Compose SDK had no feedback for failed or completed actions. This aligns it with the three Locked Figma states on Chat SDK Design System → Android → Channel List (AND-1215):

  1. Loading Error — a pagination failure showed nothing.
  2. User-triggered Action Failure — channel actions (mute, pin, archive, delete, leave, block, …) failed silently.
  3. Channel Deleted — a successful delete gave no confirmation.

Implementation

  • Loading-error banner (item 1): added ChannelsState.loadingError, set on a load-more failure and cleared on the next successful load. The stateless ChannelList renders a new ChannelListBanner ("Couldn't load new chats. Tap to retry") pinned below the header; tapping it retries via loadMore(). Exposed through a ChatComponentFactory.ChannelListBanner slot + params for customization. Mirrors the Thread List "Tap to retry" pattern.
  • Action feedback (items 2 & 3): ChannelListViewModel now exposes an internal events: SharedFlow<ChannelListEvent>. The 12 channel/user action handlers emit ActionError(action) on failure; delete emits ChannelDeleted on success. ChannelsScreen hosts a StreamSnackbarHost and maps events to snackbars — an error pill ("Error muting channel.", etc.) and a "Chat deleted." confirmation — reusing the existing StreamSnackbar.
  • Per-action error strings + "Chat deleted.", translated into all 7 supported locales.
  • No public API beyond item 1's loadingError field/handler (the events API is internal).

🎨 UI Changes

Before: a pagination failure and failed/succeeded actions produced no visible feedback.

Loading-error banner Action-failure snackbar
and1215_run_states and1215_run_snackbar

Testing

Unit tests cover the new behavior (ChannelListViewModelTest: loadingError set on failure / cleared on successful retry / kept on failed retry; action failure emits ActionError; delete emits ChannelDeleted). A Paparazzi snapshot covers ChannelListBanner; the snackbar variants are covered by StreamSnackbarTest.

Manual steps (compose sample):

  • Banner: on a list with more than one page of channels, scroll to the bottom while the next-page request fails (e.g. via a proxy) → the banner appears below the header; tap it to retry; on success it dismisses.
  • Action-failure snackbar: trigger a channel action that fails (e.g. mute while the request fails) → "Error muting channel." appears at the bottom.
  • Delete confirmation: long-press a channel → Delete Chat → confirm → "Chat deleted." appears.

Provide a patch below if it is necessary for testing

Force the loading-error banner and an action-failure snackbar on open
// ChannelListViewModel.kt — replay the events flow and emit a sample action error on open
-    private val _events = MutableSharedFlow<ChannelListEvent>(extraBufferCapacity = 1)
+    private val _events = MutableSharedFlow<ChannelListEvent>(replay = 1, extraBufferCapacity = 1)

         viewModelScope.launch { init() }
+        viewModelScope.launch {
+            _events.tryEmit(
+                ChannelListEvent.ActionError(
+                    ChannelListAction.MuteChannel,
+                    io.getstream.result.Error.GenericError("debug"),
+                ),
+            )
+        }

// ChannelList.kt (stateless ChannelList) — always render the banner
-                if (channelsState.loadingError) {
+                if (true) {

Summary by CodeRabbit

Release Notes

  • New Features

    • Tap-to-retry error banner when channel list fails to load
    • Action error notifications for channel management (mute, pin, archive, delete, leave group) and user interactions (mute, block, unblock)
    • Localized error messages across multiple languages
  • Tests

    • Added test coverage for error handling and retry banner components

andremion added 3 commits June 8, 2026 14:29
Surface a "Tap to retry" banner pinned below the Channel List header
when loading channels fails, aligning with the Figma "Loading Error"
state. Previously a pagination failure produced no visible feedback.

- Add ChannelsState.loadingError, set on load-more failure and cleared
  on a successful load
- Add ChannelListBanner composable with a ChatComponentFactory slot and
  params holder for customisation
- Render the banner above the list and wire onLoadingErrorClick to retry
  the failed load
- Add the stream_compose_channel_list_banner_error string
The content-state preview listed two items backed by the same
channelWithOnlineUser, producing identical LazyColumn keys
(ItemState.ChannelItemState.key = channel.cid) and crashing the
preview. Use channelWithOneUser for the draft-message item so each
item has a unique key.
Surface transient feedback on the Channel List when a user-triggered
action completes, aligning with the Figma "User-triggered Action Fail"
and "Channel Deleted" states. Previously channel actions failed silently.

- Add an internal ChannelListViewModel.events flow emitting ChannelListEvent
  (ActionError per failed action, ChannelDeleted on a successful delete)
- Route the 12 channel/user action handlers through the events flow
- Host a StreamSnackbarHost on ChannelsScreen and map events to snackbars
  (error pill for failures, confirmation pill for "Chat deleted")
- Add per-action error strings and "Chat deleted", with translations for
  all supported locales
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

@andremion andremion added the pr:new-feature New feature label Jun 8, 2026
@andremion

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.86 MB 5.86 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.09 MB 11.09 MB 0.00 MB 🟢
stream-chat-android-compose 12.51 MB 12.53 MB 0.02 MB 🟢

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3c65e5bb-cfa2-4860-b508-71ac3758e423

📥 Commits

Reviewing files that changed from the base of the PR and between 0bd0a41 and 9411fd6.

⛔ Files ignored due to path filters (1)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels.list_ChannelListBannerTest_error_state.png is excluded by !**/*.png
📒 Files selected for processing (19)
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/state/channels/list/ChannelListEvent.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/state/channels/list/ChannelsState.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/ChannelsScreen.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelList.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelListBanner.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.kt
  • stream-chat-android-compose/src/main/res/values-es/strings.xml
  • stream-chat-android-compose/src/main/res/values-fr/strings.xml
  • stream-chat-android-compose/src/main/res/values-hi/strings.xml
  • stream-chat-android-compose/src/main/res/values-in/strings.xml
  • stream-chat-android-compose/src/main/res/values-it/strings.xml
  • stream-chat-android-compose/src/main/res/values-ja/strings.xml
  • stream-chat-android-compose/src/main/res/values-ko/strings.xml
  • stream-chat-android-compose/src/main/res/values/strings.xml
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/channels/list/ChannelListBannerTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt

Walkthrough

This PR adds end-to-end error recovery for channel list loading failures. It introduces a loadingError state flag, defines channel-action event types, exposes an events flow from ChannelListViewModel with error tracking, creates a ChannelListBanner UI component, integrates snackbar notifications in ChannelsScreen, and provides comprehensive localization and test coverage.

Changes

Channel List Error Recovery

Layer / File(s) Summary
State model and event types
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/state/channels/list/ChannelsState.kt, ChannelListEvent.kt
ChannelsState adds loadingError: Boolean flag; new ChannelListEvent sealed interface defines ActionError and ChannelDeleted events; ChannelListAction enum lists user-triggered channel/user actions.
ViewModel event flow and action tracking
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.kt
ChannelListViewModel exposes internal events: SharedFlow<ChannelListEvent>; action methods updated to emit ActionError on failure via enqueueTrackingError helper; deleteConversation emits ChannelDeleted on success or ActionError on failure; loadMoreQueryChannels manages loadingError state across success/failure/retry cycles.
Banner UI component
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelListBanner.kt
ChannelListBanner composable renders full-width error banner with icon and "Tap to retry" text; uses theme-driven colors and typography; includes light/night mode previews.
ChannelList integration
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelList.kt
Both ChannelList overloads add onLoadingErrorClick callback parameter; ViewModel overload defaults to viewModel.loadMore(); state-backed overload conditionally renders ChannelListBanner when loadingError is true; preview data updated.
Theme factory extension
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt, ChatComponentFactory.kt
New ChannelListBannerParams data class with modifier and onClick callback; ChatComponentFactory.ChannelListBanner default implementation forwards params to banner component.
Screen snackbar integration
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/ChannelsScreen.kt
ChannelsScreen integrates SnackbarHostState and StreamSnackbarHost; new private EventHandler composable collects viewModel.events and displays short-duration snackbars for action errors and channel deletion using localized strings.
Localization and tests
stream-chat-android-compose/src/main/res/values*/strings.xml, ChannelListBannerTest.kt, ChannelListViewModelTest.kt
Localized error strings added across eight locales (default, Spanish, French, Hindi, Indonesian, Italian, Japanese, Korean); ChannelListBannerTest snapshot validates banner rendering; ChannelListViewModelTest extended with load-more error scenarios and event-emission assertions via Turbine.
Binary API surface
stream-chat-android-compose/api/stream-chat-android-compose.api
ChannelsState constructor/copy updated to include loadingError; ChannelList(ChannelsState) Compose parameter arity adjusted; new ComposableSingletons$ChannelListBannerKt and updated singleton exports; ChatComponentFactory and ChatComponentFactory$DefaultImpls extended with ChannelListBanner method entries.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

pr:test

Suggested reviewers

  • gpunto

🐰 A banner brave appeared
When channels fail to load,
Tap to retry whispers—
Errors gently told,
Streams flow pure and bold!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 51.28% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main changes: aligning Channel List feedback states (loading error, action failure, deletion) with Figma design specifications.
Description check ✅ Passed The description comprehensively covers the Goal, Implementation, UI Changes with screenshots, and Testing sections. It clearly explains the three Figma-aligned states, implementation details, localization, and provides both automated and manual testing approaches.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch andrerego/and-1215-channel-list-feedback-states

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@andremion andremion marked this pull request as ready for review June 8, 2026 16:03
@andremion andremion requested a review from a team as a code owner June 8, 2026 16:03
@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
46.9% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:new-feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant