control bar styles refactored

This commit is contained in:
NikolaBorislavovHristov 2018-12-07 14:15:16 +02:00
parent 99104f416f
commit f41c6cd69b
3 changed files with 84 additions and 234 deletions

View file

@ -1,10 +1,10 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import debounce from 'lodash.debounce';
import Icon from 'stremio-icons/dom';
import { Slider, Popup } from 'stremio-common';
import colors from 'stremio-colors';
import { Popup } from 'stremio-common';
import TimeSlider from './TimeSlider';
import VolumeSlider from './VolumeSlider';
import styles from './styles';
class ControlBar extends Component {
@ -12,9 +12,6 @@ class ControlBar extends Component {
super(props);
this.state = {
time: null,
volume: null,
volumePopupOpen: false,
sharePopupOpen: false
};
}
@ -25,69 +22,21 @@ class ControlBar extends Component {
nextProps.time !== this.props.time ||
nextProps.duration !== this.props.duration ||
nextProps.volume !== this.props.volume ||
nextState.time !== this.state.time ||
nextState.volume !== this.state.volume ||
nextState.volumePopupOpen !== this.state.volumePopupOpen ||
nextState.sharePopupOpen !== this.state.sharePopupOpen;
}
componentWillUnmount() {
this.resetTime.cancel();
this.resetVolume.cancel();
}
resetTime = debounce(() => {
this.setState({ time: null });
}, 1500)
resetVolume = debounce(() => {
this.setState({ volume: null });
}, 100)
onTimeSliderSlide = (time) => {
this.resetTime.cancel();
this.setState({ time });
}
onTimeSliderComplete = (time) => {
this.setState({ time });
setTime = (time) => {
this.props.setTime(time);
this.resetTime();
}
onTimeSliderCancel = () => {
this.resetTime.cancel();
this.setState({ time: null });
}
onVolumeSliderSlide = (volume) => {
this.resetVolume.cancel();
this.setState({ volume });
}
onVolumeSliderComplete = (volume) => {
this.setState({ volume });
setVolume = (volume) => {
this.props.setVolume(volume);
this.resetVolume();
}
onVolumeSliderCancel = () => {
this.resetVolume.cancel();
this.setState({ volume: null });
}
onPlayPauseButtonClick = () => {
this.props.paused ? this.props.play() : this.props.pause();
}
onVolumePopupOpen = () => {
this.setState({ volumePopupOpen: true });
}
onVolumePopupClose = () => {
this.setState({ volumePopupOpen: false });
}
onSharePopupOpen = () => {
this.setState({ sharePopupOpen: true });
}
@ -96,31 +45,34 @@ class ControlBar extends Component {
this.setState({ sharePopupOpen: false });
}
formatTime = (time) => {
const hours = ('0' + Math.floor((time / (1000 * 60 * 60)) % 24)).slice(-2);
const minutes = ('0' + Math.floor((time / (1000 * 60)) % 60)).slice(-2);
const seconds = ('0' + Math.floor((time / 1000) % 60)).slice(-2);
return `${hours}:${minutes}:${seconds}`;
renderShareButton() {
return (
<Popup className={styles['popup-container']} border={true} onOpen={this.onSharePopupOpen} onClose={this.onSharePopupClose}>
<Popup.Label>
<div className={classnames(styles['control-bar-button'], { [styles['active']]: this.state.sharePopupOpen })}>
<Icon className={styles['icon']} icon={'ic_share'} />
</div>
</Popup.Label>
<Popup.Menu>
<div className={classnames(styles['popup-content'], styles['share-popup-content'])} />
</Popup.Menu>
</Popup>
);
}
renderTimeSlider() {
if (this.props.time === null || this.props.duration === null) {
renderVolumeButton() {
if (this.props.volume === null) {
return null;
}
const time = this.state.time !== null ? this.state.time : this.props.time;
const icon = this.props.volume === 0 ? 'ic_volume0' :
this.props.volume < 50 ? 'ic_volume1' :
this.props.volume < 100 ? 'ic_volume2' :
'ic_volume3';
return (
<Slider
containerClassName={styles['time-slider']}
thumbClassName={styles['time-thumb']}
value={time}
minimumValue={0}
maximumValue={this.props.duration}
orientation={'horizontal'}
onSlide={this.onTimeSliderSlide}
onComplete={this.onTimeSliderComplete}
onCancel={this.onTimeSliderCancel}
/>
<div className={styles['control-bar-button']}>
<Icon className={styles['icon']} icon={icon} />
</div>
);
}
@ -131,89 +83,34 @@ class ControlBar extends Component {
const icon = this.props.paused ? 'ic_play' : 'ic_pause';
return (
<div className={styles['button']} onClick={this.onPlayPauseButtonClick}>
<div className={styles['control-bar-button']} onClick={this.onPlayPauseButtonClick}>
<Icon className={styles['icon']} icon={icon} />
</div>
);
}
renderTimeLabel() {
if (this.props.time === null || this.props.duration === null) {
return null;
}
const time = this.state.time !== null ? this.state.time : this.props.time;
return (
<div className={styles['time-label']}>{this.formatTime(time)} / {this.formatTime(this.props.duration)}</div>
);
}
renderVolumeButton() {
if (this.props.volume === null) {
return null;
}
const volume = this.state.volume !== null ? this.state.volume : this.props.volume;
const icon = volume === 0 ? 'ic_volume0' :
volume < 50 ? 'ic_volume1' :
volume < 100 ? 'ic_volume2' :
'ic_volume3';
return (
<Popup borderColor={colors.primlight} onOpen={this.onVolumePopupOpen} onClose={this.onVolumePopupClose}>
<Popup.Label>
<div className={classnames(styles['button'], { [styles['active']]: this.state.volumePopupOpen })}>
<Icon className={styles['icon']} icon={icon} />
</div>
</Popup.Label>
<Popup.Menu>
<div className={classnames(styles['popup-container'], styles['volume-popup-container'])}>
<Slider
containerClassName={styles['volume-slider']}
thumbClassName={styles['volume-thumb']}
value={volume}
minimumValue={0}
maximumValue={100}
orientation={'vertical'}
onSlide={this.onVolumeSliderSlide}
onComplete={this.onVolumeSliderComplete}
onCancel={this.onVolumeSliderCancel}
/>
</div>
</Popup.Menu>
</Popup>
);
}
renderShareButton() {
return (
<Popup borderColor={colors.primlight} onOpen={this.onSharePopupOpen} onClose={this.onSharePopupClose}>
<Popup.Label>
<div className={classnames(styles['button'], { [styles['active']]: this.state.sharePopupOpen })}>
<Icon className={styles['icon']} icon={'ic_share'} />
</div>
</Popup.Label>
<Popup.Menu>
<div className={classnames(styles['popup-container'], styles['share-popup-container'])} />
</Popup.Menu>
</Popup>
);
}
render() {
if (['paused', 'time', 'duration', 'volume'].every(propName => this.props[propName] === null)) {
if (['paused', 'time', 'duration', 'volume', 'subtitles'].every(propName => this.props[propName] === null)) {
return null;
}
return (
<div className={classnames(styles['control-bar-container'], this.props.className)}>
{this.renderTimeSlider()}
<div className={styles['buttons-bar-container']}>
<TimeSlider
className={styles['time-slider']}
time={this.props.time}
duration={this.props.duration}
setTime={this.setTime}
/>
<div className={styles['control-bar-buttons-container']}>
{this.renderPlayPauseButton()}
<div className={styles['separator']} />
{this.renderTimeLabel()}
<div className={styles['spacing']} />
{this.renderVolumeButton()}
<VolumeSlider
className={styles['volume-slider']}
volume={this.props.volume}
setVolume={this.setVolume}
/>
<div className={styles['flex-spacing']} />
{this.renderShareButton()}
</div>
</div>
@ -227,6 +124,11 @@ ControlBar.propTypes = {
time: PropTypes.number,
duration: PropTypes.number,
volume: PropTypes.number,
subtitles: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
language: PropTypes.string.isRequired
})),
play: PropTypes.func.isRequired,
pause: PropTypes.func.isRequired,
setTime: PropTypes.func.isRequired,

View file

@ -35,9 +35,9 @@ class TimeSlider extends Component {
}
onComplete = (time) => {
this.resetTimeDebounced();
this.setState({ time });
this.props.setTime(time);
this.resetTimeDebounced();
}
onCancel = () => {

View file

@ -1,127 +1,75 @@
@import 'stremio-colors';
@time-slider-height: 26px;
@buttons-bar-height: 58px;
.control-bar-container {
height: (@time-slider-height + @buttons-bar-height);
.time-slider {
height: @time-slider-height;
.time-thumb {
width: @time-slider-height;
height: @time-slider-height;
}
}
.buttons-bar-container {
height: @buttons-bar-height;
.button {
height: @buttons-bar-height;
width: @buttons-bar-height;
.icon {
width: floor((@buttons-bar-height * 0.6));
height: floor((@buttons-bar-height * 0.6));
}
&.active {
padding-top: 1px;
}
}
.time-label {
font-size: 16px;
}
.separator {
width: 1px;
margin-left: floor((@buttons-bar-height * 0.25));
margin-right: floor((@buttons-bar-height * 0.25));
}
}
}
.popup-container {
&.volume-popup-container {
padding: ceil((@buttons-bar-height * 0.4)) 0;
width: @buttons-bar-height;
.volume-slider {
width: floor((@buttons-bar-height * 0.4));
height: floor((@buttons-bar-height * 3));
.volume-thumb {
width: floor((@buttons-bar-height * 0.4));
height: floor((@buttons-bar-height * 0.4));
}
}
}
&.share-popup-container {
width: (@buttons-bar-height * 5);
height: (@buttons-bar-height * 3);
}
.control-bar-container, .popup-container {
--control-bar-button-height: 60px;
}
.control-bar-container {
top: initial !important;
padding: 0 2%;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
.buttons-bar-container {
.time-slider {
--time-slider-thumb-size: calc(var(--control-bar-button-height) * 0.4);
height: var(--time-slider-thumb-size);
width: 100%;
}
.control-bar-buttons-container {
height: var(--control-bar-button-height);
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
.button {
.control-bar-button {
width: var(--control-bar-button-height);
height: var(--control-bar-button-height);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.icon {
fill: @colorwhite80;
width: 60%;
height: 60%;
fill: var(--color-surfacelight);
overflow: visible;
}
&.active {
background-color: @colorbgmain;
background-color: var(--color-backgrounddarker);
.icon {
fill: @colorwhite;
fill: var(--color-surfacelighter);
}
}
&:hover {
.icon {
fill: @colorwhite;
fill: var(--color-surfacelighter);
}
}
}
.separator {
height: 70%;
background-color: @colorneutrallight80;
.volume-slider {
--volume-slider-thumb-size: calc(var(--control-bar-button-height) * 0.3);
height: var(--volume-slider-thumb-size);
width: calc(var(--control-bar-button-height) * 3);
}
.time-label {
color: @colorwhite;
}
.spacing {
.flex-spacing {
flex: 1
}
}
}
.popup-container {
display: flex;
justify-content: center;
align-items: center;
background-color: @colorbgmain;
--border-color: var(--color-primarylight);
.popup-content {
background-color: var(--color-backgrounddark);
&.share-popup-content {
width: calc(var(--control-bar-button-height) * 5);
height: calc(var(--control-bar-button-height) * 3);
}
}
}