Click grid raised hand participant to open queue

This commit is contained in:
ayumi-signal 2023-12-11 07:10:31 -08:00 committed by GitHub
parent 9a08070262
commit 96d5e97318
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 33 deletions

View file

@ -3969,6 +3969,7 @@ button.module-image__border-overlay:focus {
transition-duration: 300ms; transition-duration: 300ms;
transition-delay: 1000ms; transition-delay: 1000ms;
transition-timing-function: ease-in-out; transition-timing-function: ease-in-out;
pointer-events: none;
} }
&--speaking:after { &--speaking:after {
border-width: 3px; border-width: 3px;
@ -4038,8 +4039,13 @@ button.module-image__border-overlay:focus {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
visibility: hidden; visibility: hidden;
direction: inherit;
white-space: nowrap; white-space: nowrap;
} }
&--clickable {
@include button-reset;
}
} }
&--hand-raised &__footer { &--hand-raised &__footer {

View file

@ -335,7 +335,6 @@ export function CallScreen({
let hasCallStarted: boolean; let hasCallStarted: boolean;
let isConnected: boolean; let isConnected: boolean;
let participantCount: number; let participantCount: number;
let remoteParticipantsElement: ReactNode;
let conversationsByDemuxId: ConversationsByDemuxIdType; let conversationsByDemuxId: ConversationsByDemuxIdType;
let localDemuxId: number | undefined; let localDemuxId: number | undefined;
@ -348,17 +347,6 @@ export function CallScreen({
isConnected = activeCall.callState === CallState.Accepted; isConnected = activeCall.callState === CallState.Accepted;
participantCount = isConnected ? 2 : 0; participantCount = isConnected ? 2 : 0;
conversationsByDemuxId = new Map(); conversationsByDemuxId = new Map();
remoteParticipantsElement = hasCallStarted ? (
<DirectCallRemoteParticipant
conversation={conversation}
hasRemoteVideo={hasRemoteVideo}
i18n={i18n}
isReconnecting={isReconnecting}
setRendererCanvas={setRendererCanvas}
/>
) : (
<div className="module-ongoing-call__direct-call-ringing-spacer" />
);
break; break;
} }
case CallMode.Group: case CallMode.Group:
@ -373,17 +361,6 @@ export function CallScreen({
isConnected = isConnected =
activeCall.connectionState === GroupCallConnectionState.Connected; activeCall.connectionState === GroupCallConnectionState.Connected;
remoteParticipantsElement = (
<GroupCallRemoteParticipants
callViewMode={activeCall.viewMode}
getGroupCallVideoFrameSource={getGroupCallVideoFrameSource}
i18n={i18n}
remoteParticipants={activeCall.remoteParticipants}
setGroupCallVideoRequest={setGroupCallVideoRequest}
remoteAudioLevels={activeCall.remoteAudioLevels}
isCallReconnecting={isReconnecting}
/>
);
break; break;
default: default:
throw missingCaseError(activeCall); throw missingCaseError(activeCall);
@ -627,6 +604,44 @@ export function CallScreen({
toggleParticipants, toggleParticipants,
]); ]);
let remoteParticipantsElement: ReactNode;
switch (activeCall.callMode) {
case CallMode.Direct: {
remoteParticipantsElement = hasCallStarted ? (
<DirectCallRemoteParticipant
conversation={conversation}
hasRemoteVideo={hasRemoteVideo}
i18n={i18n}
isReconnecting={isReconnecting}
setRendererCanvas={setRendererCanvas}
/>
) : (
<div className="module-ongoing-call__direct-call-ringing-spacer" />
);
break;
}
case CallMode.Group:
remoteParticipantsElement = (
<GroupCallRemoteParticipants
callViewMode={activeCall.viewMode}
getGroupCallVideoFrameSource={getGroupCallVideoFrameSource}
i18n={i18n}
remoteParticipants={activeCall.remoteParticipants}
setGroupCallVideoRequest={setGroupCallVideoRequest}
remoteAudioLevels={activeCall.remoteAudioLevels}
isCallReconnecting={isReconnecting}
onClickRaisedHand={
raisedHandsCount > 0
? () => setShowRaisedHandsList(true)
: undefined
}
/>
);
break;
default:
throw missingCaseError(activeCall);
}
return ( return (
<div <div
className={classNames( className={classNames(

View file

@ -20,6 +20,7 @@ export type PropsType = {
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource; getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType; i18n: LocalizerType;
isCallReconnecting: boolean; isCallReconnecting: boolean;
onClickRaisedHand?: () => void;
onParticipantVisibilityChanged: ( onParticipantVisibilityChanged: (
demuxId: number, demuxId: number,
isVisible: boolean isVisible: boolean
@ -34,6 +35,7 @@ export function GroupCallOverflowArea({
getGroupCallVideoFrameSource, getGroupCallVideoFrameSource,
i18n, i18n,
isCallReconnecting, isCallReconnecting,
onClickRaisedHand,
onParticipantVisibilityChanged, onParticipantVisibilityChanged,
overflowedParticipants, overflowedParticipants,
remoteAudioLevels, remoteAudioLevels,
@ -121,6 +123,7 @@ export function GroupCallOverflowArea({
getGroupCallVideoFrameSource={getGroupCallVideoFrameSource} getGroupCallVideoFrameSource={getGroupCallVideoFrameSource}
i18n={i18n} i18n={i18n}
audioLevel={remoteAudioLevels.get(remoteParticipant.demuxId) ?? 0} audioLevel={remoteAudioLevels.get(remoteParticipant.demuxId) ?? 0}
onClickRaisedHand={onClickRaisedHand}
onVisibilityChanged={onParticipantVisibilityChanged} onVisibilityChanged={onParticipantVisibilityChanged}
width={OVERFLOW_PARTICIPANT_WIDTH} width={OVERFLOW_PARTICIPANT_WIDTH}
height={Math.floor( height={Math.floor(

View file

@ -1,7 +1,7 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import type { CSSProperties } from 'react'; import type { CSSProperties, ReactNode } from 'react';
import React, { import React, {
useState, useState,
useRef, useRef,
@ -37,6 +37,7 @@ type BasePropsType = {
i18n: LocalizerType; i18n: LocalizerType;
isActiveSpeakerInSpeakerView: boolean; isActiveSpeakerInSpeakerView: boolean;
isCallReconnecting: boolean; isCallReconnecting: boolean;
onClickRaisedHand?: () => void;
onVisibilityChanged?: (demuxId: number, isVisible: boolean) => unknown; onVisibilityChanged?: (demuxId: number, isVisible: boolean) => unknown;
remoteParticipant: GroupCallRemoteParticipantType; remoteParticipant: GroupCallRemoteParticipantType;
remoteParticipantsCount: number; remoteParticipantsCount: number;
@ -67,6 +68,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
getFrameBuffer, getFrameBuffer,
getGroupCallVideoFrameSource, getGroupCallVideoFrameSource,
i18n, i18n,
onClickRaisedHand,
onVisibilityChanged, onVisibilityChanged,
remoteParticipantsCount, remoteParticipantsCount,
isActiveSpeakerInSpeakerView, isActiveSpeakerInSpeakerView,
@ -238,6 +240,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
} }
let avatarSize: number; let avatarSize: number;
let footerInfoElement: ReactNode;
if (props.isInPip) { if (props.isInPip) {
containerStyles = canvasStyles; containerStyles = canvasStyles;
@ -262,6 +265,32 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
containerStyles.insetInlineStart = `${props.left}px`; containerStyles.insetInlineStart = `${props.left}px`;
containerStyles.top = `${props.top}px`; containerStyles.top = `${props.top}px`;
} }
const nameElement = (
<ContactName
module="module-ongoing-call__group-call-remote-participant__info__contact-name"
title={title}
/>
);
if (isHandRaised) {
footerInfoElement = (
<button
className="module-ongoing-call__group-call-remote-participant__info module-ongoing-call__group-call-remote-participant__info--clickable"
onClick={onClickRaisedHand}
type="button"
>
<div className="CallingStatusIndicator CallingStatusIndicator--HandRaised" />
{nameElement}
</button>
);
} else {
footerInfoElement = (
<div className="module-ongoing-call__group-call-remote-participant__info">
{nameElement}
</div>
);
}
} }
return ( return (
@ -311,15 +340,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
shouldShowSpeaking={isSpeaking} shouldShowSpeaking={isSpeaking}
/> />
<div className="module-ongoing-call__group-call-remote-participant__footer"> <div className="module-ongoing-call__group-call-remote-participant__footer">
<div className="module-ongoing-call__group-call-remote-participant__info"> {footerInfoElement}
{isHandRaised && (
<div className="CallingStatusIndicator CallingStatusIndicator--HandRaised" />
)}
<ContactName
module="module-ongoing-call__group-call-remote-participant__info__contact-name"
title={title}
/>
</div>
</div> </div>
</> </>
)} )}

View file

@ -67,6 +67,7 @@ type PropsType = {
speakerHeight: number speakerHeight: number
) => void; ) => void;
remoteAudioLevels: Map<number, number>; remoteAudioLevels: Map<number, number>;
onClickRaisedHand?: () => void;
}; };
enum VideoRequestMode { enum VideoRequestMode {
@ -114,6 +115,7 @@ export function GroupCallRemoteParticipants({
remoteParticipants, remoteParticipants,
setGroupCallVideoRequest, setGroupCallVideoRequest,
remoteAudioLevels, remoteAudioLevels,
onClickRaisedHand,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {
const [gridDimensions, setGridDimensions] = useState<Dimensions>({ const [gridDimensions, setGridDimensions] = useState<Dimensions>({
width: 0, width: 0,
@ -342,6 +344,7 @@ export function GroupCallRemoteParticipants({
key={tile.demuxId} key={tile.demuxId}
getFrameBuffer={getFrameBuffer} getFrameBuffer={getFrameBuffer}
getGroupCallVideoFrameSource={getGroupCallVideoFrameSource} getGroupCallVideoFrameSource={getGroupCallVideoFrameSource}
onClickRaisedHand={onClickRaisedHand}
height={gridParticipantHeight} height={gridParticipantHeight}
i18n={i18n} i18n={i18n}
audioLevel={remoteAudioLevels.get(tile.demuxId) ?? 0} audioLevel={remoteAudioLevels.get(tile.demuxId) ?? 0}
@ -509,6 +512,7 @@ export function GroupCallRemoteParticipants({
getGroupCallVideoFrameSource={getGroupCallVideoFrameSource} getGroupCallVideoFrameSource={getGroupCallVideoFrameSource}
i18n={i18n} i18n={i18n}
isCallReconnecting={isCallReconnecting} isCallReconnecting={isCallReconnecting}
onClickRaisedHand={onClickRaisedHand}
onParticipantVisibilityChanged={onParticipantVisibilityChanged} onParticipantVisibilityChanged={onParticipantVisibilityChanged}
overflowedParticipants={overflowedParticipants} overflowedParticipants={overflowedParticipants}
remoteAudioLevels={remoteAudioLevels} remoteAudioLevels={remoteAudioLevels}