feat(voip): navigate to call DM from message button and header#7082
feat(voip): navigate to call DM from message button and header#7082diegolmello merged 15 commits intofeat.voip-lib-newfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds per-call Changes
Sequence DiagramssequenceDiagram
participant User
participant CallUI as Call UI
participant Store as Call Store
participant DB as Database
participant Nav as Navigation
rect rgba(100, 150, 200, 0.5)
Note over CallUI,Store: Incoming non‑SIP call handling
CallUI->>Store: persist incoming call (with contact)
alt store.roomId is null and contact.username exists
Store->>DB: getDMSubscriptionByUsername(username)
DB-->>Store: return subscription {rid}
Store->>Store: setRoomId(rid)
end
end
rect rgba(150, 100, 200, 0.5)
Note over User,Nav: User presses Message button
User->>CallUI: press message button
CallUI->>Store: read contact & roomId
alt contact.sipExtension present or roomId null
CallUI->>CallUI: no action (button disabled)
else valid DM call
CallUI->>Nav: navigateToCallRoom()
Nav->>Nav: ensure stack routing (maybe navigate to ChatsStackNavigator)
Nav->>Nav: goRoom({ rid, name, t: DIRECT }, isMasterDetail)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (4)
app/lib/services/voip/MediaSessionInstance.ts (1)
171-171: Use object destructuring per ESLintprefer-destructuring.🔧 Proposed fix
-const username = contact.username; +const { username } = contact;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/lib/services/voip/MediaSessionInstance.ts` at line 171, In MediaSessionInstance, replace the direct property access "const username = contact.username" by using object destructuring to satisfy ESLint prefer-destructuring; e.g., destructure username from contact (const { username } = contact) where the variable is declared, ensuring subsequent references still use the new username binding.app/lib/database/services/Subscription.test.ts (1)
27-43: Consider adding a test for the falsy username early return.The
getDMSubscriptionByUsernamefunction has an early return whenusernameis falsy (empty string, null, undefined). Adding a test for this branch would improve coverage.📝 Suggested test case
it('returns null when username is empty', async () => { const result = await getDMSubscriptionByUsername(''); expect(result).toBeNull(); expect(mockGet).not.toHaveBeenCalled(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/lib/database/services/Subscription.test.ts` around lines 27 - 43, Add a unit test for the early-return branch in getDMSubscriptionByUsername that verifies a falsy username (e.g., empty string) immediately returns null and does not call the database; specifically, add a test case that calls getDMSubscriptionByUsername('') (or null/undefined) and asserts the result is null and that mockGet (the mocked SUBSCRIPTIONS_TABLE accessor used in other tests) was not invoked.app/views/CallView/components/CallButtons.tsx (1)
31-31: Consider!roomIdinstead ofroomId == nullfor consistency.While
roomId == nullworks correctly (covers bothnullandundefined), using!roomIdwould be more consistent with theBoolean(contact.sipExtension)pattern on the same line. Both are valid; this is a minor style consideration.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/views/CallView/components/CallButtons.tsx` at line 31, The expression computing messageDisabled uses mixed styles—Boolean(contact.sipExtension) vs roomId == null—so change the roomId check to use the falsy check (!roomId) for consistency; update the messageDisabled assignment (symbol: messageDisabled) to Boolean(contact.sipExtension) || !roomId (symbols: contact.sipExtension, roomId) ensuring behavior remains the same (covers null/undefined/empty falsy values).app/lib/services/voip/navigateToCallRoom.ts (1)
31-34: Consider potential timing betweentoggleFocusandNavigation.navigate.When
focusedis true,toggleFocus()is called synchronously, but the UI animation may still be in progress whenNavigation.navigate('ChatsStackNavigator')executes. If users report visual glitches, you may need to introduce a small delay or await the focus toggle completion.This is a minor observation - the current implementation should work in most cases.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/lib/services/voip/navigateToCallRoom.ts` around lines 31 - 34, The current code calls toggleFocus() synchronously then immediately uses Navigation.navigate('ChatsStackNavigator'), which can cause visual glitches if the focus animation is still running; in navigateToCallRoom, ensure navigation waits until the focus toggle completes by either awaiting toggleFocus() if it returns a Promise or deferring Navigation.navigate using InteractionManager.runAfterInteractions (or a short setTimeout/requestAnimationFrame) so the UI animation finishes before calling Navigation.navigate; update the logic around toggleFocus, Navigation.getCurrentRoute and the Navigation.navigate('ChatsStackNavigator') call accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/containers/MediaCallHeader/components/Content.tsx`:
- Line 31: The onPress handler in Content.tsx uses the `void` operator
(`onPress={() => void navigateToCallRoom()}`) which violates ESLint's no-void
rule; remove the `void` and either call `navigateToCallRoom()` directly in the
arrow handler (`onPress={() => navigateToCallRoom()}`) or convert the handler to
an async function and `await navigateToCallRoom()` inside it (e.g.,
`onPress={async () => { await navigateToCallRoom(); }}`), referencing the
`navigateToCallRoom` function and the `onPress` handler in the Content
component.
In `@app/lib/services/voip/MediaSessionInstance.test.ts`:
- Around line 1-6: ESLint wants a blank line separating type-only imports (e.g.,
IClientMediaCall, IDDPMessage) from value imports (e.g., waitFor,
getDMSubscriptionByUsername, getUidDirectMessage, mediaSessionStore); fix by
grouping all "import type" lines together and inserting a single blank line
before the first non-type import (ensure the imports for IClientMediaCall and
IDDPMessage remain as type imports and that waitFor,
getDMSubscriptionByUsername, getUidDirectMessage, and mediaSessionStore are in
the following group).
In `@app/lib/services/voip/MediaSessionInstance.ts`:
- Around line 96-98: The current fire-and-forget call uses the banned `void`
operator on resolveRoomIdFromContact; replace it with a promise-catch pattern so
the promise is started and any errors are handled. Specifically, in the block
that checks useCallStore.getState().roomId == null, call
this.resolveRoomIdFromContact(call.contact).catch(err => { /* log or ignore
error */ }) so you remove the `void` operator and handle errors from
resolveRoomIdFromContact(call.contact).
- Line 126: Replace the "void this.resolveRoomIdFromContact(mainCall.contact)"
call to avoid the ESLint no-void violation by calling
this.resolveRoomIdFromContact(mainCall.contact).catch(...) instead; locate the
call in MediaSessionInstance (where resolveRoomIdFromContact is invoked with
mainCall.contact) and append a .catch handler that logs or handles the error
appropriately (use the existing logger or error handling pattern in the class)
so the promise rejection is handled without using void.
In `@app/views/CallView/components/CallButtons.tsx`:
- Around line 33-35: The handleMessage function currently uses the void operator
(void navigateToCallRoom()) which violates the no-void ESLint rule; update
handleMessage to either call navigateToCallRoom() and attach an explicit no-op
catch (e.g., navigateToCallRoom().catch(() => {})) or make handleMessage async
and await navigateToCallRoom() (i.e., async function handleMessage() { await
navigateToCallRoom(); }) so that unhandled promise rejections are handled and
the linter error is resolved; locate handleMessage and navigateToCallRoom in
CallButtons.tsx to apply the change.
---
Nitpick comments:
In `@app/lib/database/services/Subscription.test.ts`:
- Around line 27-43: Add a unit test for the early-return branch in
getDMSubscriptionByUsername that verifies a falsy username (e.g., empty string)
immediately returns null and does not call the database; specifically, add a
test case that calls getDMSubscriptionByUsername('') (or null/undefined) and
asserts the result is null and that mockGet (the mocked SUBSCRIPTIONS_TABLE
accessor used in other tests) was not invoked.
In `@app/lib/services/voip/MediaSessionInstance.ts`:
- Line 171: In MediaSessionInstance, replace the direct property access "const
username = contact.username" by using object destructuring to satisfy ESLint
prefer-destructuring; e.g., destructure username from contact (const { username
} = contact) where the variable is declared, ensuring subsequent references
still use the new username binding.
In `@app/lib/services/voip/navigateToCallRoom.ts`:
- Around line 31-34: The current code calls toggleFocus() synchronously then
immediately uses Navigation.navigate('ChatsStackNavigator'), which can cause
visual glitches if the focus animation is still running; in navigateToCallRoom,
ensure navigation waits until the focus toggle completes by either awaiting
toggleFocus() if it returns a Promise or deferring Navigation.navigate using
InteractionManager.runAfterInteractions (or a short
setTimeout/requestAnimationFrame) so the UI animation finishes before calling
Navigation.navigate; update the logic around toggleFocus,
Navigation.getCurrentRoute and the Navigation.navigate('ChatsStackNavigator')
call accordingly.
In `@app/views/CallView/components/CallButtons.tsx`:
- Line 31: The expression computing messageDisabled uses mixed
styles—Boolean(contact.sipExtension) vs roomId == null—so change the roomId
check to use the falsy check (!roomId) for consistency; update the
messageDisabled assignment (symbol: messageDisabled) to
Boolean(contact.sipExtension) || !roomId (symbols: contact.sipExtension, roomId)
ensuring behavior remains the same (covers null/undefined/empty falsy values).
🪄 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: 68498b5f-5670-4ad7-9669-ea6b0aeb5ebd
⛔ Files ignored due to path filters (2)
app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snapis excluded by!**/*.snapapp/views/CallView/__snapshots__/index.test.tsx.snapis excluded by!**/*.snap
📒 Files selected for processing (14)
app/containers/MediaCallHeader/MediaCallHeader.stories.tsxapp/containers/MediaCallHeader/MediaCallHeader.test.tsxapp/containers/MediaCallHeader/components/Content.tsxapp/lib/database/services/Subscription.test.tsapp/lib/database/services/Subscription.tsapp/lib/services/voip/MediaSessionInstance.test.tsapp/lib/services/voip/MediaSessionInstance.tsapp/lib/services/voip/navigateToCallRoom.test.tsapp/lib/services/voip/navigateToCallRoom.tsapp/lib/services/voip/useCallStore.test.tsapp/lib/services/voip/useCallStore.tsapp/views/CallView/components/CallButtons.test.tsxapp/views/CallView/components/CallButtons.tsxapp/views/CallView/index.test.tsx
📜 Review details
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-03-15T13:55:42.038Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6911
File: app/containers/markdown/Markdown.stories.tsx:104-104
Timestamp: 2026-03-15T13:55:42.038Z
Learning: In Rocket.Chat React Native, the markdown parser requires a space between the underscore wrapping italic text and a mention sigil (_ mention _ instead of _mention_). Ensure stories and tests that include italic-wrapped mentions follow this form to guarantee proper parsing. Specifically, for files like app/containers/markdown/Markdown.stories.tsx, and any test/content strings that exercise italic-mentions, use the pattern _ mention _ (with spaces) to prevent the mention from being treated as plain text. Validate any test strings or story content accordingly.
Applied to files:
app/containers/MediaCallHeader/MediaCallHeader.stories.tsx
📚 Learning: 2026-03-10T15:21:45.098Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7046
File: app/containers/InAppNotification/NotifierComponent.stories.tsx:46-75
Timestamp: 2026-03-10T15:21:45.098Z
Learning: In `app/containers/InAppNotification/NotifierComponent.tsx` (React Native, Rocket.Chat), `NotifierComponent` is exported as a Redux-connected component via `connect(mapStateToProps)`. The `isMasterDetail` prop is automatically injected from `state.app.isMasterDetail` and does not need to be passed explicitly at call sites or in Storybook stories that use the default (connected) export.
Applied to files:
app/containers/MediaCallHeader/MediaCallHeader.test.tsxapp/views/CallView/index.test.tsxapp/containers/MediaCallHeader/components/Content.tsx
📚 Learning: 2026-03-30T15:49:30.957Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6875
File: app/containers/RoomItem/Actions.tsx:12-12
Timestamp: 2026-03-30T15:49:30.957Z
Learning: In RocketChat/Rocket.Chat.ReactNative, `react-native-worklets` version 0.6.1 does NOT export a built-in Jest mock (e.g., no `react-native-worklets/lib/module/mock`). The correct Jest mock approach for this version is to add a manual mock in `jest.setup.js`: `jest.mock('react-native-worklets', () => ({ scheduleOnRN: jest.fn((fn, ...args) => fn(...args)) }))`.
Applied to files:
app/views/CallView/index.test.tsxapp/lib/services/voip/MediaSessionInstance.test.ts
📚 Learning: 2026-03-17T19:15:30.463Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6970
File: .maestro/tests/room/share-message.yaml:77-79
Timestamp: 2026-03-17T19:15:30.463Z
Learning: In `.maestro/tests/room/share-message.yaml` (Rocket.Chat React Native), the `tapOn: point: 5%,10%` step is intentional: it taps the empty area above the bottom sheet and keyboard to dismiss both simultaneously. Using `action-sheet-handle` instead would only close the sheet but not the keyboard. This pattern is acceptable when both need to be dismissed together in a single step.
Applied to files:
app/views/CallView/index.test.tsx
🪛 ESLint
app/views/CallView/components/CallButtons.tsx
[error] 34-34: Expected 'undefined' and instead saw 'void'.
(no-void)
app/lib/services/voip/MediaSessionInstance.ts
[error] 97-97: Expected 'undefined' and instead saw 'void'.
(no-void)
[error] 126-126: Expected 'undefined' and instead saw 'void'.
(no-void)
[error] 171-171: Use object destructuring.
(prefer-destructuring)
app/containers/MediaCallHeader/components/Content.tsx
[error] 31-31: Expected 'undefined' and instead saw 'void'.
(no-void)
app/lib/services/voip/MediaSessionInstance.test.ts
[error] 2-2: There should be at least one empty line between import groups
(import/order)
🪛 GitHub Actions: Format Code with Prettier
app/containers/MediaCallHeader/components/Content.tsx
[error] 31-31: no-void: Expected 'undefined' and instead saw 'void'.
🪛 GitHub Check: format
app/views/CallView/components/CallButtons.tsx
[failure] 34-34:
Expected 'undefined' and instead saw 'void'
app/lib/services/voip/MediaSessionInstance.ts
[failure] 97-97:
Expected 'undefined' and instead saw 'void'
[failure] 126-126:
Expected 'undefined' and instead saw 'void'
app/containers/MediaCallHeader/components/Content.tsx
[failure] 31-31:
Expected 'undefined' and instead saw 'void'
🔇 Additional comments (14)
app/lib/database/services/Subscription.ts (1)
10-18: LGTM!The implementation is clean and handles edge cases properly:
- Early return for falsy username prevents unnecessary DB queries
Q.take(1)efficiently limits results- Nullish coalescing (
??) correctly returnsnullwhen no rows matchapp/containers/MediaCallHeader/MediaCallHeader.stories.tsx (1)
24-49: LGTM!The story mock data is correctly updated to reflect an enabled navigation scenario:
sipExtension: ''indicates a non-SIP callroomId: 'story-room-rid'provides a valid room identifierThis aligns with the navigation gating logic where the message action is enabled only for non-SIP calls with a valid
roomId.app/lib/services/voip/useCallStore.test.ts (1)
53-69: LGTM!The test suite correctly verifies:
setRoomIdupdates the store valuereset()clearsroomIdback tonullThe test isolation via
beforeEachreset is appropriate.app/views/CallView/index.test.tsx (2)
12-16: LGTM!The mock setup is correct. Although
jest.mocked(navigateToCallRoom)appears beforejest.mock(...)in the source, Jest hoistsjest.mock()calls to the top of the file during execution, so the mock is in place whenjest.mocked()runs.
249-259: LGTM!The test correctly verifies that pressing the message button triggers
navigateToCallRoom. The store state setup withsipExtension: ''androomId: 'test-room-rid'ensures the button is enabled.app/lib/services/voip/MediaSessionInstance.ts (1)
167-179: LGTM on theresolveRoomIdFromContactimplementation.The logic correctly:
- Skips SIP extension contacts (no DM room exists)
- Returns early for missing username
- Queries the DM subscription and sets roomId if found
The async handling is appropriate for a fire-and-forget pattern where navigation is enabled only after resolution.
app/lib/services/voip/useCallStore.ts (1)
73-74: LGTM!The
roomIdstate addition follows the existing store patterns:
- Proper TypeScript typing with
string | null- JSDoc documentation explains the field's purpose and lifecycle
- Initialized to
nullininitialState- Automatically cleared on
reset()via the spread ofinitialState- Simple setter implementation is appropriate
Also applies to: 94-94, 112-113, 253-255
app/containers/MediaCallHeader/MediaCallHeader.test.tsx (2)
12-22: LGTM! Well-structured mock setup.The mock for
react-native-incall-managerandnavigateToCallRoomare correctly placed before they're imported by the component under test. Usingjest.mockedafter the mock declaration is the correct pattern.
190-232: Good test coverage for navigation behavior.The tests comprehensively cover:
- Navigation enabled (non-SIP, roomId present)
- Navigation disabled for SIP calls
- Navigation disabled when roomId is null
This aligns well with the component's conditional logic.
app/views/CallView/components/CallButtons.test.tsx (1)
1-82: LGTM! Focused test coverage for message button navigation.The test file is well-structured with:
- Proper mock setup for dependencies
- Clean test isolation via
beforeEachreset- Coverage for all three message button states (enabled, SIP disabled, roomId null)
The tests correctly verify that
navigateToCallRoomis called only when the button should be active.app/containers/MediaCallHeader/components/Content.tsx (1)
21-38: Logic implementation looks correct.The component properly:
- Reads
roomIdandcontactfrom the call store- Disables interaction for SIP calls (
contact.sipExtensiontruthy) or missing room (roomId == null)- Applies visual feedback (opacity 0.5) when disabled
app/lib/services/voip/navigateToCallRoom.ts (1)
11-44: Well-structured navigation helper with appropriate guards.The implementation correctly:
- Guards against SIP calls and missing roomId/username
- Minimizes the call UI before navigating
- Ensures navigation context is correct before calling
goRoomapp/lib/services/voip/navigateToCallRoom.test.ts (1)
1-182: Excellent test coverage for navigation logic.The test suite comprehensively covers:
- All early-exit conditions (null roomId, SIP contact, missing username)
- Focus toggle behavior (both focused and unfocused states)
- Navigation context handling (multiple non-chat screens + RoomView)
The mock setup is clean and the assertions correctly verify the expected behavior and call order.
app/lib/services/voip/MediaSessionInstance.test.ts (1)
349-475: Comprehensive test coverage for roomId population logic.The new
roomId populationtest block thoroughly covers:
startCallByRoomsets roomId beforestartCall(verified via execution order tracking)newCallcaller triggers/skips DM lookup based on existing roomId and SIP statusanswerCallresolves/skips DM lookup based on SIP statusThe use of
waitForfor async assertions and order tracking via mock implementations are good testing patterns.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/lib/services/voip/navigateToCallRoom.test.ts (1)
55-99: Also assert no stack navigation on early-return branches.In no-op scenarios, asserting
Navigation.navigateis untouched makes the guard behavior explicit and prevents accidental side effects.Suggested assertion additions
@@ await navigateToCallRoom(); expect(mockGoRoom).not.toHaveBeenCalled(); expect(toggleFocus).not.toHaveBeenCalled(); + expect(mockNavigation.navigate).not.toHaveBeenCalled(); }); @@ await navigateToCallRoom(); expect(mockGoRoom).not.toHaveBeenCalled(); + expect(mockNavigation.navigate).not.toHaveBeenCalled(); }); @@ await navigateToCallRoom(); expect(mockGoRoom).not.toHaveBeenCalled(); + expect(mockNavigation.navigate).not.toHaveBeenCalled(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/lib/services/voip/navigateToCallRoom.test.ts` around lines 55 - 99, Add assertions to explicitly verify that no stack/navigation happens in the early-return branches by asserting that Navigation.navigate (or mockGoRoom wrapper) is not called. In the tests for navigateToCallRoom ('does not navigate when roomId is null', 'does not navigate for SIP contact', and 'does not navigate when username is missing') update the expectations to include an assertion that Navigation.navigate (or the mock navigation function used in this test file, e.g., mockGoRoom) was not called and where appropriate that toggleFocus was not called; reference the navigateToCallRoom function, mockGetState, mockCallStoreState, mockGoRoom, and toggleFocus to locate and add these assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/lib/services/voip/navigateToCallRoom.test.ts`:
- Around line 101-118: The tests currently only assert that toggleFocus,
Navigation.navigate and mockGoRoom were called, but not their order; update the
tests in navigateToCallRoom.test.ts (including the other cases around 139-191)
to assert call sequencing: after calling navigateToCallRoom() check the mock
invocation order numbers (e.g., toggleFocus.mock.invocationCallOrder[0] and
Navigation.navigate.mock.invocationCallOrder[0]) and assert each is less than
mockGoRoom.mock.invocationCallOrder[0] so you guarantee minimize/Navigation
happen before goRoom; use the existing mock symbols toggleFocus,
Navigation.navigate and mockGoRoom to locate where to add these ordering
assertions.
---
Nitpick comments:
In `@app/lib/services/voip/navigateToCallRoom.test.ts`:
- Around line 55-99: Add assertions to explicitly verify that no
stack/navigation happens in the early-return branches by asserting that
Navigation.navigate (or mockGoRoom wrapper) is not called. In the tests for
navigateToCallRoom ('does not navigate when roomId is null', 'does not navigate
for SIP contact', and 'does not navigate when username is missing') update the
expectations to include an assertion that Navigation.navigate (or the mock
navigation function used in this test file, e.g., mockGoRoom) was not called and
where appropriate that toggleFocus was not called; reference the
navigateToCallRoom function, mockGetState, mockCallStoreState, mockGoRoom, and
toggleFocus to locate and add these assertions.
🪄 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: 3dff821f-82b1-48c6-b7fa-260888aee7b5
📒 Files selected for processing (1)
app/lib/services/voip/navigateToCallRoom.test.ts
📜 Review details
⏰ 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: ESLint and Test / run-eslint-and-test
- GitHub Check: format
Add roomId and setRoomId to the Zustand VoIP call store so DM navigation can reference the active call room. roomId defaults to null and is cleared by reset() via initialState spread. Tests cover setRoomId and reset clearing roomId. Made-with: Cursor
Query WatermelonDB for a direct subscription by username and room type. Includes unit tests with a mocked DB collection. Made-with: Cursor
Set roomId in startCallByRoom before dialing. For outbound calls that still lack roomId after setCall, resolve DM subscription by username. For inbound answerCall, resolve the same way and skip SIP contacts. Extend MediaSessionInstance tests for ordering, newCall, and answerCall paths; stub CallKeep setCurrentCallActive for answerCall tests. Made-with: Cursor
Read call store roomId, contact, and focused state; skip SIP and missing data; minimize CallView when focused; navigate via goRoom with Redux isMasterDetail. Unit tests cover early exits and focus ordering. Made-with: Cursor
Disable message when SIP extension is set or roomId is missing. Add CallButtons tests; mock navigation helper in CallView tests and refresh story snapshots for the enabled message control. Made-with: Cursor
Replace placeholder alert with navigateToCallRoom; disable press and dim when SIP or roomId is missing. Align stories and tests with DM fixtures (roomId, non-SIP); add coverage for enabled vs SIP vs missing room. Made-with: Cursor
…awers When the message button is pressed from Profile, Accessibility, or Settings screens, explicitly navigate to ChatsStackNavigator first. This ensures goRoom has the correct navigation context to reset routes properly. Fixes navigation staying on the same screen when message is pressed from Profile/A11y/Settings while a call is active.
- Replace void operator with promise catch handlers (no-void) - Use prefer-destructuring for contact.username in MediaSessionInstance - Fix import order in MediaSessionInstance.test.ts - Add getDMSubscriptionByUsername falsy-username test with mockClear - Document getDMSubscriptionByUsername with JSDoc Made-with: Cursor
Move the InCallManager stub to setupFilesAfterEnv and remove duplicate jest.mock blocks from VoIP-related tests. Made-with: Cursor
Use mockCallStoreState helper with unknown double assertion so partial mocks satisfy @typescript-eslint/consistent-type-assertions (CI failure on navigateToCallRoom.test.ts). Made-with: Cursor
- Assert Navigation.navigate and toggleFocus stay untouched on early exits - Assert toggleFocus and ChatsStackNavigator navigation run before goRoom Made-with: Cursor
5fd7275 to
82d63a3
Compare
… tests
- Remove incorrect IClientMediaCall return type from createMockCall (returns {call, emit})
- Add missing setRoomId/roomId fields to mockUseCallStoreGetState.mockReturnValue calls
Proposed changes
Implements navigation from the VoIP call UI to the DM for the active user-to-user call (VMUX-23):
roomIdon the Zustand call store — Persists the DM room id for the active call; cleared onreset().getDMSubscriptionByUsername— WatermelonDB lookup for a direct subscription by username (with early return for falsy usernames); JSDoc added for docstring coverage.MediaSessionInstance— SetsroomIdwhen starting from a room; resolves DM by username on outbound/inbound paths when needed; skips SIP contacts. Async resolution uses.catch(...)instead ofvoidto satisfyno-voidESLint.navigateToCallRoom— Shared helper: guards SIP / missingroomId/ missing username, minimizes call UI when focused (toggleFocus), then navigates via existinggoRoom+ ReduxisMasterDetail.CallView(CallButtons) and the tappable area inMediaCallHeaderContentcall the helper; both stay disabled for SIP or whenroomIdis missing (no on-the-fly room creation).Navigation-context fix: If the user opens the DM from Profile, Accessibility, or Settings (outside the chats stack), the helper navigates to
ChatsStackNavigatorfirst when the current route is notRoomsListVieworRoomView, sogoRoomruns with the correct stack. Covered innavigateToCallRoom.test.ts.Follow-up (review / CI): Addressed CodeRabbit and ESLint feedback: removed
voidfor floating promises inCallButtons,Content, andMediaSessionInstance;prefer-destructuringforcontact.username; import grouping inMediaSessionInstance.test.ts; unit test for falsy username ongetDMSubscriptionByUsername; Prettier/format pass.Issue(s)
https://rocketchat.atlassian.net/browse/VMUX-23
How to test or reproduce
roomIdis set once the call is active (may be async on incoming paths).Screenshots
Add if you have before/after or screen recordings.
Types of changes
Checklist
Further comments
feat.voip-lib-new.roomIdon incoming calls, no DM creation from the call UI, reuse ofgoRoom/toggleFocus— per PRD / progress notes for this workstream.useCallStore.test.ts,Subscription.test.ts,MediaSessionInstance.test.ts,navigateToCallRoom.test.ts,CallButtons.test.tsx,CallView/MediaCallHeadertests and stories as needed for enabled/disabled states and snapshots.Summary by CodeRabbit
New Features
Bug Fixes
Tests