Receive side of remote mute
This commit is contained in:
parent
0d89e7b01a
commit
a444790bf9
13 changed files with 540 additions and 16 deletions
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import type { ActiveCallType } from '../types/Calling';
|
||||
import type { ActiveCallType, ObservedRemoteMuteType } from '../types/Calling';
|
||||
import { CallMode } from '../types/CallDisposition';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
|
@ -12,6 +12,7 @@ import { difference as setDifference } from '../util/setUtil';
|
|||
import { isMoreRecentThan } from '../util/timestamp';
|
||||
import { isGroupOrAdhocActiveCall } from '../util/isGroupOrAdhocCall';
|
||||
import { SECOND } from '../util/durations';
|
||||
import type { SetMutedByType } from '../state/ducks/calling';
|
||||
|
||||
type PropsType = {
|
||||
activeCall: ActiveCallType;
|
||||
|
@ -83,9 +84,11 @@ export function useScreenSharingStoppedToast({
|
|||
|
||||
function useMutedToast({
|
||||
hasLocalAudio,
|
||||
mutedBy,
|
||||
i18n,
|
||||
}: {
|
||||
hasLocalAudio: boolean;
|
||||
mutedBy: number | undefined;
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const previousHasLocalAudio = usePrevious(hasLocalAudio, hasLocalAudio);
|
||||
|
@ -95,7 +98,8 @@ function useMutedToast({
|
|||
useEffect(() => {
|
||||
if (
|
||||
previousHasLocalAudio !== undefined &&
|
||||
hasLocalAudio !== previousHasLocalAudio
|
||||
hasLocalAudio !== previousHasLocalAudio &&
|
||||
mutedBy === undefined // skip this if we were muted by someone
|
||||
) {
|
||||
hideToast(MUTED_TOAST_KEY);
|
||||
showToast({
|
||||
|
@ -107,7 +111,14 @@ function useMutedToast({
|
|||
dismissable: true,
|
||||
});
|
||||
}
|
||||
}, [hasLocalAudio, previousHasLocalAudio, hideToast, showToast, i18n]);
|
||||
}, [
|
||||
hasLocalAudio,
|
||||
previousHasLocalAudio,
|
||||
hideToast,
|
||||
showToast,
|
||||
mutedBy,
|
||||
i18n,
|
||||
]);
|
||||
}
|
||||
|
||||
function useOutgoingRingToast({
|
||||
|
@ -321,6 +332,143 @@ function useLowerHandSuggestionToast({
|
|||
}, [isHandRaised, hideToast]);
|
||||
}
|
||||
|
||||
function useMutedByToast({
|
||||
mutedBy,
|
||||
setLocalAudioRemoteMuted,
|
||||
conversationsByDemuxId,
|
||||
i18n,
|
||||
}: {
|
||||
mutedBy: number | undefined;
|
||||
setLocalAudioRemoteMuted?: SetMutedByType;
|
||||
conversationsByDemuxId?: Map<number, ConversationType>;
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const previousMutedBy = usePrevious(mutedBy, mutedBy);
|
||||
|
||||
const { showToast, hideToast } = useCallingToasts();
|
||||
const MUTED_BY_TOAST_KEY = 'MUTED_BY_TOAST_KEY';
|
||||
|
||||
useEffect(() => {
|
||||
if (setLocalAudioRemoteMuted === undefined) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
mutedBy === undefined ||
|
||||
// if it's undefined, likely we just received a remote mute request
|
||||
// and hadn't had one before.
|
||||
(previousMutedBy !== undefined && previousMutedBy === mutedBy) ||
|
||||
conversationsByDemuxId === undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const otherConversation = conversationsByDemuxId.get(mutedBy);
|
||||
const title = otherConversation?.title;
|
||||
if (title === undefined) {
|
||||
return;
|
||||
}
|
||||
setLocalAudioRemoteMuted({ mutedBy });
|
||||
let content;
|
||||
if (otherConversation?.isMe) {
|
||||
content = i18n('icu:CallControls__YouMutedYourselfToast');
|
||||
} else {
|
||||
content = i18n('icu:CallControls__MutedBySomeoneToast', {
|
||||
otherName: title,
|
||||
});
|
||||
}
|
||||
hideToast(MUTED_BY_TOAST_KEY);
|
||||
showToast({
|
||||
key: MUTED_BY_TOAST_KEY,
|
||||
content,
|
||||
dismissable: true,
|
||||
autoClose: true,
|
||||
lifetime: 10 * SECOND,
|
||||
});
|
||||
}, [
|
||||
mutedBy,
|
||||
previousMutedBy,
|
||||
conversationsByDemuxId,
|
||||
i18n,
|
||||
showToast,
|
||||
hideToast,
|
||||
MUTED_BY_TOAST_KEY,
|
||||
setLocalAudioRemoteMuted,
|
||||
]);
|
||||
}
|
||||
|
||||
function useObservedRemoteMuteToast({
|
||||
observedRemoteMute,
|
||||
conversationsByDemuxId,
|
||||
i18n,
|
||||
}: {
|
||||
observedRemoteMute: ObservedRemoteMuteType | undefined;
|
||||
conversationsByDemuxId?: Map<number, ConversationType>;
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const { showToast, hideToast } = useCallingToasts();
|
||||
const OBSERVED_REMOTE_MUTE_TOAST_KEY = 'OBSERVED_REMOTE_MUTE_TOAST_KEY';
|
||||
const previousObservedRemoteMute = usePrevious(
|
||||
observedRemoteMute,
|
||||
observedRemoteMute
|
||||
);
|
||||
useEffect(() => {
|
||||
if (
|
||||
observedRemoteMute === undefined ||
|
||||
(previousObservedRemoteMute !== undefined &&
|
||||
previousObservedRemoteMute === observedRemoteMute) ||
|
||||
conversationsByDemuxId === undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceConversation = conversationsByDemuxId.get(
|
||||
observedRemoteMute.source
|
||||
);
|
||||
const targetConversation = conversationsByDemuxId.get(
|
||||
observedRemoteMute.target
|
||||
);
|
||||
if (sourceConversation?.serviceId === targetConversation?.serviceId) {
|
||||
// Ignore self-mutes.
|
||||
return;
|
||||
}
|
||||
const targetTitle = targetConversation?.title;
|
||||
if (targetTitle === undefined) {
|
||||
return;
|
||||
}
|
||||
let content;
|
||||
if (sourceConversation?.isMe) {
|
||||
content = i18n('icu:CallControls__YouMutedSomeoneToast', {
|
||||
otherName: targetTitle,
|
||||
});
|
||||
} else {
|
||||
const sourceTitle = sourceConversation?.title;
|
||||
if (sourceTitle === undefined) {
|
||||
return;
|
||||
}
|
||||
content = i18n('icu:CallControls__SomeoneMutedSomeoneToast', {
|
||||
name: sourceTitle,
|
||||
otherName: targetTitle,
|
||||
});
|
||||
}
|
||||
|
||||
hideToast(OBSERVED_REMOTE_MUTE_TOAST_KEY);
|
||||
showToast({
|
||||
key: OBSERVED_REMOTE_MUTE_TOAST_KEY,
|
||||
content,
|
||||
dismissable: true,
|
||||
autoClose: true,
|
||||
lifetime: 10 * SECOND,
|
||||
});
|
||||
}, [
|
||||
observedRemoteMute,
|
||||
previousObservedRemoteMute,
|
||||
conversationsByDemuxId,
|
||||
i18n,
|
||||
showToast,
|
||||
hideToast,
|
||||
OBSERVED_REMOTE_MUTE_TOAST_KEY,
|
||||
]);
|
||||
}
|
||||
|
||||
type CallingButtonToastsType = {
|
||||
hasLocalAudio: boolean;
|
||||
outgoingRing: boolean | undefined;
|
||||
|
@ -331,7 +479,11 @@ type CallingButtonToastsType = {
|
|||
suggestLowerHand?: boolean;
|
||||
isHandRaised?: boolean;
|
||||
handleLowerHand?: () => void;
|
||||
mutedBy?: number;
|
||||
observedRemoteMute?: ObservedRemoteMuteType;
|
||||
conversationsByDemuxId?: Map<number, ConversationType>;
|
||||
i18n: LocalizerType;
|
||||
setLocalAudioRemoteMuted?: SetMutedByType;
|
||||
};
|
||||
|
||||
export function CallingButtonToastsContainer(
|
||||
|
@ -361,8 +513,12 @@ function CallingButtonToasts({
|
|||
handleLowerHand,
|
||||
isHandRaised,
|
||||
i18n,
|
||||
mutedBy,
|
||||
observedRemoteMute,
|
||||
conversationsByDemuxId,
|
||||
setLocalAudioRemoteMuted,
|
||||
}: CallingButtonToastsType) {
|
||||
useMutedToast({ hasLocalAudio, i18n });
|
||||
useMutedToast({ hasLocalAudio, mutedBy, i18n });
|
||||
useOutgoingRingToast({ outgoingRing, i18n });
|
||||
useRaisedHandsToast({ raisedHands, renderRaisedHandsToast });
|
||||
useLowerHandSuggestionToast({
|
||||
|
@ -371,6 +527,17 @@ function CallingButtonToasts({
|
|||
handleLowerHand,
|
||||
isHandRaised,
|
||||
});
|
||||
useMutedByToast({
|
||||
mutedBy,
|
||||
setLocalAudioRemoteMuted,
|
||||
conversationsByDemuxId,
|
||||
i18n,
|
||||
});
|
||||
useObservedRemoteMuteToast({
|
||||
observedRemoteMute,
|
||||
conversationsByDemuxId,
|
||||
i18n,
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue