fix(Thumbnail, Drawer): Remove hover state; Prevent outside propagation
This commit is contained in:
parent
c657f360e1
commit
b7ab3ea052
|
@ -4,16 +4,28 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: $drawerZ;
|
z-index: $drawerZ;
|
||||||
background-color: #141414;
|
|
||||||
border-radius: 16px 16px 0 0;
|
border-radius: 16px 16px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.drawer-portal::after {
|
||||||
|
content: '';
|
||||||
|
background-color: $participantsPaneBgColor;
|
||||||
|
margin-bottom: env(safe-area-inset-bottom, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-menu-container {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.drawer-menu {
|
.drawer-menu {
|
||||||
max-height: calc(80vh - 64px);
|
max-height: calc(80vh - 64px);
|
||||||
background: #242528;
|
background: #242528;
|
||||||
border-radius: 16px 16px 0 0;
|
border-radius: 16px 16px 0 0;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
margin-bottom: env(safe-area-inset-bottom, 0);
|
margin-bottom: env(safe-area-inset-bottom, 0);
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.drawer-toggle {
|
.drawer-toggle {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import { isMobileBrowser } from '../../../../../react/features/base/environment/utils';
|
|
||||||
import { createScreenSharingIssueEvent, sendAnalytics } from '../../../analytics';
|
import { createScreenSharingIssueEvent, sendAnalytics } from '../../../analytics';
|
||||||
import { AudioLevelIndicator } from '../../../audio-level-indicator';
|
import { AudioLevelIndicator } from '../../../audio-level-indicator';
|
||||||
import { Avatar } from '../../../base/avatar';
|
import { Avatar } from '../../../base/avatar';
|
||||||
|
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||||
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
|
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
|
||||||
import { MEDIA_TYPE, VideoTrack } from '../../../base/media';
|
import { MEDIA_TYPE, VideoTrack } from '../../../base/media';
|
||||||
import {
|
import {
|
||||||
|
@ -139,6 +139,11 @@ export type Props = {|
|
||||||
*/
|
*/
|
||||||
_isCurrentlyOnLargeVideo: boolean,
|
_isCurrentlyOnLargeVideo: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we are currently running in a mobile browser.
|
||||||
|
*/
|
||||||
|
_isMobile: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the participant is screen sharing.
|
* Indicates whether the participant is screen sharing.
|
||||||
*/
|
*/
|
||||||
|
@ -612,7 +617,7 @@ class Thumbnail extends Component<Props, State> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
_renderFakeParticipant() {
|
_renderFakeParticipant() {
|
||||||
const { _participant: { avatarURL } } = this.props;
|
const { _isMobile, _participant: { avatarURL } } = this.props;
|
||||||
const styles = this._getStyles();
|
const styles = this._getStyles();
|
||||||
const containerClassName = this._getContainerClassName();
|
const containerClassName = this._getContainerClassName();
|
||||||
|
|
||||||
|
@ -621,8 +626,10 @@ class Thumbnail extends Component<Props, State> {
|
||||||
className = { containerClassName }
|
className = { containerClassName }
|
||||||
id = 'sharedVideoContainer'
|
id = 'sharedVideoContainer'
|
||||||
onClick = { this._onClick }
|
onClick = { this._onClick }
|
||||||
onMouseEnter = { this._onMouseEnter }
|
{ ...(_isMobile ? {} : {
|
||||||
onMouseLeave = { this._onMouseLeave }
|
onMouseEnter: this._onMouseEnter,
|
||||||
|
onMouseLeave: this._onMouseLeave
|
||||||
|
}) }
|
||||||
style = { styles.thumbnail }>
|
style = { styles.thumbnail }>
|
||||||
{avatarURL ? (
|
{avatarURL ? (
|
||||||
<img
|
<img
|
||||||
|
@ -753,6 +760,7 @@ class Thumbnail extends Component<Props, State> {
|
||||||
const {
|
const {
|
||||||
_defaultLocalDisplayName,
|
_defaultLocalDisplayName,
|
||||||
_disableLocalVideoFlip,
|
_disableLocalVideoFlip,
|
||||||
|
_isMobile,
|
||||||
_isScreenSharing,
|
_isScreenSharing,
|
||||||
_localFlipX,
|
_localFlipX,
|
||||||
_disableProfile,
|
_disableProfile,
|
||||||
|
@ -772,13 +780,17 @@ class Thumbnail extends Component<Props, State> {
|
||||||
className = { containerClassName }
|
className = { containerClassName }
|
||||||
id = 'localVideoContainer'
|
id = 'localVideoContainer'
|
||||||
onClick = { this._onClick }
|
onClick = { this._onClick }
|
||||||
onMouseEnter = { this._onMouseEnter }
|
{ ...(_isMobile
|
||||||
onMouseLeave = { this._onMouseLeave }
|
? {
|
||||||
{ ...(isMobileBrowser() ? {
|
onTouchEnd: this._onTouchEnd,
|
||||||
onTouchEnd: this._onTouchEnd,
|
onTouchMove: this._onTouchMove,
|
||||||
onTouchMove: this._onTouchMove,
|
onTouchStart: this._onTouchStart
|
||||||
onTouchStart: this._onTouchStart
|
}
|
||||||
} : {}) }
|
: {
|
||||||
|
onMouseEnter: this._onMouseEnter,
|
||||||
|
onMouseLeave: this._onMouseLeave
|
||||||
|
}
|
||||||
|
) }
|
||||||
style = { styles.thumbnail }>
|
style = { styles.thumbnail }>
|
||||||
<div className = 'videocontainer__background' />
|
<div className = 'videocontainer__background' />
|
||||||
<span id = 'localVideoWrapper'>
|
<span id = 'localVideoWrapper'>
|
||||||
|
@ -875,6 +887,7 @@ class Thumbnail extends Component<Props, State> {
|
||||||
*/
|
*/
|
||||||
_renderRemoteParticipant() {
|
_renderRemoteParticipant() {
|
||||||
const {
|
const {
|
||||||
|
_isMobile,
|
||||||
_isTestModeEnabled,
|
_isTestModeEnabled,
|
||||||
_participant,
|
_participant,
|
||||||
_startSilent,
|
_startSilent,
|
||||||
|
@ -909,13 +922,17 @@ class Thumbnail extends Component<Props, State> {
|
||||||
className = { containerClassName }
|
className = { containerClassName }
|
||||||
id = { `participant_${id}` }
|
id = { `participant_${id}` }
|
||||||
onClick = { this._onClick }
|
onClick = { this._onClick }
|
||||||
onMouseEnter = { this._onMouseEnter }
|
{ ...(_isMobile
|
||||||
onMouseLeave = { this._onMouseLeave }
|
? {
|
||||||
{ ...(isMobileBrowser() ? {
|
onTouchEnd: this._onTouchEnd,
|
||||||
onTouchEnd: this._onTouchEnd,
|
onTouchMove: this._onTouchMove,
|
||||||
onTouchMove: this._onTouchMove,
|
onTouchStart: this._onTouchStart
|
||||||
onTouchStart: this._onTouchStart
|
}
|
||||||
} : {}) }
|
: {
|
||||||
|
onMouseEnter: this._onMouseEnter,
|
||||||
|
onMouseLeave: this._onMouseLeave
|
||||||
|
}
|
||||||
|
) }
|
||||||
style = { styles.thumbnail }>
|
style = { styles.thumbnail }>
|
||||||
{
|
{
|
||||||
_videoTrack && <VideoTrack
|
_videoTrack && <VideoTrack
|
||||||
|
@ -1031,6 +1048,7 @@ function _mapStateToProps(state, ownProps): Object {
|
||||||
} = state['features/base/config'];
|
} = state['features/base/config'];
|
||||||
const { NORMAL = 8 } = interfaceConfig.INDICATOR_FONT_SIZES || {};
|
const { NORMAL = 8 } = interfaceConfig.INDICATOR_FONT_SIZES || {};
|
||||||
const { localFlipX } = state['features/base/settings'];
|
const { localFlipX } = state['features/base/settings'];
|
||||||
|
const _isMobile = isMobileBrowser();
|
||||||
|
|
||||||
|
|
||||||
switch (_currentLayout) {
|
switch (_currentLayout) {
|
||||||
|
@ -1072,7 +1090,7 @@ function _mapStateToProps(state, ownProps): Object {
|
||||||
return {
|
return {
|
||||||
_audioTrack,
|
_audioTrack,
|
||||||
_connectionIndicatorAutoHideEnabled: interfaceConfig.CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,
|
_connectionIndicatorAutoHideEnabled: interfaceConfig.CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,
|
||||||
_connectionIndicatorDisabled: isMobileBrowser() || interfaceConfig.CONNECTION_INDICATOR_DISABLED,
|
_connectionIndicatorDisabled: _isMobile || interfaceConfig.CONNECTION_INDICATOR_DISABLED,
|
||||||
_currentLayout,
|
_currentLayout,
|
||||||
_defaultLocalDisplayName: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
|
_defaultLocalDisplayName: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
|
||||||
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
|
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
|
||||||
|
@ -1081,6 +1099,7 @@ function _mapStateToProps(state, ownProps): Object {
|
||||||
_isAudioOnly: Boolean(state['features/base/audio-only'].enabled),
|
_isAudioOnly: Boolean(state['features/base/audio-only'].enabled),
|
||||||
_isCurrentlyOnLargeVideo: state['features/large-video']?.participantId === id,
|
_isCurrentlyOnLargeVideo: state['features/large-video']?.participantId === id,
|
||||||
_isDominantSpeakerDisabled: interfaceConfig.DISABLE_DOMINANT_SPEAKER_INDICATOR,
|
_isDominantSpeakerDisabled: interfaceConfig.DISABLE_DOMINANT_SPEAKER_INDICATOR,
|
||||||
|
_isMobile,
|
||||||
_isScreenSharing: _videoTrack?.videoType === 'desktop',
|
_isScreenSharing: _videoTrack?.videoType === 'desktop',
|
||||||
_isTestModeEnabled: isTestModeEnabled(state),
|
_isTestModeEnabled: isTestModeEnabled(state),
|
||||||
_isVideoPlayable: id && isVideoPlayable(state, id),
|
_isVideoPlayable: id && isVideoPlayable(state, id),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -30,36 +30,38 @@ function Drawer({
|
||||||
children,
|
children,
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose }: Props) {
|
onClose }: Props) {
|
||||||
const drawerRef: Object = useRef(null);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the drawer when clicking or touching outside of it.
|
* Handles clicks within the menu, preventing the propagation of the click event.
|
||||||
*
|
*
|
||||||
* @param {Event} event - Mouse down/start touch event object.
|
* @param {Object} event - The click event.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function handleOutsideClickOrTouch(event: Event) {
|
const handleInsideClick = useCallback(event => {
|
||||||
if (drawerRef.current && !drawerRef.current.contains(event.target)) {
|
event.stopPropagation();
|
||||||
onClose();
|
}, []);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
/**
|
||||||
window.addEventListener('mousedown', handleOutsideClickOrTouch);
|
* Handles clicks outside of the menu, closing it, and also stopping further propagation.
|
||||||
window.addEventListener('touchstart', handleOutsideClickOrTouch);
|
*
|
||||||
|
* @param {Object} event - The click event.
|
||||||
return () => {
|
* @returns {void}
|
||||||
window.removeEventListener('mousedown', handleOutsideClickOrTouch);
|
*/
|
||||||
window.removeEventListener('touchstart', handleOutsideClickOrTouch);
|
const handleOutsideClick = useCallback(event => {
|
||||||
};
|
event.stopPropagation();
|
||||||
}, [ drawerRef ]);
|
onClose();
|
||||||
|
}, [ onClose ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
isOpen ? (
|
isOpen ? (
|
||||||
<div
|
<div
|
||||||
className = 'drawer-menu'
|
className = 'drawer-menu-container'
|
||||||
ref = { drawerRef }>
|
onClick = { handleOutsideClick }>
|
||||||
{children}
|
<div
|
||||||
|
className = 'drawer-menu'
|
||||||
|
onClick = { handleInsideClick }>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue