scheduleLargeVideoUpdate()

in modules/UI/videolayout/LargeVideoManager.js [192:307]


    scheduleLargeVideoUpdate() {
        if (this.updateInProcess || !this.newStreamData) {
            return;
        }

        this.updateInProcess = true;

        // Include hide()/fadeOut only if we're switching between users
        // eslint-disable-next-line eqeqeq
        const container = this.getCurrentContainer();
        const isUserSwitch = this.newStreamData.id !== container.id;
        const preUpdate = isUserSwitch ? container.hide() : Promise.resolve();

        preUpdate.then(() => {
            const { id, stream, videoType, resolve } = this.newStreamData;

            // FIXME this does not really make sense, because the videoType
            // (camera or desktop) is a completely different thing than
            // the video container type (Etherpad, SharedVideo, VideoContainer).
            const isVideoContainer = LargeVideoManager.isVideoContainer(videoType);

            this.newStreamData = null;

            logger.info(`hover in ${id}`);
            this.state = videoType;
            // eslint-disable-next-line no-shadow
            const container = this.getCurrentContainer();

            container.setStream(id, stream, videoType);

            // change the avatar url on large
            this.updateAvatar();

            const isVideoMuted = !stream || stream.isMuted();
            const state = APP.store.getState();
            const participant = getParticipantById(state, id);
            const connectionStatus = participant?.connectionStatus;
            const isVideoRenderable = !isVideoMuted
                && (APP.conference.isLocalId(id) || connectionStatus === JitsiParticipantConnectionStatus.ACTIVE);
            const isAudioOnly = APP.conference.isAudioOnly();
            const showAvatar
                = isVideoContainer
                    && ((isAudioOnly && videoType !== VIDEO_TYPE.DESKTOP) || !isVideoRenderable);

            let promise;

            // do not show stream if video is muted
            // but we still should show watermark
            if (showAvatar) {
                this.showWatermark(true);

                // If the intention of this switch is to show the avatar
                // we need to make sure that the video is hidden
                promise = container.hide();

                if ((!shouldDisplayTileView(state) || participant?.pinned) // In theory the tile view may not be
                // enabled yet when we auto pin the participant.

                        && participant && !participant.local && !participant.isFakeParticipant) {
                    // remote participant only
                    const track = getTrackByMediaTypeAndParticipant(
                        state['features/base/tracks'], MEDIA_TYPE.VIDEO, id);
                    const isScreenSharing = track?.videoType === 'desktop';

                    if (isScreenSharing) {
                        // send the event
                        sendAnalytics(createScreenSharingIssueEvent({
                            source: 'large-video',
                            connectionStatus,
                            isVideoMuted,
                            isAudioOnly,
                            isVideoContainer,
                            videoType
                        }));
                    }
                }

            } else {
                promise = container.show();
            }

            // show the avatar on large if needed
            container.showAvatar(showAvatar);

            // Clean up audio level after previous speaker.
            if (showAvatar) {
                this.updateLargeVideoAudioLevel(0);
            }

            const messageKey
                = connectionStatus === JitsiParticipantConnectionStatus.INACTIVE ? 'connection.LOW_BANDWIDTH' : null;

            // Do not show connection status message in the audio only mode,
            // because it's based on the video playback status.
            const overrideAndHide = APP.conference.isAudioOnly();

            this.updateParticipantConnStatusIndication(
                    id,
                    !overrideAndHide && messageKey);

            // Change the participant id the presence label is listening to.
            this.updatePresenceLabel(id);

            this.videoContainer.positionRemoteStatusMessages();

            // resolve updateLargeVideo promise after everything is done
            promise.then(resolve);

            return promise;
        }).then(() => {
            // after everything is done check again if there are any pending
            // new streams.
            this.updateInProcess = false;
            this.scheduleLargeVideoUpdate();
        });
    }