Skip to content

Commit

Permalink
fix(FEC-7931): UI flickering on hovering the bottom bar (#182)
Browse files Browse the repository at this point in the history
Enable smart hovering.
  • Loading branch information
Dan Ziv committed Feb 25, 2018
1 parent 240e69a commit 446fa02
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 34 deletions.
27 changes: 19 additions & 8 deletions src/components/bottom-bar/bottom-bar.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//@flow
import style from '../../styles/style.scss';
import {h, Component} from 'preact';
import {bindActions} from '../../utils/bind-actions';
import {actions} from '../../reducers/shell';
import {connect} from 'preact-redux';

/**
* BottomBar component
*
* @class BottomBar
* @example <BottomBar>...</BottomBar>
* @extends {Component}
*/
@connect(null, bindActions(actions))
/**
* BottomBar component
*
* @class BottomBar
* @example <BottomBar>...</BottomBar>
* @extends {Component}
*/
class BottomBar extends Component {
/**
* render component
Expand All @@ -19,7 +23,14 @@ class BottomBar extends Component {
*/
render(props: any): React$Element<any> {
return (
<div className={style.bottomBar}>{props.children}</div>
<div className={style.bottomBar}
onMouseOver={() => {
this.props.updateBottomBarHoverActive(true);
this.props.updatePlayerHoverState(true);
}}
onMouseLeave={() => this.props.updateBottomBarHoverActive(false)}>
{props.children}
</div>
)
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/components/language/language.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {h} from 'preact';
import {Localizer, Text} from 'preact-i18n';
import {connect} from 'preact-redux';
import {bindActions} from '../../utils/bind-actions';
import {actions} from '../../reducers/cvaa';
import {actions as cvaaActions} from '../../reducers/cvaa';
import {actions as langActions} from '../../reducers/language';
import BaseComponent from '../base';
import SmartContainer from '../smart-container';
import SmartContainerItem from '../smart-container/smart-container-item';
Expand All @@ -25,7 +26,7 @@ const mapStateToProps = state => ({
isMobile: state.shell.isMobile
});

@connect(mapStateToProps, bindActions(actions))
@connect(mapStateToProps, bindActions(Object.assign(langActions, cvaaActions)))
/**
* LanguageControl component
*
Expand Down Expand Up @@ -54,6 +55,7 @@ class LanguageControl extends BaseComponent {
* @memberof LanguageControl
*/
componentWillMount() {
this.props.updateLanguageMenuOpen(false);
this.setState({smartContainerOpen: false});
}

Expand Down Expand Up @@ -95,6 +97,7 @@ class LanguageControl extends BaseComponent {
if (e.target.classList.contains('overlay-action')) {
e.stopPropagation();
}
this.props.updateLanguageMenuOpen(false);
this.setState({smartContainerOpen: false});
}
}
Expand All @@ -106,6 +109,7 @@ class LanguageControl extends BaseComponent {
* @memberof LanguageControl
*/
onControlButtonClick(): void {
this.props.updateLanguageMenuOpen(!this.state.smartContainerOpen);
this.setState({smartContainerOpen: !this.state.smartContainerOpen});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SeekBarPlaybackContainer extends BaseComponent {
changeCurrentTime={time => this.player.currentTime = time}
playerPoster={this.props.poster}
updateSeekbarDraggingStatus={data => this.props.updateSeekbarDraggingStatus(data)}
updateSeekbarHoverActive={data => this.props.updateSeekbarHoverActive(data)}
updateCurrentTime={data => this.props.updateCurrentTime(data)}
currentTime={this.props.currentTime}
duration={this.props.duration}
Expand Down
5 changes: 3 additions & 2 deletions src/components/seekbar/seekbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {KeyMap} from "../../utils/key-map";
*/
class SeekBarControl extends Component {
state: Object;
framePreviewImg: string;
_seekBarElement: HTMLElement;
_framePreviewElement: HTMLElement;
_timeBubbleElement: HTMLElement;
Expand Down Expand Up @@ -279,7 +278,7 @@ class SeekBarControl extends Component {
if (this.props.player.duration > 0 && this.props.player.buffered.length > 0) {
const buffered = this.props.player.isLive() ? this.props.player.buffered.end(0) - this.props.player.getStartTimeOfDvrWindow() : this.props.player.buffered.end(0);
const bufferedPercent = (buffered / this.props.player.duration) * 100;
return bufferedPercent < 100 ? bufferedPercent : 100;
return bufferedPercent < 100 ? bufferedPercent : 100;
}
return 0;
}
Expand Down Expand Up @@ -431,6 +430,8 @@ class SeekBarControl extends Component {
aria-valuenow={Math.round(this.props.currentTime)}
aria-valuetext={`${toHHMMSS(this.props.currentTime)} of ${toHHMMSS(this.props.duration)}`}
onClick={e => this.onTap(e)}
onMouseOver={() => this.props.updateSeekbarHoverActive(true)}
onMouseLeave={() => this.props.updateSeekbarHoverActive(false)}
onMouseMove={e => this.onSeekbarMouseMove(e)}
onMouseDown={e => this.onSeekbarMouseDown(e)}
onTouchStart={e => this.onSeekbarTouchStart(e)}
Expand Down
3 changes: 3 additions & 0 deletions src/components/settings/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class SettingsControl extends BaseComponent {
* @memberof SettingsControl
*/
componentWillMount() {
this.props.updateSettingsMenuOpen(false);
this.setState({smartContainerOpen: false});
}

Expand Down Expand Up @@ -84,6 +85,7 @@ class SettingsControl extends BaseComponent {
if (e.target.classList.contains(style.overlayPlay)) {
e.stopPropagation();
}
this.props.updateSettingsMenuOpen(false);
this.setState({smartContainerOpen: false});
}
}
Expand All @@ -95,6 +97,7 @@ class SettingsControl extends BaseComponent {
* @memberof SettingsControl
*/
onControlButtonClick(): void {
this.props.updateSettingsMenuOpen(!this.state.smartContainerOpen);
this.setState({smartContainerOpen: !this.state.smartContainerOpen});
}

Expand Down
36 changes: 27 additions & 9 deletions src/components/shell/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const mapStateToProps = state => ({
playerHover: state.shell.playerHover,
playerNav: state.shell.playerNav,
seekbarDraggingActive: state.seekbar.draggingActive,
seekbarHoverActive: state.seekbar.hoverActive,
bottomBarHoverActive: state.shell.bottomBarHoverActive,
volumeHoverActive: state.volume.hover,
languageMenuOpen: state.language.menuOpen,
settingsMenuOpen: state.settings.menuOpen,
adBreak: state.engine.adBreak
});

Expand Down Expand Up @@ -71,7 +76,9 @@ class Shell extends BaseComponent {
this.setState({nav: false});
this.props.updatePlayerNavState(false);
}
this._showAndHideControlBar();
if (!this.props.bottomBarHoverActive) {
this._updatePlayerHoverState();
}
}

/**
Expand All @@ -94,10 +101,7 @@ class Shell extends BaseComponent {
* @memberof Shell
*/
onMouseMove(): void {
if (!this.state.hover) {
this.setState({hover: true});
this.props.updatePlayerHoverState(true);
}
this._updatePlayerHoverState();
}

/**
Expand Down Expand Up @@ -158,15 +162,15 @@ class Shell extends BaseComponent {
if (this.player.env.device.type) {
this.props.updatePlayerHoverState(true);
}
this._showAndHideControlBar();
this._updatePlayerHoverState();
}

/**
* show the control bar for few seconds and then hide it
* updates the player hover state
* @returns {void}
* @memberof Shell
*/
_showAndHideControlBar(): void {
_updatePlayerHoverState(): void {
if (!this.state.hover) {
this.props.updatePlayerHoverState(true);
this.setState({hover: true});
Expand All @@ -175,13 +179,27 @@ class Shell extends BaseComponent {
clearTimeout(this._hoverTimeout);
}
this._hoverTimeout = setTimeout(() => {
if (!this.props.seekbarDraggingActive) {
if (this._canEndHoverState()) {
this.props.updatePlayerHoverState(false);
this.setState({hover: false});
}
}, this.props._hoverTimeout || CONTROL_BAR_HOVER_DEFAULT_TIMEOUT);
}

/**
* checks if hover state can be ended based on other components states
* @returns {boolean} - if hover state can be ended
* @private
* @memberof Shell
*/
_canEndHoverState(): boolean {
return !this.props.seekbarDraggingActive
&& !this.props.seekbarHoverActive
&& !this.props.volumeHoverActive
&& !this.props.languageMenuOpen
&& !this.props.settingsMenuOpen;
}

/**
* render component
*
Expand Down
10 changes: 8 additions & 2 deletions src/components/volume/volume.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,14 @@ class VolumeControl extends BaseComponent {
<div
ref={c => this._volumeControlElement = c}
className={controlButtonClass.join(' ')}
onMouseOver={() => this.setState({hover: true})}
onMouseOut={() => this.setState({hover: false})}>
onMouseOver={() => {
this.props.updateVolumeHover(true);
this.setState({hover: true});
}}
onMouseOut={() => {
this.props.updateVolumeHover(false);
this.setState({hover: false});
}}>
<button tabIndex="0"
aria-label='Volume'
className={style.controlButton}
Expand Down
25 changes: 25 additions & 0 deletions src/reducers/language.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//@flow
export const types = {
UPDATE_MENU_OPEN: 'language/UPDATE_MENU_OPEN'
};

export const initialState = {
menuOpen: false
};

export default (state: Object = initialState, action: Object) => {
switch (action.type) {
case types.UPDATE_MENU_OPEN:
return {
...state,
menuOpen: action.menuOpen
};

default:
return state;
}
}

export const actions = {
updateLanguageMenuOpen: (menuOpen: boolean) => ({type: types.UPDATE_MENU_OPEN, menuOpen})
};
16 changes: 14 additions & 2 deletions src/reducers/seekbar.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//@flow
export const types = {
UPDATE_SEEKBAR_DRAGGING_STATUS: 'seekbar/UPDATE_SEEKBAR_DRAGGING_STATUS',
UPDATE_SEEKBAR_HOVER_ACTIVE: 'seekbar/UPDATE_SEEKBAR_HOVER_ACTIVE',
UPDATE_CURRENT_TIME: 'seekbar/UPDATE_CURRENT_TIME',
UPDATE_DURATION: 'seekbar/UPDATE_DURATION'
UPDATE_DURATION: 'seekbar/UPDATE_DURATION',
};

export const initialState = {
currentTime: 0,
duration: 0,
draggingActive: false
draggingActive: false,
hoverActive: false
};

export default (state: Object = initialState, action: Object) => {
Expand All @@ -19,6 +21,12 @@ export default (state: Object = initialState, action: Object) => {
draggingActive: action.draggingActive
};

case types.UPDATE_SEEKBAR_HOVER_ACTIVE:
return {
...state,
hoverActive: action.hoverActive
};

case types.UPDATE_CURRENT_TIME:
return {
...state,
Expand All @@ -41,6 +49,10 @@ export const actions = {
type: types.UPDATE_SEEKBAR_DRAGGING_STATUS,
draggingActive
}),
updateSeekbarHoverActive: (hoverActive: boolean) => ({
type: types.UPDATE_SEEKBAR_HOVER_ACTIVE,
hoverActive
}),
updateDuration: (duration: number) => ({type: types.UPDATE_DURATION, duration}),
updateCurrentTime: (currentTime: number) => ({type: types.UPDATE_CURRENT_TIME, currentTime})
};
15 changes: 12 additions & 3 deletions src/reducers/settings.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//@flow
export const types = {
UPDATE_QUALITY: 'settings/UPDATE_QUALITY',
UPDATE_SPEED: 'settings/UPDATE_SPEED'
UPDATE_SPEED: 'settings/UPDATE_SPEED',
UPDATE_MENU_OPEN: 'settings/UPDATE_MENU_OPEN'
};

export const initialState = {
quality: 1,
speed: 2
speed: 2,
menuOpen: false
};

export default (state: Object = initialState, action: Object) => {
Expand All @@ -23,12 +25,19 @@ export default (state: Object = initialState, action: Object) => {
speed: action.speed
};

case types.UPDATE_MENU_OPEN:
return {
...state,
menuOpen: action.menuOpen
};

default:
return state;
}
}

export const actions = {
updateQuality: (quality: string) => ({type: types.UPDATE_QUALITY, quality}),
updateSpeed: (speed: string) => ({type: types.UPDATE_SPEED, speed})
updateSpeed: (speed: string) => ({type: types.UPDATE_SPEED, speed}),
updateSettingsMenuOpen: (menuOpen: boolean) => ({type: types.UPDATE_MENU_OPEN, menuOpen})
};
12 changes: 10 additions & 2 deletions src/reducers/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export const types = {
UPDATE_PLAYER_CLIENT_RECT: 'shell/UPDATE_PLAYER_CLIENT_RECT',
UPDATE_DOCUMENT_WIDTH: 'shell/UPDATE_DOCUMENT_WIDTH',
UPDATE_PLAYER_HOVER_STATE: 'shell/UPDATE_PLAYER_HOVER_STATE',
UPDATE_PLAYER_NAV_STATE: 'shell/UPDATE_PLAYER_NAV_STATE'
UPDATE_PLAYER_NAV_STATE: 'shell/UPDATE_PLAYER_NAV_STATE',
UPDATE_BOTTOM_BAR_HOVER_ACTIVE: 'shell/UPDATE_BOTTOM_BAR_HOVER_ACTIVE'
};

export const initialState = {
Expand Down Expand Up @@ -69,6 +70,12 @@ export default (state: Object = initialState, action: Object) => {
playerNav: action.nav
};

case types.UPDATE_BOTTOM_BAR_HOVER_ACTIVE:
return {
...state,
bottomBarHoverActive: action.active
};

default:
return state;
}
Expand All @@ -82,5 +89,6 @@ export const actions = {
updatePlayerClientRect: (playerClientRect: Object) => ({type: types.UPDATE_PLAYER_CLIENT_RECT, playerClientRect}),
updateDocumentWidth: (documentWidth: number) => ({type: types.UPDATE_DOCUMENT_WIDTH, documentWidth}),
updatePlayerHoverState: (hover: boolean) => ({type: types.UPDATE_PLAYER_HOVER_STATE, hover}),
updatePlayerNavState: (nav: boolean) => ({type: types.UPDATE_PLAYER_NAV_STATE, nav})
updatePlayerNavState: (nav: boolean) => ({type: types.UPDATE_PLAYER_NAV_STATE, nav}),
updateBottomBarHoverActive: (active: boolean) => ({type: types.UPDATE_BOTTOM_BAR_HOVER_ACTIVE, active})
};

0 comments on commit 446fa02

Please sign in to comment.