Disable swipe-to-reply for deleted messages#6226
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
WalkthroughThe changes introduce a deleted message check to the reply-to-message capability, preventing users from replying to deleted messages. The SwipeToReply composable API is simplified from a lambda-based approach to a boolean flag, and test coverage is expanded to validate deleted message scenarios across capability checks. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 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 unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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
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-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt (1)
198-203:⚠️ Potential issue | 🟡 MinorMisleading comment: "message not synced" doesn't match the test scenario.
This test case excludes
READ_EVENTScapability forcanMarkAsUnread, not testing sync status.📝 Suggested fix
- // case: message not synced + // case: no READ_EVENTS capability Arguments.of( randomBoolean(), randomChannelCapabilities(exclude = setOf(ChannelCapabilities.READ_EVENTS)), false, ),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt` around lines 198 - 203, The comment "message not synced" is misleading for the Arguments.of case in CapabilitiesHelperTest; update the comment to reflect that this case is testing canMarkAsUnread behavior when the channel lacks ChannelCapabilities.READ_EVENTS (use symbols like canMarkAsUnread, ChannelCapabilities.READ_EVENTS, randomChannelCapabilities, and CapabilitiesHelperTest to locate the test), e.g., change the comment to something like "case: READ_EVENTS capability missing for canMarkAsUnread" so it accurately describes the scenario.stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt (1)
203-207:⚠️ Potential issue | 🟡 MinorMisleading comment: "message not synced" doesn't match the test scenario.
This test case excludes
READ_EVENTScapability, not testing sync status. The comment should reflect what's actually being tested.📝 Suggested fix
- // case: message not synced + // case: no READ_EVENTS capability Arguments.of( MessageOptionItemVisibility(), randomChannelCapabilities(exclude = setOf(ChannelCapabilities.READ_EVENTS)), false, ),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt` around lines 203 - 207, The comment above the test case is misleading — it says "message not synced" but the test actually constructs a scenario excluding ChannelCapabilities.READ_EVENTS via randomChannelCapabilities; update the comment to accurately describe the scenario being tested (e.g., "channel missing READ_EVENTS capability" or similar) next to the Arguments.of that uses MessageOptionItemVisibility and randomChannelCapabilities(exclude = setOf(ChannelCapabilities.READ_EVENTS)) so the comment matches the intent.
🧹 Nitpick comments (1)
stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.kt (1)
46-66: KDoc should document the deleted message condition.The KDoc lists conditions for when a reply is allowed but omits the newly added requirement that the message must not be deleted. Update the documentation to include this condition:
📝 Suggested KDoc update
/** * Determines whether a reply (quote) can be made to the given message. * * A reply is allowed when: * - Reply functionality is enabled in the UI configuration * - The message has been successfully synced with the backend + * - The message has not been deleted * - The user has the capability to quote messages in the channel *🤖 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/utils/CapabilitiesHelper.kt` around lines 46 - 66, The KDoc for canReplyToMessage is missing the condition that the message must not be deleted; update the documentation to state that replies are only allowed when replyEnabled is true, the message is synced (message.isSynced()), the message is not deleted (i.e., !message.isDeleted()), and the user has the ChannelCapabilities.QUOTE_MESSAGE capability in ownCapabilities; reference canReplyToMessage, message.isDeleted(), message.isSynced(), and ChannelCapabilities.QUOTE_MESSAGE in the updated comment.
🤖 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/messages/list/MessageItem.kt`:
- Line 737: The KDoc for the isSwipeable parameter in MessageItem.kt contains a
typo "swipe-te-reply"; update the documentation for the isSwipeable parameter
(in the MessageItem composable / function signature) to read "swipe-to-reply"
instead of "swipe-te-reply" so the param description is correct.
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt`:
- Around line 224-234: Update the misleading inline comment above this test case
so it accurately describes the scenario being tested: replace "no QUOTE_MESSAGE
capability" with a comment stating that this `Arguments.of` entry is testing a
non-COMPLETED sync status for `randomMessage` (using `randomSyncStatus(exclude =
listOf(SyncStatus.COMPLETED))`) in the `canPinMessageArguments` set; reference
the involved symbols `MessageOptionItemVisibility()`, `randomMessage`,
`randomSyncStatus`, `SyncStatus.COMPLETED`, and `randomChannelCapabilities` to
make the intent clear.
In
`@stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt`:
- Around line 219-229: The comment "no QUOTE_MESSAGE capability" above the
Arguments.of in CapabilitiesHelperTest is inaccurate for the
canPinMessageArguments test; update or remove it so it reflects the actual
scenario being tested (a message with non-COMPLETED sync status and not deleted:
see the Arguments.of that passes randomSyncStatus(exclude =
listOf(SyncStatus.COMPLETED)), deletedAt = null, deletedForMe = false) or
replace it with a clear comment like "case: message sync status is not COMPLETED
(cannot pin)"; adjust the comment near the Arguments.of to correctly describe
the test inputs referenced in canPinMessageArguments.
---
Outside diff comments:
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt`:
- Around line 203-207: The comment above the test case is misleading — it says
"message not synced" but the test actually constructs a scenario excluding
ChannelCapabilities.READ_EVENTS via randomChannelCapabilities; update the
comment to accurately describe the scenario being tested (e.g., "channel missing
READ_EVENTS capability" or similar) next to the Arguments.of that uses
MessageOptionItemVisibility and randomChannelCapabilities(exclude =
setOf(ChannelCapabilities.READ_EVENTS)) so the comment matches the intent.
In
`@stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt`:
- Around line 198-203: The comment "message not synced" is misleading for the
Arguments.of case in CapabilitiesHelperTest; update the comment to reflect that
this case is testing canMarkAsUnread behavior when the channel lacks
ChannelCapabilities.READ_EVENTS (use symbols like canMarkAsUnread,
ChannelCapabilities.READ_EVENTS, randomChannelCapabilities, and
CapabilitiesHelperTest to locate the test), e.g., change the comment to
something like "case: READ_EVENTS capability missing for canMarkAsUnread" so it
accurately describes the scenario.
---
Nitpick comments:
In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.kt`:
- Around line 46-66: The KDoc for canReplyToMessage is missing the condition
that the message must not be deleted; update the documentation to state that
replies are only allowed when replyEnabled is true, the message is synced
(message.isSynced()), the message is not deleted (i.e., !message.isDeleted()),
and the user has the ChannelCapabilities.QUOTE_MESSAGE capability in
ownCapabilities; reference canReplyToMessage, message.isDeleted(),
message.isSynced(), and ChannelCapabilities.QUOTE_MESSAGE in the updated
comment.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e72998bd-f4d4-40c9-a6f0-326f85e6e154
📒 Files selected for processing (5)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageItem.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.ktstream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.ktstream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/feature/messages/list/internal/MessageListViewExtensionsKtTest.kt
...roid-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageItem.kt
Outdated
Show resolved
Hide resolved
.../kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt
Outdated
Show resolved
Hide resolved
...i-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt
Outdated
Show resolved
Hide resolved
|
|
🚀 Available in v6.35.0 |



Goal
Prevent the swipe-to-reply gesture from being triggerable on messages that have been deleted during the current session. Previously, swipeability was computed without memoization, so a message deleted mid-session could still be swiped until the next recomposition. Additionally,
canReplyToMessagedid not check the deleted state of the message.Implementation
!message.isDeleted()check tocanReplyToMessageinCapabilitiesHelperso the core logic correctly blocks replies to deleted messages across all UI surfaces (Compose + XML).isSwipeableinMessageItemto useremember(message, ownCapabilities, optionVisibility)so the swipe state is memoized and re-evaluated reactively when the message is deleted or capabilities/theme change.optionVisibilitywas missing from the keys, which could produce a stale value if the theme changed at runtime.SwipeToReplyto acceptisSwipeable: Booleandirectly (was() -> Booleanlambda) and alignedpointerInputkeys accordingly.CapabilitiesHelperTest,MessageOptionItemVisibilityTest, andMessageListViewExtensionsKtTestto explicitly cover the deleted-message scenario and add clearer case comments.Testing
canReplyToMessage— new test cases cover the deleted-message path returningfalse.Summary by CodeRabbit
Bug Fixes
Tests