Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/eighty-weeks-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/ui-client": patch
"@rocket.chat/ui-voip": patch
---

Introduces in the call widget a quick link that redirects to the participant's direct message
1 change: 1 addition & 0 deletions apps/meteor/client/providers/MediaCallProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const MediaCallProvider = ({ children }: { children: ReactNode }) => {
onToggleWidget: undefined,
onEndCall: undefined,
peerInfo: undefined,
setOpenRoomId: undefined,
}),
[],
);
Expand Down
3 changes: 3 additions & 0 deletions apps/meteor/client/views/room/Room.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isInviteSubscription } from '@rocket.chat/core-typings';
import { ContextualbarSkeleton } from '@rocket.chat/ui-client';
import { useSetting, useRoomToolbox, useUserId } from '@rocket.chat/ui-contexts';
import { useMediaCallOpenRoomTracker } from '@rocket.chat/ui-voip';
import type { ReactElement } from 'react';
import { createElement, lazy, memo, Suspense } from 'react';
import { FocusScope } from 'react-aria';
Expand Down Expand Up @@ -34,6 +35,8 @@ const Room = (): ReactElement => {
const roomLabel =
room.t === 'd' ? t('Conversation_with__roomName__', { roomName: room.name }) : t('Channel__roomName__', { roomName: room.name });

useMediaCallOpenRoomTracker(room._id);

if (subscription && isInviteSubscription(subscription)) {
return (
<FocusScope>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ describe('useUserMediaCallAction', () => {
onToggleWidget: undefined,
onEndCall: undefined,
peerInfo: undefined,
setOpenRoomId: undefined,
});

const { result } = renderHook(() => useUserMediaCallAction(fakeUser, mockRid), { wrapper: mockAppRoot().build() });
Expand Down Expand Up @@ -114,6 +115,7 @@ describe('useUserMediaCallAction', () => {
onToggleWidget: mockOnToggleWidget,
peerInfo: undefined,
onEndCall: () => undefined,
setOpenRoomId: () => undefined,
});

const { result } = renderHook(() => useUserMediaCallAction(fakeUser, mockRid));
Expand All @@ -133,6 +135,7 @@ describe('useUserMediaCallAction', () => {
onToggleWidget: jest.fn(),
peerInfo: undefined,
onEndCall: () => undefined,
setOpenRoomId: () => undefined,
});

const { result } = renderHook(() => useUserMediaCallAction(fakeUser, mockRid));
Expand Down
4 changes: 3 additions & 1 deletion packages/ui-voip/src/components/Widget/WidgetHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const WidgetHeader = ({ title, children }: WidgetHeaderProps): ReactElement => {
<Box is='h3' color='titles-labels' fontScale='p1b' id='rcx-media-call-widget-title'>
{title}
</Box>
<Box mis={8}>{children}</Box>
<Box mis={8} display='flex' flexDirection='row'>
{children}
</Box>
</Box>
);
};
Expand Down
17 changes: 16 additions & 1 deletion packages/ui-voip/src/context/MediaCallContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type MediaCallContextType = {
remoteMuted: boolean;
remoteHeld: boolean;

onClickDirectMessage?: () => void;

onMute: () => void;
onHold: () => void;

Expand All @@ -54,6 +56,8 @@ type MediaCallContextType = {

onSelectPeer: (peerInfo: PeerInfo) => void;

setOpenRoomId: (roomId: string | undefined) => void;

getAutocompleteOptions: (filter: string) => Promise<PeerAutocompleteOptions[]>;
// This is used to get the peer info from the server in case it's not available in the autocomplete options.
getPeerInfo: (id: string) => Promise<PeerInfo | undefined>;
Expand Down Expand Up @@ -88,6 +92,8 @@ export const defaultMediaCallContextValue: MediaCallContextType = {

onSelectPeer: () => undefined,

setOpenRoomId: () => undefined,

getAutocompleteOptions: () => Promise.resolve([]),
getPeerInfo: () => Promise.resolve(undefined),
};
Expand All @@ -97,20 +103,23 @@ type MediaCallExternalContextType = {
onToggleWidget: (peerInfo?: PeerInfo) => void;
onEndCall: () => void;
peerInfo: PeerInfo | undefined;
setOpenRoomId: (roomId: string | undefined) => void;
};

type MediaCallUnauthorizedContextType = {
state: 'unauthorized';
onToggleWidget: undefined;
onEndCall: undefined;
peerInfo: undefined;
setOpenRoomId: undefined;
};

type MediaCallUnlicensedContextType = {
state: 'unlicensed';
onToggleWidget: (peerInfo?: any) => void;
onEndCall: undefined;
peerInfo: undefined;
setOpenRoomId: undefined;
};

const MediaCallContext = createContext<MediaCallContextType | MediaCallUnauthorizedContextType | MediaCallUnlicensedContextType>(
Expand Down Expand Up @@ -146,7 +155,13 @@ export const useMediaCallExternalContext = ():
return context;
}

return { state: context.state, onToggleWidget: context.onToggleWidget, onEndCall: context.onEndCall, peerInfo: context.peerInfo };
return {
state: context.state,
onToggleWidget: context.onToggleWidget,
onEndCall: context.onEndCall,
peerInfo: context.peerInfo,
setOpenRoomId: context.setOpenRoomId,
};
};

export default MediaCallContext;
12 changes: 10 additions & 2 deletions packages/ui-voip/src/context/MediaCallProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AnchorPortal } from '@rocket.chat/ui-client';
import { AnchorPortal, useGoToDirectMessage } from '@rocket.chat/ui-client';
import type { Device } from '@rocket.chat/ui-contexts';
import {
useEndpoint,
Expand All @@ -12,7 +12,7 @@ import {
useSetting,
} from '@rocket.chat/ui-contexts';
import type { ReactNode } from 'react';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';

Expand All @@ -36,6 +36,7 @@ const MediaCallProvider = ({ children }: MediaCallProviderProps) => {
const user = useUser();
const { t } = useTranslation();
const dispatchToastMessage = useToastMessageDispatch();
const [openRoomId, setOpenRoomId] = useState<string | undefined>(undefined);

const setModal = useSetModal();

Expand All @@ -57,6 +58,11 @@ const MediaCallProvider = ({ children }: MediaCallProviderProps) => {

const forceSIPRouting = useSetting('VoIP_TeamCollab_SIP_Integration_For_Internal_Calls');

const onClickDirectMessage = useGoToDirectMessage(
{ username: session.peerInfo && 'username' in session.peerInfo ? session.peerInfo.username : undefined },
openRoomId,
);

// For some reason `exhaustive-deps` is complaining that "session" is not in the dependencies
// But we're only using the changeDevice method from the session
// So I'll just destructure it here
Expand Down Expand Up @@ -262,6 +268,8 @@ const MediaCallProvider = ({ children }: MediaCallProviderProps) => {
hidden: session.hidden,
remoteMuted: session.remoteMuted,
remoteHeld: session.remoteHeld,
onClickDirectMessage,
setOpenRoomId,
onMute,
onHold,
onDeviceChange,
Expand Down
4 changes: 4 additions & 0 deletions packages/ui-voip/src/context/MockedMediaCallProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ type MockedMediaCallProviderProps = {
remoteHeld?: boolean;
muted?: boolean;
held?: boolean;
onClickDirectMessage?: () => void;
};

const MockedMediaCallProvider = ({
children,
state = 'closed',
onClickDirectMessage = undefined,
transferredBy = undefined,
remoteMuted = false,
remoteHeld = false,
Expand Down Expand Up @@ -131,6 +133,8 @@ const MockedMediaCallProvider = ({
transferredBy,
muted: mutedState,
held: heldState,
setOpenRoomId: () => undefined,
onClickDirectMessage,
remoteMuted,
remoteHeld,
onMute,
Expand Down
1 change: 1 addition & 0 deletions packages/ui-voip/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './useDevicePermissionPrompt';
export { useDraggable } from './VoipPopupDraggable/DraggableCore';
export { useMediaCallAction } from './useMediaCallAction';
export { useMediaCallOpenRoomTracker } from './useMediaCallOpenRoomTracker';
17 changes: 17 additions & 0 deletions packages/ui-voip/src/hooks/useMediaCallOpenRoomTracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useEffect } from 'react';

import { useMediaCallExternalContext } from '../context/MediaCallContext';

export const useMediaCallOpenRoomTracker = (openRoomId?: string) => {
const { setOpenRoomId } = useMediaCallExternalContext();

useEffect(() => {
if (!setOpenRoomId) {
return;
}
setOpenRoomId(openRoomId);
return () => {
setOpenRoomId(undefined);
};
}, [setOpenRoomId, openRoomId]);
};
2 changes: 1 addition & 1 deletion packages/ui-voip/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export { default as MediaCallProvider } from './context/MediaCallProvider';

export { MediaCallContext, useMediaCallExternalContext as useMediaCallContext, isCallingBlocked } from './context';
export type { PeerInfo, MediaCallState } from './context';
export { useMediaCallAction } from './hooks';
export { useMediaCallAction, useMediaCallOpenRoomTracker } from './hooks';

export { CallHistoryContextualBar } from './views';
export type { InternalCallHistoryContact, ExternalCallHistoryContact, CallHistoryData } from './views';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,11 @@ export const OngoingCallWithSlotsAndRemoteStatus: StoryFn<typeof OngoingCall> =
</MockedMediaCallProvider>
);
};

export const OngoingCallWithDmButton: StoryFn<typeof OngoingCall> = () => {
return (
<MockedMediaCallProvider onClickDirectMessage={() => undefined}>
<OngoingCall />
</MockedMediaCallProvider>
);
};
19 changes: 17 additions & 2 deletions packages/ui-voip/src/views/MediaCallWidget/OngoingCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,20 @@ import { useMediaCallContext } from '../../context';
const OngoingCall = () => {
const { t } = useTranslation();

const { muted, held, remoteMuted, remoteHeld, onMute, onHold, onForward, onEndCall, onTone, peerInfo, connectionState } =
useMediaCallContext();
const {
muted,
held,
remoteMuted,
remoteHeld,
onMute,
onHold,
onForward,
onEndCall,
onTone,
peerInfo,
connectionState,
onClickDirectMessage,
} = useMediaCallContext();

const { element: keypad, buttonProps: keypadButtonProps } = useKeypad(onTone);

Expand All @@ -41,6 +53,9 @@ const OngoingCall = () => {
<Widget>
<WidgetHandle />
<WidgetHeader title={connecting ? t('meteor_status_connecting') : <Timer />}>
{onClickDirectMessage && (
<ActionButton tiny secondary={false} label={t('Direct_Message')} icon='balloon' onClick={onClickDirectMessage} />
)}
<DevicePicker />
</WidgetHeader>
<WidgetContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ exports[`renders IncomingCall without crashing 1`] = `
Incoming Call...
</h3>
<div
class="rcx-box rcx-box--full rcx-css-ws1yyr"
class="rcx-box rcx-box--full rcx-css-qwfmt5"
>
<button
aria-label="customize"
Expand Down Expand Up @@ -188,7 +188,7 @@ exports[`renders IncomingCallTransfer without crashing 1`] = `
Transferring_call_incoming...
</h3>
<div
class="rcx-box rcx-box--full rcx-css-ws1yyr"
class="rcx-box rcx-box--full rcx-css-qwfmt5"
>
<button
aria-label="customize"
Expand Down Expand Up @@ -382,7 +382,7 @@ exports[`renders NewCall without crashing 1`] = `
New_call
</h3>
<div
class="rcx-box rcx-box--full rcx-css-ws1yyr"
class="rcx-box rcx-box--full rcx-css-qwfmt5"
>
<button
aria-label="Close"
Expand Down Expand Up @@ -584,7 +584,7 @@ exports[`renders OngoingCall without crashing 1`] = `
</time>
</h3>
<div
class="rcx-box rcx-box--full rcx-css-ws1yyr"
class="rcx-box rcx-box--full rcx-css-qwfmt5"
>
<button
aria-label="customize"
Expand Down Expand Up @@ -777,7 +777,7 @@ exports[`renders OutgoingCall without crashing 1`] = `
Calling...
</h3>
<div
class="rcx-box rcx-box--full rcx-css-ws1yyr"
class="rcx-box rcx-box--full rcx-css-qwfmt5"
>
<button
aria-label="customize"
Expand Down Expand Up @@ -917,7 +917,7 @@ exports[`renders OutgoingCallTransfer without crashing 1`] = `
Transferring_call...
</h3>
<div
class="rcx-box rcx-box--full rcx-css-ws1yyr"
class="rcx-box rcx-box--full rcx-css-qwfmt5"
>
<button
aria-label="customize"
Expand Down
Loading