feat: player add video scale property

This commit is contained in:
Timothy Z. 2026-04-22 15:31:31 +03:00
parent 5db6df4fc2
commit 5fe4592be6
4 changed files with 39 additions and 2 deletions

View file

@ -39,6 +39,9 @@ const ControlBar = React.forwardRef(({
onToggleSpeedMenu, onToggleSpeedMenu,
onToggleSideDrawer, onToggleSideDrawer,
onToggleOptionsMenu, onToggleOptionsMenu,
videoScale,
videoScaleLabel,
onVideoScaleChanged,
onToggleStatisticsMenu, onToggleStatisticsMenu,
onTouchEnd, onTouchEnd,
...props ...props
@ -176,6 +179,9 @@ const ControlBar = React.forwardRef(({
: :
null null
} }
<Button className={classnames(styles['control-bar-button'], { 'disabled': videoScale === null })} title={videoScaleLabel} tabIndex={-1} onClick={onVideoScaleChanged}>
<Icon className={styles['icon']} name={'scale'} />
</Button>
<Button className={classnames(styles['control-bar-button'], { 'disabled': !stream })} tabIndex={-1} onMouseDown={onOptionsButtonMouseDown} onClick={onToggleOptionsMenu}> <Button className={classnames(styles['control-bar-button'], { 'disabled': !stream })} tabIndex={-1} onMouseDown={onOptionsButtonMouseDown} onClick={onToggleOptionsMenu}>
<Icon className={styles['icon']} name={'more-horizontal'} /> <Icon className={styles['icon']} name={'more-horizontal'} />
</Button> </Button>
@ -194,6 +200,9 @@ ControlBar.propTypes = {
volume: PropTypes.number, volume: PropTypes.number,
muted: PropTypes.bool, muted: PropTypes.bool,
playbackSpeed: PropTypes.number, playbackSpeed: PropTypes.number,
videoScale: PropTypes.string,
videoScaleLabel: PropTypes.string,
onVideoScaleChanged: PropTypes.func,
subtitlesTracks: PropTypes.array, subtitlesTracks: PropTypes.array,
audioTracks: PropTypes.array, audioTracks: PropTypes.array,
metaItem: PropTypes.object, metaItem: PropTypes.object,

View file

@ -7,7 +7,13 @@ import styles from './Indicator.less';
type Property = { type Property = {
label: string, label: string,
format: (value: number) => string, format: (value: number | string) => string,
};
const VIDEO_SCALE_LABELS: Record<string, string> = {
'contain': 'Fit',
'cover': 'Crop',
'fill': 'Stretch',
}; };
const PROPERTIES: Record<string, Property> = { const PROPERTIES: Record<string, Property> = {
@ -15,9 +21,13 @@ const PROPERTIES: Record<string, Property> = {
label: 'SUBTITLES_DELAY', label: 'SUBTITLES_DELAY',
format: (value) => `${(value / 1000).toFixed(2)}s`, format: (value) => `${(value / 1000).toFixed(2)}s`,
}, },
'videoScale': {
label: 'VIDEO_SCALE',
format: (value) => VIDEO_SCALE_LABELS[String(value)] || String(value),
},
}; };
type VideoState = Record<string, number>; type VideoState = Record<string, number | string>;
type Props = { type Props = {
className: string, className: string,

View file

@ -97,6 +97,9 @@ const Player = ({ urlParams, queryParams }) => {
const isNavigating = React.useRef(false); const isNavigating = React.useRef(false);
const VIDEO_SCALES = ['contain', 'cover', 'fill'];
const VIDEO_SCALE_LABELS = { contain: 'Fit', cover: 'Crop', fill: 'Stretch' };
const playbackSpeed = React.useRef(video.state.playbackSpeed || 1); const playbackSpeed = React.useRef(video.state.playbackSpeed || 1);
const pressTimer = React.useRef(null); const pressTimer = React.useRef(null);
const longPress = React.useRef(false); const longPress = React.useRef(false);
@ -235,6 +238,13 @@ const Player = ({ urlParams, queryParams }) => {
}, []); }, []);
const onVideoScaleChanged = React.useCallback(() => {
const currentScale = video.state.videoScale || 'contain';
const currentIndex = VIDEO_SCALES.indexOf(currentScale);
const nextScale = VIDEO_SCALES[(currentIndex + 1) % VIDEO_SCALES.length];
video.setVideoScale(nextScale);
}, [video.state.videoScale]);
const onSubtitlesTrackSelected = React.useCallback((track) => { const onSubtitlesTrackSelected = React.useCallback((track) => {
video.setSubtitlesTrack(track?.id ?? null); video.setSubtitlesTrack(track?.id ?? null);
streamStateChanged({ streamStateChanged({
@ -999,6 +1009,9 @@ const Player = ({ urlParams, queryParams }) => {
onToggleSubtitlesMenu={toggleSubtitlesMenu} onToggleSubtitlesMenu={toggleSubtitlesMenu}
onToggleAudioMenu={toggleAudioMenu} onToggleAudioMenu={toggleAudioMenu}
onToggleSpeedMenu={toggleSpeedMenu} onToggleSpeedMenu={toggleSpeedMenu}
videoScale={video.state.videoScale}
videoScaleLabel={VIDEO_SCALE_LABELS[video.state.videoScale || 'contain']}
onVideoScaleChanged={onVideoScaleChanged}
onToggleStatisticsMenu={toggleStatisticsMenu} onToggleStatisticsMenu={toggleStatisticsMenu}
onToggleSideDrawer={toggleSideDrawer} onToggleSideDrawer={toggleSideDrawer}
onMouseMove={onBarMouseMove} onMouseMove={onBarMouseMove}

View file

@ -142,6 +142,10 @@ const useVideo = () => {
setProp('extraSubtitlesOffset', offset); setProp('extraSubtitlesOffset', offset);
}; };
const setVideoScale = (scale) => {
setProp('videoScale', scale);
};
const setSubtitlesTextColor = (color) => { const setSubtitlesTextColor = (color) => {
setProp('subtitlesTextColor', color); setProp('subtitlesTextColor', color);
setProp('extraSubtitlesTextColor', color); setProp('extraSubtitlesTextColor', color);
@ -238,6 +242,7 @@ const useVideo = () => {
setSubtitlesBackgroundColor, setSubtitlesBackgroundColor,
setSubtitlesOutlineColor, setSubtitlesOutlineColor,
setExtraSubtitlesTrack, setExtraSubtitlesTrack,
setVideoScale,
}; };
}; };