Conversation
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
WalkthroughThis PR redesigns the audio recording UI in the message composer by introducing new comprehensive recording components (AudioRecordingButton, AudioRecordingContent, AudioRecordingGesture, AudioRecordingPermission) while removing the previous recording UI implementation. The MessageComposer public API is restructured—removing the audioRecordingContent parameter and altering function signatures—alongside internal reorganization of compose singletons and a new SnackbarPopup wrapper. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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: 3
🤖 Fix all issues with AI agents
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingButton.kt`:
- Around line 590-593: The `@Suppress`("MagicNumber") above PreviewWaveformData
needs a short justification comment to make the suppression intentional: update
the declaration for PreviewWaveformData to include an inline comment or KDoc
that explains these numeric literals are static preview waveform sample values
(used only in previews, not production logic) and why the MagicNumber rule is
acceptable here, or replace the suppression with an `@OptIn` usage if applicable;
reference the symbol PreviewWaveformData and keep the suppression only after
adding that rationale.
- Around line 595-682: Replace the Compose `@Preview` annotations on the preview
functions (AudioRecordingButtonIdlePreview, AudioRecordingButtonHoldPreview,
AudioRecordingButtonLockedPreview, AudioRecordingButtonOverviewPreview) to use
the project's StreamPreview helper annotation (e.g., `@StreamPreview`) while
preserving any existing size overrides like showBackground and heightDp; ensure
any helper import is added and keep the preview bodies unchanged so the previews
still render the same content (retain ChatPreviewTheme wrappers and size
modifiers).
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingPermission.kt`:
- Around line 143-186: AudioRecordingPermissionRationale currently relies on
TimedPopup's 1000ms default which is too short for reading the rationale and
tapping "Settings"; update the TimedPopup invocation inside
AudioRecordingPermissionRationale to use a longer dismissTimeoutMs (e.g.,
3000–4000) or remove the auto-dismiss behavior and make it
dismiss-only-on-action by passing an explicit dismissTimeoutMs value or
switching to a non-timed popup API; edit the TimedPopup call in
AudioRecordingPermissionRationale to include dismissTimeoutMs = 3000 (or
implement no timeout) so the rationale/card and Settings button remain visible
long enough for users to read and interact.
🧹 Nitpick comments (4)
stream-chat-android-compose/api/stream-chat-android-compose.api (1)
2575-2576: Document the new state-basedMessageComposeroverload as the preferred pattern.Both
MessageComposeroverloads (ViewModel-based and state-based) coexist in the public API, so this is an additive change rather than a breaking one. However, if the newMessageComposerState-based variant is intended as the recommended pattern going forward, consider adding a migration note to release documentation to guide developers toward it. The state-based approach appears designed for more flexibility, so clarity on when to use each would be valuable for API consumers.stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingContent.kt (1)
205-221:Modifier.size(micStyle.size)on theIconis redundant given the parentBoxconstraints.The parent
Boxis sized tomicStyle.sizewith inner padding, so the Icon's available space is already smaller thanmicStyle.size. The explicit size modifier on the Icon won't achieve the declared size. Consider usingModifier.fillMaxSize()on the Icon instead, or removing the padding from the Box and sizing the Icon directly.stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingPermission.kt (1)
96-101: Consider makingAudioRecordingPermissionadata classor addingequals/hashCode.Since instances are created inside
remember(state)and used for recomposition comparisons, the current class identity-based equality means any recomposition that recreatesstatewill allocate a new wrapper. In practice this is likely fine sinceremember(state)already handles the caching, but making it a data class (or at least documenting the intent) would make the stability contract clearer for future maintainers.stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingButton.kt (1)
336-339: Avoid keeping a Popup mounted when no hint is shown.Guarding this keeps popups lightweight when the snackbar is idle.
♻️ Suggested guard
- SnackbarPopup( - hostState = hint.snackbarHostState, - snackbar = { AudioRecordingSnackbar(it) }, - ) + if (hint.snackbarHostState.currentSnackbarData != null) { + SnackbarPopup( + hostState = hint.snackbarHostState, + snackbar = { AudioRecordingSnackbar(it) }, + ) + }
...java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingButton.kt
Show resolved
Hide resolved
...java/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingButton.kt
Show resolved
Hide resolved
.../io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingPermission.kt
Show resolved
Hide resolved
SDK Size Comparison 📏
|
gpunto
left a comment
There was a problem hiding this comment.
Looks good, I left mostly nitpicks
...ava/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingGesture.kt
Show resolved
Hide resolved
...ava/io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingGesture.kt
Outdated
Show resolved
Hide resolved
.../io/getstream/chat/android/compose/ui/messages/composer/internal/AudioRecordingPermission.kt
Outdated
Show resolved
Hide resolved
This change simplifies the audio recording API by removing the `sendOnComplete` parameter from gesture handling and introducing a more explicit `onConfirmRecording` action. The `onStartRecording` action no longer requires an `Offset` parameter, and the `AudioRecordingActions` documentation is updated for better clarity.
d07fb44 to
124df19
Compare
…components-into-the-new-message-composer-structure
|


Goal
Prepare the Compose audio recording components for the upcoming design update by consolidating them into a self-contained structure aligned with the new message composer.
Implementation
AudioRecordingButtonthat manages the full recording lifecycle, removing theaudioRecordingContentslot fromMessageComposerandMessageComposerAudioRecordingContentfromChatComponentFactoryDefaultMessageComposerRecordingContentinto focused files:AudioRecordingButton,AudioRecordingContent,AudioRecordingGesture, andAudioRecordingPermissionMessageInputdirectly intoDefaultMessageComposerContentSnackbarPopupas a reusable componentviewConfigurationvalues🎨 UI Changes
No visual changes intended — this is a structural refactor of the existing recording UI.
Testing
Summary by CodeRabbit
Release Notes