From bf03e73876e9dcf75af16074341f2db832c04395 Mon Sep 17 00:00:00 2001 From: virtuacoplenny Date: Fri, 1 Sep 2017 14:40:05 -0700 Subject: [PATCH] feat(filmstrip): show thumbnails with toolbar and on hover (#1944) * feat(filmstrip): show thumbnails with toolbar and on hover * squash: reduce verbosity of logic for when to display * squash: remove check for fake participant Before fake participant (youtube video) would make the filmstrip always displayed. However, youtube videos already dock the toolbar, so filmstrip will remain displayed, so the check is redundant. * squash: change mouse hover listener targets --- react/features/filmstrip/actionTypes.js | 13 ++- react/features/filmstrip/actions.js | 18 ++++ .../filmstrip/components/Filmstrip.web.js | 98 ++++++++++++++++++- react/features/filmstrip/functions.js | 21 ++-- react/features/filmstrip/reducer.js | 7 ++ 5 files changed, 144 insertions(+), 13 deletions(-) diff --git a/react/features/filmstrip/actionTypes.js b/react/features/filmstrip/actionTypes.js index bd70e3e18..9bbc166c7 100644 --- a/react/features/filmstrip/actionTypes.js +++ b/react/features/filmstrip/actionTypes.js @@ -1,5 +1,16 @@ /** - * The type of action sets the visibility of the entire filmstrip; + * The type of the action which sets whether or not the filmstrip is being + * hovered with the cursor. + * + * { + * type: SET_FILMSTRIP_HOVERED, + * hovered: boolean + * } + */ +export const SET_FILMSTRIP_HOVERED = Symbol('SET_FILMSTRIP_HOVERED'); + +/** + * The type of action sets the visibility of the entire filmstrip. * * { * type: SET_FILMSTRIP_VISIBILITY, diff --git a/react/features/filmstrip/actions.js b/react/features/filmstrip/actions.js index 9e1f297b4..ce4d88e68 100644 --- a/react/features/filmstrip/actions.js +++ b/react/features/filmstrip/actions.js @@ -1,7 +1,25 @@ import { + SET_FILMSTRIP_HOVERED, SET_FILMSTRIP_VISIBILITY } from './actionTypes'; +/** + * Sets if the filmstrip is currently being hovered over. + * + * @param {boolean} hovered - Whether or not the filmstrip is currently being + * hovered over. + * @returns {{ + * type: SET_FILMSTRIP_HOVERED, + * hovered: boolean + * }} + */ +export function setFilmstripHovered(hovered) { + return { + type: SET_FILMSTRIP_HOVERED, + hovered + }; +} + /** * Sets if the entire filmstrip should be visible. * diff --git a/react/features/filmstrip/components/Filmstrip.web.js b/react/features/filmstrip/components/Filmstrip.web.js index a7c54ce28..d701b646e 100644 --- a/react/features/filmstrip/components/Filmstrip.web.js +++ b/react/features/filmstrip/components/Filmstrip.web.js @@ -1,10 +1,12 @@ /* @flow */ +import _ from 'lodash'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { Toolbox } from '../../toolbox'; +import { setFilmstripHovered } from '../actions'; import { shouldRemoteVideosBeVisible } from '../functions'; /** @@ -14,19 +16,68 @@ import { shouldRemoteVideosBeVisible } from '../functions'; * @extends Component */ class Filmstrip extends Component { + _isHovered: boolean; + + _notifyOfHoveredStateUpdate: Function; + + _onMouseOut: Function; + + _onMouseOver: Function; + + /** + * {@code Filmstrip} component's property types. + * + * @static + */ static propTypes = { + /** + * Whether or not remote videos are currently being hovered over. + */ + _hovered: React.PropTypes.bool, + /** * Whether or not the remote videos should be visible. Will toggle * a class for hiding the videos. */ _remoteVideosVisible: React.PropTypes.bool, + /** + * Updates the redux store with filmstrip hover changes. + */ + dispatch: React.PropTypes.func, + /** * Whether or not the toolbox should be displayed within the filmstrip. */ displayToolbox: React.PropTypes.bool }; + /** + * Initializes a new {@code Filmstrip} instance. + * + * @param {Object} props - The read-only properties with which the new + * instance is to be initialized. + */ + constructor(props) { + super(props); + + // Debounce the method for dispatching the new filmstrip handled state + // so that it does not get called with each mouse movement event. This + // also works around an issue where mouseout and then a mouseover event + // is fired when hovering over remote thumbnails, which are not yet in + // react. + this._notifyOfHoveredStateUpdate + = _.debounce(this._notifyOfHoveredStateUpdate, 100); + + // Cache the current hovered state for _updateHoveredState to always + // send the last known hovered state. + this._isHovered = false; + + // Bind event handlers so they are only bound once for every instance. + this._onMouseOver = this._onMouseOver.bind(this); + this._onMouseOut = this._onMouseOut.bind(this); + } + /** * Implements React's {@link Component#render()}. * @@ -54,7 +105,9 @@ class Filmstrip extends Component { id = 'remoteVideos'>
+ id = 'filmstripLocalVideo' + onMouseOut = { this._onMouseOut } + onMouseOver = { this._onMouseOver } />
@@ -65,7 +118,9 @@ class Filmstrip extends Component { */}
+ id = 'filmstripRemoteVideosContainer' + onMouseOut = { this._onMouseOut } + onMouseOver = { this._onMouseOver } />