Call lobby join button text for call links requiring approval
This commit is contained in:
parent
a0b4126b52
commit
c531c64410
6 changed files with 80 additions and 10 deletions
|
@ -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"
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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 createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
const getConversation = (callMode: CallMode) => {
|
||||||
const callMode = overrideProps.callMode ?? CallMode.Direct;
|
if (callMode === CallMode.Group) {
|
||||||
const conversation =
|
return getDefaultConversation({
|
||||||
callMode === CallMode.Group
|
|
||||||
? getDefaultConversation({
|
|
||||||
title: 'Tahoe Trip',
|
title: 'Tahoe Trip',
|
||||||
type: 'group',
|
type: 'group',
|
||||||
})
|
});
|
||||||
: getDefaultConversation();
|
}
|
||||||
|
|
||||||
|
if (callMode === CallMode.Adhoc) {
|
||||||
|
return getDefaultCallLinkConversation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDefaultConversation();
|
||||||
|
};
|
||||||
|
|
||||||
|
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
|
const callMode = overrideProps.callMode ?? CallMode.Direct;
|
||||||
|
const conversation = getConversation(callMode);
|
||||||
|
|
||||||
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} />;
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue