Skip to content

Conversation

@gabriellsh
Copy link
Member

@gabriellsh gabriellsh commented Nov 26, 2025

Proposed changes (including videos or screenshots)

Improves the call widget (when creating a new call) and transfer modal to update selected user's presence in real time.

Issue(s)

VGA-83

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • New Features

    • Realtime user presence updates when starting or transferring voice calls.
    • Improved peer autocomplete for dialing: debounced suggestion loading, a direct “enter number” option, and live presence-aware selection.
  • Chores

    • Updated VoIP UI to a newer minor release.

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

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Nov 26, 2025

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Nov 26, 2025

🦋 Changeset detected

Latest commit: cf92ee8

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

This PR includes changesets to release 40 packages
Name Type
@rocket.chat/ui-voip Minor
@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/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/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/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 26, 2025

Walkthrough

Extracts the peer-autocomplete hook into a new module, reworks context exports, adds realtime presence tracking for selected peers, and adds typed query keys; includes a changeset bumping @rocket.chat/ui-voip.

Changes

Cohort / File(s) Summary
Changelog entry
​.changeset/purple-jobs-swim.md
Added changeset documenting a minor @rocket.chat/ui-voip bump and realtime presence feature for selected users during voice-call flows.
Context implementation
packages/ui-voip/src/context/MediaCallContext.ts
Removed internal peer-autocomplete implementation and its exports from MediaCallContext.
Context exports rework
packages/ui-voip/src/context/index.ts
Stopped re-exporting peer-autocomplete from MediaCallContext; now re-exports usePeerAutocomplete and isFirstPeerAutocompleteOption from ./usePeerAutocomplete.
New peer-autocomplete hook
packages/ui-voip/src/context/usePeerAutocomplete.ts
Added usePeerAutocomplete hook: debounced input, fetch via getAutocompleteOptions, synthetic-first-option handling, presence subscription via useUserPresence, selection mapping, and exported isFirstPeerAutocompleteOption.
Query keys
packages/ui-voip/src/utils/queryKeys.ts
Added mediaCallQueryKeys with all and peerAutocomplete(filter) typed query-key helpers.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Component
    participant Hook as usePeerAutocomplete
    participant Context as MediaCallContext
    participant Presence as useUserPresence
    participant App as onSelectPeer

    UI->>Hook: mount(onSelectPeer)
    UI->>Hook: user types filter
    Hook->>Hook: debounce input
    Hook->>Context: getAutocompleteOptions(filter)
    Context-->>Hook: returns options
    Hook->>Presence: subscribe to selected user's presence
    Presence-->>Hook: presence update
    UI->>Hook: onChangeValue(selection)
    Hook->>Hook: map selection → PeerInfo (apply presence/status)
    Hook->>App: invoke onSelectPeer(PeerInfo)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • gabriellsh
  • dougfabris

Poem

🐰
I hopped through fields of signal and key,
Pulled autocomplete out to set it free,
I peek for presence — a twitch, a cheer,
So calls find ears when a friend is near,
Tiny paws, big realtime glee.

🚥 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 accurately describes the main feature: realtime user presence updates when starting/transferring voice calls, which directly matches the changeset's core purpose.
Linked Issues check ✅ Passed The PR implements realtime presence updates for both new call creation and call transfer scenarios via the new usePeerAutocomplete hook tracking peer presence, fulfilling VGA-83 requirements.
Out of Scope Changes check ✅ Passed The refactoring of usePeerAutocomplete into a separate module and query key extraction are supporting changes directly related to implementing the realtime presence feature and fall within scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/forwardCallLiveStatus

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.

@gabriellsh gabriellsh added this to the 7.14.0 milestone Nov 26, 2025
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

🧹 Nitpick comments (2)
packages/ui-voip/src/context/usePeerAutocomplete.ts (2)

20-39: Presence sync behavior matches requirements; consider a clearer internal-peer guard

The hook correctly:

  • Debounces the filter before querying autocomplete options.
  • Subscribes to useUserPresence for the currently selected internal peer.
  • Calls onSelectPeer with an updated status only when the presence actually changes, avoiding loops.

To make the intent of the presence guard clearer and more robust, you might prefer discriminating internal peers by userId instead of status:

-	useEffect(() => {
-		if (!peerInfo || !('status' in peerInfo) || !status?.status) {
+	useEffect(() => {
+		if (!peerInfo || !('userId' in peerInfo) || !status?.status) {
 			return;
 		}
-
-		if (status.status === peerInfo?.status) {
+		if (status.status === peerInfo.status) {
 			return;
 		}
-
 		onSelectPeer({
 			...peerInfo,
 			status: status.status,
 		});
 	}, [status, peerInfo, onSelectPeer]);

This keeps the behavior the same for internal peers while making the type discrimination more explicit.

Also applies to: 41-57


61-75: Avoid throwing from onChangeValue when option lookup fails

onChangeValue currently throws if localInfo is not found:

if (!localInfo) {
  throw new Error(`Peer info not found for value: ${value}`);
}

This will surface as a runtime error from a user interaction path; it’s likely safer to no-op (or log) instead, since this situation should already be impossible if the UI and options are in sync. For example:

-			if (!localInfo) {
-				throw new Error(`Peer info not found for value: ${value}`);
-			}
+			if (!localInfo) {
+				// Option not found – ignore stale selection.
+				return;
+			}

This keeps the UI resilient to any transient mismatch between the selected value and the options list.

📜 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 a20c1cc and 78e3c27.

📒 Files selected for processing (4)
  • .changeset/purple-jobs-swim.md (1 hunks)
  • packages/ui-voip/src/context/MediaCallContext.ts (1 hunks)
  • packages/ui-voip/src/context/index.ts (1 hunks)
  • packages/ui-voip/src/context/usePeerAutocomplete.ts (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:

  • packages/ui-voip/src/context/index.ts
  • packages/ui-voip/src/context/MediaCallContext.ts
  • packages/ui-voip/src/context/usePeerAutocomplete.ts
🧠 Learnings (1)
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.

Applied to files:

  • .changeset/purple-jobs-swim.md
🧬 Code graph analysis (1)
packages/ui-voip/src/context/usePeerAutocomplete.ts (3)
packages/ui-voip/src/context/index.ts (4)
  • isFirstPeerAutocompleteOption (2-2)
  • usePeerAutocomplete (2-2)
  • PeerInfo (3-3)
  • useMediaCallContext (1-1)
packages/ui-voip/src/context/MediaCallContext.ts (2)
  • PeerInfo (22-22)
  • useMediaCallContext (121-130)
packages/ui-contexts/src/index.ts (1)
  • useUserPresence (97-97)
⏰ 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). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (2)
packages/ui-voip/src/context/MediaCallContext.ts (1)

3-3: React context import change looks good

Using createContext and useContext directly from react is standard and consistent with the hooks below; no behavioral changes introduced here.

packages/ui-voip/src/context/index.ts (1)

1-2: Re-export changes preserve the public API surface

Re-exporting usePeerAutocomplete and isFirstPeerAutocompleteOption from ./usePeerAutocomplete while keeping the existing index entry points maintains backward compatibility for consumers of packages/ui-voip/src/context. This aligns well with the internal refactor of moving autocomplete logic out of MediaCallContext.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 26, 2025

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 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/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 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "01/19 21:00 (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, 0.11, 0.11, 0.11, 0.11, 0.00]
  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, 0.11, 0.11, 0.11, 0.11, 0.00]
  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.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [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, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  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, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [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, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [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.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

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

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

  • Tag: pr-37616
  • Baseline: develop
  • Timestamp: 2026-01-19 21:00:52 UTC
  • Historical data points: 30

Updated: Mon, 19 Jan 2026 21:00:53 GMT

@codecov
Copy link

codecov bot commented Nov 26, 2025

Codecov Report

❌ Patch coverage is 77.58621% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.69%. Comparing base (0b438a5) to head (cf92ee8).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37616      +/-   ##
===========================================
- Coverage    70.70%   70.69%   -0.01%     
===========================================
  Files         3139     3141       +2     
  Lines       108744   108799      +55     
  Branches     19594    19579      -15     
===========================================
+ Hits         76890    76920      +30     
- Misses       29851    29881      +30     
+ Partials      2003     1998       -5     
Flag Coverage Δ
e2e 60.36% <ø> (+0.03%) ⬆️
e2e-api 47.97% <ø> (ø)
unit 71.78% <77.58%> (-0.03%) ⬇️

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.

@scuciatto scuciatto modified the milestones: 7.14.0, 8.1.0 Jan 2, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 6 files

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

🤖 Fix all issues with AI agents
In `@packages/ui-voip/src/context/usePeerAutocomplete.ts`:
- Around line 72-76: Replace the thrown Error when a matching option isn’t found
(the localInfo check in usePeerAutocomplete’s onChangeValue handler) with
graceful handling: log a warning (e.g., console.warn or use the existing logger)
that the selected value no longer exists and return early (or call the existing
selection callback with null/undefined if the rest of the flow expects a cleared
selection) instead of throwing, so the UI won’t crash when options change
between click and handler execution.
🧹 Nitpick comments (1)
packages/ui-voip/src/context/usePeerAutocomplete.ts (1)

44-57: Ensure onSelectPeer is stable to avoid unnecessary effect runs.

The effect depends on onSelectPeer. While the status equality check on line 49-51 prevents infinite loops, if onSelectPeer is recreated on every render, this effect will still run unnecessarily each time. Consider documenting that callers should wrap onSelectPeer in useCallback, or accept a ref-based callback pattern.

📜 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 3ded3c2 and dc75a2d.

📒 Files selected for processing (2)
  • packages/ui-voip/src/context/usePeerAutocomplete.ts
  • packages/ui-voip/src/utils/queryKeys.ts
🧰 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/utils/queryKeys.ts
  • packages/ui-voip/src/context/usePeerAutocomplete.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.
🧬 Code graph analysis (1)
packages/ui-voip/src/context/usePeerAutocomplete.ts (5)
packages/ui-voip/src/context/index.ts (4)
  • isFirstPeerAutocompleteOption (2-2)
  • usePeerAutocomplete (2-2)
  • PeerInfo (3-3)
  • useMediaCallContext (1-1)
packages/ui-voip/src/components/PeerAutocomplete.tsx (1)
  • PeerAutocompleteOptions (8-14)
packages/ui-voip/src/context/MediaCallContext.ts (2)
  • PeerInfo (22-22)
  • useMediaCallContext (121-130)
packages/ui-voip/src/utils/queryKeys.ts (1)
  • mediaCallQueryKeys (1-4)
packages/ui-contexts/src/index.ts (1)
  • useUserPresence (99-99)
⏰ 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: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
🔇 Additional comments (4)
packages/ui-voip/src/utils/queryKeys.ts (1)

1-4: LGTM!

Clean query-key factory following react-query best practices. The as const assertions ensure proper tuple typing for cache key matching, and the self-referential spread pattern maintains key hierarchy correctly.

packages/ui-voip/src/context/usePeerAutocomplete.ts (3)

1-19: LGTM!

Clean utility functions for handling synthetic first-option detection. The prefix-based approach is straightforward and the helper functions are well-scoped.


21-40: LGTM!

The query setup with debouncing and keepPreviousData provides good UX during typing. The synthetic first-option prepending for non-empty filters enables direct number dialing.


85-88: LGTM!

Clean return API with proper functional update pattern for onKeypadPress avoiding stale closure issues.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@tassoevan tassoevan force-pushed the feat/forwardCallLiveStatus branch from ddaaf57 to 72d962f Compare January 19, 2026 16:24
@tassoevan tassoevan force-pushed the feat/forwardCallLiveStatus branch from 72d962f to 2eb9658 Compare January 19, 2026 16:25
@tassoevan tassoevan added the stat: QA assured Means it has been tested and approved by a company insider label Jan 19, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Jan 19, 2026
@kodiakhq kodiakhq bot merged commit 1e0b37f into develop Jan 19, 2026
44 checks passed
@kodiakhq kodiakhq bot deleted the feat/forwardCallLiveStatus branch January 19, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants