diff --git a/package.json b/package.json
index 6d3cc7206..707ff2e32 100755
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/routes/Player/ControlBar/ControlBar.js b/src/routes/Player/ControlBar/ControlBar.js
index f70e48e12..a3aac3248 100644
--- a/src/routes/Player/ControlBar/ControlBar.js
+++ b/src/routes/Player/ControlBar/ControlBar.js
@@ -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 (
+
+
+
+ );
+ }
+
+ 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 (
+
+ );
}
render() {
return (
-
-
-
- {
- this.props.time !== null && this.props.duration !== null
- ?
-
- :
- null
- }
+ {this.renderPlayPauseButton()}
+ {this.renderSeekBar()}
+ {this.renderPlayPauseButton()}
);
}
diff --git a/src/routes/Player/ControlBar/styles.less b/src/routes/Player/ControlBar/styles.less
index d7143f674..c31560033 100644
--- a/src/routes/Player/ControlBar/styles.less
+++ b/src/routes/Player/ControlBar/styles.less
@@ -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;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 4ed45af73..ed3b9332a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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=