Fix call animation from speaker to grid view so animating speaker is on top

This commit is contained in:
ayumi-signal
2025-02-19 09:13:27 -08:00
committed by GitHub
parent f7f1052246
commit 78cfa7eca3
2 changed files with 39 additions and 2 deletions

View File

@@ -4352,6 +4352,8 @@ button.module-image__border-overlay:focus {
line-height: 0;
overflow: hidden;
border-radius: 10px;
// Should match GroupCallRemoteParticipant CONTAINER_TRANSITION_TIME
transition:
top 200ms linear,
inset-inline-start 200ms linear,
@@ -4531,6 +4533,10 @@ button.module-image__border-overlay:focus {
}
}
&--is-on-top {
z-index: variables.$z-index-above-above-base;
}
&:hover {
.module-ongoing-call__group-call-remote-participant__info__contact-name {
display: block;

View File

@@ -10,7 +10,7 @@ import React, {
useEffect,
} from 'react';
import classNames from 'classnames';
import { noop } from 'lodash';
import { debounce, noop } from 'lodash';
import type { VideoFrameSource } from '@signalapp/ringrtc';
import type { GroupCallRemoteParticipantType } from '../types/Calling';
import type { LocalizerType } from '../types/Util';
@@ -36,6 +36,9 @@ const MAX_TIME_TO_SHOW_STALE_VIDEO_FRAMES = 10000;
const MAX_TIME_TO_SHOW_STALE_SCREENSHARE_FRAMES = 60000;
const DELAY_TO_SHOW_MISSING_MEDIA_KEYS = 5000;
// Should match transition time in .module-ongoing-call__group-call-remote-participant
const CONTAINER_TRANSITION_TIME = 200;
type BasePropsType = {
getFrameBuffer: () => Buffer;
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
@@ -111,6 +114,10 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
SPEAKING_LINGER_MS
);
const previousSharingScreen = usePrevious(sharingScreen, sharingScreen);
const prevIsActiveSpeakerInSpeakerView = usePrevious(
isActiveSpeakerInSpeakerView,
isActiveSpeakerInSpeakerView
);
const isImageDataCached =
sharingScreen && imageDataCache.current?.has(demuxId);
@@ -120,6 +127,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
videoAspectRatio ? videoAspectRatio >= 1 : true
);
const [showErrorDialog, setShowErrorDialog] = useState(false);
const [isOnTop, setIsOnTop] = useState(false);
// We have some state (`hasReceivedVideoRecently`) and this ref. We can't have a
// single state value like `lastReceivedVideoAt` because (1) it won't automatically
@@ -290,6 +298,27 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
};
}, [hasRemoteVideo, isVisible, renderVideoFrame, videoFrameSource]);
const setIsOnTopDebounced = useMemo(
() => debounce(setIsOnTop, CONTAINER_TRANSITION_TIME),
[setIsOnTop]
);
// When in speaker view or while transitioning out of it, keep the main speaker
// z-indexed above all other participants
useEffect(() => {
if (isActiveSpeakerInSpeakerView !== prevIsActiveSpeakerInSpeakerView) {
if (isActiveSpeakerInSpeakerView) {
setIsOnTop(true);
} else {
setIsOnTopDebounced(false);
}
}
}, [
prevIsActiveSpeakerInSpeakerView,
isActiveSpeakerInSpeakerView,
setIsOnTopDebounced,
]);
let canvasStyles: CSSProperties;
let containerStyles: CSSProperties;
@@ -521,7 +550,9 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
remoteParticipantsCount > 1 &&
'module-ongoing-call__group-call-remote-participant--speaking',
isHandRaised &&
'module-ongoing-call__group-call-remote-participant--hand-raised'
'module-ongoing-call__group-call-remote-participant--hand-raised',
isOnTop &&
'module-ongoing-call__group-call-remote-participant--is-on-top'
)}
ref={intersectionRef}
style={containerStyles}