mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-01-11 22:40:31 +00:00
Merge pull request #392 from Stremio/feat/player-buffered-seekbar
feat: display buffered amount on player seek bar
This commit is contained in:
commit
19e1fe4e3e
7 changed files with 34 additions and 11 deletions
|
|
@ -8,10 +8,11 @@ const useAnimationFrame = require('stremio/common/useAnimationFrame');
|
|||
const useLiveRef = require('stremio/common/useLiveRef');
|
||||
const styles = require('./styles');
|
||||
|
||||
const Slider = ({ className, value, minimumValue, maximumValue, disabled, onSlide, onComplete }) => {
|
||||
const Slider = ({ className, value, buffered, minimumValue, maximumValue, disabled, onSlide, onComplete }) => {
|
||||
const minimumValueRef = useLiveRef(minimumValue !== null && !isNaN(minimumValue) ? minimumValue : 0);
|
||||
const maximumValueRef = useLiveRef(maximumValue !== null && !isNaN(maximumValue) ? maximumValue : 100);
|
||||
const valueRef = useLiveRef(value !== null && !isNaN(value) ? Math.min(maximumValueRef.current, Math.max(minimumValueRef.current, value)) : 0);
|
||||
const bufferedRef = useLiveRef(buffered !== null && !isNaN(buffered) ? Math.min(maximumValueRef.current, Math.max(minimumValueRef.current, buffered)) : 0);
|
||||
const onSlideRef = useLiveRef(onSlide);
|
||||
const onCompleteRef = useLiveRef(onComplete);
|
||||
const sliderContainerRef = React.useRef(null);
|
||||
|
|
@ -95,13 +96,17 @@ const Slider = ({ className, value, minimumValue, maximumValue, disabled, onSlid
|
|||
};
|
||||
}, []);
|
||||
const thumbPosition = Math.max(0, Math.min(1, (valueRef.current - minimumValueRef.current) / (maximumValueRef.current - minimumValueRef.current)));
|
||||
const bufferedPosition = Math.max(0, Math.min(1, (bufferedRef.current - minimumValueRef.current) / (maximumValueRef.current - minimumValueRef.current)));
|
||||
return (
|
||||
<div ref={sliderContainerRef} className={classnames(className, styles['slider-container'], { 'disabled': disabled })} onMouseDown={onMouseDown}>
|
||||
<div className={styles['layer']}>
|
||||
<div className={styles['track']} />
|
||||
</div>
|
||||
<div className={styles['layer']}>
|
||||
<div className={styles['track-before']} style={{ width: `calc(100% * ${thumbPosition})` }} />
|
||||
<div className={styles['track-before']} style={{ width: `calc(100% * ${bufferedPosition})` }} />
|
||||
</div>
|
||||
<div className={styles['layer']}>
|
||||
<div className={styles['track-after']} style={{ width: `calc(100% * ${thumbPosition})` }} />
|
||||
</div>
|
||||
<div className={styles['layer']}>
|
||||
<svg className={styles['thumb']} style={{ marginLeft: `calc(100% * ${thumbPosition})` }} viewBox={'0 0 10 10'}>
|
||||
|
|
@ -115,6 +120,7 @@ const Slider = ({ className, value, minimumValue, maximumValue, disabled, onSlid
|
|||
Slider.propTypes = {
|
||||
className: PropTypes.string,
|
||||
value: PropTypes.number,
|
||||
buffered: PropTypes.number,
|
||||
minimumValue: PropTypes.number,
|
||||
maximumValue: PropTypes.number,
|
||||
disabled: PropTypes.bool,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ html.active-slider-within {
|
|||
cursor: pointer;
|
||||
|
||||
&:hover, &:global(.active) {
|
||||
.track-before {
|
||||
.track-after {
|
||||
background-color: @color-primary-light5;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ html.active-slider-within {
|
|||
background-color: @color-surface-dark5;
|
||||
}
|
||||
|
||||
.track-before {
|
||||
.track-after {
|
||||
background-color: @color-surface;
|
||||
}
|
||||
|
||||
|
|
@ -52,18 +52,28 @@ html.active-slider-within {
|
|||
}
|
||||
|
||||
.track {
|
||||
z-index: 0;
|
||||
flex: 1;
|
||||
height: var(--track-size);
|
||||
background-color: @color-primary-dark3;
|
||||
background-color: @color-surface-light5-20;
|
||||
}
|
||||
|
||||
.track-before {
|
||||
z-index: 1;
|
||||
flex: none;
|
||||
height: var(--track-size);
|
||||
background-color: @color-surface-light5-10;
|
||||
}
|
||||
|
||||
.track-after {
|
||||
z-index: 2;
|
||||
flex: none;
|
||||
height: var(--track-size);
|
||||
background-color: @color-primary-light3;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
z-index: 3;
|
||||
flex: none;
|
||||
width: var(--thumb-size);
|
||||
height: var(--thumb-size);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const ControlBar = ({
|
|||
paused,
|
||||
time,
|
||||
duration,
|
||||
buffered,
|
||||
volume,
|
||||
muted,
|
||||
playbackSpeed,
|
||||
|
|
@ -140,6 +141,7 @@ const ControlBar = ({
|
|||
className={styles['seek-bar']}
|
||||
time={time}
|
||||
duration={duration}
|
||||
buffered={buffered}
|
||||
onSeekRequested={onSeekRequested}
|
||||
/>
|
||||
<div className={styles['control-bar-buttons-container']}>
|
||||
|
|
@ -213,6 +215,7 @@ ControlBar.propTypes = {
|
|||
paused: PropTypes.bool,
|
||||
time: PropTypes.number,
|
||||
duration: PropTypes.number,
|
||||
buffered: PropTypes.number,
|
||||
volume: PropTypes.number,
|
||||
muted: PropTypes.bool,
|
||||
playbackSpeed: PropTypes.number,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const { Slider } = require('stremio/common');
|
|||
const formatTime = require('./formatTime');
|
||||
const styles = require('./styles');
|
||||
|
||||
const SeekBar = ({ className, time, duration, onSeekRequested }) => {
|
||||
const SeekBar = ({ className, time, duration, buffered, onSeekRequested }) => {
|
||||
const disabled = time === null || isNaN(time) || duration === null || isNaN(duration);
|
||||
const routeFocused = useRouteFocused();
|
||||
const [seekTime, setSeekTime] = React.useState(null);
|
||||
|
|
@ -49,6 +49,7 @@ const SeekBar = ({ className, time, duration, onSeekRequested }) => {
|
|||
:
|
||||
0
|
||||
}
|
||||
buffered={buffered}
|
||||
minimumValue={0}
|
||||
maximumValue={duration}
|
||||
disabled={disabled}
|
||||
|
|
@ -64,6 +65,7 @@ SeekBar.propTypes = {
|
|||
className: PropTypes.string,
|
||||
time: PropTypes.number,
|
||||
duration: PropTypes.number,
|
||||
buffered: PropTypes.number,
|
||||
onSeekRequested: PropTypes.func
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less';
|
||||
|
||||
:import('~stremio/common/Slider/styles.less') {
|
||||
slider-track-before: track-before;
|
||||
slider-track-after: track-after;
|
||||
slider-thumb: thumb;
|
||||
}
|
||||
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
&:hover {
|
||||
.slider:not(:global(.disabled)) {
|
||||
.slider-track-before {
|
||||
.slider-track-after {
|
||||
transition: background-color 0s 100ms;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
:import('~stremio/common/Slider/styles.less') {
|
||||
slider-track: track;
|
||||
slider-track-before: track-before;
|
||||
slider-track-after: track-after;
|
||||
}
|
||||
|
||||
.volume-slider:not(:global(.disabled)) {
|
||||
|
|
@ -12,12 +12,12 @@
|
|||
background-color: @color-surface-dark5;
|
||||
}
|
||||
|
||||
.slider-track-before {
|
||||
.slider-track-after {
|
||||
background-color: @color-surface-light3;
|
||||
}
|
||||
|
||||
&:hover, &:global(.active) {
|
||||
.slider-track-before {
|
||||
.slider-track-after {
|
||||
background-color: @color-surface-light5;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
time: null,
|
||||
duration: null,
|
||||
buffering: null,
|
||||
buffered: null,
|
||||
volume: null,
|
||||
muted: null,
|
||||
playbackSpeed: null,
|
||||
|
|
@ -668,6 +669,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
paused={videoState.paused}
|
||||
time={videoState.time}
|
||||
duration={videoState.duration}
|
||||
buffered={videoState.buffered}
|
||||
volume={videoState.volume}
|
||||
muted={videoState.muted}
|
||||
playbackSpeed={videoState.playbackSpeed}
|
||||
|
|
|
|||
Loading…
Reference in a new issue