Redesign group channel info edit screen#6301
Conversation
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
a5f2c84 to
ed53ac2
Compare
WalkthroughThis PR refactors channel editing to use a dedicated screen and ViewModel, removes Context and CopyToClipboardHandler dependencies from channel info factories and ViewModels, and replaces UserInfo/RenameChannel options with a single EditChannel option. The top-bar action callback is renamed from Changes
Sequence DiagramsequenceDiagram
participant User
participant GroupChannelInfoScreen
participant GroupChannelEditScreen
participant GroupChannelEditViewModel
participant ImagePicker
participant ChatClient
participant Channel
User->>GroupChannelInfoScreen: Tap Edit Action
activate GroupChannelInfoScreen
GroupChannelInfoScreen->>GroupChannelEditScreen: Show Dialog
activate GroupChannelEditScreen
GroupChannelEditScreen->>GroupChannelEditViewModel: Create Instance
activate GroupChannelEditViewModel
GroupChannelEditViewModel-->>GroupChannelEditScreen: Initial State (isSaving=false)
User->>ImagePicker: Tap Upload Picture
activate ImagePicker
ImagePicker->>User: Show Options (Camera/Library)
User->>ImagePicker: Select Image
ImagePicker->>ImagePicker: Cache Image File
ImagePicker-->>GroupChannelEditScreen: Return File
deactivate ImagePicker
User->>GroupChannelEditScreen: Edit Name & Tap Save
GroupChannelEditScreen->>GroupChannelEditViewModel: save(name, imageFile, removeImage)
activate GroupChannelEditViewModel
GroupChannelEditViewModel->>ChatClient: uploadImage(file)
activate ChatClient
ChatClient-->>GroupChannelEditViewModel: Image URL
deactivate ChatClient
GroupChannelEditViewModel->>ChatClient: updatePartial(set={name, image})
activate ChatClient
ChatClient->>Channel: Update Channel
Channel-->>ChatClient: Success
deactivate ChatClient
GroupChannelEditViewModel-->>GroupChannelEditScreen: SaveSuccess Event
GroupChannelEditScreen->>User: Dismiss & Refresh
deactivate GroupChannelEditViewModel
deactivate GroupChannelEditScreen
deactivate GroupChannelInfoScreen
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
stream-chat-android-compose/api/stream-chat-android-compose.api (2)
4216-4228:⚠️ Potential issue | 🟡 MinorDocument the breaking
ChannelInfoViewModel,ChannelInfoViewModelFactory, andGroupChannelInfoTopBarParamsAPI changes in the v7 migration notes.Line 4228 shows the callback renamed to
onActionClick, and lines 6916–6928 show constructor parameters removed fromChannelInfoViewModelandChannelInfoViewModelFactory. While breaking changes are acceptable for v7, the CHANGELOG currently does not document these signature changes. Add entries covering the exact parameter removals and callback renames so integrations using these APIs know what to update.Also applies to: 6916-6928
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-compose/api/stream-chat-android-compose.api` around lines 4216 - 4228, The CHANGELOG/migration notes are missing documentation for breaking API changes: update the v7 migration notes to list the signature changes for ChannelInfoViewModel and ChannelInfoViewModelFactory (remove the constructor parameters that were deleted) and for GroupChannelInfoTopBarParams (note the callback rename to onActionClick); explicitly mention the exact parameters removed and the renamed callback (onActionClick) so integrators can map old constructors/parameters to the new ones and update their code accordingly.
6267-6330:⚠️ Potential issue | 🟡 MinorAdd migration documentation for the new
systemCarettoken inStreamDesign.Colors.Lines 6267-6330 and 6385 introduce a new
systemCaretfield to the publicStreamDesign.Colorsdata class. Apps that instantiate customStreamDesign.Colorsinstances will need explicit guidance on this breaking change. Update migration or changelog documentation to cover this addition.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-compose/api/stream-chat-android-compose.api` around lines 6267 - 6330, The public data class StreamDesign.Colors gained a new field systemCaret; update the migration docs/changelog to document this breaking change by (1) noting the new systemCaret token on StreamDesign.Colors, (2) showing the fix for apps that construct custom StreamDesign.Colors instances (explicitly add systemCaret with a default/appropriate value), and (3) adding a short compatibility note and example for copy-7QP4Db0 / the Colors constructor usage to ensure consumers know to set systemCaret when upgrading.
🧹 Nitpick comments (1)
stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/channel/info/ChannelInfoViewState.kt (1)
60-64: Refresh theEditChannelKDoc.The type now represents entering the full channel edit flow, but the comment still describes a rename-only action. That mismatch will confuse SDK consumers reading the public API.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/channel/info/ChannelInfoViewState.kt` around lines 60 - 64, The KDoc for the public data class EditChannel currently says it’s a rename-only option but the type represents entering the full channel edit flow; update the KDoc for EditChannel to describe that it opens the complete channel edit screen/flow (not just rename), and revise the `@param` name to indicate it’s the current channel name used as the initial value in the edit flow; ensure the KDoc sits immediately above the public data class EditChannel(val name: String) : Option so SDK consumers see the corrected documentation.
🤖 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/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditScreen.kt`:
- Around line 124-130: The UI allows tapping Save before the picked media
finishes copying to cache so pendingImageFile can be null and the avatar is
lost; update the save flow so saving waits for the background import or disables
Save while import is in progress: expose the import state or a completion signal
from the media picker (e.g., an isImporting boolean or a Deferred/Callback
produced where pendingImageFile is set), surface that state into
GroupChannelEditContent (alongside channelName and isSaving) and change the
onSaveActionClick/use of viewModel.save to either await the import completion or
return early/disable the button until isImporting is false so viewModel.save
receives the actual cached file rather than null.
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelInfoScreen.kt`:
- Around line 120-121: The saved dialog flags showEditChannel and showAddMembers
are not keyed by channel, causing state leakage when the pane is rebound to a
different channel; update the rememberSaveable calls to use a channel-scoped key
(e.g., headerViewModel.state or the channel.cid extracted from
headerViewModel.state) so each channel has its own saved state; locate the
rememberSaveable usages for showEditChannel and showAddMembers and add the key
parameter (using headerViewModel.state or channel.cid) to ensure dialogs aren’t
restored from a previous channel.
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditTest.kt`:
- Around line 31-49: Rename the three test functions in GroupChannelEditTest
(placeholder, filled, saving) to use backtick-style Kotlin test names per repo
convention (e.g., replace fun placeholder() with a backtick-named test like fun
`placeholder snapshot`()), updating the function declarations only (the bodies
calling snapshotWithDarkMode { GroupChannelEditPlaceholder() },
snapshotWithDarkMode { GroupChannelEditFilled() }, and snapshotWithDarkMode {
GroupChannelEditSaving() } remain unchanged) so the tests follow the
`/**/src/test/**/*.kt` guideline for readability; ensure you update any imports
or references if needed.
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channel/GroupChannelEditViewModelTest.kt`:
- Around line 162-171: The test currently uses givenUpdatePartial() which
returns a completed call (via asCall()), allowing the first save coroutine to
finish before the second save is invoked; change the fixture/mocking so the
first update/save call is a blocking or delayed Call (e.g., a
CompletableDeferred-backed or delayed fake) so that when sut.save(name="first",
...) is invoked it sets isSaving=true and remains in-flight when
sut.save(name="second", ...) is called; update the test to assert only one
GroupChannelEditViewEvent.SaveSuccess is emitted and verify the underlying
update method (the repository/SDK method mocked by givenUpdatePartial()) was
invoked exactly once, ensuring the second request was not forwarded.
In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/AddMembersViewAction.kt`:
- Around line 19-25: The new `@InternalStreamChatApi` annotation on
AddMembersViewAction/AddMembersViewState/AddMembersViewController requires call
sites to opt-in; add a file-level opt-in annotation
(`@file`:OptIn(InternalStreamChatApi::class)) to each caller file that imports or
uses these symbols—specifically update AddMembersScreen.kt,
AddMembersViewModelTest.kt, AddMembersViewController.kt, and
AddMembersViewControllerTest.kt—to include the opt-in so the compiler accepts
usage of AddMembersViewAction, AddMembersViewState, and
AddMembersViewController.
---
Outside diff comments:
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Around line 4216-4228: The CHANGELOG/migration notes are missing documentation
for breaking API changes: update the v7 migration notes to list the signature
changes for ChannelInfoViewModel and ChannelInfoViewModelFactory (remove the
constructor parameters that were deleted) and for GroupChannelInfoTopBarParams
(note the callback rename to onActionClick); explicitly mention the exact
parameters removed and the renamed callback (onActionClick) so integrators can
map old constructors/parameters to the new ones and update their code
accordingly.
- Around line 6267-6330: The public data class StreamDesign.Colors gained a new
field systemCaret; update the migration docs/changelog to document this breaking
change by (1) noting the new systemCaret token on StreamDesign.Colors, (2)
showing the fix for apps that construct custom StreamDesign.Colors instances
(explicitly add systemCaret with a default/appropriate value), and (3) adding a
short compatibility note and example for copy-7QP4Db0 / the Colors constructor
usage to ensure consumers know to set systemCaret when upgrading.
---
Nitpick comments:
In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/channel/info/ChannelInfoViewState.kt`:
- Around line 60-64: The KDoc for the public data class EditChannel currently
says it’s a rename-only option but the type represents entering the full channel
edit flow; update the KDoc for EditChannel to describe that it opens the
complete channel edit screen/flow (not just rename), and revise the `@param` name
to indicate it’s the current channel name used as the initial value in the edit
flow; ensure the KDoc sits immediately above the public data class
EditChannel(val name: String) : Option so SDK consumers see the corrected
documentation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f588938d-c213-47be-bc07-223e06182d59
⛔ Files ignored due to path filters (7)
stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelEditTest_filled.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelEditTest_image_picker_no_remove.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelEditTest_image_picker_with_remove.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelEditTest_placeholder.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelEditTest_saving.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelInfoContentTest_collapsed_members.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channel.info_GroupChannelInfoContentTest_collapsed_members_in_dark_mode.pngis excluded by!**/*.png
📒 Files selected for processing (36)
stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/channel/DirectChannelInfoActivity.ktstream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/channel/GroupChannelInfoActivity.ktstream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/chats/ChatsActivity.ktstream-chat-android-compose/api/stream-chat-android-compose.apistream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/ChannelInfoNameField.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/ChannelInfoOptionItem.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/ChannelInfoUserInfoOption.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditScreen.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditUtils.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelInfoScreen.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/ChannelAvatar.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamDesign.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModel.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModelFactory.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channel/GroupChannelEditViewModel.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditTest.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModelFactoryTest.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModelTest.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channel/GroupChannelEditViewModelTest.ktstream-chat-android-ui-common/api/stream-chat-android-ui-common.apistream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/AddMembersViewAction.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/AddMembersViewController.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/ChannelInfoViewAction.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/ChannelInfoViewController.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/channel/info/AddMembersViewState.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/channel/info/ChannelInfoViewState.ktstream-chat-android-ui-common/src/main/res/values/strings.xmlstream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/ChannelInfoViewControllerTest.ktstream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/chat/info/ChatInfoExtensions.ktstream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/chat/info/ChatInfoFragment.ktstream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/chat/info/group/GroupChatInfoFragment.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/channel/ChannelInfoViewModel.ktstream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/channel/ChannelInfoViewModelFactory.kt
💤 Files with no reviewable changes (10)
- stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/channel/DirectChannelInfoActivity.kt
- stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/channel/GroupChannelInfoActivity.kt
- stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/ChannelInfoViewAction.kt
- stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModelFactoryTest.kt
- stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/ChannelInfoUserInfoOption.kt
- stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/ChannelInfoNameField.kt
- stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/channel/ChannelInfoViewModelFactory.kt
- stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModelFactory.kt
- stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/channel/ChannelInfoViewModel.kt
- stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channel/ChannelInfoViewModel.kt
...se/src/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditScreen.kt
Outdated
Show resolved
Hide resolved
...se/src/main/java/io/getstream/chat/android/compose/ui/channel/info/GroupChannelInfoScreen.kt
Show resolved
Hide resolved
.../test/kotlin/io/getstream/chat/android/compose/ui/channel/info/GroupChannelEditScreenTest.kt
Show resolved
Hide resolved
.../kotlin/io/getstream/chat/android/compose/viewmodel/channel/GroupChannelEditViewModelTest.kt
Show resolved
Hide resolved
...main/kotlin/io/getstream/chat/android/ui/common/feature/channel/info/AddMembersViewAction.kt
Show resolved
Hide resolved
bc7298d to
1be76fe
Compare
gpunto
left a comment
There was a problem hiding this comment.
Looks good, left just some minor things
...pose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/chats/ChatsActivity.kt
Show resolved
Hide resolved
...c/main/java/io/getstream/chat/android/compose/viewmodel/channel/GroupChannelEditViewModel.kt
Show resolved
Hide resolved
...pose/src/main/java/io/getstream/chat/android/compose/viewmodel/channel/GalleryImageCopier.kt
Outdated
Show resolved
Hide resolved
…op bar of `GroupChannelInfoScreen`.
…ns with a single `EditChannel` option in `ChannelInfoViewState`.
…roller. Cancel any in-flight loadMore job when a new search starts, preventing results from a previous query from being appended to the new search results.
…endency from `ChannelInfoViewModel` and `ChannelInfoViewController`.
…ing state from the UI to `GroupChannelEditViewModel`.
…Controller` to cover edge cases. - Add test to verify that `GroupChannelEditViewModel` ignores duplicate gallery imports while an import is already in progress. - Add test to ensure `GroupChannelEditViewModel` preserves the existing pending image state if a gallery import fails. - Add test to confirm that `AddMembersViewController` cancels ongoing `LoadMore` jobs when the search query is changed.
…l` initialization internally. - Update `GroupChannelEditScreen` to accept `GroupChannelEditViewModelFactory` instead of a pre-initialized `GroupChannelEditViewModel`. - Move `GroupChannelEditViewModel` creation logic from `GroupChannelInfoScreen` into `GroupChannelEditScreen` using `viewModel()`. - Wrap `GroupChannelEditPlaceholder` in a `ViewModelStore` and update it to use the new factory-based signature to improve preview reliability. - Remove unnecessary `GroupChannelEditViewModel` import in `GroupChannelInfoScreen`.
…ViewModelFactory` instantiation. - Remove `viewModelFactory` parameter from `GroupChannelEditScreen` and internalize its creation using `LocalContext` and the provided `channel.cid`. - Update `GroupChannelInfoScreen` to no longer pass a factory to `GroupChannelEditScreen`. - Simplify `GroupChannelEditPlaceholder` by removing redundant factory initialization. - Provide a default empty lambda for the `onDismiss` parameter in `GroupChannelEditScreen`.
ffc2720 to
e5381da
Compare
|



Goal
Redesign the group channel info edit experience: replace the inline rename field with a dedicated full-screen edit screen with channel image upload support, and clean up dead code paths.
Implementation
GroupChannelEditScreenwith channel avatar (local preview on selection), image upload (gallery/camera/remove via bottom sheet), name field, and save action. Opened via "Edit" button in the group channel info top bar.GroupChannelEditViewModel(compose-only) — batches name + image changes into a singleupdatePartialcall. All screen state survives DKA viarememberSaveable.RenameChannel/UserInfooptions withEditChannel, gated byUPDATE_CHANNELcapability.UserInfoClickaction andCopyToClipboardHandlerfrom the ViewModel/Controller chain.AddMembersViewAction/AddMembersViewStateas@InternalStreamChatApi.AddMembersViewController.loadMore()— stale pagination results could contaminate a newer search.systemCaretcolor token toStreamDesign.Colors.🎨 UI Changes
Screen_recording_20260327_105653.webm
Screen_recording_20260327_152421.webm
Testing
UPDATE_CHANNELcapability, verify the "Edit" button is hidden.Summary by CodeRabbit
New Features
Improvements
Refactor