feat(tile-view): double click to pin

This commit is contained in:
Leonard Kim 2018-11-30 14:13:39 -08:00 committed by Saúl Ibarra Corretgé
parent fc75adc6ff
commit ebcde745ef
6 changed files with 98 additions and 89 deletions

View File

@ -595,17 +595,7 @@ UI.removeListener = function(type, listener) {
*/
UI.emitEvent = (type, ...options) => eventEmitter.emit(type, ...options);
UI.clickOnVideo = function(videoNumber) {
const videos = $('#remoteVideos .videocontainer:not(#mixedstream)');
const videosLength = videos.length;
if (videosLength <= videoNumber) {
return;
}
const videoIndex = videoNumber === 0 ? 0 : videosLength - videoNumber;
videos[videoIndex].click();
};
UI.clickOnVideo = videoNumber => VideoLayout.togglePin(videoNumber);
// Used by torture.
UI.showToolbar = timeout => APP.store.dispatch(showToolbox(timeout));

View File

@ -15,11 +15,14 @@ export default function SharedVideoThumb(participant, videoType, VideoLayout) {
this.videoSpanId = 'sharedVideoContainer';
this.container = this.createContainer(this.videoSpanId);
this.$container = $(this.container);
this.container.onclick = this.videoClick.bind(this);
this.bindHoverHandler();
SmallVideo.call(this, VideoLayout);
this.isVideoMuted = true;
this.setDisplayName(participant.name);
this.container.onclick = this._onContainerClick;
this.container.ondblclick = this._onContainerDoubleClick;
}
SharedVideoThumb.prototype = Object.create(SmallVideo.prototype);
SharedVideoThumb.prototype.constructor = SharedVideoThumb;
@ -61,13 +64,6 @@ SharedVideoThumb.prototype.createContainer = function(spanId) {
return container;
};
/**
* The thumb click handler.
*/
SharedVideoThumb.prototype.videoClick = function() {
this._togglePin();
};
/**
* Removes RemoteVideo from the page.
*/

View File

@ -61,7 +61,8 @@ function LocalVideo(VideoLayout, emitter, streamEndedCallback) {
this.addAudioLevelIndicator();
this.updateIndicators();
this.container.onclick = this._onContainerClick.bind(this);
this.container.onclick = this._onContainerClick;
this.container.ondblclick = this._onContainerDoubleClick;
}
LocalVideo.prototype = Object.create(SmallVideo.prototype);
@ -253,40 +254,6 @@ LocalVideo.prototype.updateDOMLocation = function() {
this._updateVideoElement();
};
/**
* Callback invoked when the thumbnail is clicked. Will directly call
* VideoLayout to handle thumbnail click if certain elements have not been
* clicked.
*
* @param {MouseEvent} event - The click event to intercept.
* @private
* @returns {void}
*/
LocalVideo.prototype._onContainerClick = function(event) {
// TODO Checking the classes is a workround to allow events to bubble into
// the DisplayName component if it was clicked. React's synthetic events
// will fire after jQuery handlers execute, so stop propogation at this
// point will prevent DisplayName from getting click events. This workaround
// should be removeable once LocalVideo is a React Component because then
// the components share the same eventing system.
const $source = $(event.target || event.srcElement);
const { classList } = event.target;
const clickedOnDisplayName
= $source.parents('.displayNameContainer').length > 0;
const clickedOnPopover = $source.parents('.popover').length > 0
|| classList.contains('popover');
const ignoreClick = clickedOnDisplayName || clickedOnPopover;
if (event.stopPropagation && !ignoreClick) {
event.stopPropagation();
}
if (!ignoreClick) {
this._togglePin();
}
};
/**
* Renders the React Element for displaying video in {@code LocalVideo}.
*

View File

@ -22,8 +22,7 @@ import {
} from '../../../react/features/remote-video-menu';
import {
LAYOUTS,
getCurrentLayout,
shouldDisplayTileView
getCurrentLayout
} from '../../../react/features/video-layout';
/* eslint-enable no-unused-vars */
@ -89,7 +88,8 @@ function RemoteVideo(user, VideoLayout, emitter) {
this._setAudioVolume = this._setAudioVolume.bind(this);
this._stopRemoteControl = this._stopRemoteControl.bind(this);
this.container.onclick = this._onContainerClick.bind(this);
this.container.onclick = this._onContainerClick;
this.container.ondblclick = this._onContainerDoubleClick;
}
RemoteVideo.prototype = Object.create(SmallVideo.prototype);
@ -613,36 +613,6 @@ RemoteVideo.prototype.removePresenceLabel = function() {
}
};
/**
* Callback invoked when the thumbnail is clicked. Will directly call
* VideoLayout to handle thumbnail click if certain elements have not been
* clicked.
*
* @param {MouseEvent} event - The click event to intercept.
* @private
* @returns {void}
*/
RemoteVideo.prototype._onContainerClick = function(event) {
const $source = $(event.target || event.srcElement);
const { classList } = event.target;
const ignoreClick = $source.parents('.popover').length > 0
|| classList.contains('popover');
if (!ignoreClick) {
this._togglePin();
}
// On IE we need to populate this handler on video <object> and it does not
// give event instance as an argument, so we check here for methods.
if (event.stopPropagation && event.preventDefault && !ignoreClick) {
event.stopPropagation();
event.preventDefault();
}
return false;
};
RemoteVideo.createContainer = function(spanId) {
const container = document.createElement('span');

View File

@ -142,6 +142,9 @@ function SmallVideo(VideoLayout) {
// Bind event handlers so they are only bound once for every instance.
this._onPopoverHover = this._onPopoverHover.bind(this);
this.updateView = this.updateView.bind(this);
this._onContainerClick = this._onContainerClick.bind(this);
this._onContainerDoubleClick = this._onContainerDoubleClick.bind(this);
}
/**
@ -821,12 +824,71 @@ SmallVideo.prototype.updateIndicators = function() {
};
/**
* Pins the participant displayed by this thumbnail or unpins if already pinned.
* Callback invoked when the thumbnail is double clicked. Will pin the
* participant if in tile view.
*
* @param {MouseEvent} event - The click event to intercept.
* @private
* @returns {void}
*/
SmallVideo.prototype._togglePin = function() {
SmallVideo.prototype._onContainerDoubleClick = function(event) {
if (this._pinningRequiresDoubleClick() && this._shouldTriggerPin(event)) {
APP.store.dispatch(pinParticipant(this.id));
}
};
/**
* Callback invoked when the thumbnail is clicked and potentially trigger
* pinning of the participant.
*
* @param {MouseEvent} event - The click event to intercept.
* @private
* @returns {void}
*/
SmallVideo.prototype._onContainerClick = function(event) {
const triggerPin = this._shouldTriggerPin(event)
&& !this._pinningRequiresDoubleClick();
if (event.stopPropagation && triggerPin) {
event.stopPropagation();
event.preventDefault();
}
if (triggerPin) {
this.togglePin();
}
return false;
};
/**
* Returns whether or not a click event is targeted at certain elements which
* should not trigger a pin.
*
* @param {MouseEvent} event - The click event to intercept.
* @private
* @returns {boolean}
*/
SmallVideo.prototype._shouldTriggerPin = function(event) {
// TODO Checking the classes is a workround to allow events to bubble into
// the DisplayName component if it was clicked. React's synthetic events
// will fire after jQuery handlers execute, so stop propogation at this
// point will prevent DisplayName from getting click events. This workaround
// should be removeable once LocalVideo is a React Component because then
// the components share the same eventing system.
const $source = $(event.target || event.srcElement);
return $source.parents('.displayNameContainer').length === 0
&& $source.parents('.popover').length === 0
&& !event.target.classList.contains('popover');
};
/**
* Pins the participant displayed by this thumbnail or unpins if already pinned.
*
* @returns {void}
*/
SmallVideo.prototype.togglePin = function() {
const pinnedParticipant
= getPinnedParticipant(APP.store.getState()) || {};
const participantIdToPin
@ -836,6 +898,17 @@ SmallVideo.prototype._togglePin = function() {
APP.store.dispatch(pinParticipant(participantIdToPin));
};
/**
* Returns whether or not clicking to pin the participant needs to be a double
* click instead of a single click.
*
* @private
* @returns {boolean}
*/
SmallVideo.prototype._pinningRequiresDoubleClick = function() {
return shouldDisplayTileView(APP.store.getState());
};
/**
* Removes the React element responsible for showing connection status, dominant
* speaker, and raised hand icons.

View File

@ -391,6 +391,19 @@ const VideoLayout = {
return id || null;
},
/**
* Triggers a thumbnail to pin or unpin itself.
*
* @param {number} videoNumber - The index of the video to toggle pin on.
* @private
*/
togglePin(videoNumber) {
const videos = getAllThumbnails();
const videoView = videos[videoNumber];
videoView && videoView.togglePin();
},
/**
* Callback invoked to update display when the pin participant has changed.
*