snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
Some checks failed
Prosody Plugin Tests / test (push) Failing after 10m11s
Close stale issues and PRs / stale (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-15 15:56:32 +05:00
commit 1d2bfcac0c
3159 changed files with 464524 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
import React from 'react';
import { connect } from 'react-redux';
import { PLAYBACK_STATUSES } from '../../constants';
import AbstractVideoManager, {
IProps,
_mapDispatchToProps,
_mapStateToProps
} from './AbstractVideoManager';
/**
* Manager of shared video.
*/
class VideoManager extends AbstractVideoManager {
playerRef: React.RefObject<HTMLVideoElement>;
/**
* Initializes a new VideoManager instance.
*
* @param {Object} props - This component's props.
*
* @returns {void}
*/
constructor(props: IProps) {
super(props);
this.playerRef = React.createRef();
}
/**
* Retrieves the current player ref.
*/
get player() {
return this.playerRef.current;
}
/**
* Indicates the playback state of the video.
*
* @returns {string}
*/
override getPlaybackStatus() {
let status;
if (!this.player) {
return;
}
if (this.player.paused) {
status = PLAYBACK_STATUSES.PAUSED;
} else {
status = PLAYBACK_STATUSES.PLAYING;
}
return status;
}
/**
* Indicates whether the video is muted.
*
* @returns {boolean}
*/
override isMuted() {
return this.player?.muted;
}
/**
* Retrieves current volume.
*
* @returns {number}
*/
override getVolume() {
return Number(this.player?.volume);
}
/**
* Retrieves current time.
*
* @returns {number}
*/
override getTime() {
return Number(this.player?.currentTime);
}
/**
* Seeks video to provided time.
*
* @param {number} time - The time to seek to.
*
* @returns {void}
*/
override seek(time: number) {
if (this.player) {
this.player.currentTime = time;
}
}
/**
* Plays video.
*
* @returns {void}
*/
override play() {
return this.player?.play();
}
/**
* Pauses video.
*
* @returns {void}
*/
override pause() {
return this.player?.pause();
}
/**
* Mutes video.
*
* @returns {void}
*/
override mute() {
if (this.player) {
this.player.muted = true;
}
}
/**
* Unmutes video.
*
* @returns {void}
*/
override unMute() {
if (this.player) {
this.player.muted = false;
}
}
/**
* Retrieves video tag params.
*
* @returns {void}
*/
getPlayerOptions() {
const { _isOwner, follower, videoId } = this.props;
let options: any = {
// A follower starts itself from the meeting's shared state
// (see syncFollower), so it must not autoplay a paused video.
autoPlay: !follower,
src: videoId,
controls: _isOwner,
// A follower plays no audio; starting it muted also keeps the
// browser from blocking the autoplay.
muted: follower,
// Forwarded rather than dropped: the event's target carries the
// MediaError and the resolved source, which is the only diagnostic
// behind the message a follower shows on a second screen.
onError: (e: any) => this.onError(e),
onPlay: () => this.onPlay(),
onVolumeChange: () => this.onVolumeChange()
};
if (_isOwner) {
options = {
...options,
onPause: () => this.onPause(),
onTimeUpdate: this.throttledFireUpdateSharedVideoEvent
};
}
return options;
}
/**
* Implements React Component's render.
*
* @inheritdoc
*/
override render() {
return (
<video
id = 'sharedVideoPlayer'
ref = { this.playerRef }
{ ...this.getPlayerOptions() } />
);
}
}
export default connect(_mapStateToProps, _mapDispatchToProps)(VideoManager);