fix(toolbar): Hide/Show toolbar on tap on mobile web.
* A tap on video space will toggle the toolbar. * Double tapping on a tile will pin the participant.
This commit is contained in:
parent
667a6eac80
commit
366dc8d11b
|
@ -6,6 +6,7 @@ import React from 'react';
|
|||
import VideoLayout from '../../../../../modules/UI/videolayout/VideoLayout';
|
||||
import { getConferenceNameForTitle } from '../../../base/conference';
|
||||
import { connect, disconnect } from '../../../base/connection';
|
||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect as reactReduxConnect } from '../../../base/redux';
|
||||
import { setColorAlpha } from '../../../base/util';
|
||||
|
@ -18,6 +19,7 @@ import { getIsLobbyVisible } from '../../../lobby/functions';
|
|||
import { ParticipantsPane } from '../../../participants-pane/components/web';
|
||||
import { getParticipantsPaneOpen } from '../../../participants-pane/functions';
|
||||
import { Prejoin, isPrejoinPageVisible } from '../../../prejoin';
|
||||
import { toggleToolboxVisible } from '../../../toolbox/actions.any';
|
||||
import { fullScreenChanged, showToolbox } from '../../../toolbox/actions.web';
|
||||
import { JitsiPortal, Toolbox } from '../../../toolbox/components/web';
|
||||
import { LAYOUTS, getCurrentLayout } from '../../../video-layout';
|
||||
|
@ -119,6 +121,7 @@ class Conference extends AbstractConference<Props, *> {
|
|||
_onMouseLeave: Function;
|
||||
_onMouseMove: Function;
|
||||
_onShowToolbar: Function;
|
||||
_onVidespaceTouchStart: Function;
|
||||
_originalOnMouseMove: Function;
|
||||
_originalOnShowToolbar: Function;
|
||||
_setBackground: Function;
|
||||
|
@ -157,6 +160,7 @@ class Conference extends AbstractConference<Props, *> {
|
|||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
this._onFullScreenChange = this._onFullScreenChange.bind(this);
|
||||
this._onVidespaceTouchStart = this._onVidespaceTouchStart.bind(this);
|
||||
this._setBackground = this._setBackground.bind(this);
|
||||
}
|
||||
|
||||
|
@ -229,12 +233,14 @@ class Conference extends AbstractConference<Props, *> {
|
|||
<div
|
||||
className = { _layoutClassName }
|
||||
id = 'videoconference_page'
|
||||
onMouseMove = { this._onShowToolbar }
|
||||
onMouseMove = { isMobileBrowser() ? undefined : this._onShowToolbar }
|
||||
ref = { this._setBackground }>
|
||||
<ConferenceInfo />
|
||||
|
||||
<Notice />
|
||||
<div id = 'videospace'>
|
||||
<div
|
||||
id = 'videospace'
|
||||
onTouchStart = { this._onVidespaceTouchStart }>
|
||||
<LargeVideo />
|
||||
{!_isParticipantsPaneVisible
|
||||
&& <div id = 'notification-participant-list'>
|
||||
|
@ -292,6 +298,16 @@ class Conference extends AbstractConference<Props, *> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler used for touch start on Video container.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onVidespaceTouchStart() {
|
||||
this.props.dispatch(toggleToolboxVisible());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Redux state when full screen mode has been enabled or
|
||||
* disabled.
|
||||
|
|
|
@ -155,6 +155,7 @@ class Filmstrip extends PureComponent <Props> {
|
|||
this._listItemKey = this._listItemKey.bind(this);
|
||||
this._onGridItemsRendered = this._onGridItemsRendered.bind(this);
|
||||
this._onListItemsRendered = this._onListItemsRendered.bind(this);
|
||||
this._onTouchStart = this._onTouchStart.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -500,6 +501,20 @@ class Filmstrip extends PureComponent <Props> {
|
|||
this._doToggleFilmstrip();
|
||||
}
|
||||
|
||||
_onTouchStart: (SyntheticEvent<HTMLButtonElement>) => void;
|
||||
|
||||
/**
|
||||
* Handler for onTouchStart.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} e - The synthetic event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onTouchStart(e: SyntheticEvent<HTMLButtonElement>) {
|
||||
// Don't propagate the touchStart event so the toolbar doesn't get toggled.
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a React Element for changing the visibility of the filmstrip when
|
||||
* clicked.
|
||||
|
@ -520,6 +535,7 @@ class Filmstrip extends PureComponent <Props> {
|
|||
id = 'toggleFilmstripButton'
|
||||
onClick = { this._onToolbarToggleFilmstrip }
|
||||
onFocus = { this._onTabIn }
|
||||
onTouchStart = { this._onTouchStart }
|
||||
tabIndex = { 0 }>
|
||||
<Icon
|
||||
aria-label = { t('toolbar.accessibilityLabel.toggleFilmstrip') }
|
||||
|
|
|
@ -258,6 +258,12 @@ class Thumbnail extends Component<Props, State> {
|
|||
*/
|
||||
videoMenuTriggerRef: Object;
|
||||
|
||||
/**
|
||||
* Timeout used to detect double tapping.
|
||||
* It is active while user has tapped once.
|
||||
*/
|
||||
_firstTap: ?TimeoutID;
|
||||
|
||||
/**
|
||||
* Initializes a new Thumbnail instance.
|
||||
*
|
||||
|
@ -281,6 +287,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
this.timeoutHandle = null;
|
||||
this.videoMenuTriggerRef = null;
|
||||
|
||||
this._clearDoubleClickTimeout = this._clearDoubleClickTimeout.bind(this);
|
||||
this._setInstance = this._setInstance.bind(this);
|
||||
this._updateAudioLevel = this._updateAudioLevel.bind(this);
|
||||
this._onCanPlay = this._onCanPlay.bind(this);
|
||||
|
@ -437,6 +444,18 @@ class Thumbnail extends Component<Props, State> {
|
|||
this._stopListeningForAudioUpdates(this.props._audioTrack);
|
||||
}
|
||||
|
||||
_clearDoubleClickTimeout: () => void
|
||||
|
||||
/**
|
||||
* Clears the first click timeout.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_clearDoubleClickTimeout() {
|
||||
clearTimeout(this._firstTap);
|
||||
this._firstTap = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts listening for audio level updates from the library.
|
||||
*
|
||||
|
@ -580,12 +599,21 @@ class Thumbnail extends Component<Props, State> {
|
|||
_onTouchStart: () => void;
|
||||
|
||||
/**
|
||||
* Set showing popover context menu after x miliseconds.
|
||||
* Handler for touch start.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onTouchStart() {
|
||||
this.timeoutHandle = setTimeout(this._showPopupMenu, SHOW_TOOLBAR_CONTEXT_MENU_AFTER);
|
||||
|
||||
if (this._firstTap) {
|
||||
this._clearDoubleClickTimeout();
|
||||
this._onClick();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._firstTap = setTimeout(this._clearDoubleClickTimeout, 300);
|
||||
}
|
||||
|
||||
_onTouchEnd: () => void;
|
||||
|
@ -790,7 +818,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
<span
|
||||
className = { containerClassName }
|
||||
id = 'localVideoContainer'
|
||||
onClick = { this._onClick }
|
||||
{ ...(_isMobile
|
||||
? {
|
||||
onTouchEnd: this._onTouchEnd,
|
||||
|
@ -798,6 +825,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
onTouchStart: this._onTouchStart
|
||||
}
|
||||
: {
|
||||
onClick: this._onClick,
|
||||
onMouseEnter: this._onMouseEnter,
|
||||
onMouseLeave: this._onMouseLeave
|
||||
}
|
||||
|
@ -932,7 +960,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
<span
|
||||
className = { containerClassName }
|
||||
id = { `participant_${id}` }
|
||||
onClick = { this._onClick }
|
||||
onClick = { _isMobile ? undefined : this._onClick }
|
||||
{ ...(_isMobile
|
||||
? {
|
||||
onTouchEnd: this._onTouchEnd,
|
||||
|
|
|
@ -4,7 +4,8 @@ import type { Dispatch } from 'redux';
|
|||
|
||||
import {
|
||||
SET_TOOLBOX_ENABLED,
|
||||
SET_TOOLBOX_VISIBLE
|
||||
SET_TOOLBOX_VISIBLE,
|
||||
TOGGLE_TOOLBOX_VISIBLE
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
|
@ -43,3 +44,24 @@ export function setToolboxVisible(visible: boolean): Object {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to toggle the toolbox visibility.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function toggleToolboxVisible() {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
const state = getState();
|
||||
const { toolbarConfig: { alwaysVisible } } = state['features/base/config'];
|
||||
const { visible } = state['features/toolbox'];
|
||||
|
||||
if (visible && alwaysVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: TOGGLE_TOOLBOX_VISIBLE
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,28 +1,2 @@
|
|||
// @flow
|
||||
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { TOGGLE_TOOLBOX_VISIBLE } from './actionTypes';
|
||||
|
||||
export * from './actions.any';
|
||||
|
||||
/**
|
||||
* Action to toggle the toolbox visibility.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function toggleToolboxVisible() {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
const state = getState();
|
||||
const { toolbarConfig: { alwaysVisible } } = state['features/base/config'];
|
||||
const { visible } = state['features/toolbox'];
|
||||
|
||||
if (visible && alwaysVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: TOGGLE_TOOLBOX_VISIBLE
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { overwriteConfig } from '../base/config';
|
||||
import { isMobileBrowser } from '../base/environment/utils';
|
||||
|
||||
import {
|
||||
CLEAR_TOOLBOX_TIMEOUT,
|
||||
|
@ -220,7 +221,8 @@ export function setToolbarHovered(hovered: boolean): Object {
|
|||
}
|
||||
|
||||
/**
|
||||
* Dispatches an action which sets new timeout and clears the previous one.
|
||||
* Dispatches an action which sets new timeout for the toolbox visibility and clears the previous one.
|
||||
* On mobile browsers the toolbox does not hide on timeout. It is toggled on simple tap.
|
||||
*
|
||||
* @param {Function} handler - Function to be invoked after the timeout.
|
||||
* @param {number} timeoutMS - Delay.
|
||||
|
@ -231,10 +233,15 @@ export function setToolbarHovered(hovered: boolean): Object {
|
|||
* }}
|
||||
*/
|
||||
export function setToolboxTimeout(handler: Function, timeoutMS: number): Object {
|
||||
return {
|
||||
type: SET_TOOLBOX_TIMEOUT,
|
||||
handler,
|
||||
timeoutMS
|
||||
return function(dispatch) {
|
||||
if (isMobileBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: SET_TOOLBOX_TIMEOUT,
|
||||
handler,
|
||||
timeoutMS
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue