From 5db81dc1a054607900b2d40595f6078526590975 Mon Sep 17 00:00:00 2001 From: NikolaBorislavovHristov Date: Mon, 12 Nov 2018 13:38:20 +0200 Subject: [PATCH] custom seek bar implemented --- package.json | 1 + src/routes/Player/ControlBar/ControlBar.js | 109 ++++++++++++++++----- src/routes/Player/ControlBar/styles.less | 48 ++++++++- yarn.lock | 2 +- 4 files changed, 131 insertions(+), 29 deletions(-) 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=