Skip to content

Commit

Permalink
Handles safety number changes while in a call
Browse files Browse the repository at this point in the history
  • Loading branch information
josh-signal committed Dec 8, 2020
1 parent 561baf6 commit 318013e
Show file tree
Hide file tree
Showing 26 changed files with 387 additions and 162 deletions.
4 changes: 4 additions & 0 deletions _locales/en/messages.json
Expand Up @@ -425,6 +425,10 @@
"message": "Call Anyway",
"description": "Used on a warning dialog to make it clear that it might be risky to call the conversation."
},
"continueCall": {
"message": "Continue Call",
"description": "Used on a warning dialog to make it clear that it might be risky to continue the group call."
},
"noLongerVerified": {
"message": "Your safety number with $name$ has changed and is no longer verified. Click to show.",
"description": "Shown in conversation banner when user's safety number has changed, but they were previously verified.",
Expand Down
2 changes: 1 addition & 1 deletion js/signal_protocol_store.js
Expand Up @@ -904,7 +904,7 @@
// state we had before.
return false;
},
async isUntrusted(identifier) {
isUntrusted(identifier) {
if (identifier === null || identifier === undefined) {
throw new Error('Tried to set verified for undefined/null key');
}
Expand Down
35 changes: 33 additions & 2 deletions ts/components/CallManager.stories.tsx
Expand Up @@ -17,7 +17,9 @@ import {
} from '../types/Calling';
import { ConversationTypeType } from '../state/ducks/conversations';
import { Colors, ColorType } from '../types/Colors';
import { getDefaultConversation } from '../util/getDefaultConversation';
import { setup as setupI18n } from '../../js/modules/i18n';
import { Props as SafetyNumberViewerProps } from '../state/smart/SafetyNumberViewer';
import enMessages from '../../_locales/en/messages.json';

const i18n = setupI18n('en', enMessages);
Expand Down Expand Up @@ -68,12 +70,16 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
getGroupCallVideoFrameSource: noop as any,
hangUp: action('hang-up'),
i18n,
keyChangeOk: action('key-change-ok'),
me: {
...getDefaultConversation({
color: select('Caller color', Colors, 'ultramarine' as ColorType),
title: text('Caller Title', 'Morty Smith'),
}),
uuid: 'cb0dd0c8-7393-41e9-a0aa-d631c4109541',
color: select('Caller color', Colors, 'ultramarine' as ColorType),
title: text('Caller Title', 'Morty Smith'),
},
renderDeviceSelection: () => <div />,
renderSafetyNumberViewer: (_: SafetyNumberViewerProps) => <div />,
setGroupCallVideoRequest: action('set-group-call-video-request'),
setLocalAudio: action('set-local-audio'),
setLocalPreview: action('set-local-preview'),
Expand Down Expand Up @@ -110,6 +116,7 @@ story.add('Ongoing Group Call', () => (
...getCommonActiveCallData(),
callMode: CallMode.Group,
connectionState: GroupCallConnectionState.Connected,
conversationsWithSafetyNumberChanges: [],
deviceCount: 0,
joinState: GroupCallJoinState.Joined,
maxDevices: 5,
Expand Down Expand Up @@ -145,3 +152,27 @@ story.add('Call Request Needed', () => (
})}
/>
));

story.add('Group call - Safety Number Changed', () => (
<CallManager
{...createProps({
activeCall: {
...getCommonActiveCallData(),
callMode: CallMode.Group,
connectionState: GroupCallConnectionState.Connected,
conversationsWithSafetyNumberChanges: [
{
...getDefaultConversation({
title: 'Aaron',
}),
},
],
deviceCount: 0,
joinState: GroupCallJoinState.Joined,
maxDevices: 5,
peekedParticipants: [],
remoteParticipants: [],
},
})}
/>
));
43 changes: 31 additions & 12 deletions ts/components/CallManager.tsx
Expand Up @@ -8,6 +8,10 @@ import { CallingLobby } from './CallingLobby';
import { CallingParticipantsList } from './CallingParticipantsList';
import { CallingPip } from './CallingPip';
import { IncomingCallBar } from './IncomingCallBar';
import {
SafetyNumberChangeDialog,
SafetyNumberProps,
} from './SafetyNumberChangeDialog';
import {
ActiveCallType,
CallEndedReason,
Expand All @@ -24,6 +28,7 @@ import {
DeclineCallType,
DirectCallStateType,
HangUpType,
KeyChangeOkType,
SetGroupCallVideoRequestType,
SetLocalAudioType,
SetLocalPreviewType,
Expand All @@ -32,9 +37,12 @@ import {
StartCallType,
} from '../state/ducks/calling';
import { LocalizerType } from '../types/Util';
import { ColorType } from '../types/Colors';
import { missingCaseError } from '../util/missingCaseError';

interface MeType extends ConversationType {
uuid: string;
}

export interface PropsType {
activeCall?: ActiveCallType;
availableCameras: Array<MediaDeviceInfo>;
Expand All @@ -48,21 +56,15 @@ export interface PropsType {
call: DirectCallStateType;
conversation: ConversationType;
};
keyChangeOk: (_: KeyChangeOkType) => void;
renderDeviceSelection: () => JSX.Element;
renderSafetyNumberViewer: (props: SafetyNumberProps) => JSX.Element;
startCall: (payload: StartCallType) => void;
toggleParticipants: () => void;
acceptCall: (_: AcceptCallType) => void;
declineCall: (_: DeclineCallType) => void;
i18n: LocalizerType;
me: {
avatarPath?: string;
color?: ColorType;
name?: string;
phoneNumber?: string;
profileName?: string;
title: string;
uuid: string;
};
me: MeType;
setGroupCallVideoRequest: (_: SetGroupCallVideoRequestType) => void;
setLocalAudio: (_: SetLocalAudioType) => void;
setLocalVideo: (_: SetLocalVideoType) => void;
Expand All @@ -84,9 +86,11 @@ const ActiveCallManager: React.FC<ActiveCallManagerPropsType> = ({
closeNeedPermissionScreen,
hangUp,
i18n,
keyChangeOk,
getGroupCallVideoFrameSource,
me,
renderDeviceSelection,
renderSafetyNumberViewer,
setGroupCallVideoRequest,
setLocalAudio,
setLocalPreview,
Expand Down Expand Up @@ -203,6 +207,7 @@ const ActiveCallManager: React.FC<ActiveCallManagerPropsType> = ({
<CallingParticipantsList
i18n={i18n}
onClose={toggleParticipants}
ourUuid={me.uuid}
participants={peekedParticipants}
/>
) : null}
Expand Down Expand Up @@ -233,13 +238,11 @@ const ActiveCallManager: React.FC<ActiveCallManagerPropsType> = ({
...participant,
hasAudio: participant.hasRemoteAudio,
hasVideo: participant.hasRemoteVideo,
isSelf: false,
})),
{
...me,
hasAudio: hasLocalAudio,
hasVideo: hasLocalVideo,
isSelf: true,
},
]
: [];
Expand Down Expand Up @@ -268,9 +271,25 @@ const ActiveCallManager: React.FC<ActiveCallManagerPropsType> = ({
<CallingParticipantsList
i18n={i18n}
onClose={toggleParticipants}
ourUuid={me.uuid}
participants={groupCallParticipantsForParticipantsList}
/>
) : null}
{activeCall.callMode === CallMode.Group &&
activeCall.conversationsWithSafetyNumberChanges.length ? (
<SafetyNumberChangeDialog
confirmText={i18n('continueCall')}
contacts={activeCall.conversationsWithSafetyNumberChanges}
i18n={i18n}
onCancel={() => {
hangUp({ conversationId: activeCall.conversation.id });
}}
onConfirm={() => {
keyChangeOk({ conversationId: activeCall.conversation.id });
}}
renderSafetyNumber={renderSafetyNumberViewer}
/>
) : null}
</>
);
};
Expand Down
51 changes: 29 additions & 22 deletions ts/components/CallScreen.stories.tsx
Expand Up @@ -12,13 +12,14 @@ import {
CallState,
GroupCallConnectionState,
GroupCallJoinState,
GroupCallPeekedParticipantType,
GroupCallRemoteParticipantType,
} from '../types/Calling';
import { ConversationType } from '../state/ducks/conversations';
import { Colors } from '../types/Colors';
import { CallScreen, PropsType } from './CallScreen';
import { setup as setupI18n } from '../../js/modules/i18n';
import { missingCaseError } from '../util/missingCaseError';
import { getDefaultConversation } from '../util/getDefaultConversation';
import enMessages from '../../_locales/en/messages.json';

const i18n = setupI18n('en', enMessages);
Expand Down Expand Up @@ -50,7 +51,7 @@ interface DirectCallOverrideProps extends OverridePropsBase {
interface GroupCallOverrideProps extends OverridePropsBase {
callMode: CallMode.Group;
connectionState?: GroupCallConnectionState;
peekedParticipants?: Array<GroupCallPeekedParticipantType>;
peekedParticipants?: Array<ConversationType>;
remoteParticipants?: Array<GroupCallRemoteParticipantType>;
}

Expand Down Expand Up @@ -83,6 +84,7 @@ const createActiveGroupCallProp = (overrideProps: GroupCallOverrideProps) => ({
callMode: CallMode.Group as CallMode.Group,
connectionState:
overrideProps.connectionState || GroupCallConnectionState.Connected,
conversationsWithSafetyNumberChanges: [],
joinState: GroupCallJoinState.Joined,
maxDevices: 5,
deviceCount: (overrideProps.remoteParticipants || []).length,
Expand Down Expand Up @@ -240,14 +242,15 @@ story.add('Group call - 1', () => (
callMode: CallMode.Group,
remoteParticipants: [
{
uuid: '72fa60e5-25fb-472d-8a56-e56867c57dda',
demuxId: 0,
hasRemoteAudio: true,
hasRemoteVideo: true,
isBlocked: false,
isSelf: false,
title: 'Tyler',
videoAspectRatio: 1.3,
...getDefaultConversation({
isBlocked: false,
uuid: '72fa60e5-25fb-472d-8a56-e56867c57dda',
title: 'Tyler',
}),
},
],
})}
Expand All @@ -260,34 +263,37 @@ story.add('Group call - Many', () => (
callMode: CallMode.Group,
remoteParticipants: [
{
uuid: '094586f5-8fc2-4ce2-a152-2dfcc99f4630',
demuxId: 0,
hasRemoteAudio: true,
hasRemoteVideo: true,
isBlocked: false,
isSelf: false,
title: 'Amy',
videoAspectRatio: 1.3,
...getDefaultConversation({
isBlocked: false,
title: 'Amy',
uuid: '094586f5-8fc2-4ce2-a152-2dfcc99f4630',
}),
},
{
uuid: 'cb5bdb24-4cbb-4650-8a7a-1a2807051e74',
demuxId: 1,
hasRemoteAudio: true,
hasRemoteVideo: true,
isBlocked: false,
isSelf: true,
title: 'Bob',
videoAspectRatio: 1.3,
...getDefaultConversation({
isBlocked: false,
title: 'Bob',
uuid: 'cb5bdb24-4cbb-4650-8a7a-1a2807051e74',
}),
},
{
uuid: '2d7d13ae-53dc-4a51-8dc7-976cd85e0b57',
demuxId: 2,
hasRemoteAudio: true,
hasRemoteVideo: true,
isBlocked: true,
isSelf: false,
title: 'Alice',
videoAspectRatio: 1.3,
...getDefaultConversation({
isBlocked: true,
title: 'Alice',
uuid: '2d7d13ae-53dc-4a51-8dc7-976cd85e0b57',
}),
},
],
})}
Expand All @@ -301,14 +307,15 @@ story.add('Group call - reconnecting', () => (
connectionState: GroupCallConnectionState.Reconnecting,
remoteParticipants: [
{
uuid: '33871c64-0c22-45ce-8aa4-0ec237ac4a31',
demuxId: 0,
hasRemoteAudio: true,
hasRemoteVideo: true,
isBlocked: false,
isSelf: false,
title: 'Tyler',
videoAspectRatio: 1.3,
...getDefaultConversation({
isBlocked: false,
title: 'Tyler',
uuid: '33871c64-0c22-45ce-8aa4-0ec237ac4a31',
}),
},
],
})}
Expand Down
19 changes: 12 additions & 7 deletions ts/components/CallingLobby.stories.tsx
Expand Up @@ -11,6 +11,7 @@ import { ColorType } from '../types/Colors';
import { CallingLobby, PropsType } from './CallingLobby';
import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json';
import { getDefaultConversation } from '../util/getDefaultConversation';

const i18n = setupI18n('en', enMessages);

Expand All @@ -33,7 +34,10 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
hasLocalVideo: boolean('hasLocalVideo', overrideProps.hasLocalVideo || false),
i18n,
isGroupCall: boolean('isGroupCall', overrideProps.isGroupCall || false),
me: overrideProps.me || { color: 'ultramarine' as ColorType },
me: overrideProps.me || {
color: 'ultramarine' as ColorType,
uuid: generateUuid(),
},
onCallCanceled: action('on-call-canceled'),
onJoinCall: action('on-join-call'),
peekedParticipants: overrideProps.peekedParticipants || [],
Expand All @@ -48,11 +52,11 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
toggleSettings: action('toggle-settings'),
});

const fakePeekedParticipant = (title: string) => ({
isSelf: false,
title,
uuid: generateUuid(),
});
const fakePeekedParticipant = (title: string) =>
getDefaultConversation({
title,
uuid: generateUuid(),
});

const story = storiesOf('Components/CallingLobby', module);

Expand All @@ -72,8 +76,9 @@ story.add('No Camera, local avatar', () => {
const props = createProps({
availableCameras: [],
me: {
color: 'ultramarine' as ColorType,
avatarPath: '/fixtures/kitten-4-112-112.jpg',
color: 'ultramarine' as ColorType,
uuid: generateUuid(),
},
});
return <CallingLobby {...props} />;
Expand Down

0 comments on commit 318013e

Please sign in to comment.