Skip to content

Implement mute action in message menu#6194

Open
gpunto wants to merge 1 commit intov7from
mute-action
Open

Implement mute action in message menu#6194
gpunto wants to merge 1 commit intov7from
mute-action

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Feb 26, 2026

Goal

The new designs also show the mute action in the message menu, so here we implement it

Implementation

  • Add MuteUser/UnmuteUser to MessageActions
  • Add Channel to SelectedMessageState because capabilities aren't enough to know if muting is possible
  • Add functions to check if the mute action should be visible

🎨 UI Changes

No UI-specific change, just the mute action will start showing up.

Testing

You can check in the sample that muting/unmuting through the message action works

Summary by CodeRabbit

Release Notes

  • New Features
    • Added mute and unmute user actions to message context menus, allowing users to manage communication preferences with other users directly from selected messages.

@gpunto gpunto added the pr:new-feature New feature label Feb 26, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 26, 2026

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.

🎉 Great job! This PR is ready for review.

@github-actions
Copy link
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.69 MB 0.44 MB 🟡
stream-chat-android-ui-components 10.60 MB 10.96 MB 0.36 MB 🟡
stream-chat-android-compose 12.81 MB 11.89 MB -0.92 MB 🚀

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

@gpunto
Copy link
Contributor Author

gpunto commented Feb 26, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

✅ Actions performed

Review triggered.

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.

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

Walkthrough

This PR refactors capability handling across the chat UI stack by replacing ownCapabilities: Set<String> parameters with Channel context objects, and introduces mute/unmute user functionality. The change propagates from the Compose UI through UI Common state management to capability checks, enabling channel-aware user moderation actions.

Changes

Cohort / File(s) Summary
Compose Message Options
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messageoptions/MessageOptionItemVisibility.kt, MessageOptions.kt
Added isMuteUserVisible boolean flag to MessageOptionItemVisibility; refactored defaultMessageOptionsState to accept Channel instead of ownCapabilities, derives capabilities from channel, and adds mute/unmute user option with visibility gating.
Compose State & Preview Updates
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/selectedmessage/SelectedMessageMenu.kt, MessagesScreen.kt, stream-chat-android-compose-sample/src/main/java/.../MessagesActivity.kt
Updated preview and internal calls to defaultMessageOptionsState to pass Channel instead of ownCapabilities; adjusted state object construction to use channel-derived context.
Compose Tests & Extensions
stream-chat-android-compose/src/main/java/.../util/extensions/MessageOptionItemVisibility.kt, MessageOptionItemVisibilityTest.kt
Added internal extension canMuteUser() that delegates visibility checks; introduced parameterized test with four test cases covering various mute user scenarios.
Compose API Declarations
stream-chat-android-compose/api/stream-chat-android-compose.api
Updated MessageOptionItemVisibility constructor and data class accessors; added component11() and isMuteUserVisible() method; refactored defaultMessageOptionsState signature to use Channel parameter.
Documentation
stream-chat-android-docs/src/main/kotlin/.../SelectedMessageMenu.kt
Updated three code snippet usages to pass channel from selectedMessageState.channel instead of ownCapabilities to defaultMessageOptionsState.
UI Common State Models
stream-chat-android-ui-common/src/main/kotlin/.../SelectedMessageState.kt, MessageAction.kt
Replaced abstract ownCapabilities: Set<String> with abstract channel: Channel in base SelectedMessageState; added derived ownCapabilities getter; updated all subclasses to take channel parameter; added new MuteUser and UnmuteUser message action classes.
UI Common Controllers & Capabilities
stream-chat-android-ui-common/src/main/kotlin/.../MessageListController.kt, CapabilitiesHelper.kt
Updated state constructors across SelectedMessageFailedModerationState, SelectedMessageOptionsState, SelectedMessageReactionsState, SelectedMessageReactionsPickerState to pass channel instead of ownCapabilities; added canMuteUser() and canBlockUser() capability helpers; implemented handling for MuteUser and UnmuteUser actions.
UI Common API & Tests
stream-chat-android-ui-common/api/stream-chat-android-ui-common.api, CapabilitiesHelperTest.kt
Updated API signatures for four SelectedMessage*State classes to use Channel instead of Set; added getChannel() accessor methods; introduced canMuteUser() and canBlockUser() in API; added parameterized test with four scenarios for canMuteUser() capability.
UI Components
stream-chat-android-ui-components/src/main/kotlin/.../MessageListView.kt
Added imports and no-op handling for MuteUser and UnmuteUser message actions, consistent with existing UnblockUser handling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A whisker-twitch of refactoring grace,
Channels now flow through every place,
Mute and unmute, a feature so fine,
State models dance in perfect line,
Capabilities checked with Channel's might,
Message options shining bright!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.03% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers the required sections (Goal, Implementation) but lacks UI Changes details, Testing specifics, and the Contributor/Reviewer checklists from the template. Add comparison screenshots, detailed testing steps, and complete the Contributor and Reviewer checklists to fully meet repository requirements.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: implementing the mute action in the message menu, which aligns with the primary objective.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mute-action

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
stream-chat-android-compose/api/stream-chat-android-compose.api (1)

1643-1657: ⚠️ Potential issue | 🟠 Major

Keep backward-compatible overloads for MessageOptionItemVisibility public API.

Line 1643 and Line 1656 change constructor/copy arity (10 → 11 booleans), which is a binary/source-breaking change for existing consumers. Please keep deprecated overloads with the previous signatures (delegating with isMuteUserVisible = true) to avoid breaking v7 adopters.

🤖 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
1643 - 1657, The public API for MessageOptionItemVisibility changed arity (10 →
11 booleans) and will break callers; restore backward-compatible overloads: add
deprecated constructor and deprecated copy overloads that match the old
10-Boolean signatures and delegate to the new primary constructor/copy by
passing isMuteUserVisible = true; ensure the overload names match
MessageOptionItemVisibility's existing constructors and copy/copy$default so
callers keep binary/source compatibility and annotate them deprecated with a
migration note.
🧹 Nitpick comments (1)
stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt (1)

1605-1619: Please add direct tests for new mute/unmute action branches.

Line 1618 and Line 1619 add new performMessageAction paths; controller-level tests here would lock down dispatch behavior and prevent regressions.

🤖 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/feature/messages/list/MessageListController.kt`
around lines 1605 - 1619, Add controller-level tests for performMessageAction
covering the new MuteUser and UnmuteUser branches: write unit tests that call
MessageListController.performMessageAction with a MuteUser and an UnmuteUser
action respectively, verify that the controller invokes muteUser(message.user)
and unmuteUser(message.user) (mock or spy the controller methods), and ensure no
other branches are executed (e.g., overlay removed and no incorrect
_messageActions changes). Target the MessageListController test file and assert
side-effects/interaction counts to lock down dispatch behavior and prevent
regressions.
🤖 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`:
- Line 1676: Restore the original public overload of defaultMessageOptionsState
that accepts Set<String> (the old signature) instead of replacing it; mark that
overload as `@Deprecated` and have it delegate its work to the new
defaultMessageOptionsState that accepts Channel by converting or mapping the
Set<String> into a Channel-compatible form (or by extracting the necessary info
and calling the new method), ensuring both methods coexist so you avoid the hard
API break while the new Channel-based API is the primary implementation.

---

Outside diff comments:
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Around line 1643-1657: The public API for MessageOptionItemVisibility changed
arity (10 → 11 booleans) and will break callers; restore backward-compatible
overloads: add deprecated constructor and deprecated copy overloads that match
the old 10-Boolean signatures and delegate to the new primary constructor/copy
by passing isMuteUserVisible = true; ensure the overload names match
MessageOptionItemVisibility's existing constructors and copy/copy$default so
callers keep binary/source compatibility and annotate them deprecated with a
migration note.

---

Nitpick comments:
In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt`:
- Around line 1605-1619: Add controller-level tests for performMessageAction
covering the new MuteUser and UnmuteUser branches: write unit tests that call
MessageListController.performMessageAction with a MuteUser and an UnmuteUser
action respectively, verify that the controller invokes muteUser(message.user)
and unmuteUser(message.user) (mock or spy the controller methods), and ensure no
other branches are executed (e.g., overlay removed and no incorrect
_messageActions changes). Target the MessageListController test file and assert
side-effects/interaction counts to lock down dispatch behavior and prevent
regressions.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 78c5901 and b3c703b.

⛔ Files ignored due to path filters (2)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_their_message.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_their_message_in_dark_mode.png is excluded by !**/*.png
📒 Files selected for processing (16)
  • stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/ui/MessagesActivity.kt
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messageoptions/MessageOptionItemVisibility.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messageoptions/MessageOptions.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/selectedmessage/SelectedMessageMenu.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/MessagesScreen.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibility.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt
  • stream-chat-android-docs/src/main/kotlin/io/getstream/chat/docs/kotlin/compose/messages/SelectedMessageMenu.kt
  • stream-chat-android-ui-common/api/stream-chat-android-ui-common.api
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/messages/MessageAction.kt
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/messages/list/SelectedMessageState.kt
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.kt
  • stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt
  • stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/list/MessageListView.kt

@gpunto gpunto marked this pull request as ready for review February 26, 2026 11:28
@gpunto gpunto requested a review from a team as a code owner February 26, 2026 11:28
currentUser: User?,
message: Message,
channel: Channel,
): Boolean = muteUserEnabled && channel.config.muteEnabled && !message.isOwnMessage(currentUser)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the channel.config.muteEnabled relevant for muting users as well? I think that it refers to whether the channel can be muted, but not individual users. I believe we should be able to mute a user, even if the channel could not.

Image

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.

2 participants