Improve in call display of missing media keys
This commit is contained in:
parent
5c6a289bb4
commit
01b087f056
5 changed files with 128 additions and 37 deletions
|
@ -1881,6 +1881,10 @@
|
||||||
"messageformat": "Can't receive audio and video from {name}",
|
"messageformat": "Can't receive audio and video from {name}",
|
||||||
"description": "When you can't view someone's audio and video in a call because their media keys are unavailable"
|
"description": "When you can't view someone's audio and video in a call because their media keys are unavailable"
|
||||||
},
|
},
|
||||||
|
"icu:calling__missing-media-keys--unknown-contact": {
|
||||||
|
"messageformat": "Can't receive audio and video",
|
||||||
|
"description": "When you can't view someone's audio and video in a call because their media keys are unavailable, and their profile information is not available"
|
||||||
|
},
|
||||||
"icu:calling__missing-media-keys-info": {
|
"icu:calling__missing-media-keys-info": {
|
||||||
"messageformat": "This may be because they have not verified your safety number change, there's a problem with their device, or they have blocked you.",
|
"messageformat": "This may be because they have not verified your safety number change, there's a problem with their device, or they have blocked you.",
|
||||||
"description": "Detailed explanation why you can't view someone's audio and video in a call because their media keys are unavailable."
|
"description": "Detailed explanation why you can't view someone's audio and video in a call because their media keys are unavailable."
|
||||||
|
|
|
@ -3873,10 +3873,6 @@ button.module-image__border-overlay:focus {
|
||||||
padding-inline: 16px;
|
padding-inline: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-ongoing-call__group-call-remote-participant__error-icon {
|
|
||||||
margin-block-end: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-ongoing-call__group-call-remote-participant__error {
|
.module-ongoing-call__group-call-remote-participant__error {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -4099,7 +4095,7 @@ button.module-image__border-overlay:focus {
|
||||||
// when @container size is big enough
|
// when @container size is big enough
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
margin-block-end: 12px;
|
margin-block-end: 16px;
|
||||||
margin-inline: 8px;
|
margin-inline: 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
|
@ -4113,7 +4109,7 @@ button.module-image__border-overlay:focus {
|
||||||
padding-block: 3px;
|
padding-block: 3px;
|
||||||
padding-inline: 10px;
|
padding-inline: 10px;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background-color: $color-gray-75;
|
background-color: $color-black-alpha-30;
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
|
@ -4128,12 +4124,29 @@ button.module-image__border-overlay:focus {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shown in the mini version / overflow sidebar
|
||||||
|
&--icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--icon-blocked {
|
||||||
|
@include color-svg('../images/icons/v3/block/block.svg', $color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--icon-missing-media-keys {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v3/error/error-circle.svg',
|
||||||
|
$color-white
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__error-icon {
|
&__error-icon {
|
||||||
width: 24px;
|
width: 20px;
|
||||||
height: 24px;
|
height: 20px;
|
||||||
margin-block-end: 8px;
|
margin-block-end: 12px;
|
||||||
|
|
||||||
&--blocked {
|
&--blocked {
|
||||||
@include color-svg('../images/icons/v3/block/block.svg', $color-white);
|
@include color-svg('../images/icons/v3/block/block.svg', $color-white);
|
||||||
|
@ -4141,7 +4154,7 @@ button.module-image__border-overlay:focus {
|
||||||
|
|
||||||
&--missing-media-keys {
|
&--missing-media-keys {
|
||||||
@include color-svg(
|
@include color-svg(
|
||||||
'../images/icons/v3/error/error-circle-solid.svg',
|
'../images/icons/v3/error/error-circle.svg',
|
||||||
$color-white
|
$color-white
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,8 +65,9 @@ type DirectCallOverrideProps = OverridePropsBase & {
|
||||||
};
|
};
|
||||||
|
|
||||||
type GroupCallOverrideProps = OverridePropsBase & {
|
type GroupCallOverrideProps = OverridePropsBase & {
|
||||||
callMode: CallMode.Group;
|
callMode: CallMode.Group | CallMode.Adhoc;
|
||||||
connectionState?: GroupCallConnectionState;
|
connectionState?: GroupCallConnectionState;
|
||||||
|
groupMembers?: Array<ConversationType>;
|
||||||
peekedParticipants?: Array<ConversationType>;
|
peekedParticipants?: Array<ConversationType>;
|
||||||
pendingParticipants?: Array<ConversationType>;
|
pendingParticipants?: Array<ConversationType>;
|
||||||
raisedHands?: Set<number>;
|
raisedHands?: Set<number>;
|
||||||
|
@ -131,7 +132,8 @@ const createActiveGroupCallProp = (overrideProps: GroupCallOverrideProps) => ({
|
||||||
localDemuxId: LOCAL_DEMUX_ID,
|
localDemuxId: LOCAL_DEMUX_ID,
|
||||||
maxDevices: 5,
|
maxDevices: 5,
|
||||||
deviceCount: (overrideProps.remoteParticipants || []).length,
|
deviceCount: (overrideProps.remoteParticipants || []).length,
|
||||||
groupMembers: overrideProps.remoteParticipants || [],
|
groupMembers:
|
||||||
|
overrideProps.groupMembers || overrideProps.remoteParticipants || [],
|
||||||
// Because remote participants are a superset, we can use them in place of peeked
|
// Because remote participants are a superset, we can use them in place of peeked
|
||||||
// participants.
|
// participants.
|
||||||
isConversationTooBigToRing: false,
|
isConversationTooBigToRing: false,
|
||||||
|
@ -173,6 +175,12 @@ const createActiveCallProp = (
|
||||||
return { ...baseResult, ...createActiveDirectCallProp(overrideProps) };
|
return { ...baseResult, ...createActiveDirectCallProp(overrideProps) };
|
||||||
case CallMode.Group:
|
case CallMode.Group:
|
||||||
return { ...baseResult, ...createActiveGroupCallProp(overrideProps) };
|
return { ...baseResult, ...createActiveGroupCallProp(overrideProps) };
|
||||||
|
case CallMode.Adhoc:
|
||||||
|
return {
|
||||||
|
...baseResult,
|
||||||
|
...createActiveGroupCallProp(overrideProps),
|
||||||
|
callMode: CallMode.Adhoc as CallMode.Adhoc,
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
throw missingCaseError(overrideProps);
|
throw missingCaseError(overrideProps);
|
||||||
}
|
}
|
||||||
|
@ -872,3 +880,26 @@ export function GroupCallSomeoneBlocked(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function CallLinkUnknownContactMissingMediaKeys(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<CallScreen
|
||||||
|
{...createProps({
|
||||||
|
callMode: CallMode.Adhoc,
|
||||||
|
groupMembers: [],
|
||||||
|
remoteParticipants: allRemoteParticipants
|
||||||
|
.slice(0, 5)
|
||||||
|
.map((participant, index) => ({
|
||||||
|
...participant,
|
||||||
|
title: index === 1 ? 'Unknown Contact' : participant.title,
|
||||||
|
titleNoDefault:
|
||||||
|
index === 1 ? undefined : participant.titleNoDefault,
|
||||||
|
addedTime: index === 1 ? Date.now() - 60000 : undefined,
|
||||||
|
hasRemoteAudio: false,
|
||||||
|
hasRemoteVideo: false,
|
||||||
|
mediaKeysReceived: index !== 1,
|
||||||
|
})),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -137,6 +137,7 @@ export function GroupCallOverflowArea({
|
||||||
remoteParticipantsCount={remoteParticipantsCount}
|
remoteParticipantsCount={remoteParticipantsCount}
|
||||||
isActiveSpeakerInSpeakerView={false}
|
isActiveSpeakerInSpeakerView={false}
|
||||||
isCallReconnecting={isCallReconnecting}
|
isCallReconnecting={isCallReconnecting}
|
||||||
|
isInOverflow
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -43,6 +43,7 @@ type BasePropsType = {
|
||||||
imageDataCache: React.RefObject<CallingImageDataCache>;
|
imageDataCache: React.RefObject<CallingImageDataCache>;
|
||||||
isActiveSpeakerInSpeakerView: boolean;
|
isActiveSpeakerInSpeakerView: boolean;
|
||||||
isCallReconnecting: boolean;
|
isCallReconnecting: boolean;
|
||||||
|
isInOverflow?: boolean;
|
||||||
onClickRaisedHand?: () => void;
|
onClickRaisedHand?: () => void;
|
||||||
onVisibilityChanged?: (demuxId: number, isVisible: boolean) => unknown;
|
onVisibilityChanged?: (demuxId: number, isVisible: boolean) => unknown;
|
||||||
remoteParticipant: GroupCallRemoteParticipantType;
|
remoteParticipant: GroupCallRemoteParticipantType;
|
||||||
|
@ -80,6 +81,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
||||||
remoteParticipantsCount,
|
remoteParticipantsCount,
|
||||||
isActiveSpeakerInSpeakerView,
|
isActiveSpeakerInSpeakerView,
|
||||||
isCallReconnecting,
|
isCallReconnecting,
|
||||||
|
isInOverflow,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -98,6 +100,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
||||||
sharedGroupNames,
|
sharedGroupNames,
|
||||||
sharingScreen,
|
sharingScreen,
|
||||||
title,
|
title,
|
||||||
|
titleNoDefault,
|
||||||
videoAspectRatio,
|
videoAspectRatio,
|
||||||
} = props.remoteParticipant;
|
} = props.remoteParticipant;
|
||||||
|
|
||||||
|
@ -357,26 +360,60 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
||||||
{i18n('icu:moreInfo')}
|
{i18n('icu:moreInfo')}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isBlocked) {
|
if (isBlocked) {
|
||||||
noVideoNode = (
|
if (isInOverflow) {
|
||||||
<>
|
noVideoNode = (
|
||||||
<i className="module-ongoing-call__group-call-remote-participant__error-icon module-ongoing-call__group-call-remote-participant__error-icon--blocked" />
|
<button
|
||||||
<div className="module-ongoing-call__group-call-remote-participant__error">
|
type="button"
|
||||||
{i18n('icu:calling__blocked-participant', { name: title })}
|
className="module-ongoing-call__group-call-remote-participant__more-info module-ongoing-call__group-call-remote-participant__more-info--icon module-ongoing-call__group-call-remote-participant__more-info--icon-blocked"
|
||||||
</div>
|
onClick={() => {
|
||||||
{showDialogButton}
|
setShowErrorDialog(true);
|
||||||
</>
|
}}
|
||||||
);
|
aria-label={i18n('icu:calling__blocked-participant', {
|
||||||
|
name: title,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
noVideoNode = (
|
||||||
|
<>
|
||||||
|
<i className="module-ongoing-call__group-call-remote-participant__error-icon module-ongoing-call__group-call-remote-participant__error-icon--blocked" />
|
||||||
|
<div className="module-ongoing-call__group-call-remote-participant__error">
|
||||||
|
{i18n('icu:calling__blocked-participant', { name: title })}
|
||||||
|
</div>
|
||||||
|
{showDialogButton}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (showMissingMediaKeys) {
|
} else if (showMissingMediaKeys) {
|
||||||
noVideoNode = (
|
const errorMessage = titleNoDefault
|
||||||
<>
|
? i18n('icu:calling__missing-media-keys', {
|
||||||
<i className="module-ongoing-call__group-call-remote-participant__error-icon module-ongoing-call__group-call-remote-participant__error-icon--missing-media-keys" />
|
name: titleNoDefault,
|
||||||
<div className="module-ongoing-call__group-call-remote-participant__error">
|
})
|
||||||
{i18n('icu:calling__missing-media-keys', { name: title })}
|
: i18n('icu:calling__missing-media-keys--unknown-contact');
|
||||||
</div>
|
if (isInOverflow) {
|
||||||
{showDialogButton}
|
noVideoNode = (
|
||||||
</>
|
<button
|
||||||
);
|
type="button"
|
||||||
|
className="module-ongoing-call__group-call-remote-participant__more-info module-ongoing-call__group-call-remote-participant__more-info--icon module-ongoing-call__group-call-remote-participant__more-info--icon-missing-media-keys"
|
||||||
|
onClick={() => {
|
||||||
|
setShowErrorDialog(true);
|
||||||
|
}}
|
||||||
|
aria-label={errorMessage}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
noVideoNode = (
|
||||||
|
<>
|
||||||
|
<i className="module-ongoing-call__group-call-remote-participant__error-icon module-ongoing-call__group-call-remote-participant__error-icon--missing-media-keys" />
|
||||||
|
<div className="module-ongoing-call__group-call-remote-participant__error">
|
||||||
|
{errorMessage}
|
||||||
|
</div>
|
||||||
|
{showDialogButton}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
noVideoNode = (
|
noVideoNode = (
|
||||||
<Avatar
|
<Avatar
|
||||||
|
@ -424,13 +461,17 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
||||||
} else if (showMissingMediaKeys) {
|
} else if (showMissingMediaKeys) {
|
||||||
setErrorDialogTitle(
|
setErrorDialogTitle(
|
||||||
<div className="module-ongoing-call__group-call-remote-participant__more-info-modal-title">
|
<div className="module-ongoing-call__group-call-remote-participant__more-info-modal-title">
|
||||||
<I18n
|
{titleNoDefault ? (
|
||||||
i18n={i18n}
|
<I18n
|
||||||
id="icu:calling__missing-media-keys"
|
i18n={i18n}
|
||||||
components={{
|
id="icu:calling__missing-media-keys"
|
||||||
name: <ContactName key="name" title={title} />,
|
components={{
|
||||||
}}
|
name: <ContactName key="name" title={titleNoDefault} />,
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
i18n('icu:calling__missing-media-keys--unknown-contact')
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
setErrorDialogBody(i18n('icu:calling__missing-media-keys-info'));
|
setErrorDialogBody(i18n('icu:calling__missing-media-keys-info'));
|
||||||
|
@ -445,6 +486,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
||||||
showErrorDialog,
|
showErrorDialog,
|
||||||
showMissingMediaKeys,
|
showMissingMediaKeys,
|
||||||
title,
|
title,
|
||||||
|
titleNoDefault,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue