Call lobby join button text for call links requiring approval

This commit is contained in:
ayumi-signal 2024-04-29 14:31:44 -07:00 committed by GitHub
parent a0b4126b52
commit c531c64410
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 80 additions and 10 deletions

View file

@ -1625,6 +1625,10 @@
"messageformat": "Call full", "messageformat": "Call full",
"description": "Button in the call lobby when you can't join because the call is full" "description": "Button in the call lobby when you can't join because the call is full"
}, },
"icu:CallingLobbyJoinButton--ask-to-join": {
"messageformat": "Ask to join",
"description": "Button label in the call lobby for joining a call link which requires admin approval"
},
"icu:calling__button--video-disabled": { "icu:calling__button--video-disabled": {
"messageformat": "Camera disabled", "messageformat": "Camera disabled",
"description": "Button tooltip label when the camera is disabled" "description": "Button tooltip label when the camera is disabled"

View file

@ -53,6 +53,7 @@ import { CallingAdhocCallInfo } from './CallingAdhocCallInfo';
import { callLinkRootKeyToUrl } from '../util/callLinkRootKeyToUrl'; import { callLinkRootKeyToUrl } from '../util/callLinkRootKeyToUrl';
import { ToastType } from '../types/Toast'; import { ToastType } from '../types/Toast';
import type { ShowToastAction } from '../state/ducks/toast'; import type { ShowToastAction } from '../state/ducks/toast';
import { isSharingPhoneNumberWithEverybody } from '../util/phoneNumberSharingMode';
const GROUP_CALL_RING_DURATION = 60 * 1000; const GROUP_CALL_RING_DURATION = 60 * 1000;
@ -257,6 +258,7 @@ function ActiveCallManager({
| undefined | undefined
| Array<Pick<ConversationType, 'id' | 'firstName' | 'title'>>; | Array<Pick<ConversationType, 'id' | 'firstName' | 'title'>>;
let isConvoTooBigToRing = false; let isConvoTooBigToRing = false;
let isAdhocAdminApprovalRequired = false;
let isAdhocJoinRequestPending = false; let isAdhocJoinRequestPending = false;
switch (activeCall.callMode) { switch (activeCall.callMode) {
@ -286,8 +288,11 @@ function ActiveCallManager({
isCallFull = activeCall.deviceCount >= activeCall.maxDevices; isCallFull = activeCall.deviceCount >= activeCall.maxDevices;
isConvoTooBigToRing = activeCall.isConversationTooBigToRing; isConvoTooBigToRing = activeCall.isConversationTooBigToRing;
({ groupMembers } = activeCall); ({ groupMembers } = activeCall);
isAdhocAdminApprovalRequired =
!callLink?.adminKey &&
callLink?.restrictions === CallLinkRestrictions.AdminApproval;
isAdhocJoinRequestPending = isAdhocJoinRequestPending =
callLink?.restrictions === CallLinkRestrictions.AdminApproval && isAdhocAdminApprovalRequired &&
activeCall.joinState === GroupCallJoinState.Pending; activeCall.joinState === GroupCallJoinState.Pending;
break; break;
} }
@ -324,9 +329,11 @@ function ActiveCallManager({
hasLocalAudio={hasLocalAudio} hasLocalAudio={hasLocalAudio}
hasLocalVideo={hasLocalVideo} hasLocalVideo={hasLocalVideo}
i18n={i18n} i18n={i18n}
isAdhocAdminApprovalRequired={isAdhocAdminApprovalRequired}
isAdhocJoinRequestPending={isAdhocJoinRequestPending} isAdhocJoinRequestPending={isAdhocJoinRequestPending}
isCallFull={isCallFull} isCallFull={isCallFull}
isConversationTooBigToRing={isConvoTooBigToRing} isConversationTooBigToRing={isConvoTooBigToRing}
isSharingPhoneNumberWithEverybody={isSharingPhoneNumberWithEverybody()}
me={me} me={me}
onCallCanceled={cancelActiveCall} onCallCanceled={cancelActiveCall}
onJoinCall={joinActiveCall} onJoinCall={joinActiveCall}

View file

@ -20,6 +20,7 @@ import {
} from '../test-both/helpers/getDefaultConversation'; } from '../test-both/helpers/getDefaultConversation';
import { CallingToastProvider } from './CallingToast'; import { CallingToastProvider } from './CallingToast';
import { CallMode } from '../types/Calling'; import { CallMode } from '../types/Calling';
import { getDefaultCallLinkConversation } from '../test-both/helpers/fakeCallLink';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
@ -33,15 +34,24 @@ const camera = {
}, },
}; };
const getConversation = (callMode: CallMode) => {
if (callMode === CallMode.Group) {
return getDefaultConversation({
title: 'Tahoe Trip',
type: 'group',
});
}
if (callMode === CallMode.Adhoc) {
return getDefaultCallLinkConversation();
}
return getDefaultConversation();
};
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => { const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
const callMode = overrideProps.callMode ?? CallMode.Direct; const callMode = overrideProps.callMode ?? CallMode.Direct;
const conversation = const conversation = getConversation(callMode);
callMode === CallMode.Group
? getDefaultConversation({
title: 'Tahoe Trip',
type: 'group',
})
: getDefaultConversation();
return { return {
availableCameras: overrideProps.availableCameras || [camera], availableCameras: overrideProps.availableCameras || [camera],
@ -55,9 +65,13 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
hasLocalAudio: overrideProps.hasLocalAudio ?? true, hasLocalAudio: overrideProps.hasLocalAudio ?? true,
hasLocalVideo: overrideProps.hasLocalVideo ?? false, hasLocalVideo: overrideProps.hasLocalVideo ?? false,
i18n, i18n,
isAdhocAdminApprovalRequired:
overrideProps.isAdhocAdminApprovalRequired ?? false,
isAdhocJoinRequestPending: false, isAdhocJoinRequestPending: false,
isConversationTooBigToRing: false, isConversationTooBigToRing: false,
isCallFull: overrideProps.isCallFull ?? false, isCallFull: overrideProps.isCallFull ?? false,
isSharingPhoneNumberWithEverybody:
overrideProps.isSharingPhoneNumberWithEverybody ?? false,
me: me:
overrideProps.me || overrideProps.me ||
getDefaultConversation({ getDefaultConversation({
@ -206,3 +220,20 @@ export function GroupCallWith0PeekedParticipantsBigGroup(): JSX.Element {
}); });
return <CallingLobby {...props} />; return <CallingLobby {...props} />;
} }
export function CallLink(): JSX.Element {
const props = createProps({
callMode: CallMode.Adhoc,
});
return <CallingLobby {...props} />;
}
// Due to storybook font loading, if you directly load this story then
// the button width is not calculated correctly
export function CallLinkAdminApproval(): JSX.Element {
const props = createProps({
callMode: CallMode.Adhoc,
isAdhocAdminApprovalRequired: true,
});
return <CallingLobby {...props} />;
}

View file

@ -28,7 +28,6 @@ import type { ConversationType } from '../state/ducks/conversations';
import { useCallingToasts } from './CallingToast'; import { useCallingToasts } from './CallingToast';
import { CallingButtonToastsContainer } from './CallingToastManager'; import { CallingButtonToastsContainer } from './CallingToastManager';
import { isGroupOrAdhocCallMode } from '../util/isGroupOrAdhocCall'; import { isGroupOrAdhocCallMode } from '../util/isGroupOrAdhocCall';
import { isSharingPhoneNumberWithEverybody } from '../util/phoneNumberSharingMode';
export type PropsType = { export type PropsType = {
availableCameras: Array<MediaDeviceInfo>; availableCameras: Array<MediaDeviceInfo>;
@ -59,9 +58,11 @@ export type PropsType = {
hasLocalAudio: boolean; hasLocalAudio: boolean;
hasLocalVideo: boolean; hasLocalVideo: boolean;
i18n: LocalizerType; i18n: LocalizerType;
isAdhocAdminApprovalRequired: boolean;
isAdhocJoinRequestPending: boolean; isAdhocJoinRequestPending: boolean;
isConversationTooBigToRing: boolean; isConversationTooBigToRing: boolean;
isCallFull?: boolean; isCallFull?: boolean;
isSharingPhoneNumberWithEverybody: boolean;
me: Readonly< me: Readonly<
Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'serviceId'> Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'serviceId'>
>; >;
@ -87,9 +88,11 @@ export function CallingLobby({
hasLocalAudio, hasLocalAudio,
hasLocalVideo, hasLocalVideo,
i18n, i18n,
isAdhocAdminApprovalRequired,
isAdhocJoinRequestPending, isAdhocJoinRequestPending,
isCallFull = false, isCallFull = false,
isConversationTooBigToRing, isConversationTooBigToRing,
isSharingPhoneNumberWithEverybody,
me, me,
onCallCanceled, onCallCanceled,
onJoinCall, onJoinCall,
@ -214,6 +217,8 @@ export function CallingLobby({
callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.CallIsFull; callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.CallIsFull;
} else if (isCallConnecting) { } else if (isCallConnecting) {
callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.Loading; callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.Loading;
} else if (isAdhocAdminApprovalRequired) {
callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.AskToJoin;
} else if (peekedParticipants.length || callMode === CallMode.Adhoc) { } else if (peekedParticipants.length || callMode === CallMode.Adhoc) {
callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.Join; callingLobbyJoinButtonVariant = CallingLobbyJoinButtonVariant.Join;
} else { } else {
@ -303,7 +308,7 @@ export function CallingLobby({
{callMode === CallMode.Adhoc && ( {callMode === CallMode.Adhoc && (
<div className="CallingLobby__CallLinkNotice"> <div className="CallingLobby__CallLinkNotice">
{isSharingPhoneNumberWithEverybody() {isSharingPhoneNumberWithEverybody
? i18n('icu:CallingLobby__CallLinkNotice--phone-sharing') ? i18n('icu:CallingLobby__CallLinkNotice--phone-sharing')
: i18n('icu:CallingLobby__CallLinkNotice')} : i18n('icu:CallingLobby__CallLinkNotice')}
</div> </div>

View file

@ -14,6 +14,7 @@ export enum CallingLobbyJoinButtonVariant {
Join = 'Join', Join = 'Join',
Loading = 'Loading', Loading = 'Loading',
Start = 'Start', Start = 'Start',
AskToJoin = 'AskToJoin',
} }
type PropsType = { type PropsType = {
@ -55,6 +56,9 @@ export function CallingLobbyJoinButton({
[CallingLobbyJoinButtonVariant.Start]: i18n( [CallingLobbyJoinButtonVariant.Start]: i18n(
'icu:CallingLobbyJoinButton--start' 'icu:CallingLobbyJoinButton--start'
), ),
[CallingLobbyJoinButtonVariant.AskToJoin]: i18n(
'icu:CallingLobbyJoinButton--ask-to-join'
),
}; };
return ( return (

View file

@ -1,5 +1,6 @@
// Copyright 2024 Signal Messenger, LLC // Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import type { CallingConversationType } from '../../types/Calling';
import type { CallLinkType } from '../../types/CallLink'; import type { CallLinkType } from '../../types/CallLink';
import { CallLinkRestrictions } from '../../types/CallLink'; import { CallLinkRestrictions } from '../../types/CallLink';
import { MONTH } from '../../util/durations/constants'; import { MONTH } from '../../util/durations/constants';
@ -24,3 +25,21 @@ export const FAKE_CALL_LINK_WITH_ADMIN_KEY: CallLinkType = {
roomId: 'c097eb04cc278d6bc7ed9fb2ddeac00dc9646ae6ddb38513dad9a8a4fe3c38f4', roomId: 'c097eb04cc278d6bc7ed9fb2ddeac00dc9646ae6ddb38513dad9a8a4fe3c38f4',
rootKey: 'bpmc-mrgn-hntf-mffd-mndd-xbxk-zmgq-qszg', rootKey: 'bpmc-mrgn-hntf-mffd-mndd-xbxk-zmgq-qszg',
}; };
export function getDefaultCallLinkConversation(
callLinkOverrideProps: Partial<CallLinkType> = {}
): CallingConversationType {
const { roomId: id, name: title } = {
...FAKE_CALL_LINK,
...callLinkOverrideProps,
};
return {
id,
type: 'callLink',
isMe: false,
title,
sharedGroupNames: [],
acceptedMessageRequest: true,
badges: [],
};
}