mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
custom seek bar implemented
This commit is contained in:
parent
a8ff78e0f2
commit
5db81dc1a0
4 changed files with 131 additions and 29 deletions
|
|
@ -14,6 +14,7 @@
|
|||
"dependencies": {
|
||||
"classnames": "2.2.6",
|
||||
"events": "1.1.1",
|
||||
"lodash.debounce": "4.0.8",
|
||||
"prop-types": "15.6.2",
|
||||
"react": "16.6.0",
|
||||
"react-dom": "16.6.0",
|
||||
|
|
|
|||
|
|
@ -1,38 +1,97 @@
|
|||
import React, { Component } from 'react';
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import debounce from 'lodash.debounce';
|
||||
import Icon from 'stremio-icons/dom';
|
||||
import styles from './styles';
|
||||
|
||||
class ControlBar extends Component {
|
||||
onSeekRequested = (event) => {
|
||||
this.props.seek(event.target.value);
|
||||
class ControlBar extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
seekTime: -1
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.resetSeekTime.cancel();
|
||||
}
|
||||
|
||||
resetSeekTime = debounce(() => {
|
||||
this.setState({ seekTime: -1 });
|
||||
}, 3000)
|
||||
|
||||
calculateSeekTime = (mouseX, seekBarElement) => {
|
||||
const { left, width } = seekBarElement.getBoundingClientRect();
|
||||
const position = Math.min(Math.max(mouseX - left, 0), width);
|
||||
const seekTime = Math.floor((position / width) * this.props.duration);
|
||||
return seekTime;
|
||||
}
|
||||
|
||||
onStartSliding = ({ currentTarget, clientX, button }) => {
|
||||
if (button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mousemove = ({ clientX }) => {
|
||||
this.setState({ seekTime: this.calculateSeekTime(clientX, currentTarget) });
|
||||
};
|
||||
const mouseup = ({ clientX }) => {
|
||||
window.removeEventListener('mousemove', mousemove);
|
||||
window.removeEventListener('mouseup', mouseup);
|
||||
document.body.style['pointer-events'] = 'initial';
|
||||
currentTarget.classList.remove(styles['active']);
|
||||
const seekTime = this.calculateSeekTime(clientX, currentTarget);
|
||||
this.props.seek(seekTime);
|
||||
this.resetSeekTime();
|
||||
};
|
||||
|
||||
window.addEventListener('mousemove', mousemove);
|
||||
window.addEventListener('mouseup', mouseup);
|
||||
document.body.style['pointer-events'] = 'none';
|
||||
currentTarget.classList.add(styles['active']);
|
||||
this.setState({ seekTime: this.calculateSeekTime(clientX, currentTarget) });
|
||||
this.resetSeekTime.cancel();
|
||||
}
|
||||
|
||||
renderPlayPauseButton() {
|
||||
return (
|
||||
<div className={styles['button']} onClick={this.props.paused ? this.props.play : this.props.pause}>
|
||||
<Icon
|
||||
className={styles['icon']}
|
||||
icon={this.props.paused ? 'ic_play' : 'ic_pause'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderSeekBar() {
|
||||
if (this.props.time === null || this.props.duration === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const thumbPosition = this.state.seekTime !== -1 ?
|
||||
this.state.seekTime / this.props.duration
|
||||
:
|
||||
this.props.time / this.props.duration;
|
||||
|
||||
return (
|
||||
<div className={styles['seek-bar']} onMouseDown={this.onStartSliding}>
|
||||
<div className={styles['seek-line']} />
|
||||
<div className={styles['thumb-container']} style={{ left: `calc(100% * ${thumbPosition})` }}>
|
||||
<div className={styles['thumb']} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={classnames(this.props.className, styles['root-container'])}>
|
||||
<div className={styles['button']} onClick={this.props.paused ? this.props.play : this.props.pause}>
|
||||
<Icon
|
||||
className={styles['icon']}
|
||||
icon={this.props.paused ? 'ic_play' : 'ic_pause'}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
this.props.time !== null && this.props.duration !== null
|
||||
?
|
||||
<input
|
||||
className={styles['seek-bar']}
|
||||
type={'range'}
|
||||
step={1000}
|
||||
min={0}
|
||||
max={this.props.duration}
|
||||
value={this.props.time}
|
||||
onChange={this.onSeekRequested}
|
||||
/>
|
||||
:
|
||||
null
|
||||
}
|
||||
{this.renderPlayPauseButton()}
|
||||
{this.renderSeekBar()}
|
||||
{this.renderPlayPauseButton()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
@import 'stremio-colors';
|
||||
|
||||
@control-bar-height: 56px;
|
||||
@control-bar-height: 52px;
|
||||
|
||||
.root-container {
|
||||
height: @control-bar-height;
|
||||
top: initial !important;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: @colorprimlight60;
|
||||
align-items: center;
|
||||
|
||||
.button {
|
||||
height: @control-bar-height;
|
||||
|
|
@ -24,11 +24,53 @@
|
|||
.icon {
|
||||
width: 66%;
|
||||
height: 66%;
|
||||
fill: @colorwhite;
|
||||
}
|
||||
}
|
||||
|
||||
.seek-bar {
|
||||
flex: 1
|
||||
height: round((@control-bar-height * 0.5));
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.seek-line {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: round((@control-bar-height * 0.2));
|
||||
height: round((@control-bar-height * 0.1));
|
||||
background-color: @colorprim80;
|
||||
}
|
||||
|
||||
.thumb-container {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: round((@control-bar-height * 0.5));
|
||||
height: round((@control-bar-height * 0.5));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.thumb {
|
||||
width: round((@control-bar-height * 0.4));
|
||||
height: round((@control-bar-height * 0.4));
|
||||
border-radius: 50%;
|
||||
background-color: @colorprimlight;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: @colorprimlight60;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.thumb-container {
|
||||
background-color: @colorprimlight60;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4638,7 +4638,7 @@ locate-path@^3.0.0:
|
|||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
lodash.debounce@^4.0.8:
|
||||
lodash.debounce@4.0.8, lodash.debounce@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||
|
|
|
|||
Loading…
Reference in a new issue