Skip to content

[ECO-5065] feat: add message reactions feature to chat API #139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 23, 2025

Conversation

ttypic
Copy link
Collaborator

@ttypic ttypic commented Jun 17, 2025

Introduced support for message reactions in the chat API, enabling the addition, deletion, and subscription to reactions. Implemented related interfaces, listeners, data types, and integration tests to ensure proper functionality and integration with messages.

Summary by CodeRabbit

  • New Features

    • Introduced support for message reactions, allowing users to add, delete, and view reactions on chat messages.
    • Added configuration options for message reactions at the room level, including reaction types and raw event subscriptions.
    • Enabled real-time subscriptions to reaction summaries and raw reaction events for enhanced chat interactivity.
  • Bug Fixes

    • Improved validation and error handling for message reaction operations.
  • Tests

    • Added comprehensive unit and integration tests to ensure correct behavior of message reactions and event subscriptions.

@ttypic ttypic requested a review from sacOO7 June 17, 2025 11:38
Copy link

coderabbitai bot commented Jun 17, 2025

"""

Walkthrough

The changes introduce a comprehensive message reactions feature to the chat system. This includes new APIs for sending and deleting reactions, structured models for reaction summaries, integration with message retrieval, room and message options for reactions, and both unit and integration tests validating reaction functionality and event subscriptions.

Changes

File(s) Change Summary
.../ChatApi.kt Added send/delete message reactions APIs; updated message retrieval to parse reactions; enhanced request handling.
.../EventTypes.kt Removed "meta.occupancy" mapping from message action map.
.../Message.kt Added reactions property and logic to Message; introduced models and parsing for reactions; added extension functions.
.../Messages.kt Added reactions property to Messages interface and implementation; integrated reactions into lifecycle management.
.../MessagesReactions.kt Introduced full message reactions subsystem: interfaces, event types, models, implementation, and event subscription.
.../RoomOptions.kt Made options non-nullable; added MessageOptions for reactions; updated channel mode logic for reaction subscriptions.
.../MessagesReactionsTest.kt Added unit tests for message reactions: sending, event type precedence, summary and raw event subscriptions.
.../integration/MessageReactionsIntegrationTest.kt Added integration tests for sending, deleting, and handling message reactions and event subscriptions.
gradle/libs.versions.toml Updated "ably" dependency version from 1.2.50 to 1.2.53.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant MessagesReactions
    participant ChatApi
    participant Server

    Client->>MessagesReactions: send(messageSerial, name, type, count)
    MessagesReactions->>ChatApi: sendMessageReaction(roomId, messageSerial, type, name, count)
    ChatApi->>Server: POST /rooms/{roomId}/messages/{messageSerial}/reactions
    Server-->>ChatApi: Response
    ChatApi-->>MessagesReactions: Result
    MessagesReactions-->>Client: Completion

    Client->>MessagesReactions: delete(messageSerial, name, type)
    MessagesReactions->>ChatApi: deleteMessageReaction(roomId, messageSerial, type, name)
    ChatApi->>Server: DELETE /rooms/{roomId}/messages/{messageSerial}/reactions
    Server-->>ChatApi: Response
    ChatApi-->>MessagesReactions: Result
    MessagesReactions-->>Client: Completion

    Server-->>MessagesReactions: Reaction summary/annotation event
    MessagesReactions-->>Client: Notifies subscribers with event
Loading

Assessment against linked issues

Objective Addressed Explanation
Implement message reaction feature in Kotlin client (ECO-5065)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Suggested reviewers

  • sacOO7

Poem

In the chat where messages flow,
Now reactions can sparkle and glow! 🎉
With thumbs and hearts, the bunnies cheer,
For every emoji, far and near.
Hop, skip, and tap—reactions are here,
Bringing more joy to the chat frontier! 🐇💬
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78a6a43 and 1f329de.

📒 Files selected for processing (13)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessageTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
🚧 Files skipped from review as they are similar to previous changes (9)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt
  • gradle/libs.versions.toml
  • chat-android/src/main/java/com/ably/chat/Messages.kt
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt
  • chat-android/src/main/java/com/ably/chat/Message.kt
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: coverage
  • GitHub Check: check
  • GitHub Check: build
🔇 Additional comments (8)
chat-android/src/test/java/com/ably/chat/MessageTest.kt (2)

18-42: LGTM - Version comparison logic test.

The test correctly validates that when an event's message version is less than or equal to the current message version, the same message instance is returned without modification.


101-127: LGTM - Reaction summary update test.

The test properly validates that reaction summaries are correctly applied to messages, verifying the copy operation and reaction state updates.

chat-android/src/main/java/com/ably/chat/RoomOptions.kt (2)

91-115: LGTM - Well-designed MessageOptions interface.

The MessageOptions interface is well-structured with clear documentation, sensible defaults, and proper integration with the room configuration system.


18-41: LGTM - Property nullability improvements.

Making the properties non-nullable with proper defaults improves the API design and reduces potential null-related issues.

chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (4)

364-386: LGTM - Comprehensive validation logic.

The checkSendArguments method provides thorough validation including serial checks, count restrictions for reaction types, and empty name validation. This addresses the upfront validation requirements effectively.


272-332: LGTM - Well-architected event handling system.

The implementation uses proper coroutine scoping, shared flows for event distribution, and conditional subscription setup based on configuration. The separation of concerns between summary and raw events is well-designed.


450-493: LGTM - Robust message summary processing.

The internalMessageSummaryListener method handles edge cases well, including empty summaries and missing serials, with appropriate logging for debugging.


88-144: LGTM - Well-defined reaction type system.

The enum definitions clearly document the different reaction types with proper spec references and behavioral descriptions. The type system is comprehensive and follows established patterns.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch ECO-5065/room-reactions

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 3

🧹 Nitpick comments (6)
chat-android/src/main/java/com/ably/chat/Messages.kt (2)

32-35: Document lifecycle of reactions property

reactions remains accessible even after Messages.dispose() is called, yet any subsequent call will operate on an already-disposed DefaultMessagesReactions instance. Please either

  1. set _reactions to a no-op/failed state after disposal, or
  2. clarify in KDoc that the property must not be used once the parent Messages is disposed.

528-534: Dispose reactions before other teardown to avoid event leaks

_reactions.dispose() is invoked after the channel’s state listener is removed and maps are cleared.
If _reactions happens to unregister listeners on the same channel this ordering is harmless, but calling it first (or inside a try/finally) is safer and guarantees all internal listeners are dropped even if an earlier teardown step throws.

chat-android/src/main/java/com/ably/chat/ChatApi.kt (1)

50-66: Gracefully handle malformed reactions JSON

getMessages blindly casts with getAsJsonObject(MessageProperty.Reactions).
If the backend ever returns a non-object or corrupt payload this will throw IllegalStateException and break pagination.
Consider guarding with takeIf { it.isJsonObject } or catching IllegalStateException and logging instead of propagating.

chat-android/src/main/java/com/ably/chat/Message.kt (1)

139-149: with(MessageEvent) keeps outdated reactions

The helper copies the incoming event.message but then resets reactions = this.reactions, discarding any newer summary that might have arrived between the two events.

If the intention is to preserve the latest reactions, consider comparing versions or timestamps before overwriting.

chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1)

128-140: Consider adding timeout to avoid hanging tests

waitForRawReactions relies on the test finishing only when all events arrive.
Wrapping await() in withTimeout() (e.g. 5 s) will fail fast instead of hanging indefinitely when infrastructure is flaky.

chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)

244-257: Avoid over-provisioning channel modes

annotation_publish is added unconditionally, even when messages.rawMessageReactions == false.
If the application never sends reactions this widens the channel capabilities it must request/authorise for no benefit (principle of least privilege).

-val channelModes = mutableSetOf(
-    ChannelMode.publish, ChannelMode.subscribe,
-    ChannelMode.presence, ChannelMode.annotation_publish)
+val channelModes = mutableSetOf(
+    ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence).apply {
+    if (messages.rawMessageReactions) add(ChannelMode.annotation_publish)
+}

Same condition you already use for annotation_subscribe, keeps behaviour unchanged for reaction-enabled rooms while tightening others.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 178ad12 and 79925d9.

📒 Files selected for processing (8)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
🧰 Additional context used
🧬 Code Graph Analysis (5)
chat-android/src/main/java/com/ably/chat/ChatApi.kt (1)
chat-android/src/main/java/com/ably/chat/Message.kt (1)
  • buildMessageReactions (222-234)
chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (2)
chat-android/src/test/java/com/ably/chat/room/RoomTestHelpers.kt (2)
  • createMockRealtimeClient (50-62)
  • createMockChatApi (82-86)
chat-android/src/test/java/io/ably/lib/realtime/RealtimeUtils.kt (1)
  • buildRealtimeChannel (24-29)
chat-android/src/main/java/com/ably/chat/Message.kt (1)
chat-android/src/main/java/com/ably/chat/Utils.kt (1)
  • clientError (200-200)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)
chat-android/src/main/java/com/ably/chat/Utils.kt (2)
  • ablyException (173-181)
  • ablyException (183-186)
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1)
chat-android/src/main/java/com/ably/chat/Utils.kt (1)
  • clientError (200-200)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: coverage
  • GitHub Check: build
  • GitHub Check: check
🔇 Additional comments (4)
chat-android/src/main/java/com/ably/chat/Message.kt (2)

96-100: Nice addition

Exposing reaction summaries on the Message interface makes the model self-contained. 👍


222-234: Defensive parsing looks good

buildMessageReactions safely defaults to empty maps and isolates JSON parsing. Looks solid.

chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1)

40-54: Excellent coverage

The tests verify default-option propagation and explicit-parameter precedence for reaction type. Good job.

chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1)

268-272: Potential unbounded memory growth

rawEventBus is created with extraBufferCapacity = UNLIMITED.
If the downstream consumer stops collecting (e.g. UI screen in background), the flow retains every raw reaction event and can exhaust memory under high traffic.

Consider:

  • Switching to a bounded buffer similar to the summary bus (e.g. 1 or 64) with DROP_OLDEST.
  • Or pause the annotation subscription when no subscribeRaw listeners are registered.

Either approach caps memory usage without losing critical data for typical UI use-cases.

@ttypic ttypic force-pushed the ECO-5065/room-reactions branch from 79925d9 to 8a071fd Compare June 17, 2025 13:51
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: 2

♻️ Duplicate comments (1)
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1)

309-334: Still missing input validation in send()

Blank reaction names and invalid count values slip through, hitting the server. The same feedback was raised previously.

🧹 Nitpick comments (5)
chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1)

128-137: receivedReactions is mutated from a listener thread – not thread-safe

mutableListOf isn’t safe for concurrent writes. Use a thread-safe collection or guard mutations with synchronized to avoid rare ConcurrentModificationExceptions in CI.

chat-android/src/main/java/com/ably/chat/RoomOptions.kt (2)

244-257: annotation_publish enabled unconditionally

annotation_publish is added even when reactions are disabled. Consider adding it only when the room can actually publish reactions to reduce unnecessary channel capabilities exposure.

-        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence, ChannelMode.annotation_publish)
+        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence)
+        if (reactionsEnabled() || messages.rawMessageReactions) {
+            channelModes += ChannelMode.annotation_publish
+        }

229-234: Extend validation to new message-level options

validateRoomOptions() still checks only typing throttle. Add sanity checks, e.g. positive count default, or forbid rawMessageReactions=true when corresponding channel mode isn’t requested.

chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (2)

260-262: Minor naming nit – rawEventlisteners

rawEventlistenersrawEventListeners for consistency with Kotlin naming conventions.


368-375: Guard subscribeRaw() when raw reactions are disabled

If messages.rawMessageReactions is false, callers will silently receive no events. Consider throwing early or logging a warning to aid debugging.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79925d9 and 8a071fd.

📒 Files selected for processing (9)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
✅ Files skipped from review due to trivial changes (1)
  • gradle/libs.versions.toml
🚧 Files skipped from review as they are similar to previous changes (4)
  • chat-android/src/main/java/com/ably/chat/Messages.kt
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt
  • chat-android/src/main/java/com/ably/chat/Message.kt
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt
🧰 Additional context used
🧬 Code Graph Analysis (1)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)
chat-android/src/main/java/com/ably/chat/Utils.kt (2)
  • ablyException (173-181)
  • ablyException (183-186)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: check
  • GitHub Check: build
  • GitHub Check: coverage
🔇 Additional comments (1)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)

18-42: Switch to non-nullable option objects is a breaking API change

presence, typing, reactions, occupancy, and new messages are now mandatory. Down-stream callers that previously passed null will no longer compile. Confirm semantic-versioning expectations and update release notes.

@github-actions github-actions bot temporarily deployed to staging/pull/139/dokka June 17, 2025 13:55 Inactive
@ttypic ttypic force-pushed the ECO-5065/room-reactions branch from 8a071fd to ce11c4b Compare June 17, 2025 16:22
@github-actions github-actions bot temporarily deployed to staging/pull/139/dokka June 17, 2025 16:25 Inactive
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

♻️ Duplicate comments (2)
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (2)

352-354: Wrong variable in error message (still unfixed)

The exception references nullable type instead of the resolved reactionType, yielding confusing messages.

-            throw clientError("cannot delete reaction of type $type without a name")
+            throw clientError("cannot delete reaction of type $reactionType without a name")

319-337: Input validation for send() still missing

Blank names and invalid count values are not rejected early. See previous review comment with concrete diff.

🧹 Nitpick comments (1)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)

173-179: EquatableRoomOptions discards future reactions state

reactions is always mapped to a singleton EquatableRoomReactionsOptions, so any fields added later to MutableRoomReactionsOptions will never participate in equality checks or caching logic.
Convert the actual instance instead of a constant placeholder (or keep the mapping but add a TODO to revisit when the interface stops being empty).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a071fd and ce11c4b.

📒 Files selected for processing (9)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
🚧 Files skipped from review as they are similar to previous changes (6)
  • gradle/libs.versions.toml
  • chat-android/src/main/java/com/ably/chat/Messages.kt
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt
  • chat-android/src/main/java/com/ably/chat/Message.kt
🧰 Additional context used
🧬 Code Graph Analysis (1)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)
chat-android/src/main/java/com/ably/chat/Utils.kt (2)
  • ablyException (173-181)
  • ablyException (183-186)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build
  • GitHub Check: check
  • GitHub Check: coverage
🔇 Additional comments (1)
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1)

267-275: Unbounded raw-event buffer can exhaust memory

MutableSharedFlow is created with extraBufferCapacity = UNLIMITED; if listeners are slow, every reaction event will pile up.
Use a bounded buffer (or back-pressure) to avoid an OOM risk.

-    private val rawEventBus = MutableSharedFlow<MessageReactionRawEvent>(
-        extraBufferCapacity = UNLIMITED,
-        onBufferOverflow = BufferOverflow.DROP_OLDEST,
-    )
+    private val rawEventBus = MutableSharedFlow<MessageReactionRawEvent>(
+        extraBufferCapacity = 64, // tune as appropriate
+        onBufferOverflow = BufferOverflow.DROP_OLDEST,
+    )
⛔ Skipped due to learnings
Learnt from: sacOO7
PR: ably/ably-chat-kotlin#124
File: chat-android/src/main/java/com/ably/chat/Utils.kt:0-0
Timestamp: 2025-04-28T11:41:59.070Z
Learning: The `AwaitableSharedFlow` class in `com.ably.chat` intentionally uses `Channel.UNLIMITED` buffer capacity to ensure `tryEmit()` never fails due to buffer constraints, which is an important design requirement for the Ably Chat Kotlin SDK.

@ttypic ttypic force-pushed the ECO-5065/room-reactions branch from ce11c4b to 04dddcb Compare June 18, 2025 09:07
@github-actions github-actions bot temporarily deployed to staging/pull/139/dokka June 18, 2025 09:11 Inactive
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: 0

♻️ Duplicate comments (3)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)

244-256: ChannelMode.annotation_publish must be added conditionally

annotation_publish is still inserted unconditionally even when a room does not request raw reactions.
This widens the capability set for every room, risking permission errors for customers with restricted keys and breaking the principle of least privilege.

-        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence, ChannelMode.annotation_publish)
+        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence)
+
+        // Enable publish-side annotations only if the room opted-in for raw reactions
+        if (messages.rawMessageReactions) {
+            channelModes.add(ChannelMode.annotation_publish)
+        }

Please gate annotation_publish behind messages.rawMessageReactions, update the affected unit tests, and re-run the integration suite.

chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (2)

352-355: Wrong variable referenced in error path

The exception message still interpolates the nullable type parameter instead of the resolved reactionType, leading to confusing errors (e.g. “…type null…”).

-            throw clientError("cannot delete reaction of type $type without a name")
+            throw clientError("cannot delete reaction of type $reactionType without a name")

313-338: Missing input validation for send()

send() accepts blank names and any count regardless of reaction type.
Validate early to surface client errors before making a network call:

require(name.isNotBlank()) { "reaction name must not be blank" }
if (reactionType != MessageReactionType.Multiple && count != 1) {
    throw clientError("count must be 1 for reaction type $reactionType")
}
🧹 Nitpick comments (3)
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (2)

264-266: Minor: inconsistent variable casing

rawEventlistenersrawEventListeners for consistency with listeners.
A tiny rename avoids cognitive friction.


272-275: Unlimited buffer may exhaust memory under heavy load

rawEventBus is configured with UNLIMITED extra buffer capacity. A flood of reactions could OOM the client.
Consider back-pressure (e.g. fixed size with DROP_OLDEST) or making the capacity configurable.

chat-android/src/test/java/com/ably/chat/MessagesTest.kt (1)

198-204: Defensive check around captured listeners

channelStateListenerSlots.first() will throw if no listener was captured (e.g. if mocking logic changes).
Use firstOrNull()?.onChannelStateChanged(...) and fail the test explicitly if null for clearer diagnostics.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce11c4b and 04dddcb.

📒 Files selected for processing (12)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
✅ Files skipped from review due to trivial changes (1)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt
🚧 Files skipped from review as they are similar to previous changes (6)
  • gradle/libs.versions.toml
  • chat-android/src/main/java/com/ably/chat/Messages.kt
  • chat-android/src/main/java/com/ably/chat/Message.kt
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt
🧰 Additional context used
🧠 Learnings (1)
chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt (2)
Learnt from: sacOO7
PR: ably/ably-chat-kotlin#89
File: chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt:44-48
Timestamp: 2024-12-10T14:47:31.766Z
Learning: In tests in `RoomFeatureSharedChannelTest.kt` for the Ably Chat Kotlin project, the order of `ChannelMode.publish` and `ChannelMode.subscribe` in the `modes` array does not affect functionality; assertions should not enforce a specific order for these modes.
Learnt from: sacOO7
PR: ably/ably-chat-kotlin#75
File: chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt:43-45
Timestamp: 2024-12-02T12:10:18.954Z
Learning: In the `RoomFeatureSharedChannelTest.kt` tests, prefer using assertions like `Assert.assertEquals` that provide detailed error messages over general assertions like `Assert.assertTrue`, to aid in debugging when a test fails due to a missing mode.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build
  • GitHub Check: check
  • GitHub Check: coverage
🔇 Additional comments (2)
chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt (2)

74-83: Test now hard-codes annotation_publish – will break once the mode is gated

The assertion list mirrors the current (incorrect) unconditional behaviour.
After fixing RoomOptions.channelOptions() as noted earlier, update this expectation to include annotation_publish only when messages.rawMessageReactions is true.


108-112: Presence of annotation_publish in second assertion block may become invalid

Same reasoning as above – the test will fail once the production code stops always adding annotation_publish.
Please adapt the expected size / content accordingly.

@ttypic ttypic force-pushed the ECO-5065/room-reactions branch from 04dddcb to 1a10c14 Compare June 18, 2025 09:17
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: 0

♻️ Duplicate comments (3)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)

244-257: annotation_publish still added unconditionally – resurrected issue

The mode is added regardless of whether the client has opted-in to raw reactions. This widens required capabilities and can break apps running with restricted API keys (exactly the concern raised in the previous review).

-        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence, ChannelMode.annotation_publish)
+        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence)
 ...
-        if (messages.rawMessageReactions) {
-            channelModes.add(ChannelMode.annotation_subscribe)
+        if (messages.rawMessageReactions) {
+            channelModes.add(ChannelMode.annotation_publish)
+            channelModes.add(ChannelMode.annotation_subscribe)
         }

Please gate annotation_publish the same way you already gate annotation_subscribe.

chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (2)

313-338: Missing upfront argument validation in send()

Empty reaction names or invalid count values are still allowed through, even though this was highlighted earlier. Surface these errors client-side to avoid needless network calls.

+        require(name.isNotBlank()) { "reaction name must not be blank" }
+        if (reactionType != MessageReactionType.Multiple && count != 1) {
+            throw clientError("count must be 1 for reaction type $reactionType")
+        }

352-355: Error message uses wrong variable and omits validation

$type may be null, resulting in a confusing exception message. Use reactionType, and enforce the same non-blank rule as in send().

-            throw clientError("cannot delete reaction of type $type without a name")
+            throw clientError("cannot delete reaction of type $reactionType without a name")

Also add require(!(name?.isBlank() ?: false)) for non-Unique deletions.

🧹 Nitpick comments (1)
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1)

270-276: Unbounded rawEventBus may lead to memory pressure

extraBufferCapacity = UNLIMITED risks OOM if the consumer lags. Consider a reasonable bound (e.g. 10 000) or use DROP_OLDEST with a finite buffer.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04dddcb and 1a10c14.

📒 Files selected for processing (12)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
🚧 Files skipped from review as they are similar to previous changes (9)
  • gradle/libs.versions.toml
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt
  • chat-android/src/main/java/com/ably/chat/Messages.kt
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt
  • chat-android/src/main/java/com/ably/chat/Message.kt
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build
  • GitHub Check: coverage
  • GitHub Check: check

@github-actions github-actions bot temporarily deployed to staging/pull/139/dokka June 18, 2025 09:19 Inactive
Copy link

github-actions bot commented Jun 18, 2025

@sacOO7
Copy link
Contributor

sacOO7 commented Jun 18, 2025

Spec PR -> ably/specification#319

Assert.assertEquals(ChannelMode.publish, capturedChannelOptions[0].modes[0])
Assert.assertEquals(ChannelMode.subscribe, capturedChannelOptions[0].modes[1])
Assert.assertEquals(ChannelMode.presence, capturedChannelOptions[0].modes[2])
Assert.assertEquals(ChannelMode.annotation_publish, capturedChannelOptions[0].modes[3])
Copy link
Contributor

@sacOO7 sacOO7 Jun 19, 2025

Choose a reason for hiding this comment

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

CHA-MR9, for future regressions, can you add buildRoomOptions with rawMessageReactions=true
We can assert on
Assert.assertEquals(ChannelMode.annotation_subscribe, capturedChannelOptions[0].modes[4])

@ttypic ttypic force-pushed the ECO-5065/room-reactions branch 2 times, most recently from 4c1ba0f to 0825b75 Compare June 19, 2025 11:36
@github-actions github-actions bot temporarily deployed to staging/pull/139/dokka June 19, 2025 11:39 Inactive
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

♻️ Duplicate comments (4)
chat-android/src/main/java/com/ably/chat/RoomOptions.kt (1)

244-259: Critical issue: annotation_publish is enabled unconditionally.

The ChannelMode.annotation_publish is added to all rooms regardless of whether reactions are enabled. This could cause permission errors with restricted API keys and unnecessarily widens the capability set.

The previous review comment about this issue has not been addressed. The code should conditionally add annotation_publish only when reactions are explicitly enabled:

-        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence, ChannelMode.annotation_publish)
+        val channelModes = mutableSetOf(ChannelMode.publish, ChannelMode.subscribe, ChannelMode.presence)
+
+        if (messages.rawMessageReactions) {
+            channelModes.add(ChannelMode.annotation_publish)
+        }
chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (3)

334-359: Add input validation for better error handling.

The send() method accepts any name (including empty/blank) and any count for all reaction types without validation. This can lead to unnecessary network calls and confusing server-side errors.

Add upfront validation as suggested in previous reviews:

 override suspend fun send(
     messageSerial: String,
     name: String,
     type: MessageReactionType?,
     count: Int,
 ) {
+    require(messageSerial.isNotBlank()) { "messageSerial must not be blank" }  
+    require(name.isNotBlank()) { "reaction name must not be blank" }
+    
     val reactionType = type ?: options.defaultMessageReactionType
+    
+    if (reactionType != MessageReactionType.Multiple && count != 1) {
+        throw clientError("count must be 1 for reaction type $reactionType")
+    }
 
     logger.trace(

361-383: Fix error message variable reference.

The error message on line 374 incorrectly references the nullable $type parameter instead of the non-null reactionType variable, which could display "null" in error messages.

+    require(messageSerial.isNotBlank()) { "messageSerial must not be blank" }
+    
     if (reactionType != MessageReactionType.Unique && name == null) {
-        throw clientError("cannot delete reaction of type $type without a name")
+        throw clientError("cannot delete reaction of type $reactionType without a name")
     }

394-401: Add validation for raw message reactions subscription.

The subscribeRaw() method should verify that raw message reactions are enabled before allowing subscription, as per specification CHA-MR7a.

 override fun subscribeRaw(listener: MessagesReactions.MessageRawReactionListener): Subscription {
+    if (!options.rawMessageReactions) {
+        throw clientError("Raw message reactions must be enabled to subscribe to raw events")
+    }
+    
     logger.trace("MessagesReactions.subscribeRaw()")
     rawEventlisteners.add(listener)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a10c14 and 0825b75.

📒 Files selected for processing (13)
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt (0 hunks)
  • chat-android/src/main/java/com/ably/chat/Message.kt (7 hunks)
  • chat-android/src/main/java/com/ably/chat/Messages.kt (4 hunks)
  • chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (1 hunks)
  • chat-android/src/main/java/com/ably/chat/RoomOptions.kt (7 hunks)
  • chat-android/src/test/java/com/ably/chat/MessageTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt (1 hunks)
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt (2 hunks)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • chat-android/src/main/java/com/ably/chat/EventTypes.kt
🚧 Files skipped from review as they are similar to previous changes (9)
  • chat-android/src/test/java/com/ably/chat/room/lifecycle/MonitoringTest.kt
  • gradle/libs.versions.toml
  • chat-android/src/test/java/com/ably/chat/room/RoomFeatureSharedChannelTest.kt
  • chat-android/src/test/java/com/ably/chat/MessagesTest.kt
  • chat-android/src/main/java/com/ably/chat/Messages.kt
  • chat-android/src/test/java/com/ably/chat/MessagesReactionsTest.kt
  • chat-android/src/main/java/com/ably/chat/ChatApi.kt
  • chat-android/src/main/java/com/ably/chat/Message.kt
  • chat-android/src/test/java/com/ably/chat/integration/MessageReactionsIntegrationTest.kt
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: coverage
  • GitHub Check: build
  • GitHub Check: check
🔇 Additional comments (16)
chat-android/src/test/java/com/ably/chat/MessageTest.kt (6)

18-42: LGTM! Version comparison logic test is well-structured.

The test correctly validates that when an event version is less than or equal to the current message version, the same message instance is returned (using assertSame). This prevents unnecessary updates and maintains referential equality.


47-67: LGTM! Message update test validates proper version handling.

The test correctly verifies that when an event has a higher version, the message content is updated with the event's data. The assertion checks the updated text content as expected.


72-95: LGTM! Serial mismatch validation is properly tested.

The test correctly validates that attempting to apply an event with a different serial throws an AblyException with the expected error code (40_000) and status code (400). This ensures data integrity.


100-127: LGTM! Reaction summary update test is comprehensive.

The test validates that applying a MessageReactionSummaryEvent correctly updates the message's reactions by comparing the expected updated message with the actual result. The test covers all reaction types (unique, distinct, multiple).


132-151: LGTM! Serial mismatch validation for reaction events is correct.

The test properly validates that applying a MessageReactionSummaryEvent with a different message serial throws an AblyException with appropriate error codes, maintaining data consistency.


178-196: LGTM! Helper function provides good test setup.

The createMessage helper function provides reasonable defaults and allows for easy customization of message properties in tests. The function covers all necessary fields for creating test messages.

chat-android/src/main/java/com/ably/chat/RoomOptions.kt (4)

18-41: LGTM! Non-nullable property change improves API clarity.

Converting the optional properties to non-nullable with the addition of the messages property makes the API more predictable and easier to use. The documentation is clear about the purpose of each property.


91-115: LGTM! MessageOptions interface is well-designed.

The interface provides clear configuration for message reactions with:

  • rawMessageReactions flag for controlling individual reaction events
  • defaultMessageReactionType for setting the default reaction behavior
  • Comprehensive documentation explaining the purpose and defaults

144-148: LGTM! Implementation classes provide sensible defaults.

The MutableMessageOptions class provides appropriate defaults:

  • rawMessageReactions = false (conservative default)
  • defaultMessageReactionType = MessageReactionType.Distinct (common use case)

254-256: LGTM! Conditional annotation_subscribe is correctly implemented.

The code properly adds ChannelMode.annotation_subscribe only when rawMessageReactions is enabled, which matches the expected behavior for subscribing to individual reaction events.

chat-android/src/main/java/com/ably/chat/MessagesReactions.kt (6)

22-86: LGTM! Comprehensive interface design for message reactions.

The MessagesReactions interface provides a well-structured API with:

  • Clear method signatures for send/delete operations
  • Proper separation of summary vs raw event subscriptions
  • Well-documented parameters and return types
  • Functional interfaces for event listeners

88-144: LGTM! Well-defined enums with proper documentation.

The enum definitions are comprehensive:

  • MessageReactionEventType covers create/delete actions
  • MessageReactionSummaryEventType for summary events
  • MessageReactionType with detailed spec references and use case examples
  • Proper companion object with utility method for type lookup

228-244: LGTM! Convenient extension functions for Message objects.

The extension functions provide a more intuitive API by accepting Message objects directly rather than requiring users to extract the serial manually. This improves developer experience.


272-332: LGTM! Well-structured implementation with proper resource management.

The DefaultMessagesReactions class demonstrates good practices:

  • Proper coroutine scope management with supervisor job
  • Thread-safe collections for listeners
  • Appropriate event bus configuration with buffer overflow handling
  • Proper subscription management and cleanup in dispose()

409-452: LGTM! Robust message summary event handling.

The internalMessageSummaryListener method properly:

  • Filters for summary events with serials
  • Handles empty summaries (when all reactions are deleted)
  • Correctly parses different reaction types from the summary
  • Emits well-formed events to the event bus

454-515: LGTM! Comprehensive annotation event handling.

The internalAnnotationListener method demonstrates excellent error handling:

  • Validates required fields with appropriate logging
  • Handles unknown types and actions gracefully
  • Special handling for unique reaction deletes (which may have empty names)
  • Proper default value handling for counts
  • Well-structured event creation and emission

@ttypic ttypic requested a review from sacOO7 June 20, 2025 12:31
@github-actions github-actions bot temporarily deployed to staging/pull/139/dokka June 20, 2025 12:33 Inactive
Copy link
Contributor

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

overall looks good to me ( apart from minor comments )

ttypic added 3 commits June 23, 2025 11:57
Introduced support for message reactions in the chat API, enabling the addition, deletion, and subscription to reactions. Implemented related interfaces, listeners, data types, and integration tests to ensure proper functionality and integration with messages.
…d error tests

Added validation to ensure `messageSerial` is not empty in `send`, `delete`, and `subscribeRaw` methods. Updated tests to cover validation scenarios.
Enhanced validation in the `send` method to ensure proper usage of `count`, `name`, and `type` parameters. Updated tests to cover new validation scenarios.
Copy link
Contributor

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

LGTM

@ttypic ttypic merged commit eaf0f83 into main Jun 23, 2025
4 of 5 checks passed
@ttypic ttypic deleted the ECO-5065/room-reactions branch June 23, 2025 12:24
@ttypic ttypic mentioned this pull request Jun 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants