fix: Prevent app remount when VoIP license/permission changes - #41200
Conversation
|
Looks like this PR is ready to merge! 🎉 |
🦋 Changeset detectedLatest commit: 62b3088 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
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 |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📜 Recent review details⏰ Context from checks skipped due to timeout. (2)
|
| Layer / File(s) | Summary |
|---|---|
App-level enabled computation apps/meteor/client/providers/MediaCallProvider.tsx |
Removes the unauthorized-context branch and computes enabled from teams-voip license module presence and internal/external voice call permissions, passing it to MediaCallProviderBase. |
ui-voip provider enabled wiring packages/ui-voip/src/providers/MediaCallProvider.tsx, packages/ui-voip/src/providers/MediaCallInstanceProvider.tsx, packages/ui-voip/src/providers/useMediaSessionInstance.ts |
Adds an optional enabled prop (default true) that is forwarded through the provider chain; widget UI/popout render only when enabled, and the media session store cleans up or returns null when disabled. |
Changeset entry .changeset/voip-provider-app-remount.md |
Adds a patch changeset for @rocket.chat/ui-voip and @rocket.chat/meteor describing the fix for full app remounting on VoIP availability changes. |
Estimated code review effort: 2 (Simple) | ~12 minutes
Suggested labels
Suggested labels: type: bug
Suggested reviewers
Suggested reviewers: gabriellsh, ggazzo
🚥 Pre-merge checks | ✅ 5
✅ 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 clearly matches the main change: preventing app remounts when VoIP license or permission state changes. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
Warning
Review ran into problems
🔥 Problems
Errors were encountered while retrieving linked issues.
Errors (1)
- CORE-2104: Request failed with status code 401
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #41200 +/- ##
===========================================
- Coverage 69.52% 69.47% -0.06%
===========================================
Files 3663 3663
Lines 145125 145119 -6
Branches 25726 25863 +137
===========================================
- Hits 100896 100818 -78
- Misses 39945 40000 +55
- Partials 4284 4301 +17
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ui-voip/src/providers/MediaCallInstanceProvider.tsx`:
- Around line 13-22: The current `MediaCallInstanceProvider` can orphan an
active call when `enabled` turns false because it stops rendering and passes
`undefined` into `useMediaSessionInstance` without explicitly ending the
existing session. Update `MediaCallInstanceProvider` so that `enabled` only
gates initialization when there is no active call, and ensure any live session
is explicitly torn down or preserved when `enabled` flips false mid-call. Use
`useMediaSessionInstance`, `openRoomId`, and `MediaCallInstanceProvider` as the
key places to adjust the lifecycle behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7eb80485-4867-423c-97d6-cdd9bc85c57c
📒 Files selected for processing (4)
.changeset/voip-provider-app-remount.mdapps/meteor/client/providers/MediaCallProvider.tsxpackages/ui-voip/src/providers/MediaCallInstanceProvider.tsxpackages/ui-voip/src/providers/MediaCallProvider.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: cubic · AI code reviewer
- GitHub Check: Hacktron Security Check
- GitHub Check: 🚢 Build Docker (arm64, authorization-service, queue-worker-service, ddp-streamer-service, cove...
🧰 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/ui-voip/src/providers/MediaCallInstanceProvider.tsxpackages/ui-voip/src/providers/MediaCallProvider.tsxapps/meteor/client/providers/MediaCallProvider.tsx
🧠 Learnings (5)
📚 Learning: 2026-03-16T21:50:37.589Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: .changeset/migrate-users-register-openapi.md:3-3
Timestamp: 2026-03-16T21:50:37.589Z
Learning: For changes related to OpenAPI migrations in Rocket.Chat/OpenAPI, when removing endpoint types and validators from rocket.chat/rest-typings (e.g., UserRegisterParamsPOST, /v1/users.register) document this as a minor changeset (not breaking) per RocketChat/Rocket.Chat-Open-API#150 Rule 7. Note that the endpoint type is re-exposed via a module augmentation .d.ts in the consuming package (e.g., packages/web-ui-registration/src/users-register.d.ts). In reviews, ensure the changeset clearly states: this is a non-breaking change, the major version should not be bumped, and the changeset reflects a minor version bump. Do not treat this as a breaking change during OpenAPI migrations.
Applied to files:
.changeset/voip-provider-app-remount.md
📚 Learning: 2026-02-26T19:22:29.385Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/views/CallHistoryContextualbar/CallHistoryActions.tsx:40-40
Timestamp: 2026-02-26T19:22:29.385Z
Learning: For TSX files in the UI VOIP package, ensure that when a media session state is 'unavailable', the voiceCall action is excluded from the actions object passed to CallHistoryActions so it does not render in the menu. This filtering should occur upstream (before getItems is called) to avoid tooltips or UI hints for unavailable actions. If there are multiple actions with availability states, implement a centralized helper to filter actions based on session state.
Applied to files:
packages/ui-voip/src/providers/MediaCallInstanceProvider.tsxpackages/ui-voip/src/providers/MediaCallProvider.tsx
📚 Learning: 2026-05-05T12:34:29.042Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 40331
File: packages/ui-voip/src/views/MediaCallWidget/OngoingCallWithScreen.tsx:69-69
Timestamp: 2026-05-05T12:34:29.042Z
Learning: In Rocket.Chat’s `packages/ui-voip` UI (e.g., media/call widgets), voice/media calls are only supported in Direct Message (DM) rooms. Rocket.Chat models a DM as a “room” with exactly two participants, so handlers like `onClickDirectMessage` are the correct destination—even when the UI text/element says “Open in room” (e.g., on the shared screen card/`StreamCard`). During review, don’t flag a “DM vs room” mismatch for these cases; they intentionally map to the same destination.
Applied to files:
packages/ui-voip/src/providers/MediaCallInstanceProvider.tsxpackages/ui-voip/src/providers/MediaCallProvider.tsx
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.
Applied to files:
packages/ui-voip/src/providers/MediaCallInstanceProvider.tsxpackages/ui-voip/src/providers/MediaCallProvider.tsxapps/meteor/client/providers/MediaCallProvider.tsx
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.
Applied to files:
packages/ui-voip/src/providers/MediaCallInstanceProvider.tsxpackages/ui-voip/src/providers/MediaCallProvider.tsxapps/meteor/client/providers/MediaCallProvider.tsx
🔇 Additional comments (3)
apps/meteor/client/providers/MediaCallProvider.tsx (1)
1-16: LGTM!packages/ui-voip/src/providers/MediaCallProvider.tsx (1)
9-30: LGTM!.changeset/voip-provider-app-remount.md (1)
1-6: LGTM!
There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Proposed changes (including videos or screenshots)
Introduced here: #36717
Issue found while working here: #40916
Problem
MediaCallProvider wraps the entire app, and it returned two different components depending on whether VoIP was available:
When the teams-voip license module (or a call permission) changed, children moved from one component type to another. React treats that as a different tree, so it unmounted and remounted the whole app — the sidebar visibly flashed and the VoIP session disconnected/reconnected.
Fix
Always render the same provider and pass an enabled flag, so toggling access only starts/stops the VoIP session internally instead of swapping the tree:
MediaCallProvider(ui-voip) andMediaCallInstanceProvidernow accept enabled. When disabled, they keep the provider mounted but create no VoIP session and skip the call UI.<MediaCallProviderBase enabled={hasModule && (canMakeInternalCall || canMakeExternalCall)}>, dropping the swapped stub branch.Issue(s)
Steps to test or reproduce
Further comments
CORE-2104
Summary by CodeRabbit