Reuse html element for local preview visuals
This commit is contained in:
parent
bb69f81b9f
commit
17c908bbf4
14 changed files with 86 additions and 109 deletions
|
@ -4231,6 +4231,10 @@ button.module-image__border-overlay:focus {
|
|||
}
|
||||
}
|
||||
|
||||
&__local-preview-video-container {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
&__local-preview-fullsize {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -4283,14 +4287,19 @@ button.module-image__border-overlay:focus {
|
|||
}
|
||||
|
||||
&__video {
|
||||
// The background-color is seen while the video loads.
|
||||
background-color: $color-gray-75;
|
||||
height: 100%;
|
||||
transform: rotateY(180deg);
|
||||
width: 100%;
|
||||
|
||||
&--presenting {
|
||||
transform: inherit;
|
||||
video {
|
||||
// The background-color is seen while the video loads.
|
||||
background-color: $color-gray-75;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
transform: rotateY(180deg);
|
||||
&--presenting {
|
||||
transform: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4373,8 +4382,13 @@ button.module-image__border-overlay:focus {
|
|||
height: 32px;
|
||||
position: absolute;
|
||||
inset-inline-end: 4px;
|
||||
transform: rotateY(180deg);
|
||||
width: 32px;
|
||||
|
||||
video {
|
||||
transform: rotateY(180deg);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,14 @@
|
|||
height: 100%;
|
||||
max-height: calc(100% - 140px);
|
||||
opacity: 0.6;
|
||||
|
||||
// Border radius should clip children
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&--camera-is-on video {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&--camera-is-off {
|
||||
|
|
|
@ -130,7 +130,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
|||
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
||||
setIsCallActive: action('set-is-call-active'),
|
||||
setLocalAudio: action('set-local-audio'),
|
||||
setLocalPreview: action('set-local-preview'),
|
||||
setLocalPreviewContainer: action('set-local-preview-container'),
|
||||
setLocalVideo: action('set-local-video'),
|
||||
setRendererCanvas: action('set-renderer-canvas'),
|
||||
setOutgoingRing: action('set-outgoing-ring'),
|
||||
|
|
|
@ -37,7 +37,6 @@ import type {
|
|||
SendGroupCallReactionType,
|
||||
SetGroupCallVideoRequestType,
|
||||
SetLocalAudioType,
|
||||
SetLocalPreviewType,
|
||||
SetLocalVideoType,
|
||||
SetRendererCanvasType,
|
||||
StartCallType,
|
||||
|
@ -127,7 +126,7 @@ export type PropsType = {
|
|||
setIsCallActive: (_: boolean) => void;
|
||||
setLocalAudio: (_: SetLocalAudioType) => void;
|
||||
setLocalVideo: (_: SetLocalVideoType) => void;
|
||||
setLocalPreview: (_: SetLocalPreviewType) => void;
|
||||
setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
|
||||
setOutgoingRing: (_: boolean) => void;
|
||||
setRendererCanvas: (_: SetRendererCanvasType) => void;
|
||||
showShareCallLinkViaSignal: (
|
||||
|
@ -192,7 +191,7 @@ function ActiveCallManager({
|
|||
sendGroupCallReaction,
|
||||
setGroupCallVideoRequest,
|
||||
setLocalAudio,
|
||||
setLocalPreview,
|
||||
setLocalPreviewContainer,
|
||||
setLocalVideo,
|
||||
setRendererCanvas,
|
||||
setOutgoingRing,
|
||||
|
@ -351,7 +350,7 @@ function ActiveCallManager({
|
|||
hasLocalVideo={hasLocalVideo}
|
||||
i18n={i18n}
|
||||
setGroupCallVideoRequest={setGroupCallVideoRequestForConversation}
|
||||
setLocalPreview={setLocalPreview}
|
||||
setLocalPreviewContainer={setLocalPreviewContainer}
|
||||
setRendererCanvas={setRendererCanvas}
|
||||
switchToPresentationView={switchToPresentationView}
|
||||
switchFromPresentationView={switchFromPresentationView}
|
||||
|
@ -383,7 +382,7 @@ function ActiveCallManager({
|
|||
onJoinCall={joinActiveCall}
|
||||
outgoingRing={outgoingRing}
|
||||
peekedParticipants={peekedParticipants}
|
||||
setLocalPreview={setLocalPreview}
|
||||
setLocalPreviewContainer={setLocalPreviewContainer}
|
||||
setLocalAudio={setLocalAudio}
|
||||
setLocalVideo={setLocalVideo}
|
||||
setOutgoingRing={setOutgoingRing}
|
||||
|
@ -471,7 +470,7 @@ function ActiveCallManager({
|
|||
sendGroupCallRaiseHand={sendGroupCallRaiseHand}
|
||||
sendGroupCallReaction={sendGroupCallReaction}
|
||||
setGroupCallVideoRequest={setGroupCallVideoRequestForConversation}
|
||||
setLocalPreview={setLocalPreview}
|
||||
setLocalPreviewContainer={setLocalPreviewContainer}
|
||||
setRendererCanvas={setRendererCanvas}
|
||||
setLocalAudio={setLocalAudio}
|
||||
setLocalVideo={setLocalVideo}
|
||||
|
@ -567,7 +566,7 @@ export function CallManager({
|
|||
setGroupCallVideoRequest,
|
||||
setIsCallActive,
|
||||
setLocalAudio,
|
||||
setLocalPreview,
|
||||
setLocalPreviewContainer,
|
||||
setLocalVideo,
|
||||
setOutgoingRing,
|
||||
setRendererCanvas,
|
||||
|
@ -662,7 +661,7 @@ export function CallManager({
|
|||
sendGroupCallReaction={sendGroupCallReaction}
|
||||
setGroupCallVideoRequest={setGroupCallVideoRequest}
|
||||
setLocalAudio={setLocalAudio}
|
||||
setLocalPreview={setLocalPreview}
|
||||
setLocalPreviewContainer={setLocalPreviewContainer}
|
||||
setLocalVideo={setLocalVideo}
|
||||
setOutgoingRing={setOutgoingRing}
|
||||
setRendererCanvas={setRendererCanvas}
|
||||
|
|
|
@ -219,7 +219,7 @@ const createProps = (
|
|||
sendGroupCallReaction: action('send-group-call-reaction'),
|
||||
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
||||
setLocalAudio: action('set-local-audio'),
|
||||
setLocalPreview: action('set-local-preview'),
|
||||
setLocalPreviewContainer: action('set-local-preview-container'),
|
||||
setLocalVideo: action('set-local-video'),
|
||||
setRendererCanvas: action('set-renderer-canvas'),
|
||||
stickyControls: false,
|
||||
|
|
|
@ -13,7 +13,6 @@ import type {
|
|||
SendGroupCallRaiseHandType,
|
||||
SendGroupCallReactionType,
|
||||
SetLocalAudioType,
|
||||
SetLocalPreviewType,
|
||||
SetLocalVideoType,
|
||||
SetRendererCanvasType,
|
||||
} from '../state/ducks/calling';
|
||||
|
@ -119,7 +118,7 @@ export type PropsType = {
|
|||
) => void;
|
||||
setLocalAudio: (_: SetLocalAudioType) => void;
|
||||
setLocalVideo: (_: SetLocalVideoType) => void;
|
||||
setLocalPreview: (_: SetLocalPreviewType) => void;
|
||||
setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
|
||||
setRendererCanvas: (_: SetRendererCanvasType) => void;
|
||||
stickyControls: boolean;
|
||||
switchToPresentationView: () => void;
|
||||
|
@ -209,7 +208,7 @@ export function CallScreen({
|
|||
sendGroupCallReaction,
|
||||
setLocalAudio,
|
||||
setLocalVideo,
|
||||
setLocalPreview,
|
||||
setLocalPreviewContainer,
|
||||
setRendererCanvas,
|
||||
stickyControls,
|
||||
switchToPresentationView,
|
||||
|
@ -294,15 +293,6 @@ export function CallScreen({
|
|||
|
||||
const [showControls, setShowControls] = useState(true);
|
||||
|
||||
const localVideoRef = useRef<HTMLVideoElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalPreview({ element: localVideoRef });
|
||||
return () => {
|
||||
setLocalPreview({ element: undefined });
|
||||
};
|
||||
}, [setLocalPreview, setRendererCanvas]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!showControls ||
|
||||
|
@ -431,7 +421,10 @@ export function CallScreen({
|
|||
)}
|
||||
>
|
||||
{isSendingVideo ? (
|
||||
<video ref={localVideoRef} autoPlay />
|
||||
<div
|
||||
className="module-ongoing-call__local-preview-container"
|
||||
ref={setLocalPreviewContainer}
|
||||
/>
|
||||
) : (
|
||||
<CallBackgroundBlur avatarUrl={me.avatarUrl}>
|
||||
<div className="module-calling__spacer module-calling__camera-is-off-spacer" />
|
||||
|
@ -444,14 +437,13 @@ export function CallScreen({
|
|||
);
|
||||
} else {
|
||||
localPreviewNode = isSendingVideo ? (
|
||||
<video
|
||||
<div
|
||||
className={classNames(
|
||||
'module-ongoing-call__footer__local-preview__video',
|
||||
presentingSource &&
|
||||
'module-ongoing-call__footer__local-preview__video--presenting'
|
||||
)}
|
||||
ref={localVideoRef}
|
||||
autoPlay
|
||||
ref={setLocalPreviewContainer}
|
||||
/>
|
||||
) : (
|
||||
<CallBackgroundBlur avatarUrl={me.avatarUrl}>
|
||||
|
|
|
@ -84,7 +84,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
|||
outgoingRing: overrideProps.outgoingRing ?? false,
|
||||
peekedParticipants: overrideProps.peekedParticipants || [],
|
||||
setLocalAudio: action('set-local-audio'),
|
||||
setLocalPreview: action('set-local-preview'),
|
||||
setLocalPreviewContainer: action('set-local-preview-container'),
|
||||
setLocalVideo: action('set-local-video'),
|
||||
setOutgoingRing: action('set-outgoing-ring'),
|
||||
showParticipantsList: overrideProps.showParticipantsList ?? false,
|
||||
|
|
|
@ -6,7 +6,6 @@ import FocusTrap from 'focus-trap-react';
|
|||
import classNames from 'classnames';
|
||||
import type {
|
||||
SetLocalAudioType,
|
||||
SetLocalPreviewType,
|
||||
SetLocalVideoType,
|
||||
} from '../state/ducks/calling';
|
||||
import { CallingButton, CallingButtonType } from './CallingButton';
|
||||
|
@ -74,7 +73,7 @@ export type PropsType = {
|
|||
peekedParticipants: Array<ConversationType>;
|
||||
setLocalAudio: (_: SetLocalAudioType) => void;
|
||||
setLocalVideo: (_: SetLocalVideoType) => void;
|
||||
setLocalPreview: (_: SetLocalPreviewType) => void;
|
||||
setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
|
||||
setOutgoingRing: (_: boolean) => void;
|
||||
showParticipantsList: boolean;
|
||||
toggleParticipants: () => void;
|
||||
|
@ -100,7 +99,7 @@ export function CallingLobby({
|
|||
onJoinCall,
|
||||
peekedParticipants,
|
||||
setLocalAudio,
|
||||
setLocalPreview,
|
||||
setLocalPreviewContainer,
|
||||
setLocalVideo,
|
||||
setOutgoingRing,
|
||||
toggleParticipants,
|
||||
|
@ -108,8 +107,6 @@ export function CallingLobby({
|
|||
toggleSettings,
|
||||
outgoingRing,
|
||||
}: PropsType): JSX.Element {
|
||||
const localVideoRef = React.useRef<null | HTMLVideoElement>(null);
|
||||
|
||||
const shouldShowLocalVideo = hasLocalVideo && availableCameras.length > 0;
|
||||
|
||||
const isGroupOrAdhocCall = isGroupOrAdhocCallMode(callMode);
|
||||
|
@ -130,14 +127,6 @@ export function CallingLobby({
|
|||
? togglePip
|
||||
: undefined;
|
||||
|
||||
React.useEffect(() => {
|
||||
setLocalPreview({ element: localVideoRef });
|
||||
|
||||
return () => {
|
||||
setLocalPreview({ element: undefined });
|
||||
};
|
||||
}, [setLocalPreview]);
|
||||
|
||||
React.useEffect(() => {
|
||||
function handleKeyDown(event: KeyboardEvent): void {
|
||||
let eventHandled = false;
|
||||
|
@ -275,10 +264,9 @@ export function CallingLobby({
|
|||
>
|
||||
<div className="module-calling__container dark-theme">
|
||||
{shouldShowLocalVideo ? (
|
||||
<video
|
||||
<div
|
||||
className="module-CallingLobby__local-preview module-CallingLobby__local-preview--camera-is-on"
|
||||
ref={localVideoRef}
|
||||
autoPlay
|
||||
ref={setLocalPreviewContainer}
|
||||
/>
|
||||
) : (
|
||||
<CallBackgroundBlur
|
||||
|
|
|
@ -78,7 +78,7 @@ export default {
|
|||
hasLocalVideo: false,
|
||||
i18n,
|
||||
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
||||
setLocalPreview: action('set-local-preview'),
|
||||
setLocalPreviewContainer: action('set-local-preview-container'),
|
||||
setRendererCanvas: action('set-renderer-canvas'),
|
||||
switchFromPresentationView: action('switch-to-presentation-view'),
|
||||
switchToPresentationView: action('switch-to-presentation-view'),
|
||||
|
|
|
@ -7,10 +7,7 @@ import type { VideoFrameSource } from '@signalapp/ringrtc';
|
|||
import { CallingPipRemoteVideo } from './CallingPipRemoteVideo';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import type { ActiveCallType, GroupCallVideoRequest } from '../types/Calling';
|
||||
import type {
|
||||
SetLocalPreviewType,
|
||||
SetRendererCanvasType,
|
||||
} from '../state/ducks/calling';
|
||||
import type { SetRendererCanvasType } from '../state/ducks/calling';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { useActivateSpeakerViewOnPresenting } from '../hooks/useActivateSpeakerViewOnPresenting';
|
||||
import type { CallingImageDataCache } from './CallManager';
|
||||
|
@ -60,7 +57,7 @@ export type PropsType = {
|
|||
_: Array<GroupCallVideoRequest>,
|
||||
speakerHeight: number
|
||||
) => void;
|
||||
setLocalPreview: (_: SetLocalPreviewType) => void;
|
||||
setLocalPreviewContainer: (container: HTMLDivElement | null) => void;
|
||||
setRendererCanvas: (_: SetRendererCanvasType) => void;
|
||||
switchToPresentationView: () => void;
|
||||
switchFromPresentationView: () => void;
|
||||
|
@ -80,7 +77,7 @@ export function CallingPip({
|
|||
imageDataCache,
|
||||
i18n,
|
||||
setGroupCallVideoRequest,
|
||||
setLocalPreview,
|
||||
setLocalPreviewContainer,
|
||||
setRendererCanvas,
|
||||
switchToPresentationView,
|
||||
switchFromPresentationView,
|
||||
|
@ -89,7 +86,6 @@ export function CallingPip({
|
|||
const isRTL = i18n.getLocaleDirection() === 'rtl';
|
||||
|
||||
const videoContainerRef = React.useRef<null | HTMLDivElement>(null);
|
||||
const localVideoRef = React.useRef(null);
|
||||
|
||||
const [windowWidth, setWindowWidth] = React.useState(window.innerWidth);
|
||||
const [windowHeight, setWindowHeight] = React.useState(window.innerHeight);
|
||||
|
@ -104,10 +100,6 @@ export function CallingPip({
|
|||
switchFromPresentationView,
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
setLocalPreview({ element: localVideoRef });
|
||||
}, [setLocalPreview]);
|
||||
|
||||
const hangUp = React.useCallback(() => {
|
||||
hangUpActiveCall('pip button click');
|
||||
}, [hangUpActiveCall]);
|
||||
|
@ -313,10 +305,9 @@ export function CallingPip({
|
|||
setGroupCallVideoRequest={setGroupCallVideoRequest}
|
||||
/>
|
||||
{hasLocalVideo ? (
|
||||
<video
|
||||
<div
|
||||
className="module-calling-pip__video--local"
|
||||
ref={localVideoRef}
|
||||
autoPlay
|
||||
ref={setLocalPreviewContainer}
|
||||
/>
|
||||
) : null}
|
||||
<div className="module-calling-pip__actions">
|
||||
|
|
|
@ -326,10 +326,14 @@ export type NotifyScreenShareStatusOptionsType = Readonly<
|
|||
>;
|
||||
|
||||
export class CallingClass {
|
||||
readonly videoCapturer: GumVideoCapturer;
|
||||
private readonly videoCapturer: GumVideoCapturer;
|
||||
|
||||
readonly videoRenderer: CanvasVideoRenderer;
|
||||
|
||||
private localPreviewContainer: HTMLDivElement | null = null;
|
||||
|
||||
private localPreview: HTMLVideoElement | undefined;
|
||||
|
||||
private reduxInterface?: CallingReduxInterface;
|
||||
|
||||
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> {
|
||||
const calls = await DataWriter.getRecentStaleRingsAndMarkOlderMissed();
|
||||
|
||||
|
|
|
@ -420,11 +420,6 @@ type StartCallLinkLobbyPayloadType = {
|
|||
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
|
||||
export type SetRendererCanvasType = {
|
||||
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(
|
||||
payload: SetRendererCanvasType
|
||||
): ThunkAction<void, RootStateType, unknown, never> {
|
||||
|
@ -2661,7 +2648,6 @@ export const actions = {
|
|||
setGroupCallVideoRequest,
|
||||
setIsCallActive,
|
||||
setLocalAudio,
|
||||
setLocalPreview,
|
||||
setLocalVideo,
|
||||
setOutgoingRing,
|
||||
setRendererCanvas,
|
||||
|
@ -3802,8 +3788,7 @@ export function reducer(
|
|||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
capturerBaton: undefined,
|
||||
...(action.payload == null ? abortCapturer(state) : state),
|
||||
activeCallState: {
|
||||
...activeCallState,
|
||||
presentingSource: action.payload,
|
||||
|
|
|
@ -116,6 +116,10 @@ async function notifyForCall(
|
|||
});
|
||||
}
|
||||
|
||||
function setLocalPreviewContainer(container: HTMLDivElement | null): void {
|
||||
callingService.setLocalPreviewContainer(container);
|
||||
}
|
||||
|
||||
const playRingtone = callingTones.playRingtone.bind(callingTones);
|
||||
const stopRingtone = callingTones.stopRingtone.bind(callingTones);
|
||||
|
||||
|
@ -449,7 +453,6 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
|||
setIsCallActive,
|
||||
setLocalAudio,
|
||||
setLocalVideo,
|
||||
setLocalPreview,
|
||||
setOutgoingRing,
|
||||
setRendererCanvas,
|
||||
switchToPresentationView,
|
||||
|
@ -509,7 +512,7 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
|||
setGroupCallVideoRequest={setGroupCallVideoRequest}
|
||||
setIsCallActive={setIsCallActive}
|
||||
setLocalAudio={setLocalAudio}
|
||||
setLocalPreview={setLocalPreview}
|
||||
setLocalPreviewContainer={setLocalPreviewContainer}
|
||||
setLocalVideo={setLocalVideo}
|
||||
setOutgoingRing={setOutgoingRing}
|
||||
setRendererCanvas={setRendererCanvas}
|
||||
|
|
|
@ -2032,13 +2032,6 @@
|
|||
"updated": "2024-01-06T00:59:20.678Z",
|
||||
"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",
|
||||
"path": "ts/components/CallScreen.tsx",
|
||||
|
@ -2085,13 +2078,6 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"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",
|
||||
"path": "ts/components/CallingPendingParticipants.tsx",
|
||||
|
@ -2102,11 +2088,11 @@
|
|||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/CallingPip.tsx",
|
||||
"line": " const localVideoRef = React.useRef(null);",
|
||||
"path": "ts/components/CallingPendingParticipants.tsx",
|
||||
"line": " const lastParticipantRef = React.useRef<ConversationType | undefined>();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-26T19:12:24.410Z",
|
||||
"reasonDetail": "Used to get the local video element for rendering."
|
||||
"updated": "2024-09-20T02:11:27.851Z",
|
||||
"reasonDetail": "For fading out, to keep showing the last known participant"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
|
@ -3126,13 +3112,5 @@
|
|||
"line": " message.innerHTML = window.i18n('icu:optimizingApplication');",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue