initial implementation

This commit is contained in:
rift 2025-11-27 21:16:43 -05:00
parent 17746db439
commit 69fea4daac
3 changed files with 50 additions and 1 deletions

View file

@ -21,6 +21,7 @@ const ControlBar = ({
volume,
muted,
playbackSpeed,
pictureInPicture,
subtitlesTracks,
audioTracks,
metaItem,
@ -33,6 +34,8 @@ const ControlBar = ({
onMuteRequested,
onUnmuteRequested,
onVolumeChangeRequested,
onPipEnableRequested,
onPipDisableRequested,
onSeekRequested,
onToggleSubtitlesMenu,
onToggleAudioMenu,
@ -40,6 +43,7 @@ const ControlBar = ({
onToggleSideDrawer,
onToggleOptionsMenu,
onToggleStatisticsMenu,
onTogglePip,
onTouchEnd,
...props
}) => {
@ -95,6 +99,17 @@ const ControlBar = ({
const onChromecastButtonClick = React.useCallback(() => {
chromecast.transport.requestSession();
}, []);
const onPipButtonClick = React.useCallback(() => {
if (pictureInPicture) {
if (typeof onPipDisableRequested === 'function') {
onPipDisableRequested();
}
} else {
if (typeof onPipEnableRequested === 'function') {
onPipEnableRequested();
}
}
}, [pictureInPicture, onPipEnableRequested, onPipDisableRequested])
React.useEffect(() => {
const onStateChanged = () => {
setChromecastServiceActive(chromecast.active);
@ -153,7 +168,10 @@ const ControlBar = ({
<Icon className={styles['icon']} name={'more-vertical'} />
</Button>
<div className={classnames(styles['control-bar-buttons-menu-container'], { 'open': buttonsMenuOpen })}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': statistics === null || statistics.type === 'Err' || stream === null || typeof stream.infoHash !== 'string' || typeof stream.fileIdx !== 'number' })} tabIndex={-1} onMouseDown={onStatisticsButtonMouseDown} onClick={onToggleStatisticsMenu}>
<Button className={classnames(styles['control-bar-button'], { 'disabled': stream === null })} tabIndex={-1} onClick={onPipButtonClick}>
<Icon className={styles['icon']} name={'open-in-browser'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': statistics === null || statistics.type === 'Err' || stream === null || typeof stream.infoHash !== 'string' || typeof stream.fileIdx !== 'number' })} tabIndex={-1} onMouseDown={onStatisticsButtonMouseDown} onClick={onToggleStatisticsMenu}>
<Icon className={styles['icon']} name={'network'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': playbackSpeed === null })} tabIndex={-1} onMouseDown={onSpeedButtonMouseDown} onClick={onToggleSpeedMenu}>
@ -193,6 +211,7 @@ ControlBar.propTypes = {
buffered: PropTypes.number,
volume: PropTypes.number,
muted: PropTypes.bool,
pictureInPicture: PropTypes.bool,
playbackSpeed: PropTypes.number,
subtitlesTracks: PropTypes.array,
audioTracks: PropTypes.array,
@ -207,6 +226,8 @@ ControlBar.propTypes = {
onUnmuteRequested: PropTypes.func,
onVolumeChangeRequested: PropTypes.func,
onSeekRequested: PropTypes.func,
onPipEnableRequested: PropTypes.func,
onPipDisableRequested: PropTypes.func,
onToggleSubtitlesMenu: PropTypes.func,
onToggleAudioMenu: PropTypes.func,
onToggleSpeedMenu: PropTypes.func,
@ -216,6 +237,7 @@ ControlBar.propTypes = {
onMouseOver: PropTypes.func,
onMouseMove: PropTypes.func,
onTouchEnd: PropTypes.func,
onPipButtonClick: PropTypes.func,
};
module.exports = ControlBar;

View file

@ -276,6 +276,21 @@ const Player = ({ urlParams, queryParams }) => {
}
}, [player.nextVideo, handleNextVideoNavigation, profile.settings]);
const onPipEnableRequested = React.useCallback(() => {
console.log("Entering picture in picture");
const videoElement = video.containerRef.current?.querySelector('video');
videoElement.requestPictureInPicture().then(() => {
video.setPictureInPicture(true);
});
}, []);
const onPipDisableRequested = React.useCallback(() => {
console.log("Exiting picture in picture");
document.exitPictureInPicture().then(() => {
video.setPictureInPicture(false);
});
}, []);
const onVideoClick = React.useCallback(() => {
if (video.state.paused !== null) {
if (video.state.paused) {
@ -876,6 +891,7 @@ const Player = ({ urlParams, queryParams }) => {
volume={video.state.volume}
muted={video.state.muted}
playbackSpeed={video.state.playbackSpeed}
pictureInPicture={video.state.pictureInPicture}
subtitlesTracks={video.state.subtitlesTracks.concat(video.state.extraSubtitlesTracks)}
audioTracks={video.state.audioTracks}
metaItem={player.metaItem}
@ -887,6 +903,8 @@ const Player = ({ urlParams, queryParams }) => {
onNextVideoRequested={onNextVideoRequested}
onMuteRequested={onMuteRequested}
onUnmuteRequested={onUnmuteRequested}
onPipEnableRequested={onPipEnableRequested}
onPipDisableRequested={onPipDisableRequested}
onVolumeChangeRequested={onVolumeChangeRequested}
onSeekRequested={onSeekRequested}
onToggleOptionsMenu={toggleOptionsMenu}
@ -895,6 +913,7 @@ const Player = ({ urlParams, queryParams }) => {
onToggleSpeedMenu={toggleSpeedMenu}
onToggleStatisticsMenu={toggleStatisticsMenu}
onToggleSideDrawer={toggleSideDrawer}
onMouseMove={onBarMouseMove}
onMouseOver={onBarMouseMove}
onTouchEnd={onContainerMouseLeave}

View file

@ -94,6 +94,13 @@ const useVideo = () => {
dispatch({ type: 'setProp', propName: name, propValue: value });
};
const setPictureInPicture = (value) => {
setState((state) => ({
...state,
pictureInPicture: value
}));
};
const setSubtitlesTrack = (id) => {
setProp('selectedSubtitlesTrackId', id);
setProp('selectedExtraSubtitlesTrackId', null);
@ -172,6 +179,7 @@ const useVideo = () => {
addExtraSubtitlesTracks,
addLocalSubtitles,
setProp,
setPictureInPicture,
setSubtitlesTrack,
setExtraSubtitlesTrack,
};