Reuse html element for local preview visuals

This commit is contained in:
Fedor Indutny 2024-10-01 15:17:43 -07:00 committed by GitHub
parent bb69f81b9f
commit 17c908bbf4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 86 additions and 109 deletions

View file

@ -4231,6 +4231,10 @@ button.module-image__border-overlay:focus {
} }
} }
&__local-preview-video-container {
display: contents;
}
&__local-preview-fullsize { &__local-preview-fullsize {
position: absolute; position: absolute;
top: 0; top: 0;
@ -4283,18 +4287,23 @@ button.module-image__border-overlay:focus {
} }
&__video { &__video {
height: 100%;
width: 100%;
video {
// The background-color is seen while the video loads. // The background-color is seen while the video loads.
background-color: $color-gray-75; background-color: $color-gray-75;
height: 100%; height: 100%;
transform: rotateY(180deg);
width: 100%; width: 100%;
transform: rotateY(180deg);
&--presenting { &--presenting {
transform: inherit; transform: inherit;
} }
} }
} }
} }
}
&__controls { &__controls {
z-index: $z-index-above-above-base; z-index: $z-index-above-above-base;
@ -4373,8 +4382,13 @@ button.module-image__border-overlay:focus {
height: 32px; height: 32px;
position: absolute; position: absolute;
inset-inline-end: 4px; inset-inline-end: 4px;
transform: rotateY(180deg);
width: 32px; width: 32px;
video {
transform: rotateY(180deg);
width: 100%;
height: 100%;
}
} }
} }

View file

@ -14,6 +14,14 @@
height: 100%; height: 100%;
max-height: calc(100% - 140px); max-height: calc(100% - 140px);
opacity: 0.6; opacity: 0.6;
// Border radius should clip children
overflow: hidden;
}
&--camera-is-on video {
width: auto;
height: 100%;
} }
&--camera-is-off { &--camera-is-off {

View file

@ -130,7 +130,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
setGroupCallVideoRequest: action('set-group-call-video-request'), setGroupCallVideoRequest: action('set-group-call-video-request'),
setIsCallActive: action('set-is-call-active'), setIsCallActive: action('set-is-call-active'),
setLocalAudio: action('set-local-audio'), setLocalAudio: action('set-local-audio'),
setLocalPreview: action('set-local-preview'), setLocalPreviewContainer: action('set-local-preview-container'),
setLocalVideo: action('set-local-video'), setLocalVideo: action('set-local-video'),
setRendererCanvas: action('set-renderer-canvas'), setRendererCanvas: action('set-renderer-canvas'),
setOutgoingRing: action('set-outgoing-ring'), setOutgoingRing: action('set-outgoing-ring'),

View file

@ -37,7 +37,6 @@ import type {
SendGroupCallReactionType, SendGroupCallReactionType,
SetGroupCallVideoRequestType, SetGroupCallVideoRequestType,
SetLocalAudioType, SetLocalAudioType,
SetLocalPreviewType,
SetLocalVideoType, SetLocalVideoType,
SetRendererCanvasType, SetRendererCanvasType,
StartCallType, StartCallType,
@ -127,7 +126,7 @@ export type PropsType = {
setIsCallActive: (_: boolean) => void; setIsCallActive: (_: boolean) => void;
setLocalAudio: (_: SetLocalAudioType) => void; setLocalAudio: (_: SetLocalAudioType) => void;
setLocalVideo: (_: SetLocalVideoType) => void; setLocalVideo: (_: SetLocalVideoType) => void;
setLocalPreview: (_: SetLocalPreviewType) => void; setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
setOutgoingRing: (_: boolean) => void; setOutgoingRing: (_: boolean) => void;
setRendererCanvas: (_: SetRendererCanvasType) => void; setRendererCanvas: (_: SetRendererCanvasType) => void;
showShareCallLinkViaSignal: ( showShareCallLinkViaSignal: (
@ -192,7 +191,7 @@ function ActiveCallManager({
sendGroupCallReaction, sendGroupCallReaction,
setGroupCallVideoRequest, setGroupCallVideoRequest,
setLocalAudio, setLocalAudio,
setLocalPreview, setLocalPreviewContainer,
setLocalVideo, setLocalVideo,
setRendererCanvas, setRendererCanvas,
setOutgoingRing, setOutgoingRing,
@ -351,7 +350,7 @@ function ActiveCallManager({
hasLocalVideo={hasLocalVideo} hasLocalVideo={hasLocalVideo}
i18n={i18n} i18n={i18n}
setGroupCallVideoRequest={setGroupCallVideoRequestForConversation} setGroupCallVideoRequest={setGroupCallVideoRequestForConversation}
setLocalPreview={setLocalPreview} setLocalPreviewContainer={setLocalPreviewContainer}
setRendererCanvas={setRendererCanvas} setRendererCanvas={setRendererCanvas}
switchToPresentationView={switchToPresentationView} switchToPresentationView={switchToPresentationView}
switchFromPresentationView={switchFromPresentationView} switchFromPresentationView={switchFromPresentationView}
@ -383,7 +382,7 @@ function ActiveCallManager({
onJoinCall={joinActiveCall} onJoinCall={joinActiveCall}
outgoingRing={outgoingRing} outgoingRing={outgoingRing}
peekedParticipants={peekedParticipants} peekedParticipants={peekedParticipants}
setLocalPreview={setLocalPreview} setLocalPreviewContainer={setLocalPreviewContainer}
setLocalAudio={setLocalAudio} setLocalAudio={setLocalAudio}
setLocalVideo={setLocalVideo} setLocalVideo={setLocalVideo}
setOutgoingRing={setOutgoingRing} setOutgoingRing={setOutgoingRing}
@ -471,7 +470,7 @@ function ActiveCallManager({
sendGroupCallRaiseHand={sendGroupCallRaiseHand} sendGroupCallRaiseHand={sendGroupCallRaiseHand}
sendGroupCallReaction={sendGroupCallReaction} sendGroupCallReaction={sendGroupCallReaction}
setGroupCallVideoRequest={setGroupCallVideoRequestForConversation} setGroupCallVideoRequest={setGroupCallVideoRequestForConversation}
setLocalPreview={setLocalPreview} setLocalPreviewContainer={setLocalPreviewContainer}
setRendererCanvas={setRendererCanvas} setRendererCanvas={setRendererCanvas}
setLocalAudio={setLocalAudio} setLocalAudio={setLocalAudio}
setLocalVideo={setLocalVideo} setLocalVideo={setLocalVideo}
@ -567,7 +566,7 @@ export function CallManager({
setGroupCallVideoRequest, setGroupCallVideoRequest,
setIsCallActive, setIsCallActive,
setLocalAudio, setLocalAudio,
setLocalPreview, setLocalPreviewContainer,
setLocalVideo, setLocalVideo,
setOutgoingRing, setOutgoingRing,
setRendererCanvas, setRendererCanvas,
@ -662,7 +661,7 @@ export function CallManager({
sendGroupCallReaction={sendGroupCallReaction} sendGroupCallReaction={sendGroupCallReaction}
setGroupCallVideoRequest={setGroupCallVideoRequest} setGroupCallVideoRequest={setGroupCallVideoRequest}
setLocalAudio={setLocalAudio} setLocalAudio={setLocalAudio}
setLocalPreview={setLocalPreview} setLocalPreviewContainer={setLocalPreviewContainer}
setLocalVideo={setLocalVideo} setLocalVideo={setLocalVideo}
setOutgoingRing={setOutgoingRing} setOutgoingRing={setOutgoingRing}
setRendererCanvas={setRendererCanvas} setRendererCanvas={setRendererCanvas}

View file

@ -219,7 +219,7 @@ const createProps = (
sendGroupCallReaction: action('send-group-call-reaction'), sendGroupCallReaction: action('send-group-call-reaction'),
setGroupCallVideoRequest: action('set-group-call-video-request'), setGroupCallVideoRequest: action('set-group-call-video-request'),
setLocalAudio: action('set-local-audio'), setLocalAudio: action('set-local-audio'),
setLocalPreview: action('set-local-preview'), setLocalPreviewContainer: action('set-local-preview-container'),
setLocalVideo: action('set-local-video'), setLocalVideo: action('set-local-video'),
setRendererCanvas: action('set-renderer-canvas'), setRendererCanvas: action('set-renderer-canvas'),
stickyControls: false, stickyControls: false,

View file

@ -13,7 +13,6 @@ import type {
SendGroupCallRaiseHandType, SendGroupCallRaiseHandType,
SendGroupCallReactionType, SendGroupCallReactionType,
SetLocalAudioType, SetLocalAudioType,
SetLocalPreviewType,
SetLocalVideoType, SetLocalVideoType,
SetRendererCanvasType, SetRendererCanvasType,
} from '../state/ducks/calling'; } from '../state/ducks/calling';
@ -119,7 +118,7 @@ export type PropsType = {
) => void; ) => void;
setLocalAudio: (_: SetLocalAudioType) => void; setLocalAudio: (_: SetLocalAudioType) => void;
setLocalVideo: (_: SetLocalVideoType) => void; setLocalVideo: (_: SetLocalVideoType) => void;
setLocalPreview: (_: SetLocalPreviewType) => void; setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
setRendererCanvas: (_: SetRendererCanvasType) => void; setRendererCanvas: (_: SetRendererCanvasType) => void;
stickyControls: boolean; stickyControls: boolean;
switchToPresentationView: () => void; switchToPresentationView: () => void;
@ -209,7 +208,7 @@ export function CallScreen({
sendGroupCallReaction, sendGroupCallReaction,
setLocalAudio, setLocalAudio,
setLocalVideo, setLocalVideo,
setLocalPreview, setLocalPreviewContainer,
setRendererCanvas, setRendererCanvas,
stickyControls, stickyControls,
switchToPresentationView, switchToPresentationView,
@ -294,15 +293,6 @@ export function CallScreen({
const [showControls, setShowControls] = useState(true); const [showControls, setShowControls] = useState(true);
const localVideoRef = useRef<HTMLVideoElement | null>(null);
useEffect(() => {
setLocalPreview({ element: localVideoRef });
return () => {
setLocalPreview({ element: undefined });
};
}, [setLocalPreview, setRendererCanvas]);
useEffect(() => { useEffect(() => {
if ( if (
!showControls || !showControls ||
@ -431,7 +421,10 @@ export function CallScreen({
)} )}
> >
{isSendingVideo ? ( {isSendingVideo ? (
<video ref={localVideoRef} autoPlay /> <div
className="module-ongoing-call__local-preview-container"
ref={setLocalPreviewContainer}
/>
) : ( ) : (
<CallBackgroundBlur avatarUrl={me.avatarUrl}> <CallBackgroundBlur avatarUrl={me.avatarUrl}>
<div className="module-calling__spacer module-calling__camera-is-off-spacer" /> <div className="module-calling__spacer module-calling__camera-is-off-spacer" />
@ -444,14 +437,13 @@ export function CallScreen({
); );
} else { } else {
localPreviewNode = isSendingVideo ? ( localPreviewNode = isSendingVideo ? (
<video <div
className={classNames( className={classNames(
'module-ongoing-call__footer__local-preview__video', 'module-ongoing-call__footer__local-preview__video',
presentingSource && presentingSource &&
'module-ongoing-call__footer__local-preview__video--presenting' 'module-ongoing-call__footer__local-preview__video--presenting'
)} )}
ref={localVideoRef} ref={setLocalPreviewContainer}
autoPlay
/> />
) : ( ) : (
<CallBackgroundBlur avatarUrl={me.avatarUrl}> <CallBackgroundBlur avatarUrl={me.avatarUrl}>

View file

@ -84,7 +84,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
outgoingRing: overrideProps.outgoingRing ?? false, outgoingRing: overrideProps.outgoingRing ?? false,
peekedParticipants: overrideProps.peekedParticipants || [], peekedParticipants: overrideProps.peekedParticipants || [],
setLocalAudio: action('set-local-audio'), setLocalAudio: action('set-local-audio'),
setLocalPreview: action('set-local-preview'), setLocalPreviewContainer: action('set-local-preview-container'),
setLocalVideo: action('set-local-video'), setLocalVideo: action('set-local-video'),
setOutgoingRing: action('set-outgoing-ring'), setOutgoingRing: action('set-outgoing-ring'),
showParticipantsList: overrideProps.showParticipantsList ?? false, showParticipantsList: overrideProps.showParticipantsList ?? false,

View file

@ -6,7 +6,6 @@ import FocusTrap from 'focus-trap-react';
import classNames from 'classnames'; import classNames from 'classnames';
import type { import type {
SetLocalAudioType, SetLocalAudioType,
SetLocalPreviewType,
SetLocalVideoType, SetLocalVideoType,
} from '../state/ducks/calling'; } from '../state/ducks/calling';
import { CallingButton, CallingButtonType } from './CallingButton'; import { CallingButton, CallingButtonType } from './CallingButton';
@ -74,7 +73,7 @@ export type PropsType = {
peekedParticipants: Array<ConversationType>; peekedParticipants: Array<ConversationType>;
setLocalAudio: (_: SetLocalAudioType) => void; setLocalAudio: (_: SetLocalAudioType) => void;
setLocalVideo: (_: SetLocalVideoType) => void; setLocalVideo: (_: SetLocalVideoType) => void;
setLocalPreview: (_: SetLocalPreviewType) => void; setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
setOutgoingRing: (_: boolean) => void; setOutgoingRing: (_: boolean) => void;
showParticipantsList: boolean; showParticipantsList: boolean;
toggleParticipants: () => void; toggleParticipants: () => void;
@ -100,7 +99,7 @@ export function CallingLobby({
onJoinCall, onJoinCall,
peekedParticipants, peekedParticipants,
setLocalAudio, setLocalAudio,
setLocalPreview, setLocalPreviewContainer,
setLocalVideo, setLocalVideo,
setOutgoingRing, setOutgoingRing,
toggleParticipants, toggleParticipants,
@ -108,8 +107,6 @@ export function CallingLobby({
toggleSettings, toggleSettings,
outgoingRing, outgoingRing,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {
const localVideoRef = React.useRef<null | HTMLVideoElement>(null);
const shouldShowLocalVideo = hasLocalVideo && availableCameras.length > 0; const shouldShowLocalVideo = hasLocalVideo && availableCameras.length > 0;
const isGroupOrAdhocCall = isGroupOrAdhocCallMode(callMode); const isGroupOrAdhocCall = isGroupOrAdhocCallMode(callMode);
@ -130,14 +127,6 @@ export function CallingLobby({
? togglePip ? togglePip
: undefined; : undefined;
React.useEffect(() => {
setLocalPreview({ element: localVideoRef });
return () => {
setLocalPreview({ element: undefined });
};
}, [setLocalPreview]);
React.useEffect(() => { React.useEffect(() => {
function handleKeyDown(event: KeyboardEvent): void { function handleKeyDown(event: KeyboardEvent): void {
let eventHandled = false; let eventHandled = false;
@ -275,10 +264,9 @@ export function CallingLobby({
> >
<div className="module-calling__container dark-theme"> <div className="module-calling__container dark-theme">
{shouldShowLocalVideo ? ( {shouldShowLocalVideo ? (
<video <div
className="module-CallingLobby__local-preview module-CallingLobby__local-preview--camera-is-on" className="module-CallingLobby__local-preview module-CallingLobby__local-preview--camera-is-on"
ref={localVideoRef} ref={setLocalPreviewContainer}
autoPlay
/> />
) : ( ) : (
<CallBackgroundBlur <CallBackgroundBlur

View file

@ -78,7 +78,7 @@ export default {
hasLocalVideo: false, hasLocalVideo: false,
i18n, i18n,
setGroupCallVideoRequest: action('set-group-call-video-request'), setGroupCallVideoRequest: action('set-group-call-video-request'),
setLocalPreview: action('set-local-preview'), setLocalPreviewContainer: action('set-local-preview-container'),
setRendererCanvas: action('set-renderer-canvas'), setRendererCanvas: action('set-renderer-canvas'),
switchFromPresentationView: action('switch-to-presentation-view'), switchFromPresentationView: action('switch-to-presentation-view'),
switchToPresentationView: action('switch-to-presentation-view'), switchToPresentationView: action('switch-to-presentation-view'),

View file

@ -7,10 +7,7 @@ import type { VideoFrameSource } from '@signalapp/ringrtc';
import { CallingPipRemoteVideo } from './CallingPipRemoteVideo'; import { CallingPipRemoteVideo } from './CallingPipRemoteVideo';
import type { LocalizerType } from '../types/Util'; import type { LocalizerType } from '../types/Util';
import type { ActiveCallType, GroupCallVideoRequest } from '../types/Calling'; import type { ActiveCallType, GroupCallVideoRequest } from '../types/Calling';
import type { import type { SetRendererCanvasType } from '../state/ducks/calling';
SetLocalPreviewType,
SetRendererCanvasType,
} from '../state/ducks/calling';
import { missingCaseError } from '../util/missingCaseError'; import { missingCaseError } from '../util/missingCaseError';
import { useActivateSpeakerViewOnPresenting } from '../hooks/useActivateSpeakerViewOnPresenting'; import { useActivateSpeakerViewOnPresenting } from '../hooks/useActivateSpeakerViewOnPresenting';
import type { CallingImageDataCache } from './CallManager'; import type { CallingImageDataCache } from './CallManager';
@ -60,7 +57,7 @@ export type PropsType = {
_: Array<GroupCallVideoRequest>, _: Array<GroupCallVideoRequest>,
speakerHeight: number speakerHeight: number
) => void; ) => void;
setLocalPreview: (_: SetLocalPreviewType) => void; setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
setRendererCanvas: (_: SetRendererCanvasType) => void; setRendererCanvas: (_: SetRendererCanvasType) => void;
switchToPresentationView: () => void; switchToPresentationView: () => void;
switchFromPresentationView: () => void; switchFromPresentationView: () => void;
@ -80,7 +77,7 @@ export function CallingPip({
imageDataCache, imageDataCache,
i18n, i18n,
setGroupCallVideoRequest, setGroupCallVideoRequest,
setLocalPreview, setLocalPreviewContainer,
setRendererCanvas, setRendererCanvas,
switchToPresentationView, switchToPresentationView,
switchFromPresentationView, switchFromPresentationView,
@ -89,7 +86,6 @@ export function CallingPip({
const isRTL = i18n.getLocaleDirection() === 'rtl'; const isRTL = i18n.getLocaleDirection() === 'rtl';
const videoContainerRef = React.useRef<null | HTMLDivElement>(null); const videoContainerRef = React.useRef<null | HTMLDivElement>(null);
const localVideoRef = React.useRef(null);
const [windowWidth, setWindowWidth] = React.useState(window.innerWidth); const [windowWidth, setWindowWidth] = React.useState(window.innerWidth);
const [windowHeight, setWindowHeight] = React.useState(window.innerHeight); const [windowHeight, setWindowHeight] = React.useState(window.innerHeight);
@ -104,10 +100,6 @@ export function CallingPip({
switchFromPresentationView, switchFromPresentationView,
}); });
React.useEffect(() => {
setLocalPreview({ element: localVideoRef });
}, [setLocalPreview]);
const hangUp = React.useCallback(() => { const hangUp = React.useCallback(() => {
hangUpActiveCall('pip button click'); hangUpActiveCall('pip button click');
}, [hangUpActiveCall]); }, [hangUpActiveCall]);
@ -313,10 +305,9 @@ export function CallingPip({
setGroupCallVideoRequest={setGroupCallVideoRequest} setGroupCallVideoRequest={setGroupCallVideoRequest}
/> />
{hasLocalVideo ? ( {hasLocalVideo ? (
<video <div
className="module-calling-pip__video--local" className="module-calling-pip__video--local"
ref={localVideoRef} ref={setLocalPreviewContainer}
autoPlay
/> />
) : null} ) : null}
<div className="module-calling-pip__actions"> <div className="module-calling-pip__actions">

View file

@ -326,10 +326,14 @@ export type NotifyScreenShareStatusOptionsType = Readonly<
>; >;
export class CallingClass { export class CallingClass {
readonly videoCapturer: GumVideoCapturer; private readonly videoCapturer: GumVideoCapturer;
readonly videoRenderer: CanvasVideoRenderer; readonly videoRenderer: CanvasVideoRenderer;
private localPreviewContainer: HTMLDivElement | null = null;
private localPreview: HTMLVideoElement | undefined;
private reduxInterface?: CallingReduxInterface; private reduxInterface?: CallingReduxInterface;
public _sfuUrl?: string; public _sfuUrl?: string;
@ -953,6 +957,21 @@ export class CallingClass {
); );
} }
public setLocalPreviewContainer(container: HTMLDivElement | null): void {
// Reuse HTMLVideoElement between different containers so that the preview
// of the last frame stays valid even if there are no new frames on the
// underlying MediaStream.
if (this.localPreview == null) {
this.localPreview = document.createElement('video');
this.localPreview.autoplay = true;
this.videoCapturer.setLocalPreview({ current: this.localPreview });
}
this.localPreviewContainer?.removeChild(this.localPreview);
this.localPreviewContainer = container;
this.localPreviewContainer?.appendChild(this.localPreview);
}
public async cleanupStaleRingingCalls(): Promise<void> { public async cleanupStaleRingingCalls(): Promise<void> {
const calls = await DataWriter.getRecentStaleRingsAndMarkOlderMissed(); const calls = await DataWriter.getRecentStaleRingsAndMarkOlderMissed();

View file

@ -420,11 +420,6 @@ type StartCallLinkLobbyPayloadType = {
callLinkRootKey: string; callLinkRootKey: string;
}; };
// eslint-disable-next-line local-rules/type-alias-readonlydeep
export type SetLocalPreviewType = {
element: React.RefObject<HTMLVideoElement> | undefined;
};
// eslint-disable-next-line local-rules/type-alias-readonlydeep // eslint-disable-next-line local-rules/type-alias-readonlydeep
export type SetRendererCanvasType = { export type SetRendererCanvasType = {
element: React.RefObject<HTMLCanvasElement> | undefined; element: React.RefObject<HTMLCanvasElement> | undefined;
@ -1835,14 +1830,6 @@ function setIsCallActive(
}; };
} }
function setLocalPreview(
payload: SetLocalPreviewType
): ThunkAction<void, RootStateType, unknown, never> {
return () => {
calling.videoCapturer.setLocalPreview(payload.element);
};
}
function setRendererCanvas( function setRendererCanvas(
payload: SetRendererCanvasType payload: SetRendererCanvasType
): ThunkAction<void, RootStateType, unknown, never> { ): ThunkAction<void, RootStateType, unknown, never> {
@ -2661,7 +2648,6 @@ export const actions = {
setGroupCallVideoRequest, setGroupCallVideoRequest,
setIsCallActive, setIsCallActive,
setLocalAudio, setLocalAudio,
setLocalPreview,
setLocalVideo, setLocalVideo,
setOutgoingRing, setOutgoingRing,
setRendererCanvas, setRendererCanvas,
@ -3802,8 +3788,7 @@ export function reducer(
} }
return { return {
...state, ...(action.payload == null ? abortCapturer(state) : state),
capturerBaton: undefined,
activeCallState: { activeCallState: {
...activeCallState, ...activeCallState,
presentingSource: action.payload, presentingSource: action.payload,

View file

@ -116,6 +116,10 @@ async function notifyForCall(
}); });
} }
function setLocalPreviewContainer(container: HTMLDivElement | null): void {
callingService.setLocalPreviewContainer(container);
}
const playRingtone = callingTones.playRingtone.bind(callingTones); const playRingtone = callingTones.playRingtone.bind(callingTones);
const stopRingtone = callingTones.stopRingtone.bind(callingTones); const stopRingtone = callingTones.stopRingtone.bind(callingTones);
@ -449,7 +453,6 @@ export const SmartCallManager = memo(function SmartCallManager() {
setIsCallActive, setIsCallActive,
setLocalAudio, setLocalAudio,
setLocalVideo, setLocalVideo,
setLocalPreview,
setOutgoingRing, setOutgoingRing,
setRendererCanvas, setRendererCanvas,
switchToPresentationView, switchToPresentationView,
@ -509,7 +512,7 @@ export const SmartCallManager = memo(function SmartCallManager() {
setGroupCallVideoRequest={setGroupCallVideoRequest} setGroupCallVideoRequest={setGroupCallVideoRequest}
setIsCallActive={setIsCallActive} setIsCallActive={setIsCallActive}
setLocalAudio={setLocalAudio} setLocalAudio={setLocalAudio}
setLocalPreview={setLocalPreview} setLocalPreviewContainer={setLocalPreviewContainer}
setLocalVideo={setLocalVideo} setLocalVideo={setLocalVideo}
setOutgoingRing={setOutgoingRing} setOutgoingRing={setOutgoingRing}
setRendererCanvas={setRendererCanvas} setRendererCanvas={setRendererCanvas}

View file

@ -2032,13 +2032,6 @@
"updated": "2024-01-06T00:59:20.678Z", "updated": "2024-01-06T00:59:20.678Z",
"reasonDetail": "Recent bursts shown for burst behavior like throttling." "reasonDetail": "Recent bursts shown for burst behavior like throttling."
}, },
{
"rule": "React-useRef",
"path": "ts/components/CallScreen.tsx",
"line": " const localVideoRef = useRef<HTMLVideoElement | null>(null);",
"reasonCategory": "usageTrusted",
"updated": "2021-12-01T01:31:12.757Z"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/CallScreen.tsx", "path": "ts/components/CallScreen.tsx",
@ -2085,13 +2078,6 @@
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2024-01-16T22:59:06.336Z" "updated": "2024-01-16T22:59:06.336Z"
}, },
{
"rule": "React-useRef",
"path": "ts/components/CallingLobby.tsx",
"line": " const localVideoRef = React.useRef<null | HTMLVideoElement>(null);",
"reasonCategory": "usageTrusted",
"updated": "2021-07-30T16:57:33.618Z"
},
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/CallingPendingParticipants.tsx", "path": "ts/components/CallingPendingParticipants.tsx",
@ -2102,11 +2088,11 @@
}, },
{ {
"rule": "React-useRef", "rule": "React-useRef",
"path": "ts/components/CallingPip.tsx", "path": "ts/components/CallingPendingParticipants.tsx",
"line": " const localVideoRef = React.useRef(null);", "line": " const lastParticipantRef = React.useRef<ConversationType | undefined>();",
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2020-10-26T19:12:24.410Z", "updated": "2024-09-20T02:11:27.851Z",
"reasonDetail": "Used to get the local video element for rendering." "reasonDetail": "For fading out, to keep showing the last known participant"
}, },
{ {
"rule": "React-useRef", "rule": "React-useRef",
@ -3126,13 +3112,5 @@
"line": " message.innerHTML = window.i18n('icu:optimizingApplication');", "line": " message.innerHTML = window.i18n('icu:optimizingApplication');",
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2021-09-17T21:02:59.414Z" "updated": "2021-09-17T21:02:59.414Z"
},
{
"rule": "React-useRef",
"path": "ts/components/CallingPendingParticipants.tsx",
"line": " const lastParticipantRef = React.useRef<ConversationType | undefined>();",
"reasonCategory": "usageTrusted",
"updated": "2024-09-20T02:11:27.851Z",
"reasonDetail": "For fading out, to keep showing the last known participant"
} }
] ]