Update SwipeToReplyIcon according new designs#6244
Conversation
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
...e/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt
Outdated
Show resolved
Hide resolved
SDK Size Comparison 📏
|
WalkthroughA new SwipeToReplyIcon composable UI component is introduced to render a styled reply button. The internal function is integrated into ChatComponentFactory to replace an inlined icon implementation, with the public API surface extended to include a singleton class for composable caching. Snapshot testing is added for the new component. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan for PR comments
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: 2
🤖 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/api/stream-chat-android-compose.api`:
- Around line 1777-1782: The new compiler-generated class
ComposableSingletons$SwipeToReplyIconKt is leaking into the public ABI because
the lambda/singleton was declared in a way that makes it public; make the
generated singleton/internal lambda non-public by moving the swipe-to-reply
composable and its helper lambda into a private/internal scope or annotating the
backing property with `@JvmSynthetic` or private visibility so it does not
generate a public top-level class. Concretely, locate the SwipeToReplyIcon
composable and the backing property/function referenced by lambda-1 and
getLambda-1$stream_chat_android_compose_release and change their declarations to
private/internal (or add `@JvmSynthetic` to the synthetic accessor) so the
compiler won’t emit the public ComposableSingletons$SwipeToReplyIconKt symbol.
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt`:
- Around line 52-55: In SwipeToReplyIcon update the decorative Icon call (the
Icon using painterResource(R.drawable.stream_compose_ic_reply)) to use
contentDescription = null instead of an empty string so the accessibility node
is omitted; locate the Icon invocation in the SwipeToReplyIcon composable and
set its contentDescription to null (keeping tint and other params unchanged).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: c873cdcd-fb68-490d-a141-30d638255306
⛔ Files ignored due to path filters (1)
stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_SwipeToReplyIconTest_swipe_to_reply_icon.pngis excluded by!**/*.png
📒 Files selected for processing (4)
stream-chat-android-compose/api/stream-chat-android-compose.apistream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.ktstream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIconTest.kt
| public final class io/getstream/chat/android/compose/ui/components/messages/ComposableSingletons$SwipeToReplyIconKt { | ||
| public static final field INSTANCE Lio/getstream/chat/android/compose/ui/components/messages/ComposableSingletons$SwipeToReplyIconKt; | ||
| public static field lambda-1 Lkotlin/jvm/functions/Function2; | ||
| public fun <init> ()V | ||
| public final fun getLambda-1$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function2; | ||
| } |
There was a problem hiding this comment.
Avoid leaking the new Compose singleton into the public SDK ABI.
This adds ComposableSingletons$SwipeToReplyIconKt as a public type even though the PR only changes the icon’s visuals. That turns a compiler-generated implementation detail into supported API surface. Please adjust the source-level implementation so the new swipe-to-reply UI stays internal and the .api file does not gain this extra symbol.
🤖 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
1777 - 1782, The new compiler-generated class
ComposableSingletons$SwipeToReplyIconKt is leaking into the public ABI because
the lambda/singleton was declared in a way that makes it public; make the
generated singleton/internal lambda non-public by moving the swipe-to-reply
composable and its helper lambda into a private/internal scope or annotating the
backing property with `@JvmSynthetic` or private visibility so it does not
generate a public top-level class. Concretely, locate the SwipeToReplyIcon
composable and the backing property/function referenced by lambda-1 and
getLambda-1$stream_chat_android_compose_release and change their declarations to
private/internal (or add `@JvmSynthetic` to the synthetic accessor) so the
compiler won’t emit the public ComposableSingletons$SwipeToReplyIconKt symbol.
| Icon( | ||
| painter = painterResource(R.drawable.stream_compose_ic_reply), | ||
| contentDescription = "", | ||
| tint = ChatTheme.colors.buttonSecondaryTextOnAccent, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, locate and examine the SwipeToReplyIcon.kt file
find . -name "SwipeToReplyIcon.kt" -type f | head -5Repository: GetStream/stream-chat-android
Length of output: 193
🏁 Script executed:
# Once located, examine the specific lines mentioned (52-55)
cat -n stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt | sed -n '36,67p'Repository: GetStream/stream-chat-android
Length of output: 1129
🌐 Web query:
Jetpack Compose Icon contentDescription null vs empty string accessibility semantics
💡 Result:
In Jetpack Compose, contentDescription has three distinct meanings:
-
contentDescription = null→ absent description. Compose won’t add aContentDescriptionsemantic for thatIcon/Image, which is what you want for purely decorative graphics or when the parent already provides the label (common with semantics merging in clickable/material components). Android’s guidance explicitly calls out usingnullfor decorative graphics. [1] -
contentDescription = ""(empty string) → present-but-empty description. This is not the same asnull: you are still explicitly setting the semantic, just to an empty value. Compose API guidelines call this out directly: “null description is NOT the same as\"\"description” becausenullmeans “don’t add accessibility info”. [2] In practice, an empty description often leads to poor screen reader output (e.g., unlabeled/generic announcements) and can also interfere with merged labeling, so it’s rarely what you want. -
Non-empty string → meaningful label that TalkBack/screen readers can announce for an icon-only control (use localized strings). [1]
Rule of thumb: use null for decorative, use a real localized string for meaningful/actionable icons, and avoid "" unless you have a very specific reason to set an explicitly-empty content description. [1] [2]
Sources:
[1] Android Developers — API defaults (Compose accessibility) https://developer.android.com/develop/ui/compose/accessibility/api-defaults
[2] Compose component API guidelines (Git at Google) https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-component-api-guidelines.md
Use null for the decorative reply icon.
contentDescription = "" doesn't exclude the icon from accessibility; it creates a blank semantic entry. For decorative icons, use contentDescription = null to omit the accessibility node entirely.
Proposed fix
Icon(
painter = painterResource(R.drawable.stream_compose_ic_reply),
- contentDescription = "",
+ contentDescription = null,
tint = ChatTheme.colors.buttonSecondaryTextOnAccent,
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt`
around lines 52 - 55, In SwipeToReplyIcon update the decorative Icon call (the
Icon using painterResource(R.drawable.stream_compose_ic_reply)) to use
contentDescription = null instead of an empty string so the accessibility node
is omitted; locate the Icon invocation in the SwipeToReplyIcon composable and
set its contentDescription to null (keeping tint and other params unchanged).
|



Goal
Update the SwipeToReply icon according design.
Implementation
Adds bubble background.
🎨 UI Changes
See snapshot tests.
Testing
Swipe to reply to see the new icon
Summary by CodeRabbit
Release Notes
New Features
Tests