-
Notifications
You must be signed in to change notification settings - Fork 13k
chore: Update Media Call components and missing parts #36985
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Looks like this PR is ready to merge! 🎉 |
|
WalkthroughRefactors MediaCallContext for richer peer modeling and async handlers, adds ConnectionState and hidden, rewires autocomplete to external selection, introduces draggable Widget context/handle, adds TransferModal, updates keypad/info slots with i18n, and adjusts many components/stories to the new peer and context shapes. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as NewCall View
participant AC as usePeerAutocomplete
participant Ctx as MediaCallContext
participant Prov as Provider
UI->>AC: init(onSelectPeer, peerInfo)
UI->>AC: user selects option
alt SIP / first option
AC-->>Ctx: onSelectPeer({ number })
else known user option
AC-->>Ctx: onSelectPeer({ userId, displayName, avatarUrl? })
else no local match
AC-->>AC: throw Error
end
UI->>Ctx: onCall()
Ctx->>Prov: onCall() Promise
Prov-->>Ctx: resolve/reject
Ctx-->>UI: Promise settled
sequenceDiagram
autonumber
participant Modal as TransferModal
participant AC as usePeerAutocomplete
participant Parent as Caller
Modal->>AC: init(onSelectPeer, peerInfo)
Modal->>Modal: user selects peer
Modal->>Modal: user confirms
alt selected user
Modal-->>Parent: onConfirm('user', userId)
else selected SIP
Modal-->>Parent: onConfirm('sip', number)
else invalid
Modal-->>Modal: throw Error
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (30)
packages/ui-voip/src/v2/components/ActionButton.tsx (3)
12-15: Ref forwarding looks good; add displayName for DevTools.Forwarding the ref to IconButton is correct. Add an explicit displayName for clearer debugging.
-}); +}); + +ActionButton.displayName = 'ActionButton'; export default ActionButton;Also applies to: 27-30
3-3: Use type-only imports and align onClick typing with React.Reduces emitted JS and matches IconButton’s handler type.
-import { ComponentProps, forwardRef } from 'react'; +import { forwardRef } from 'react'; +import type { ComponentProps, MouseEventHandler } from 'react'; @@ disabled?: boolean; - onClick?: () => void; + onClick?: MouseEventHandler<HTMLButtonElement>; } & Omit<ComponentProps<typeof IconButton>, 'icon' | 'title' | 'aria-label' | 'disabled' | 'onClick'>;Also applies to: 5-10
17-21: Avoid forcing medium size; let consumers choose or rely on IconButton default.Prevents conflicting size flags when callers pass small/large.
- medium secondary={secondary} icon={<Icon size={16} name={icon} />} title={label} aria-label={label} disabled={disabled} onClick={onClick} {...props}Also applies to: 26-26
packages/ui-voip/src/v2/components/PeerInfo/PhoneNumber.tsx (1)
9-12: A11Y: mark decorative icon hidden; consider RTL-safe number rendering; verify static ID uniqueness
- Icon appears decorative—hide it from SRs.
- Phone numbers render poorly in RTL locales; force LTR on the numeral span.
- Static id may collide if multiple widgets exist. Confirm only one instance or derive a unique id.
Apply:
- <Box display='flex' flexDirection='row' id='rcx-media-call-widget-caller-info'> - <Icon size='x20' name='phone' mie={8} /> - <Box fontScale='p2b'>{number}</Box> + <Box display='flex' flexDirection='row' id='rcx-media-call-widget-caller-info'> + <Icon size='x20' name='phone' mie={8} aria-hidden='true' /> + <Box fontScale='p2b' dir='ltr'>{number}</Box>packages/ui-voip/src/v2/useKeypad.tsx (1)
20-35: A11Y and UX: label the read-only input, clamp length, clear on close; simplify handler
- Add aria-label and polite live region so SRs get updates.
- Prevent unbounded growth; clamp digits.
- Clear digits when closing.
- Prefer explicit
(tone: string)over rest args.Apply:
- const element = ( + const element = ( <Box display='flex' justifyContent='center' alignItems='center' w='100%' flexDirection='column' mbe={8}> <Field mbe={8}> <FieldRow> - <TextInput value={inputValue} readOnly small mi={24} /> + <TextInput + value={inputValue} + readOnly + small + mi={24} + aria-label={t('Dialed_digits')} + aria-live='polite' + /> </FieldRow> </Field> <Keypad - onKeyPress={(...args) => { - setInputValue((inputValue) => inputValue + args[0]); - onPress(...args); - }} + onKeyPress={(tone: string) => { + setInputValue((prev) => (prev + tone).slice(0, 64)); + onPress(tone); + }} /> <Divider w='100%' /> </Box> ); ... return { element: open ? element : null, buttonProps: { title: open ? t('Close_dialpad') : t('Open_dialpad'), - onClick: () => setOpen((open) => !open), + onClick: () => + setOpen((isOpen) => { + if (isOpen) setInputValue(''); + return !isOpen; + }), }, };Also applies to: 39-42
packages/ui-voip/src/v2/components/Widget/WidgetHeader.tsx (1)
13-15: Avoid static IDs; derive a stable unique title idStatic ids can collide if multiple widgets render. Use
useId()or accept anidprop and pass it from the parent that setsaria-labelledby.Apply:
-import type { ReactElement, ReactNode } from 'react'; +import type { ReactElement, ReactNode } from 'react'; +import { useId } from 'react'; @@ -const WidgetHeader = ({ title, children }: WidgetHeaderProps): ReactElement => { +const WidgetHeader = ({ title, children }: WidgetHeaderProps): ReactElement => { + const titleId = useId(); return ( <Box is='header' mi={12} mb={4} display='flex' alignItems='center' justifyContent='space-between'> - <Box is='h3' color='titles-labels' fontScale='p1b' id='rcx-media-call-widget-title'> + <Box is='h3' color='titles-labels' fontScale='p1b' id={titleId}> {title} </Box> <Box mis={8}>{children}</Box> </Box> );packages/ui-voip/src/v2/components/PeerInfo/PeerInfo.stories.tsx (1)
16-26: Trim the large base64 avatar in story to keep bundles/snaps lean.Replace the long data URI with a 1x1 placeholder or a tiny asset to improve Storybook perf/readability.
Apply:
- avatarUrl='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgG...rs//Z' + avatarUrl='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='packages/ui-voip/src/v2/views/IncomingCall.tsx (1)
31-31: Keep wrapper to avoid passing click event to onAccept.onAccept likely takes no args/returns Promise; wrapper is appropriate.
If onAccept is guaranteed to be no-arg, consider
onClick={() => void onAccept()}to ignore any returned Promise explicitly.packages/ui-voip/src/v2/index.ts (1)
1-3: Potential name confusion: type PeerInfo vs component PeerInfo.Exporting a type named PeerInfo alongside a PeerInfo component elsewhere can confuse consumers’ imports.
Consider aliasing the type:
-export type { PeerInfo } from './MediaCallContext'; +export type { PeerInfo as PeerInfoType } from './MediaCallContext';and adjust downstream imports accordingly.
packages/ui-voip/src/v2/components/Widget/WidgetHandle.tsx (3)
15-26: Prevent externalrefprops from overridinghandleRef.
{...props}comes afterref={handleRef}, so a consumer‑providedrefwould silently replace the drag handle ref and break dragging.Apply this diff to ensure the internal ref wins:
- className={dragHandle} - ref={handleRef} - {...props} + className={dragHandle} + {...props} + ref={handleRef}
5-6: Guard against missing provider (DX).
useDraggableWidget()throws if the context is absent. IfWidgetHandleis ever rendered outside the provider, it will crash. Consider a dev‑only warning and a no‑op ref to fail softer.Also applies to: 15-17
18-29: A11y: identify the drag handle.Expose an accessible name/role for the handle (e.g.,
aria-roledescription="drag handle"andaria-label="Drag"). Optional, but helps SR users.packages/ui-voip/src/v2/views/NewCall.tsx (1)
41-43: Disable “Call” until a peer is selected.Avoid firing
onCallwith nopeerInfo.Apply this diff:
- <Button medium icon='phone' success flexGrow={1} onClick={onCall}> + <Button medium icon='phone' success flexGrow={1} onClick={onCall} disabled={!peerInfo}>packages/ui-voip/src/v2/useInfoSlots.ts (2)
49-66: Don’t drop muted/held badges while reconnecting.Early return shows only the connection state slot and hides muted/held. If you intended to prepend connection state, remove the short‑circuit and avoid name shadowing for clarity.
Apply this diff:
- const slots: Slot[] = []; + const nextSlots: Slot[] = []; const heldSlot = getHeldSlot(held, t); const mutedSlot = getMutedSlot(muted, t); const connectionStateSlot = getConnectionStateSlot(connectionState, t); - if (connectionStateSlot) { - slots.push(connectionStateSlot); - setSlots(slots); - return; - } - if (heldSlot) { - slots.push(heldSlot); - } - if (mutedSlot) { - slots.push(mutedSlot); - } - setSlots(slots); + if (connectionStateSlot) { + nextSlots.push(connectionStateSlot); + } + if (heldSlot) { + nextSlots.push(heldSlot); + } + if (mutedSlot) { + nextSlots.push(mutedSlot); + } + setSlots(nextSlots);
44-69: Compute slots without state.This value is derived;
useMemowould simplify and avoid state effects.If desired, I can provide a full
useMemorewrite.packages/ui-voip/src/v2/TransferModal.tsx (2)
20-24: WireisLoadingto the confirm button to prevent double submits.Prop exists but isn’t used. Disable and show loading while confirming.
Apply this diff:
-const TransferModal = ({ onCancel, onConfirm }: TransferModalProps) => { +const TransferModal = ({ onCancel, onConfirm, isLoading }: TransferModalProps) => { @@ - <Button danger onClick={confirm} disabled={!peer}> + <Button danger onClick={confirm} disabled={!peer || isLoading} loading={isLoading}>Also applies to: 26-26, 69-75
35-51: Optional: handle async confirm flow.If
onConfirmcan be async, consider makingconfirmasync and delegatingisLoadingfrom parent or local state.Do you expect
onConfirmto return a Promise?packages/ui-voip/src/v2/views/OngoingCall.tsx (2)
51-51: Localize the Dialpad label.Use
t('Dialpad')for consistency with the rest.Apply this diff:
- <ActionButton disabled={connecting || reconnecting} icon='dialpad' label='Dialpad' {...keypadButtonProps} /> + <ActionButton disabled={connecting || reconnecting} icon='dialpad' label={t('Dialpad')} {...keypadButtonProps} />
53-53: Different icons for Hold on/off — replace second icon with 'play'.
File: packages/ui-voip/src/v2/views/OngoingCall.tsx (line 53). Verified @rocket.chat/fuselage uses "play" for resume; apply diff:- <ToggleButton label={t('Hold')} icons={['pause-shape-unfilled', 'pause-shape-unfilled']} pressed={held} onToggle={onHold} /> + <ToggleButton label={t('Hold')} icons={['pause-shape-unfilled', 'play']} pressed={held} onToggle={onHold} />packages/ui-voip/src/v2/components/PeerInfo/InternalUser.tsx (2)
11-13: A11y: add alt/aria for avatar and hide decorative iconProvide an accessible name when the avatar renders and mark the fallback icon as decorative.
- <Box mie={8}>{avatarUrl ? <Avatar url={avatarUrl} size='x20' /> : <Icon name='user' size='x20' />}</Box> + <Box mie={8}> + {avatarUrl ? ( + <Avatar url={avatarUrl} size='x20' title={displayName} aria-label={displayName} /> + ) : ( + <Icon name='user' size='x20' aria-hidden='true' /> + )} + </Box>
11-11: Prevent possible ID collisionsIf multiple widgets render simultaneously, a hardcoded id risks duplication. Prefer a prop or useId() to generate a stable unique id, and have Widget.tsx reference it.
-import { Avatar, Box, Icon } from '@rocket.chat/fuselage'; +import { Avatar, Box, Icon } from '@rocket.chat/fuselage'; +import { useId } from 'react'; @@ -const InternalUser = ({ displayName, avatarUrl, callerId }: InternalUserProps) => { +const InternalUser = ({ displayName, avatarUrl, callerId }: InternalUserProps) => { + const callerInfoId = useId(); return ( - <Box display='flex' flexDirection='row' id='rcx-media-call-widget-caller-info'> + <Box display='flex' flexDirection='row' id={callerInfoId}> @@ - {callerId && ( + {callerId && ( <Box fontScale='c1' color='secondary-info'> {callerId} </Box> )}Then pass callerInfoId upward or expose via context for aria-describedby.
packages/ui-voip/src/v2/components/Widget/Widget.tsx (4)
44-47: Fix ARIA relationships: use aria-describedby for caller infoaria-labelledby should reference the title; secondary descriptive content belongs in aria-describedby to avoid referencing missing IDs when caller info isn’t rendered.
- <WidgetBase {...props} ref={draggableRef} aria-labelledby='rcx-media-call-widget-title rcx-media-call-widget-caller-info'> + <WidgetBase + {...props} + ref={draggableRef} + aria-labelledby='rcx-media-call-widget-title' + aria-describedby='rcx-media-call-widget-caller-info' + >Please confirm that an element with id="rcx-media-call-widget-title" is always present (WidgetHeader).
37-39: Guard DOM usage; avoid SSR warningsuseLayoutEffect doesn’t run on the server, but add a document check to be safe in mixed render environments.
- useLayoutEffect(() => { - boundingRef(document.body); - }, [boundingRef]); + useLayoutEffect(() => { + if (typeof document !== 'undefined') { + boundingRef(document.body); + } + }, [boundingRef]);
43-47: Auto-focus should be opt-inAuto-focusing can unexpectedly steal focus. Consider a prop (autoFocus = false) and pass it to FocusScope.
-type WidgetProps = { - children: React.ReactNode; -} & ComponentProps<typeof WidgetBase>; +type WidgetProps = { + children: React.ReactNode; + autoFocus?: boolean; +} & ComponentProps<typeof WidgetBase>; @@ -const Widget = ({ children, ...props }: WidgetProps) => { +const Widget = ({ children, autoFocus = false, ...props }: WidgetProps) => { @@ - <FocusScope autoFocus> + <FocusScope autoFocus={autoFocus}>
12-26: Initial position via style: consider persisting/reading from draggable APIYou already have a TODO; persisting last position (e.g., in localStorage) improves UX.
packages/ui-voip/src/v2/MockedMediaCallProvider.tsx (3)
29-31: Type onDeviceChange to DeviceMatch the context signature for stronger type safety.
-import { useState } from 'react'; +import { useState } from 'react'; +import type { Device } from '@rocket.chat/ui-contexts'; @@ -const onDeviceChange = (device: any) => { +const onDeviceChange = (device: Device) => {
48-56: getPeerInfo: return type OK; consider narrowing local variable nameMinor: avoid overshadowing by reusing the name peerInfo locally; rename to found or record for readability.
- const getPeerInfo = (id: string) => { - const peerInfo = myData.find((item) => item.value === id); - if (!peerInfo) { + const getPeerInfo = (id: string) => { + const found = myData.find((item) => item.value === id); + if (!found) { return Promise.resolve(undefined); } return Promise.resolve({ - displayName: peerInfo.label, - userId: peerInfo.value, - avatarUrl: peerInfo.avatarUrl, - username: peerInfo.identifier, - callerId: peerInfo.value, + displayName: found.label, + userId: found.value, + avatarUrl: found.avatarUrl, + username: found.identifier, + callerId: found.value, }); };
29-31: Console logs in mock providerFine for dev, but ensure these don’t leak into production builds.
Also applies to: 33-41
packages/ui-voip/src/v2/MediaCallContext.ts (2)
146-147: Autocomplete value should reflect external number tooWhen the selected peer is external ({ number }), consider reflecting it in value to keep input synced.
- value: peerInfo && 'userId' in peerInfo ? peerInfo.userId : undefined, + value: + peerInfo ? ('userId' in peerInfo ? peerInfo.userId : (peerInfo.number ?? undefined)) : undefined,
20-29: ConnectionState coverageIf you plan to represent disconnected/error states, consider adding them now to avoid another breaking change later.
Also applies to: 57-64
📜 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.
⛔ Files ignored due to path filters (1)
packages/ui-voip/src/v2/__snapshots__/MediaCallWidget.spec.tsx.snapis excluded by!**/*.snap
📒 Files selected for processing (23)
packages/ui-voip/src/v2/MediaCallContext.ts(5 hunks)packages/ui-voip/src/v2/MediaCallWidget.stories.tsx(1 hunks)packages/ui-voip/src/v2/MediaCallWidget.tsx(1 hunks)packages/ui-voip/src/v2/MockedMediaCallProvider.tsx(5 hunks)packages/ui-voip/src/v2/TransferModal.tsx(1 hunks)packages/ui-voip/src/v2/components/ActionButton.tsx(3 hunks)packages/ui-voip/src/v2/components/DevicePicker.tsx(2 hunks)packages/ui-voip/src/v2/components/PeerInfo/InternalUser.tsx(1 hunks)packages/ui-voip/src/v2/components/PeerInfo/PeerInfo.stories.tsx(1 hunks)packages/ui-voip/src/v2/components/PeerInfo/PeerInfo.tsx(1 hunks)packages/ui-voip/src/v2/components/PeerInfo/PhoneNumber.tsx(1 hunks)packages/ui-voip/src/v2/components/Widget/Widget.tsx(2 hunks)packages/ui-voip/src/v2/components/Widget/WidgetDraggableContext.ts(1 hunks)packages/ui-voip/src/v2/components/Widget/WidgetHandle.tsx(3 hunks)packages/ui-voip/src/v2/components/Widget/WidgetHeader.tsx(1 hunks)packages/ui-voip/src/v2/components/Widget/WidgetInfo.tsx(2 hunks)packages/ui-voip/src/v2/index.ts(1 hunks)packages/ui-voip/src/v2/useInfoSlots.ts(2 hunks)packages/ui-voip/src/v2/useKeypad.tsx(1 hunks)packages/ui-voip/src/v2/views/IncomingCall.tsx(2 hunks)packages/ui-voip/src/v2/views/NewCall.tsx(2 hunks)packages/ui-voip/src/v2/views/OngoingCall.tsx(3 hunks)packages/ui-voip/src/v2/views/OutgoingCall.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
packages/ui-voip/src/v2/MediaCallWidget.tsx (1)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
useMediaCallContext(86-88)
packages/ui-voip/src/v2/views/OutgoingCall.tsx (2)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
useMediaCallContext(86-88)apps/meteor/app/utils/lib/i18n.ts (1)
t(6-6)
packages/ui-voip/src/v2/useInfoSlots.ts (1)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
ConnectionState(20-20)
packages/ui-voip/src/v2/MediaCallWidget.stories.tsx (1)
packages/livechat/src/components/Button/index.tsx (1)
Button(34-99)
packages/ui-voip/src/v2/views/NewCall.tsx (1)
packages/ui-voip/src/v2/MediaCallContext.ts (2)
useMediaCallContext(86-88)usePeerAutocomplete(100-150)
packages/ui-voip/src/v2/views/OngoingCall.tsx (3)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
useMediaCallContext(86-88)packages/ui-voip/src/v2/useKeypad.tsx (1)
useKeypad(15-44)packages/ui-voip/src/v2/useInfoSlots.ts (1)
useInfoSlots(44-69)
packages/ui-voip/src/v2/components/Widget/WidgetInfo.tsx (1)
packages/ui-voip/src/v2/useInfoSlots.ts (1)
Slot(7-11)
packages/ui-voip/src/v2/components/Widget/WidgetHandle.tsx (1)
packages/ui-voip/src/v2/components/Widget/WidgetDraggableContext.ts (1)
useDraggableWidget(13-19)
packages/ui-voip/src/v2/views/IncomingCall.tsx (1)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
useMediaCallContext(86-88)
packages/ui-voip/src/v2/components/Widget/Widget.tsx (2)
packages/ui-voip/src/components/VoipPopupDraggable/DraggableCore.ts (1)
useDraggable(525-584)packages/ui-voip/src/v2/components/Widget/WidgetDraggableContext.ts (1)
DragContext(3-11)
packages/ui-voip/src/v2/components/PeerInfo/InternalUser.tsx (1)
packages/ui-voip/src/v2/components/PeerInfo/PeerInfo.stories.tsx (1)
InternalUser(11-29)
packages/ui-voip/src/v2/MockedMediaCallProvider.tsx (2)
packages/ui-voip/src/v2/index.ts (1)
PeerInfo(2-2)packages/ui-voip/src/v2/MediaCallContext.ts (1)
PeerInfo(22-22)
packages/ui-voip/src/v2/TransferModal.tsx (1)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
usePeerAutocomplete(100-150)
⏰ 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: 📦 Build Packages
- GitHub Check: CodeQL-Build
🔇 Additional comments (13)
packages/ui-voip/src/v2/components/ActionButton.tsx (1)
12-15: Confirm ref target and button type.Please verify IconButton forwards refs to an HTMLButtonElement and that it sets type="button" by default to avoid accidental form submits.
Also applies to: 17-28
packages/ui-voip/src/v2/components/DevicePicker.tsx (1)
25-26: Type/shape check: onDeviceChange now receives a device object—confirm it matches context typeEnsure the Device object here matches MediaCallContext’s expected shape (id/kind/label, etc.). If context expects a different key (e.g., deviceId), adapt the mapper.
Also applies to: 38-39, 49-50
packages/ui-voip/src/v2/components/PeerInfo/PeerInfo.stories.tsx (1)
14-15: Prop rename alignment looks correct.Using callerId/displayName matches the updated PeerInfo API and will route to InternalUser.
packages/ui-voip/src/v2/views/IncomingCall.tsx (1)
10-10: API rename to onAccept is handled correctly.Matches the context change and keeps semantics clear.
packages/ui-voip/src/v2/components/PeerInfo/PeerInfo.tsx (1)
8-11: Approve — 'displayName' type-guard is correct.
InternalUserProps declares displayName and PhoneNumberProps does not, so the 'in' check correctly narrows the union at runtime.packages/ui-voip/src/v2/views/OutgoingCall.tsx (1)
10-23: Verify connectionState enum casing and i18n key.
- ConnectionState: I couldn't find the authoritative enum/type in this verification — confirm the ConnectionState definition includes 'CONNECTING' (exact uppercase) and that comparisons in packages/ui-voip/src/v2/views/OutgoingCall.tsx and packages/ui-voip/src/v2/views/OngoingCall.tsx use that exact value or the enum constant.
- i18n: "meteor_status_connecting" exists in en and many other locales (packages/i18n/src/locales/en.i18n.json and others) — confirmed.
packages/ui-voip/src/v2/MediaCallWidget.tsx (1)
5-9: Approve — early-return on hidden is correct; default verifiedMediaCallContext.createContext sets
hidden: falseand MockedMediaCallProvider supplieshidden: false(packages/ui-voip/src/v2/MediaCallContext.ts, packages/ui-voip/src/v2/MockedMediaCallProvider.tsx).packages/ui-voip/src/v2/views/OngoingCall.tsx (1)
30-32: Good gating on transient connection states.Disabling dialpad/forward during CONNECTING/RECONNECTING is solid UX.
Also applies to: 51-55
packages/ui-voip/src/v2/useInfoSlots.ts (1)
33-41: Use a dedicated "meteor_status_reconnecting" i18n key (or confirm intent).Repo search shows only
meteor_status_connectingis present (packages/ui-voip/src/v2/useInfoSlots.ts, packages/ui-voip/src/v2/views/OngoingCall.tsx, packages/ui-voip/src/v2/views/OutgoingCall.tsx and locale files); nometeor_status_reconnectingkey found. Addmeteor_status_reconnectingand update useInfoSlots for distinct messaging, or confirm that reusingmeteor_status_connectingis intentional.packages/ui-voip/src/v2/TransferModal.tsx (1)
56-75: i18n keys present — no missing keys found.
Transfer_call, Close, Cancel and Hang_up_and_transfer_call are defined (seen in packages/i18n/src/locales/en.i18n.json) and present across locale files; tests reference these keys.packages/ui-voip/src/v2/components/PeerInfo/InternalUser.tsx (1)
18-18: Verify token name "secondary-info" exists in Fuselage themeIf not, switch to a supported token (e.g., 'hint' or 'secondary-info' equivalent).
packages/ui-voip/src/v2/MockedMediaCallProvider.tsx (1)
11-16: PeerInfo shape change looks consistentdisplayName/userId/username/callerId mapping aligns with the new context type.
Please run a repo-wide check for legacy props (name, identifier) to avoid stale usages:
packages/ui-voip/src/v2/MediaCallContext.ts (1)
45-47: API change: onCall/onAccept now Promise-returning with no params — verify call sitesConfirm all call sites await/handle the returned Promise and no longer pass a peerId (selection now flows via onSelectPeer).
packages/ui-voip/src/v2/components/Widget/WidgetDraggableContext.ts
Outdated
Show resolved
Hide resolved
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #36985 +/- ##
===========================================
+ Coverage 66.25% 66.39% +0.14%
===========================================
Files 3389 3390 +1
Lines 115174 115279 +105
Branches 21078 21111 +33
===========================================
+ Hits 76304 76536 +232
+ Misses 36265 36141 -124
+ Partials 2605 2602 -3
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.
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 (3)
packages/ui-voip/src/v2/TransferModal.tsx (3)
52-58: Hook Modal onClose to support ESC/overlay dismissalWire
onCloseso users can dismiss via ESC/backdrop; improves a11y and matches common Modal behavior.- <Modal open aria-labelledby={modalId}> + <Modal open aria-labelledby={modalId} onClose={onCancel}>
34-50: Don’t throw from a click handler; gate confirm by valid peer shapeAvoid uncaught exceptions from UI. Compute a safe
isConfirmableand disable the action unless the peer hasuserIdornumber.const autocomplete = usePeerAutocomplete(setPeer, peer); - const confirm = () => { - if (!peer) { - return; - } + const isConfirmable = Boolean(peer && ('userId' in peer || 'number' in peer)); + + const confirm = () => { + if (!isConfirmable || !peer) { + return; + } if ('userId' in peer) { onConfirm('user', peer.userId); return; } if ('number' in peer) { onConfirm('sip', peer.number); return; } - throw new Error('Peer info is missing userId and/or number'); + return; };- <Button danger onClick={confirm} disabled={!peer}> + <Button danger onClick={confirm} disabled={!isConfirmable}> {t('Hang_up_and_transfer_call')} </Button>Also applies to: 72-74
30-31: Tiny nit: simplify initial stateYou can omit the explicit
undefinedinitializer.- const [peer, setPeer] = useState<PeerInfoType | undefined>(undefined); + const [peer, setPeer] = useState<PeerInfoType | undefined>();
📜 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.
📒 Files selected for processing (6)
packages/i18n/src/locales/en.i18n.json(2 hunks)packages/ui-voip/src/v2/TransferModal.tsx(1 hunks)packages/ui-voip/src/v2/components/PeerInfo/PhoneNumber.tsx(1 hunks)packages/ui-voip/src/v2/components/Widget/WidgetDraggableContext.ts(1 hunks)packages/ui-voip/src/v2/components/Widget/WidgetInfo.tsx(2 hunks)packages/ui-voip/src/v2/views/IncomingCall.tsx(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/i18n/src/locales/en.i18n.json
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/ui-voip/src/v2/components/PeerInfo/PhoneNumber.tsx
- packages/ui-voip/src/v2/views/IncomingCall.tsx
- packages/ui-voip/src/v2/components/Widget/WidgetDraggableContext.ts
- packages/ui-voip/src/v2/components/Widget/WidgetInfo.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
packages/ui-voip/src/v2/TransferModal.tsx (1)
packages/ui-voip/src/v2/MediaCallContext.ts (1)
usePeerAutocomplete(100-150)
⏰ 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/v2/TransferModal.tsx (2)
32-33: Good integration with the new autocomplete contractUsing
usePeerAutocomplete(setPeer, peer)cleanly externalizes selection state.
56-57: i18n keys present — no action requiredTransfer_call, Hang_up_and_transfer_call, Close and Cancel exist in packages/i18n/src/locales (e.g. packages/i18n/src/locales/en.i18n.json: "Cancel"@933, "Close"@1039, "Hang_up_and_transfer_call"@2370, "Transfer_call"@5239).
Proposed changes (including videos or screenshots)
Issue(s)
Steps to test or reproduce
Further comments
Summary by CodeRabbit
New Features
Refactor
Chores