Skip to content

Conversation

@aleksandernsilva
Copy link
Contributor

@aleksandernsilva aleksandernsilva commented Nov 28, 2025

Proposed changes (including videos or screenshots)

This pull request adds a visual badge for invited users in the room members contextual. The changes also add a new story and snapshot test for rooms with invited members.

Screenshot 2025-12-01 at 10 22 51

Issue(s)

FB-63

Steps to test or reproduce

ℹ️ Currently invitation requests are only available for federated rooms.
ℹ️ You'll need two workspaces with federation enabled (I'll refer to them as ws-a and ws-b)

  • Create a room federated room (ws-a)
  • Invite an user from ws-b to the room (ws-a)
  • Send a message
  • Access members list in the room toolbox
  • Invited status should be displayed besides the inviter user

Further comments

Summary by CodeRabbit

  • New Features

    • Room members list displays an invitation badge for invited members.
  • Storybook

    • Added a story demonstrating an invited-member scenario to preview invitation UI and controls.
  • Refactor

    • Member-related components and props updated to carry subscription/invitation data for consistent rendering.
  • API & Types

    • Direct-message members endpoint and public typings now include per-member subscription info so invitation status is exposed.

✏️ Tip: You can customize this high-level summary in your review settings.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Nov 28, 2025

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Nov 28, 2025

🦋 Changeset detected

Latest commit: 99bf882

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 42 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/apps Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/freeswitch Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/model-typings Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-client Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/ui-voip Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/stream-hub-service Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/models Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 28, 2025

Walkthrough

Adds per-member subscription data end-to-end: server augments members with subscription docs, REST typings and client hook types include subscription, RoomMembers components thread and render an InvitationBadge for subscription?.status === 'INVITED', and Storybook adds a story showing an invited member.

Changes

Cohort / File(s) Summary
Types / Hook
apps/meteor/client/views/hooks/useMembersList.ts
Expands RoomMember to a Serialized<...> shape, adds federated and roles typing, and includes `subscription: Pick<ISubscription, '_id'
Components
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx, apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx, apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
Replace local RoomMemberUser/IUser props with imported RoomMember; thread subscription from list → row → item; RoomMembersItem renders InvitationBadge when subscription?.status === 'INVITED'.
Storybook
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
Adds exported story WithInvitedMember (Template.bind) whose args include a member with subscription.status === 'INVITED'.
Server API
apps/meteor/app/api/server/v1/im.ts, packages/rest-typings/src/v1/dm/im.ts
im.members endpoint now queries Subscriptions for member IDs, merges subscription into each member object, and REST typings updated to include subscription in responses.
Changeset
.changeset/nasty-moons-speak.md
Adds note about invitation badge and bumps package version via changeset.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client (UI / Storybook)
    participant Server as API Server (/v1/im.members)
    participant DB as Subscriptions Collection
    participant Members as Members Retrieval Logic

    Client->>Server: GET /v1/im.members?roomId=...
    Server->>Members: fetch members for roomId
    Members-->>Server: members[] (user objects)
    Server->>DB: find subscriptions by roomId & userIds
    DB-->>Server: subscriptions[] (subscription docs)
    Server->>Server: merge subscriptions into members by userId
    Server-->>Client: 200 OK { members: [ { ..., subscription: { _id, status, ts, roles } }, ... ] }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review RoomMember Serialized wrapper and subscription shape versus ISubscription in useMembersList.ts.
  • Verify optional access and null-safety for subscription across RoomMembers → Row → Item.
  • Inspect server merge logic in apps/meteor/app/api/server/v1/im.ts for correct mapping and missing-subscription handling.
  • Confirm REST typing in packages/rest-typings/src/v1/dm/im.ts matches runtime response.

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • ggazzo
  • gabriellsh

Poem

🐰 I hopped through types and threads today,
I tucked a tiny badge where invites stay,
When INVITED sparkles, a ribbon does appear,
I twitch my nose — the members cheer,
🥕 small badge, big delight!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding an invitation badge to the room members list, which is fully reflected in the code changes.
Linked Issues check ✅ Passed The PR implements the invitation badge for room members list as required by FB-63, adding visual indicators and supporting UI components with proper data flow.
Out of Scope Changes check ✅ Passed All changes are within scope: they extend the RoomMember type with subscription data, add InvitationBadge rendering, update API endpoints and type signatures, and add corresponding stories and tests for the feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/members-list-invite-badge

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.

@aleksandernsilva
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

✅ 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.

Copy link
Contributor

@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

🧹 Nitpick comments (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1)

1-6: Shared RoomMemberUser type looks correct; consider reusing IUser['roles'] to avoid duplication

The alias cleanly centralizes the member shape and the status?: UserStatus | SubscriptionStatus union fits the invited-member use case.

You can make the roles typing more robust (and drop the IRole import) by reusing the existing IUser.roles definition instead of duplicating IRole['_id'][]:

-import type { IUser, IRole, SubscriptionStatus, UserStatus } from '@rocket.chat/core-typings';
-
-export type RoomMemberUser = Pick<IUser, 'username' | '_id' | 'name' | 'freeSwitchExtension' | 'federated'> & {
-	roles?: IRole['_id'][];
-	status?: UserStatus | SubscriptionStatus;
-};
+import type { IUser, SubscriptionStatus, UserStatus } from '@rocket.chat/core-typings';
+
+export type RoomMemberUser = Pick<IUser, 'username' | '_id' | 'name' | 'freeSwitchExtension' | 'federated'> &
+	Partial<Pick<IUser, 'roles'>> & {
+		status?: UserStatus | SubscriptionStatus;
+	};
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

96-96: Clarify isABACRoom configuration.

Setting isABACRoom: true in the invited member story appears unrelated to the invitation feature. This should likely be false to isolate the invitation badge functionality, unless ABAC rooms have specific invitation behavior.

Consider applying this diff if ABAC is not relevant to the invitation scenario:

 	reload: action('reload'),
-	isABACRoom: true,
+	isABACRoom: false,
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 54a4be7 and cd472aa.

⛔ Files ignored due to path filters (1)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/__snapshots__/RoomMembers.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (7)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (3 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/badges/InvitationBadge.tsx (1 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1 hunks)
  • packages/i18n/src/locales/en.i18n.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/badges/InvitationBadge.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
🧠 Learnings (7)
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
📚 Learning: 2025-11-17T15:07:13.273Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37398
File: packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx:357-363
Timestamp: 2025-11-17T15:07:13.273Z
Learning: In packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx, IconElement is a presentational, non-actionable element that does not require wrapping in AppIdProvider, similar to plain_text and mrkdwn renderers. Only actionable elements (those with actions, actionId, or interactive behavior) should be wrapped in AppIdProvider.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/badges/InvitationBadge.tsx
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • packages/i18n/src/locales/en.i18n.json
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
🧬 Code graph analysis (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1)
  • RoomMemberUser (3-6)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (1)
apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1)
  • RoomMemberUser (3-6)
🔇 Additional comments (4)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (1)

1-41: LGTM! Type refactoring is clean.

The migration from local type definition to centralized RoomMemberUser type improves maintainability, and the new status prop is correctly wired to RoomMembersItem.

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (1)

1-12: LGTM! Type centralization is consistent.

Moving the RoomMemberUser type to a dedicated types module improves code organization and reusability.

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (1)

19-20: LGTM! Invitation badge integration is well-structured.

The component correctly:

  • Uses the centralized RoomMemberUser type
  • Conditionally renders InvitationBadge for invited members
  • Wraps the badge in OptionColumn for proper layout

The string literal comparison status === 'INVITED' should be verified to match the enum definition (see verification comment in the stories file).

Also applies to: 25-30, 37-37, 63-67

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

82-82: Remove this comment—'INVITED' is a valid SubscriptionStatus value.

SubscriptionStatus is defined as type SubscriptionStatus = 'INVITED' in packages/core-typings/src/ISubscription.ts. The status value in the story correctly uses this type.

@ggazzo ggazzo force-pushed the feat/invites branch 2 times, most recently from b2cc5c0 to 0d14b19 Compare December 3, 2025 18:49
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from cd472aa to 8316778 Compare December 3, 2025 19:42
@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

📦 Docker Image Size Report

📉 Changes

Service Current Baseline Change Percent
sum of all images 1.2GiB 1.2GiB -31MiB
rocketchat 358MiB 347MiB +12MiB
omnichannel-transcript-service 132MiB 132MiB -553B
queue-worker-service 132MiB 132MiB -1.4KiB
ddp-streamer-service 126MiB 168MiB -43MiB
account-service 113MiB 113MiB -529B
authorization-service 111MiB 111MiB -2.2KiB
stream-hub-service 111MiB 111MiB -773B
presence-service 111MiB 111MiB -372B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/15 22:28", "11/16 01:28", "11/17 23:50", "11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 22:56", "12/19 23:14 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.16, 0.12]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "queue-worker-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
  line "rocketchat" [0.36, 0.36, 0.35, 0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.35]
  line "stream-hub-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
Loading

Statistics (last 25 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.2GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 1.2GiB
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-37643
  • Baseline: develop
  • Timestamp: 2025-12-19 23:14:28 UTC
  • Historical data points: 25

Updated: Fri, 19 Dec 2025 23:14:29 GMT

@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 67.69%. Comparing base (700fc7f) to head (99bf882).
⚠️ Report is 4 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37643      +/-   ##
===========================================
- Coverage    67.71%   67.69%   -0.02%     
===========================================
  Files         3475     3475              
  Lines       113861   113860       -1     
  Branches     20942    20943       +1     
===========================================
- Hits         77097    77080      -17     
- Misses       34579    34592      +13     
- Partials      2185     2188       +3     
Flag Coverage Δ
e2e 57.18% <80.00%> (-0.02%) ⬇️
e2e-api 44.01% <ø> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch 3 times, most recently from bc5722b to 9c7345e Compare December 8, 2025 00:59
@sampaiodiego sampaiodiego force-pushed the feat/invites branch 2 times, most recently from c420eb2 to 36e006f Compare December 8, 2025 14:17
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from 9c7345e to b243f28 Compare December 8, 2025 17:53
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from b243f28 to 2fe6480 Compare December 8, 2025 23:11
Base automatically changed from feat/invites to develop December 10, 2025 01:45
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from 2fe6480 to ffa1368 Compare December 10, 2025 19:45
@aleksandernsilva aleksandernsilva changed the title feat: Added invitation badge to room members list feat(federation): Added invitation badge to room members list Dec 10, 2025
@aleksandernsilva aleksandernsilva changed the title feat(federation): Added invitation badge to room members list feat: Added invitation badge to room members list Dec 10, 2025
@tassoevan tassoevan requested a review from ggazzo December 19, 2025 14:09
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch 3 times, most recently from 8b4ed2f to 2e911d6 Compare December 19, 2025 20:31
Copy link
Contributor

@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

🧹 Nitpick comments (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

101-101: Clarify the necessity of isABACRoom: true for this story.

The WithInvitedMember story demonstrates invitation status, but setting isABACRoom: true appears unrelated to the invitation feature. Is this flag necessary, or was it copied from the WithABACRoom story?

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (1)

63-67: Consider using a constant for the status comparison.

The conditional rendering logic is correct, but the string literal 'INVITED' could be replaced with a constant or enum value for better type safety and maintainability.

🔎 Suggested refactor using a constant

If a SubscriptionStatus constant/enum is available, consider:

-{subscription?.status === 'INVITED' && (
+{subscription?.status === SubscriptionStatus.INVITED && (
  <OptionColumn>
    <InvitationBadge mbs={2} size='x20' invitationDate={subscription.ts} />
  </OptionColumn>
)}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8b4ed2f and 2e911d6.

⛔ Files ignored due to path filters (1)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/__snapshots__/RoomMembers.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (6)
  • .changeset/nasty-moons-speak.md (1 hunks)
  • apps/meteor/client/views/hooks/useMembersList.ts (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (4 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (4 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • .changeset/nasty-moons-speak.md
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
🧠 Learnings (5)
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
🧬 Code graph analysis (1)
apps/meteor/client/views/hooks/useMembersList.ts (1)
packages/core-typings/src/ISubscription.ts (1)
  • ISubscription (11-81)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (2)
apps/meteor/client/views/hooks/useMembersList.ts (1)

23-28: LGTM! Type definition properly extended.

The RoomMember type is appropriately wrapped in Serialized<> for API data and includes the optional subscription field. The use of Pick<ISubscription, ...> correctly selects only the necessary subscription fields.

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

85-85: No changes needed. The string literal 'INVITED' is already type-safe and the correct way to satisfy the SubscriptionStatus type in core-typings. SubscriptionStatus is a type alias with only one valid value ('INVITED'), not an enum, so there is no constant to import. The subscription object is properly typed without modification.

Likely an incorrect or invalid review comment.

@sampaiodiego sampaiodiego force-pushed the feat/members-list-invite-badge branch from 2e911d6 to 5f4b7b0 Compare December 19, 2025 21:43
@sampaiodiego sampaiodiego requested review from a team as code owners December 19, 2025 21:43
Copy link
Contributor

@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

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2e911d6 and 5f4b7b0.

⛔ Files ignored due to path filters (1)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/__snapshots__/RoomMembers.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • .changeset/nasty-moons-speak.md (1 hunks)
  • apps/meteor/app/api/server/v1/im.ts (1 hunks)
  • apps/meteor/client/views/hooks/useMembersList.ts (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (4 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (4 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (2 hunks)
  • packages/rest-typings/src/v1/dm/im.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .changeset/nasty-moons-speak.md
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/app/api/server/v1/im.ts
  • packages/rest-typings/src/v1/dm/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
🧠 Learnings (6)
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/app/api/server/v1/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/app/api/server/v1/im.ts
  • packages/rest-typings/src/v1/dm/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • packages/rest-typings/src/v1/dm/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/rest-typings/src/v1/dm/im.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
🧬 Code graph analysis (3)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (1)
apps/meteor/client/views/hooks/useMembersList.ts (1)
  • RoomMember (23-28)
packages/rest-typings/src/v1/dm/im.ts (1)
packages/core-typings/src/ISubscription.ts (1)
  • ISubscription (11-81)
apps/meteor/client/views/hooks/useMembersList.ts (1)
packages/core-typings/src/ISubscription.ts (1)
  • ISubscription (11-81)
🔇 Additional comments (4)
apps/meteor/app/api/server/v1/im.ts (1)

419-432: LGTM! Subscription augmentation logic is correct.

The implementation correctly fetches subscriptions for room members and merges them into the response. The use of Array.find appropriately handles cases where a subscription may not exist for a member, resulting in undefined, which aligns with the optional subscription field in the type definitions.

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (1)

1-1: LGTM! Type updates are consistent.

The transition from RoomMemberUser to the imported RoomMember type correctly reflects the new data structure that includes optional subscription information. The changes are purely type-level with no behavioral modifications.

Also applies to: 25-25, 36-36, 93-96

apps/meteor/client/views/hooks/useMembersList.ts (1)

1-1: LGTM! Type definitions are well-structured.

The RoomMember type correctly:

  • Uses Serialized<> wrapper for proper date handling
  • Marks subscription as optional with ?, aligning with the discussion in past review comments
  • Includes the necessary subscription fields for invitation status tracking

The type structure is consistent across the client-side codebase.

Also applies to: 23-28, 30-35

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

85-85: 'INVITED' is the valid SubscriptionStatus value.

The SubscriptionStatus type is defined as 'INVITED' in the codebase (packages/core-typings/src/ISubscription.ts), making it the only valid value for ISubscription.status.

isTeam: false,
isDirect: false,
reload: action('reload'),
isABACRoom: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect prop value: isABACRoom should be false.

The WithInvitedMember story demonstrates invitation functionality, not ABAC room behavior. Setting isABACRoom: true appears to be a copy-paste error from the WithABACRoom story and will disable the invite button.

🔎 Proposed fix
-	isABACRoom: true,
+	isABACRoom: false,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isABACRoom: true,
isABACRoom: false,
🤖 Prompt for AI Agents
In
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
around line 101, the WithInvitedMember story incorrectly sets isABACRoom: true
which disables invite behavior; change this prop to isABACRoom: false so the
invite button and invitation flow work as intended. Update the story prop value
accordingly and run the story to verify the invite button is enabled.

Comment on lines 52 to 53
members: Pick<IUser, '_id' | 'status' | 'name' | 'username' | 'utcOffset'> &
{ subscription: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'> }[];
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix type syntax and make subscription optional.

Two issues:

  1. Array bracket placement error: The [] is positioned incorrectly, causing TypeScript to interpret subscription as an array property rather than an array of member objects. The type should wrap the entire intersection in parentheses.

  2. Missing optional marker: Based on the past review discussion, subscription should be optional since this type is shared between endpoints where not all have subscription support yet.

🔎 Proposed fix
-		members: Pick<IUser, '_id' | 'status' | 'name' | 'username' | 'utcOffset'> &
-			{ subscription: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'> }[];
+		members: (Pick<IUser, '_id' | 'status' | 'name' | 'username' | 'utcOffset'> & {
+			subscription?: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'>;
+		})[];
🤖 Prompt for AI Agents
In packages/rest-typings/src/v1/dm/im.ts around lines 52-53, the member type
currently places the array brackets incorrectly and marks subscription as
required; wrap the entire intersection in parentheses so the array applies to
the whole member shape (i.e. (A & B)[]), and make the subscription property
optional by adding a ? to its key so the type becomes (Pick<IUser, '...'> & {
subscription?: Pick<ISubscription, '...'> })[] — update the line accordingly.

@sampaiodiego sampaiodiego force-pushed the feat/members-list-invite-badge branch from 23da6ed to 99bf882 Compare December 19, 2025 22:36
Copy link
Contributor

@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)
packages/rest-typings/src/v1/dm/im.ts (1)

52-54: Make subscription optional to support endpoints without invitation support.

As discussed in the previous review, the subscription field should be optional since this type is shared between /v1/im.members and /v1/rooms.membersOrderedByRole, where the latter doesn't have invitation support yet.

🔎 Proposed fix
 		members: (Pick<IUser, '_id' | 'status' | 'name' | 'username' | 'utcOffset'> & {
-			subscription: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'>;
+			subscription?: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'>;
 		})[];
apps/meteor/client/views/hooks/useMembersList.ts (1)

23-27: Make subscription optional to align with REST API types.

The subscription field should be optional to match the REST API type definition. Since the type is shared between endpoints where not all have subscription support, making this field optional ensures type consistency across the stack.

🔎 Proposed fix
 export type RoomMember = Serialized<
 	Pick<IUser, 'username' | '_id' | 'name' | 'status' | 'federated' | 'freeSwitchExtension'> & { roles?: IRole['_id'][] } & {
-		subscription: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'>;
+		subscription?: Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'>;
 	}
 >;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 23da6ed and 99bf882.

📒 Files selected for processing (5)
  • .changeset/nasty-moons-speak.md (1 hunks)
  • apps/meteor/app/api/server/v1/im.ts (1 hunks)
  • apps/meteor/client/views/hooks/useMembersList.ts (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (2 hunks)
  • packages/rest-typings/src/v1/dm/im.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • packages/rest-typings/src/v1/dm/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/app/api/server/v1/im.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • .changeset/nasty-moons-speak.md
  • packages/rest-typings/src/v1/dm/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • .changeset/nasty-moons-speak.md
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/rest-typings/src/v1/dm/im.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • packages/rest-typings/src/v1/dm/im.ts
  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/app/api/server/v1/im.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
  • apps/meteor/app/api/server/v1/im.ts
🧬 Code graph analysis (2)
packages/rest-typings/src/v1/dm/im.ts (1)
packages/core-typings/src/ISubscription.ts (1)
  • ISubscription (11-81)
apps/meteor/client/views/hooks/useMembersList.ts (2)
packages/apps/src/AppsEngine.ts (1)
  • IRole (15-15)
packages/core-typings/src/ISubscription.ts (1)
  • ISubscription (11-81)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (1)
.changeset/nasty-moons-speak.md (1)

1-5: LGTM!

The changeset is properly formatted with the correct version bump (patch) and an accurate description of the feature.

Comment on lines +426 to +435
const membersWithSubscriptionInfo = members.map((member) => {
const sub = subs.find((sub) => sub.u._id === member._id);

const { u: _u, ...subscription } = sub || {};

return {
...member,
subscription,
};
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix type safety issue with subscription fallback.

When a subscription is not found, the current code creates an empty object {} instead of undefined. This results in a subscription field that doesn't match the expected type Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'>, potentially causing runtime errors when components try to access properties like subscription._id or subscription.status.

🔎 Proposed fix
 		const membersWithSubscriptionInfo = members.map((member) => {
 			const sub = subs.find((sub) => sub.u._id === member._id);
 
-			const { u: _u, ...subscription } = sub || {};
-
-			return {
-				...member,
-				subscription,
-			};
+			if (!sub) {
+				return member;
+			}
+
+			const { u: _u, ...subscription } = sub;
+
+			return {
+				...member,
+				subscription,
+			};
 		});
🤖 Prompt for AI Agents
In apps/meteor/app/api/server/v1/im.ts around lines 426 to 435, the mapping
creates an empty object when no subscription is found which breaks the expected
Pick<ISubscription, '_id' | 'status' | 'ts' | 'roles'> type; update the map so
that when subs.find(...) returns undefined you set subscription to undefined
(not {}), and when a sub exists explicitly pick only the allowed fields (or
construct the Pick) before returning — i.e. guard the destructure against
undefined and assign subscription = undefined when absent, or subscription = {
_id: sub._id, status: sub.status, ts: sub.ts, roles: sub.roles } when present.

@sampaiodiego sampaiodiego merged commit 0b39d87 into develop Dec 19, 2025
51 checks passed
@sampaiodiego sampaiodiego deleted the feat/members-list-invite-badge branch December 19, 2025 23:56
gaolin1 pushed a commit to gaolin1/medsense.webchat that referenced this pull request Jan 6, 2026
Co-authored-by: Diego Sampaio <chinello@gmail.com>
@dougfabris dougfabris modified the milestones: 7.14.0, 8.0.0 Jan 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants