From 4ae563cc953dc027eedc1261ab6eb475339a3162 Mon Sep 17 00:00:00 2001 From: ayumi-signal <143036029+ayumi-signal@users.noreply.github.com> Date: Fri, 28 Jun 2024 17:13:20 -0700 Subject: [PATCH] Block users from joining call links --- _locales/en/messages.json | 12 +++++ .../components/CallingAdhocCallInfo.scss | 4 ++ ts/components/CallManager.stories.tsx | 1 + ts/components/CallManager.tsx | 6 +++ .../CallingAdhocCallInfo.stories.tsx | 33 ++++++++++++ ts/components/CallingAdhocCallInfo.tsx | 50 +++++++++++++++++-- ts/services/calling.ts | 9 ++++ ts/state/ducks/calling.ts | 25 +++++++++- ts/state/smart/CallManager.tsx | 2 + 9 files changed, 137 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 08a2123e6aa..fa65c304907 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -3694,6 +3694,18 @@ "messageformat": "Remove this person from the call", "description": "Button in the in-call info popup for call link calls showing all participants. The action is to remove the participant from the call." }, + "icu:CallingAdhocCallInfo__RemoveClientDialogBody": { + "messageformat": "Remove {name} from the call?", + "description": "Info text in confirmation dialog when removing or blocking someone from an ongoing call for a call link." + }, + "icu:CallingAdhocCallInfo__RemoveClientDialogButton--remove": { + "messageformat": "Remove", + "description": "Button in confirmation dialog when removing or blocking someone from an ongoing call for a call link." + }, + "icu:CallingAdhocCallInfo__RemoveClientDialogButton--block": { + "messageformat": "Block from call", + "description": "Button in confirmation dialog when removing or blocking someone from an ongoing call for a call link." + }, "icu:CallingAdhocCallInfo__UnknownContactLabel": { "messageformat": "{count, plural, one {# person} other {# people}}", "description": "Label showing number of unknown contacts in the in-call participant info popup for call links." diff --git a/stylesheets/components/CallingAdhocCallInfo.scss b/stylesheets/components/CallingAdhocCallInfo.scss index e7f7881e6a1..8b62a33cb05 100644 --- a/stylesheets/components/CallingAdhocCallInfo.scss +++ b/stylesheets/components/CallingAdhocCallInfo.scss @@ -137,3 +137,7 @@ // Should match background of .module-calling-participants-list__contact:hover outline-color: $color-gray-62; } + +.CallingAdhocCallInfo__RemoveClientDialog { + width: 440px; +} diff --git a/ts/components/CallManager.stories.tsx b/ts/components/CallManager.stories.tsx index 4414bbe4872..bad05373596 100644 --- a/ts/components/CallManager.stories.tsx +++ b/ts/components/CallManager.stories.tsx @@ -100,6 +100,7 @@ const createProps = (storyProps: Partial = {}): PropsType => ({ openSystemPreferencesAction: action('open-system-preferences-action'), playRingtone: action('play-ringtone'), removeClient: action('remove-client'), + blockClient: action('block-client'), renderDeviceSelection: () =>
, renderEmojiPicker: () => <>EmojiPicker, renderReactionPicker: () =>
, diff --git a/ts/components/CallManager.tsx b/ts/components/CallManager.tsx index f2f3fc17d2e..f156d01734b 100644 --- a/ts/components/CallManager.tsx +++ b/ts/components/CallManager.tsx @@ -117,6 +117,7 @@ export type PropsType = { openSystemPreferencesAction: () => unknown; playRingtone: () => unknown; removeClient: (payload: RemoveClientType) => void; + blockClient: (payload: RemoveClientType) => void; sendGroupCallRaiseHand: (payload: SendGroupCallRaiseHandType) => void; sendGroupCallReaction: (payload: SendGroupCallReactionType) => void; setGroupCallVideoRequest: (_: SetGroupCallVideoRequestType) => void; @@ -163,6 +164,7 @@ function ActiveCallManager({ activeCall, approveUser, availableCameras, + blockClient, callLink, cancelCall, changeCallView, @@ -397,6 +399,7 @@ function ActiveCallManager({ onCopyCallLink={onCopyCallLink} onShareCallLinkViaSignal={handleShareCallLinkViaSignal} removeClient={removeClient} + blockClient={blockClient} showContactModal={showContactModal} /> ) : ( @@ -494,6 +497,7 @@ function ActiveCallManager({ onCopyCallLink={onCopyCallLink} onShareCallLinkViaSignal={handleShareCallLinkViaSignal} removeClient={removeClient} + blockClient={blockClient} showContactModal={showContactModal} /> ) : ( @@ -515,6 +519,7 @@ export function CallManager({ activeCall, approveUser, availableCameras, + blockClient, bounceAppIconStart, bounceAppIconStop, callLink, @@ -613,6 +618,7 @@ export function CallManager({ activeCall={activeCall} availableCameras={availableCameras} approveUser={approveUser} + blockClient={blockClient} callLink={callLink} cancelCall={cancelCall} changeCallView={changeCallView} diff --git a/ts/components/CallingAdhocCallInfo.stories.tsx b/ts/components/CallingAdhocCallInfo.stories.tsx index 9efd3fc127c..6585fc7ee04 100644 --- a/ts/components/CallingAdhocCallInfo.stories.tsx +++ b/ts/components/CallingAdhocCallInfo.stories.tsx @@ -68,6 +68,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({ onCopyCallLink: action('on-copy-call-link'), onShareCallLinkViaSignal: action('on-share-call-link-via-signal'), removeClient: overrideProps.removeClient || action('remove-client'), + blockClient: overrideProps.blockClient || action('block-client'), showContactModal: action('show-contact-modal'), }); @@ -140,3 +141,35 @@ export function Overflow(): JSX.Element { }); return ; } + +export function AsAdmin(): JSX.Element { + const props = createProps({ + participants: [ + createParticipant({ + title: 'Son Goku', + }), + createParticipant({ + hasRemoteAudio: true, + hasRemoteVideo: true, + presenting: true, + name: 'Rage Trunks', + title: 'Rage Trunks', + }), + createParticipant({ + hasRemoteAudio: true, + title: 'Prince Vegeta', + }), + createParticipant({ + hasRemoteAudio: true, + hasRemoteVideo: true, + name: 'Goku', + title: 'Goku', + }), + createParticipant({ + title: 'Someone With A Really Long Name', + }), + ], + isCallLinkAdmin: true, + }); + return ; +} diff --git a/ts/components/CallingAdhocCallInfo.tsx b/ts/components/CallingAdhocCallInfo.tsx index 9aba9221c9a..0b76725c496 100644 --- a/ts/components/CallingAdhocCallInfo.tsx +++ b/ts/components/CallingAdhocCallInfo.tsx @@ -20,6 +20,7 @@ import { AVATAR_COLOR_COUNT, AvatarColors } from '../types/Colors'; import { Button } from './Button'; import { Modal } from './Modal'; import { Theme } from '../util/theme'; +import { ConfirmationDialog } from './ConfirmationDialog'; const MAX_UNKNOWN_AVATARS_COUNT = 3; @@ -40,7 +41,8 @@ export type PropsType = { readonly onClose: () => void; readonly onCopyCallLink: () => void; readonly onShareCallLinkViaSignal: () => void; - readonly removeClient: ((payload: RemoveClientType) => void) | null; + readonly removeClient: (payload: RemoveClientType) => void; + readonly blockClient: (payload: RemoveClientType) => void; readonly showContactModal: ( contactId: string, conversationId?: string @@ -145,6 +147,7 @@ export function CallingAdhocCallInfo({ isCallLinkAdmin, ourServiceId, participants, + blockClient, onClose, onCopyCallLink, onShareCallLinkViaSignal, @@ -153,6 +156,11 @@ export function CallingAdhocCallInfo({ }: PropsType): JSX.Element | null { const [isUnknownContactDialogVisible, setIsUnknownContactDialogVisible] = React.useState(false); + const [removeClientDialogState, setRemoveClientDialogState] = React.useState<{ + demuxId: number; + name: string; + } | null>(null); + const hideUnknownContactDialog = React.useCallback( () => setIsUnknownContactDialogVisible(false), [setIsUnknownContactDialogVisible] @@ -256,7 +264,6 @@ export function CallingAdhocCallInfo({ )} /> {isCallLinkAdmin && - removeClient && participant.demuxId && !(ourServiceId && participant.serviceId === ourServiceId) ? (