Group calls: mute in the lobby if joining a large call
This commit is contained in:
parent
09af7eeece
commit
f8bbf5c998
12 changed files with 499 additions and 279 deletions
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020-2021 Signal Messenger, LLC
|
||||
// Copyright 2020-2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
@ -51,11 +51,11 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
|||
(isGroupCall ? times(3, () => getDefaultConversation()) : undefined),
|
||||
hasLocalAudio: boolean(
|
||||
'hasLocalAudio',
|
||||
overrideProps.hasLocalAudio || false
|
||||
overrideProps.hasLocalAudio ?? true
|
||||
),
|
||||
hasLocalVideo: boolean(
|
||||
'hasLocalVideo',
|
||||
overrideProps.hasLocalVideo || false
|
||||
overrideProps.hasLocalVideo ?? false
|
||||
),
|
||||
i18n,
|
||||
isGroupCall,
|
||||
|
@ -122,9 +122,9 @@ story.add('Local Video', () => {
|
|||
return <CallingLobby {...props} />;
|
||||
});
|
||||
|
||||
story.add('Local Video', () => {
|
||||
story.add('Initially muted', () => {
|
||||
const props = createProps({
|
||||
hasLocalVideo: true,
|
||||
hasLocalAudio: false,
|
||||
});
|
||||
return <CallingLobby {...props} />;
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020-2021 Signal Messenger, LLC
|
||||
// Copyright 2020-2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
@ -13,6 +13,7 @@ import { CallingButton, CallingButtonType } from './CallingButton';
|
|||
import { TooltipPlacement } from './Tooltip';
|
||||
import { CallBackgroundBlur } from './CallBackgroundBlur';
|
||||
import { CallingHeader } from './CallingHeader';
|
||||
import { CallingToast, DEFAULT_LIFETIME } from './CallingToast';
|
||||
import { CallingPreCallInfo, RingMode } from './CallingPreCallInfo';
|
||||
import {
|
||||
CallingLobbyJoinButton,
|
||||
|
@ -92,6 +93,21 @@ export const CallingLobby = ({
|
|||
toggleSettings,
|
||||
outgoingRing,
|
||||
}: PropsType): JSX.Element => {
|
||||
const [isMutedToastVisible, setIsMutedToastVisible] = React.useState(
|
||||
!hasLocalAudio
|
||||
);
|
||||
React.useEffect(() => {
|
||||
if (!isMutedToastVisible) {
|
||||
return;
|
||||
}
|
||||
const timeout = setTimeout(() => {
|
||||
setIsMutedToastVisible(false);
|
||||
}, DEFAULT_LIFETIME);
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, [isMutedToastVisible]);
|
||||
|
||||
const localVideoRef = React.useRef<null | HTMLVideoElement>(null);
|
||||
|
||||
const shouldShowLocalVideo = hasLocalVideo && availableCameras.length > 0;
|
||||
|
@ -221,6 +237,15 @@ export const CallingLobby = ({
|
|||
/>
|
||||
)}
|
||||
|
||||
<CallingToast
|
||||
isVisible={isMutedToastVisible}
|
||||
onClick={() => setIsMutedToastVisible(false)}
|
||||
>
|
||||
{i18n(
|
||||
'calling__lobby-automatically-muted-because-there-are-a-lot-of-people'
|
||||
)}
|
||||
</CallingToast>
|
||||
|
||||
<CallingHeader
|
||||
i18n={i18n}
|
||||
isGroupCall={isGroupCall}
|
||||
|
|
27
ts/components/CallingToast.tsx
Normal file
27
ts/components/CallingToast.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { FunctionComponent } from 'react';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
type PropsType = {
|
||||
isVisible: boolean;
|
||||
onClick: () => unknown;
|
||||
};
|
||||
|
||||
export const DEFAULT_LIFETIME = 5000;
|
||||
|
||||
export const CallingToast: FunctionComponent<PropsType> = ({
|
||||
isVisible,
|
||||
onClick,
|
||||
children,
|
||||
}) => (
|
||||
<button
|
||||
className={classNames('CallingToast', !isVisible && 'CallingToast--hidden')}
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
|
@ -1,12 +1,12 @@
|
|||
// Copyright 2020-2021 Signal Messenger, LLC
|
||||
// Copyright 2020-2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { ActiveCallType } from '../types/Calling';
|
||||
import { CallMode, GroupCallConnectionState } from '../types/Calling';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import { CallingToast, DEFAULT_LIFETIME } from './CallingToast';
|
||||
|
||||
type PropsType = {
|
||||
activeCall: ActiveCallType;
|
||||
|
@ -101,8 +101,6 @@ function useScreenSharingToast({ activeCall, i18n }: PropsType): ToastType {
|
|||
return result;
|
||||
}
|
||||
|
||||
const DEFAULT_DELAY = 5000;
|
||||
|
||||
// In the future, this component should show toasts when users join or leave. See
|
||||
// DESKTOP-902.
|
||||
export const CallingToastManager: React.FC<PropsType> = props => {
|
||||
|
@ -131,7 +129,7 @@ export const CallingToastManager: React.FC<PropsType> = props => {
|
|||
if (timeoutRef && timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
timeoutRef.current = setTimeout(dismissToast, DEFAULT_DELAY);
|
||||
timeoutRef.current = setTimeout(dismissToast, DEFAULT_LIFETIME);
|
||||
}
|
||||
|
||||
setToastMessage(toast.message);
|
||||
|
@ -144,17 +142,9 @@ export const CallingToastManager: React.FC<PropsType> = props => {
|
|||
};
|
||||
}, [dismissToast, setToastMessage, timeoutRef, toast]);
|
||||
|
||||
const isVisible = Boolean(toastMessage);
|
||||
|
||||
return (
|
||||
<button
|
||||
className={classNames('module-ongoing-call__toast', {
|
||||
'module-ongoing-call__toast--hidden': !isVisible,
|
||||
})}
|
||||
type="button"
|
||||
onClick={dismissToast}
|
||||
>
|
||||
<CallingToast isVisible={Boolean(toastMessage)} onClick={dismissToast}>
|
||||
{toastMessage}
|
||||
</button>
|
||||
</CallingToast>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue