fix(rn, bottomsheet) fix not rendering above presentation sheets

Move all sheets to render in a new container which uses FullWindowOverlay, which allows rendering above presentation controllers on iOS.
This commit is contained in:
Saúl Ibarra Corretgé 2022-06-20 16:53:19 +02:00 committed by GitHub
parent 0e98f90205
commit 6ad279f029
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 210 additions and 325 deletions

View File

@ -749,4 +749,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: bef1335067eaa4e8c558b1248f8ab3948de855bc PODFILE CHECKSUM: bef1335067eaa4e8c558b1248f8ab3948de855bc
COCOAPODS: 1.11.2 COCOAPODS: 1.11.3

View File

@ -1,10 +1,11 @@
// @flow // @flow
import React from 'react'; import React, { Fragment } from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import SplashScreen from 'react-native-splash-screen'; import SplashScreen from 'react-native-splash-screen';
import { DialogContainer } from '../../base/dialog'; import { DialogContainer } from '../../base/dialog';
import BottomSheetContainer from '../../base/dialog/components/native/BottomSheetContainer';
import { updateFlags } from '../../base/flags/actions'; import { updateFlags } from '../../base/flags/actions';
import { CALL_INTEGRATION_ENABLED, SERVER_URL_CHANGE_ENABLED } from '../../base/flags/constants'; import { CALL_INTEGRATION_ENABLED, SERVER_URL_CHANGE_ENABLED } from '../../base/flags/constants';
import { getFeatureFlag } from '../../base/flags/functions'; import { getFeatureFlag } from '../../base/flags/functions';
@ -240,7 +241,10 @@ export class App extends AbstractApp {
*/ */
_renderDialogContainer() { _renderDialogContainer() {
return ( return (
<Fragment>
<DialogContainer /> <DialogContainer />
<BottomSheetContainer />
</Fragment>
); );
} }
} }

View File

@ -7,6 +7,15 @@
*/ */
export const HIDE_DIALOG = 'HIDE_DIALOG'; export const HIDE_DIALOG = 'HIDE_DIALOG';
/**
* The type of Redux action which closes a sheet.
*
* {
* type: HIDE_SHEET
* }
*/
export const HIDE_SHEET = 'HIDE_SHEET';
/** /**
* The type of Redux action which begins a request to open a dialog. * The type of Redux action which begins a request to open a dialog.
* *
@ -18,3 +27,15 @@ export const HIDE_DIALOG = 'HIDE_DIALOG';
* *
*/ */
export const OPEN_DIALOG = 'OPEN_DIALOG'; export const OPEN_DIALOG = 'OPEN_DIALOG';
/**
* The type of Redux action which begins a request to open a sheet.
*
* {
* type: OPEN_SHEET,
* component: React.Component,
* props: PropTypes
* }
*
*/
export const OPEN_SHEET = 'OPEN_SHEET';

View File

@ -2,7 +2,12 @@
import type { Dispatch } from 'redux'; import type { Dispatch } from 'redux';
import { HIDE_DIALOG, OPEN_DIALOG } from './actionTypes'; import {
HIDE_DIALOG,
HIDE_SHEET,
OPEN_DIALOG,
OPEN_SHEET
} from './actionTypes';
import { isDialogOpen } from './functions'; import { isDialogOpen } from './functions';
/** /**
@ -24,6 +29,19 @@ export function hideDialog(component: ?Object) {
}; };
} }
/**
* Closes the active sheet.
*
* @returns {{
* type: HIDE_SHEET,
* }}
*/
export function hideSheet() {
return {
type: HIDE_SHEET
};
}
/** /**
* Signals Dialog to open dialog. * Signals Dialog to open dialog.
* *
@ -44,6 +62,26 @@ export function openDialog(component: Object, componentProps: ?Object) {
}; };
} }
/**
* Opens the requested sheet.
*
* @param {Object} component - The component to display as a sheet.
* @param {Object} [componentProps] - The React {@code Component} props of the
* specified {@code component}.
* @returns {{
* type: OPEN_SHEET,
* component: React.Component,
* componentProps: (Object | undefined)
* }}
*/
export function openSheet(component: Object, componentProps: ?Object) {
return {
type: OPEN_SHEET,
component,
componentProps
};
}
/** /**
* Signals Dialog to open a dialog with the specified component if the component * Signals Dialog to open a dialog with the specified component if the component
* is not already open. If it is open, then Dialog is signaled to close its * is not already open. If it is open, then Dialog is signaled to close its

View File

@ -2,6 +2,8 @@ import React, { PureComponent, type Node } from 'react';
import { SafeAreaView, ScrollView, View } from 'react-native'; import { SafeAreaView, ScrollView, View } from 'react-native';
import { SlidingView } from '../../../react'; import { SlidingView } from '../../../react';
import { connect } from '../../../redux';
import { hideSheet } from '../../actions';
import { bottomSheetStyles as styles } from './styles'; import { bottomSheetStyles as styles } from './styles';
@ -20,6 +22,11 @@ type Props = {
*/ */
children: Node, children: Node,
/**
* Redux Dispatch function.
*/
dispatch: Function,
/** /**
* Handler for the cancel event, which happens when the user dismisses * Handler for the cancel event, which happens when the user dismisses
* the sheet. * the sheet.
@ -61,6 +68,31 @@ class BottomSheet extends PureComponent<Props> {
showSlidingView: true showSlidingView: true
}; };
/**
* Initializes a new instance.
*
* @param {Props} props - The React {@code Component} props to initialize
* the new instance with.
*/
constructor(props: Props) {
super(props);
this._onCancel = this._onCancel.bind(this);
}
/**
* Handles the cancel event, when the user dismissed the sheet. By default we close it.
*
* @returns {void}
*/
_onCancel() {
if (this.props.onCancel) {
this.props.onCancel();
} else {
this.props.dispatch(hideSheet());
}
}
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -80,7 +112,7 @@ class BottomSheet extends PureComponent<Props> {
<SlidingView <SlidingView
accessibilityRole = 'menu' accessibilityRole = 'menu'
accessibilityViewIsModal = { true } accessibilityViewIsModal = { true }
onHide = { this.props.onCancel } onHide = { this._onCancel }
position = 'bottom' position = 'bottom'
show = { showSlidingView }> show = { showSlidingView }>
<View <View
@ -116,4 +148,4 @@ class BottomSheet extends PureComponent<Props> {
} }
} }
export default BottomSheet; export default connect()(BottomSheet);

View File

@ -0,0 +1,26 @@
import React from 'react';
import { Platform, StyleSheet, View } from 'react-native';
import { FullWindowOverlay } from 'react-native-screens';
import { useSelector } from 'react-redux';
const Wrapper = Platform.select({
ios: FullWindowOverlay,
default: View
});
const BottomSheetContainer: () => JSX.Element = () => {
const { sheet, sheetProps } = useSelector(state => state['features/base/dialog']);
const { reducedUI } = useSelector(state => state['features/base/responsive-ui']);
if (!sheet || reducedUI) {
return null;
}
return (
<Wrapper style={StyleSheet.absoluteFill}>
{ React.createElement(sheet, sheetProps) }
</Wrapper>
);
}
export default BottomSheetContainer;

View File

@ -1,8 +1,11 @@
/* @flow */
import { assign, ReducerRegistry } from '../redux'; import { assign, ReducerRegistry } from '../redux';
import { HIDE_DIALOG, OPEN_DIALOG } from './actionTypes'; import {
HIDE_DIALOG,
HIDE_SHEET,
OPEN_DIALOG,
OPEN_SHEET
} from './actionTypes';
/** /**
* Reduces redux actions which show or hide dialogs. * Reduces redux actions which show or hide dialogs.
@ -32,6 +35,18 @@ ReducerRegistry.register('features/base/dialog', (state = {}, action) => {
component: action.component, component: action.component,
componentProps: action.componentProps componentProps: action.componentProps
}); });
case HIDE_SHEET:
return assign(state, {
sheet: undefined,
sheetProps: undefined
});
case OPEN_SHEET:
return assign(state, {
sheet: action.component,
sheetProps: action.componentProps
});
} }
return state; return state;

View File

@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { openDialog } from '../../../../base/dialog/actions'; import { openSheet } from '../../../../base/dialog/actions';
import AudioRoutePickerDialog from '../../../../mobile/audio-mode/components/AudioRoutePickerDialog'; import AudioRoutePickerDialog from '../../../../mobile/audio-mode/components/AudioRoutePickerDialog';
import AudioIcon from './AudioIcon'; import AudioIcon from './AudioIcon';
@ -19,7 +19,7 @@ const SelectSoundDevice = () : JSX.Element => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const onSelect = useCallback(() => const onSelect = useCallback(() =>
dispatch(openDialog(AudioRoutePickerDialog)) dispatch(openSheet(AudioRoutePickerDialog))
, [ dispatch ]); , [ dispatch ]);
return ( return (

View File

@ -1,7 +1,6 @@
// @flow
import type { Dispatch } from 'redux'; import type { Dispatch } from 'redux';
import { openDialog } from '../../../base/dialog'; import { openSheet } from '../../../base/dialog';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { IconVolumeEmpty } from '../../../base/icons'; import { IconVolumeEmpty } from '../../../base/icons';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
@ -32,7 +31,7 @@ class AudioDeviceToggleButton extends AbstractButton<Props, *> {
* @returns {void} * @returns {void}
*/ */
_handleClick() { _handleClick() {
this.props.dispatch(openDialog(AudioRoutePickerDialog)); this.props.dispatch(openSheet(AudioRoutePickerDialog));
} }
} }

View File

@ -1,10 +1,8 @@
// @flow
import _ from 'lodash'; import _ from 'lodash';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { NativeModules, Text, TouchableHighlight, View } from 'react-native'; import { NativeModules, Text, TouchableHighlight, View } from 'react-native';
import { hideDialog, BottomSheet } from '../../../base/dialog'; import { hideSheet, BottomSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { import {
@ -143,11 +141,6 @@ const deviceInfoMap = {
} }
}; };
/**
* The exported React {@code Component}.
*/
let AudioRoutePickerDialog_; // eslint-disable-line prefer-const
/** /**
* Implements a React {@code Component} which prompts the user when a password * Implements a React {@code Component} which prompts the user when a password
* is required to join a conference. * is required to join a conference.
@ -218,36 +211,10 @@ class AudioRoutePickerDialog extends Component<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
// Bind event handlers so they are only bound once per instance.
this._onCancel = this._onCancel.bind(this);
// Trigger an initial update. // Trigger an initial update.
AudioMode.updateDeviceList && AudioMode.updateDeviceList(); AudioMode.updateDeviceList && AudioMode.updateDeviceList();
} }
/**
* Dispatches a redux action to hide this sheet.
*
* @returns {void}
*/
_hide() {
this.props.dispatch(hideDialog(AudioRoutePickerDialog_));
}
_onCancel: () => void;
/**
* Cancels the dialog by hiding it.
*
* @private
* @returns {void}
*/
_onCancel() {
this._hide();
}
_onSelectDeviceFn: (Device) => Function;
/** /**
* Builds and returns a function which handles the selection of a device * Builds and returns a function which handles the selection of a device
* on the sheet. The selected device will be used by {@code AudioMode}. * on the sheet. The selected device will be used by {@code AudioMode}.
@ -258,7 +225,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
*/ */
_onSelectDeviceFn(device: Device) { _onSelectDeviceFn(device: Device) {
return () => { return () => {
this._hide(); this.props.dispatch(hideSheet());
AudioMode.setAudioDevice(device.uid || device.type); AudioMode.setAudioDevice(device.uid || device.type);
}; };
} }
@ -329,7 +296,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
} }
return ( return (
<BottomSheet onCancel = { this._onCancel }> <BottomSheet>
{ content } { content }
</BottomSheet> </BottomSheet>
); );
@ -348,6 +315,4 @@ function _mapStateToProps(state) {
}; };
} }
AudioRoutePickerDialog_ = translate(connect(_mapStateToProps)(AudioRoutePickerDialog)); export default translate(connect(_mapStateToProps)(AudioRoutePickerDialog));
export default AudioRoutePickerDialog_;

View File

@ -1,6 +1,6 @@
// @flow import type { Dispatch } from 'redux';
import { openDialog } from '../base/dialog'; import { openSheet } from '../base/dialog';
import { SharedVideoMenu } from '../video-menu'; import { SharedVideoMenu } from '../video-menu';
import { LocalVideoMenu } from '../video-menu/components/native'; import { LocalVideoMenu } from '../video-menu/components/native';
import ConnectionStatusComponent import ConnectionStatusComponent
@ -20,7 +20,7 @@ export * from './actions.any';
* @returns {Function} * @returns {Function}
*/ */
export function showContextMenuReject(participant: Object) { export function showContextMenuReject(participant: Object) {
return openDialog(ContextMenuLobbyParticipantReject, { participant }); return openSheet(ContextMenuLobbyParticipantReject, { participant });
} }
@ -31,7 +31,7 @@ export function showContextMenuReject(participant: Object) {
* @returns {Function} * @returns {Function}
*/ */
export function showConnectionStatus(participantID: string) { export function showConnectionStatus(participantID: string) {
return openDialog(ConnectionStatusComponent, { participantID }); return openSheet(ConnectionStatusComponent, { participantID });
} }
/** /**
@ -46,9 +46,9 @@ export function showContextMenuDetails(participantId: string, local: boolean = f
const { remoteVideoMenu } = getState()['features/base/config']; const { remoteVideoMenu } = getState()['features/base/config'];
if (local) { if (local) {
dispatch(openDialog(LocalVideoMenu)); dispatch(openSheet(LocalVideoMenu));
} else if (!remoteVideoMenu?.disabled) { } else if (!remoteVideoMenu?.disabled) {
dispatch(openDialog(RemoteVideoMenu, { participantId })); dispatch(openSheet(RemoteVideoMenu, { participantId }));
} }
}; };
} }
@ -60,7 +60,7 @@ export function showContextMenuDetails(participantId: string, local: boolean = f
* @returns {Function} * @returns {Function}
*/ */
export function showSharedVideoMenu(participantId: string) { export function showSharedVideoMenu(participantId: string) {
return openDialog(SharedVideoMenu, { participantId }); return openSheet(SharedVideoMenu, { participantId });
} }
/** /**

View File

@ -1,5 +1,3 @@
// @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { TouchableOpacity } from 'react-native'; import { TouchableOpacity } from 'react-native';
@ -7,7 +5,7 @@ import { Text } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics'; import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
import { hideDialog } from '../../../../../base/dialog/actions'; import { hideSheet } from '../../../../../base/dialog/actions';
import BottomSheet from '../../../../../base/dialog/components/native/BottomSheet'; import BottomSheet from '../../../../../base/dialog/components/native/BottomSheet';
import { import {
Icon, Icon,
@ -29,7 +27,6 @@ type Props = {
const BreakoutRoomContextMenu = ({ room }: Props) => { const BreakoutRoomContextMenu = ({ room }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const closeDialog = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
const isLocalModerator = useSelector(isLocalParticipantModerator); const isLocalModerator = useSelector(isLocalParticipantModerator);
const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig); const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig);
const { t } = useTranslation(); const { t } = useTranslation();
@ -37,23 +34,22 @@ const BreakoutRoomContextMenu = ({ room }: Props) => {
const onJoinRoom = useCallback(() => { const onJoinRoom = useCallback(() => {
sendAnalytics(createBreakoutRoomsEvent('join')); sendAnalytics(createBreakoutRoomsEvent('join'));
dispatch(moveToRoom(room.jid)); dispatch(moveToRoom(room.jid));
closeDialog(); dispatch(hideSheet());
}, [ dispatch, room ]); }, [ dispatch, room ]);
const onRemoveBreakoutRoom = useCallback(() => { const onRemoveBreakoutRoom = useCallback(() => {
dispatch(removeBreakoutRoom(room.jid)); dispatch(removeBreakoutRoom(room.jid));
closeDialog(); dispatch(hideSheet());
}, [ dispatch, room ]); }, [ dispatch, room ]);
const onCloseBreakoutRoom = useCallback(() => { const onCloseBreakoutRoom = useCallback(() => {
dispatch(closeBreakoutRoom(room.id)); dispatch(closeBreakoutRoom(room.id));
closeDialog(); dispatch(hideSheet());
}, [ dispatch, room ]); }, [ dispatch, room ]);
return ( return (
<BottomSheet <BottomSheet
addScrollViewPadding = { false } addScrollViewPadding = { false }
onCancel = { closeDialog }
showSlidingView = { true }> showSlidingView = { true }>
{ {
!hideJoinRoomButton && ( !hideJoinRoomButton && (

View File

@ -1,11 +1,9 @@
// @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FlatList } from 'react-native'; import { FlatList } from 'react-native';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { openDialog } from '../../../../../base/dialog'; import { openSheet } from '../../../../../base/dialog';
import { participantMatchesSearch } from '../../../../functions'; import { participantMatchesSearch } from '../../../../functions';
import CollapsibleList from '../../../native/CollapsibleList'; import CollapsibleList from '../../../native/CollapsibleList';
import styles from '../../../native/styles'; import styles from '../../../native/styles';
@ -41,7 +39,7 @@ export const CollapsibleRoom = ({ room, searchString }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const _openContextMenu = useCallback(() => { const _openContextMenu = useCallback(() => {
dispatch(openDialog(BreakoutRoomContextMenu, { room })); dispatch(openSheet(BreakoutRoomContextMenu, { room }));
}, [ room ]); }, [ room ]);
const roomParticipantsNr = Object.values(room.participants || {}).length; const roomParticipantsNr = Object.values(room.participants || {}).length;
const title const title

View File

@ -1,5 +1,3 @@
// @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { TouchableOpacity, View } from 'react-native'; import { TouchableOpacity, View } from 'react-native';
@ -7,7 +5,6 @@ import { Text } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Avatar } from '../../../base/avatar'; import { Avatar } from '../../../base/avatar';
import { hideDialog } from '../../../base/dialog';
import BottomSheet from '../../../base/dialog/components/native/BottomSheet'; import BottomSheet from '../../../base/dialog/components/native/BottomSheet';
import { import {
Icon, IconClose Icon, IconClose
@ -16,6 +13,7 @@ import { setKnockingParticipantApproval } from '../../../lobby/actions.native';
import { getKnockingParticipantsById } from '../../../lobby/functions'; import { getKnockingParticipantsById } from '../../../lobby/functions';
import styles from './styles'; import styles from './styles';
type Props = { type Props = {
/** /**
@ -28,7 +26,6 @@ const ContextMenuLobbyParticipantReject = ({ participant: p }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const knockParticipantsIDArr = useSelector(getKnockingParticipantsById); const knockParticipantsIDArr = useSelector(getKnockingParticipantsById);
const knockParticipantIsAvailable = knockParticipantsIDArr.find(knockPartId => knockPartId === p.id); const knockParticipantIsAvailable = knockParticipantsIDArr.find(knockPartId => knockPartId === p.id);
const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
const displayName = p.name; const displayName = p.name;
const reject = useCallback(() => dispatch(setKnockingParticipantApproval(p.id, false), [ dispatch ])); const reject = useCallback(() => dispatch(setKnockingParticipantApproval(p.id, false), [ dispatch ]));
const { t } = useTranslation(); const { t } = useTranslation();
@ -50,7 +47,6 @@ const ContextMenuLobbyParticipantReject = ({ participant: p }: Props) => {
return ( return (
<BottomSheet <BottomSheet
addScrollViewPadding = { false } addScrollViewPadding = { false }
onCancel = { cancel }
/* eslint-disable-next-line react/jsx-no-bind */ /* eslint-disable-next-line react/jsx-no-bind */
renderHeader = { renderMenuHeader } renderHeader = { renderMenuHeader }
showSlidingView = { Boolean(knockParticipantIsAvailable) } showSlidingView = { Boolean(knockParticipantIsAvailable) }

View File

@ -1,5 +1,3 @@
// @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { TouchableOpacity, View } from 'react-native'; import { TouchableOpacity, View } from 'react-native';
@ -16,7 +14,7 @@ import {
isSupported as isAvModerationSupported, isSupported as isAvModerationSupported,
isEnabled as isAvModerationEnabled isEnabled as isAvModerationEnabled
} from '../../../av-moderation/functions'; } from '../../../av-moderation/functions';
import { openDialog, hideDialog } from '../../../base/dialog/actions'; import { openDialog, hideSheet } from '../../../base/dialog/actions';
import BottomSheet from '../../../base/dialog/components/native/BottomSheet'; import BottomSheet from '../../../base/dialog/components/native/BottomSheet';
import { import {
Icon, Icon,
@ -32,10 +30,10 @@ import styles from './styles';
export const ContextMenuMore = () => { export const ContextMenuMore = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]); const muteAllVideo = useCallback(() => {
const muteAllVideo = useCallback(() => dispatch(openDialog(MuteEveryonesVideoDialog));
dispatch(openDialog(MuteEveryonesVideoDialog)), dispatch(hideSheet());
[ dispatch ]); }, [ dispatch ]);
const { t } = useTranslation(); const { t } = useTranslation();
const isModerationSupported = useSelector(isAvModerationSupported); const isModerationSupported = useSelector(isAvModerationSupported);
@ -54,7 +52,6 @@ export const ContextMenuMore = () => {
return ( return (
<BottomSheet <BottomSheet
addScrollViewPadding = { false } addScrollViewPadding = { false }
onCancel = { cancel }
showSlidingView = { true }> showSlidingView = { true }>
<TouchableOpacity <TouchableOpacity
onPress = { muteAllVideo } onPress = { muteAllVideo }

View File

@ -6,7 +6,7 @@ import { View } from 'react-native';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { openDialog } from '../../../base/dialog'; import { openDialog, openSheet } from '../../../base/dialog';
import JitsiScreen from '../../../base/modal/components/JitsiScreen'; import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { isLocalParticipantModerator } from '../../../base/participants'; import { isLocalParticipantModerator } from '../../../base/participants';
import { equals } from '../../../base/redux'; import { equals } from '../../../base/redux';
@ -42,7 +42,7 @@ import styles from './styles';
const ParticipantsPane = () => { const ParticipantsPane = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [ searchString, setSearchString ] = useState(''); const [ searchString, setSearchString ] = useState('');
const openMoreMenu = useCallback(() => dispatch(openDialog(ContextMenuMore)), [ dispatch ]); const openMoreMenu = useCallback(() => dispatch(openSheet(ContextMenuMore)), [ dispatch ]);
const isLocalModerator = useSelector(isLocalParticipantModerator); const isLocalModerator = useSelector(isLocalParticipantModerator);
const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)), const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)),
[ dispatch ]); [ dispatch ]);

View File

@ -1,11 +1,9 @@
// @flow
import React from 'react'; import React from 'react';
import { TouchableWithoutFeedback, View } from 'react-native'; import { TouchableWithoutFeedback, View } from 'react-native';
import type { Dispatch } from 'redux'; import type { Dispatch } from 'redux';
import { getDefaultURL } from '../../app/functions'; import { getDefaultURL } from '../../app/functions';
import { openDialog } from '../../base/dialog/actions'; import { openSheet } from '../../base/dialog/actions';
import { translate } from '../../base/i18n'; import { translate } from '../../base/i18n';
import { NavigateSectionList, type Section } from '../../base/react'; import { NavigateSectionList, type Section } from '../../base/react';
import { connect } from '../../base/redux'; import { connect } from '../../base/redux';
@ -56,9 +54,6 @@ type Props = {
* *
*/ */
class RecentList extends AbstractRecentList<Props> { class RecentList extends AbstractRecentList<Props> {
_getRenderListEmptyComponent: () => React$Node;
_onPress: string => {};
/** /**
* Initializes a new {@code RecentList} instance. * Initializes a new {@code RecentList} instance.
* *
@ -105,8 +100,6 @@ class RecentList extends AbstractRecentList<Props> {
); );
} }
_onLongPress: (Object) => void;
/** /**
* Handles the list's navigate action. * Handles the list's navigate action.
* *
@ -115,7 +108,7 @@ class RecentList extends AbstractRecentList<Props> {
* @returns {void} * @returns {void}
*/ */
_onLongPress(item) { _onLongPress(item) {
this.props.dispatch(openDialog(RecentListItemMenu, { item })); this.props.dispatch(openSheet(RecentListItemMenu, { item }));
} }
} }

View File

@ -1,9 +1,7 @@
// @flow
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { BottomSheet, hideDialog, isDialogOpen } from '../../base/dialog'; import { BottomSheet, hideSheet } from '../../base/dialog';
import { bottomSheetStyles } from '../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../base/dialog/components/native/styles';
import { type Item } from '../../base/react/Types'; import { type Item } from '../../base/react/Types';
import { connect } from '../../base/redux'; import { connect } from '../../base/redux';
@ -22,17 +20,9 @@ type Props = {
/** /**
* Item being rendered in this menu. * Item being rendered in this menu.
*/ */
item: Item, item: Item
/**
* True if the menu is currently open, false otherwise.
*/
_isOpen: boolean
} }
// eslint-disable-next-line prefer-const
let RecentListItemMenu_;
/** /**
* Class to implement a popup menu that opens upon long pressing a recent list item. * Class to implement a popup menu that opens upon long pressing a recent list item.
*/ */
@ -65,7 +55,6 @@ class RecentListItemMenu extends PureComponent<Props> {
return ( return (
<BottomSheet <BottomSheet
onCancel = { this._onCancel }
renderHeader = { this._renderMenuHeader }> renderHeader = { this._renderMenuHeader }>
<DeleteItemButton { ...buttonProps } /> <DeleteItemButton { ...buttonProps } />
<ShowDialInInfoButton { ...buttonProps } /> <ShowDialInInfoButton { ...buttonProps } />
@ -73,8 +62,6 @@ class RecentListItemMenu extends PureComponent<Props> {
); );
} }
_onCancel: () => boolean;
/** /**
* Callback to hide this menu. * Callback to hide this menu.
* *
@ -82,17 +69,9 @@ class RecentListItemMenu extends PureComponent<Props> {
* @returns {boolean} * @returns {boolean}
*/ */
_onCancel() { _onCancel() {
if (this.props._isOpen) { this.props.dispatch(hideSheet());
this.props.dispatch(hideDialog(RecentListItemMenu_));
return true;
} }
return false;
}
_renderMenuHeader: () => React$Element<any>;
/** /**
* Function to render the menu's header. * Function to render the menu's header.
* *
@ -118,19 +97,4 @@ class RecentListItemMenu extends PureComponent<Props> {
} }
} }
/** export default connect()(RecentListItemMenu);
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @private
* @returns {Props}
*/
function _mapStateToProps(state) {
return {
_isOpen: isDialogOpen(state, RecentListItemMenu_)
};
}
RecentListItemMenu_ = connect(_mapStateToProps)(RecentListItemMenu);
export default RecentListItemMenu_;

View File

@ -1,6 +1,4 @@
// @flow import { openSheet } from '../base/dialog';
import { openDialog } from '../base/dialog';
import JitsiMeetJS from '../base/lib-jitsi-meet'; import JitsiMeetJS from '../base/lib-jitsi-meet';
import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications'; import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
@ -15,7 +13,7 @@ export * from './actions.any';
*/ */
export function openHighlightDialog() { export function openHighlightDialog() {
return (dispatch: Function) => { return (dispatch: Function) => {
dispatch(openDialog(HighlightDialog)); dispatch(openSheet(HighlightDialog));
}; };
} }

View File

@ -1,27 +1,26 @@
// @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch, batch } from 'react-redux'; import { useDispatch, batch } from 'react-redux';
import { hideDialog, BottomSheet } from '../../../../base/dialog'; import { BottomSheet, hideSheet } from '../../../../base/dialog';
import { highlightMeetingMoment } from '../../../actions.any'; import { highlightMeetingMoment } from '../../../actions.any';
import styles from '../styles.native'; import styles from '../styles.native';
const HighlightDialog = () => { const HighlightDialog = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const closeDialog = useCallback(() => dispatch(hideDialog()), [ dispatch ]); const closeDialog = useCallback(() => dispatch(hideSheet()), [ dispatch ]);
const highlightMoment = useCallback(() => { const highlightMoment = useCallback(() => {
batch(() => { batch(() => {
dispatch(highlightMeetingMoment()); dispatch(highlightMeetingMoment());
dispatch(hideDialog()); dispatch(hideSheet());
}); });
}, [ dispatch ]); }, [ dispatch ]);
return ( return (
<BottomSheet onCancel = { closeDialog }> <BottomSheet>
<View style = { styles.highlightDialog }> <View style = { styles.highlightDialog }>
<Text style = { styles.highlightDialogHeading }>{ `${t('recording.highlightMoment')}?` }</Text> <Text style = { styles.highlightDialogHeading }>{ `${t('recording.highlightMoment')}?` }</Text>
<Text style = { styles.highlightDialogText }> <Text style = { styles.highlightDialogText }>

View File

@ -3,7 +3,7 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Divider } from 'react-native-paper'; import { Divider } from 'react-native-paper';
import { BottomSheet, hideDialog, isDialogOpen } from '../../../base/dialog'; import { BottomSheet, hideSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { SharedDocumentButton } from '../../../etherpad'; import { SharedDocumentButton } from '../../../etherpad';
@ -73,15 +73,6 @@ type State = {
scrolledToTop: boolean scrolledToTop: boolean
} }
/**
* The exported React {@code Component}. We need it to execute
* {@link hideDialog}.
*
* XXX It does not break our coding style rule to not utilize globals for state,
* because it is merely another name for {@code export}'s {@code default}.
*/
let OverflowMenu_; // eslint-disable-line prefer-const
/** /**
* Implements a React {@code Component} with some extra actions in addition to * Implements a React {@code Component} with some extra actions in addition to
* those in the toolbar. * those in the toolbar.
@ -139,7 +130,6 @@ class OverflowMenu extends PureComponent<Props, State> {
return ( return (
<BottomSheet <BottomSheet
onCancel = { this._onCancel }
renderFooter = { _reactionsEnabled && !toolbarButtons.has('raisehand') renderFooter = { _reactionsEnabled && !toolbarButtons.has('raisehand')
? this._renderReactionMenu ? this._renderReactionMenu
: null }> : null }>
@ -167,26 +157,16 @@ class OverflowMenu extends PureComponent<Props, State> {
); );
} }
_onCancel: () => boolean;
/** /**
* Hides this {@code OverflowMenu}. * Hides this {@code OverflowMenu}.
* *
* @private * @private
* @returns {boolean} * @returns {void}
*/ */
_onCancel() { _onCancel() {
if (this.props._isOpen) { this.props.dispatch(hideSheet());
this.props.dispatch(hideDialog(OverflowMenu_));
return true;
} }
return false;
}
_renderReactionMenu: () => React$Element<any>;
/** /**
* Functoin to render the reaction menu as the footer of the bottom sheet. * Functoin to render the reaction menu as the footer of the bottom sheet.
* *
@ -210,13 +190,10 @@ function _mapStateToProps(state) {
const { disableSelfView } = state['features/base/settings']; const { disableSelfView } = state['features/base/settings'];
return { return {
_isOpen: isDialogOpen(state, OverflowMenu_),
_reactionsEnabled: isReactionsEnabled(state), _reactionsEnabled: isReactionsEnabled(state),
_selfViewHidden: Boolean(disableSelfView), _selfViewHidden: Boolean(disableSelfView),
_width: state['features/base/responsive-ui'].clientWidth _width: state['features/base/responsive-ui'].clientWidth
}; };
} }
OverflowMenu_ = connect(_mapStateToProps)(OverflowMenu); export default connect(_mapStateToProps)(OverflowMenu);
export default OverflowMenu_;

View File

@ -1,6 +1,4 @@
// @flow import { openSheet } from '../../../base/dialog';
import { openDialog } from '../../../base/dialog';
import { getFeatureFlag, OVERFLOW_MENU_ENABLED } from '../../../base/flags'; import { getFeatureFlag, OVERFLOW_MENU_ENABLED } from '../../../base/flags';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { IconHorizontalPoints } from '../../../base/icons'; import { IconHorizontalPoints } from '../../../base/icons';
@ -35,7 +33,7 @@ class OverflowMenuButton extends AbstractButton<Props, *> {
* @returns {void} * @returns {void}
*/ */
_handleClick() { _handleClick() {
this.props.dispatch(openDialog(OverflowMenu)); this.props.dispatch(openSheet(OverflowMenu));
} }
} }

View File

@ -1,33 +1 @@
// @flow
import { hideDialog } from '../base/dialog';
import { RemoteVideoMenu, SharedVideoMenu, LocalVideoMenu } from './components/native';
/**
* Hides the local video menu.
*
* @returns {Function}
*/
export function hideLocalVideoMenu() {
return hideDialog(LocalVideoMenu);
}
/**
* Hides the remote video menu.
*
* @returns {Function}
*/
export function hideRemoteVideoMenu() {
return hideDialog(RemoteVideoMenu);
}
/**
* Hides the shared video menu.
*
* @returns {Function}
*/
export function hideSharedVideoMenu() {
return hideDialog(SharedVideoMenu);
}
export * from './actions.any'; export * from './actions.any';

View File

@ -1,6 +1,4 @@
// @flow import { openSheet } from '../../../base/dialog';
import { openDialog } from '../../../base/dialog';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { IconInfo } from '../../../base/icons'; import { IconInfo } from '../../../base/icons';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
@ -42,7 +40,7 @@ class ConnectionStatusButton extends AbstractButton<Props, *> {
_handleClick() { _handleClick() {
const { dispatch, participantID } = this.props; const { dispatch, participantID } = this.props;
dispatch(openDialog(ConnectionStatusComponent, { dispatch(openSheet(ConnectionStatusComponent, {
participantID participantID
})); }));
} }

View File

@ -1,13 +1,10 @@
// @flow
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { withTheme } from 'react-native-paper'; import { withTheme } from 'react-native-paper';
import { Avatar } from '../../../base/avatar'; import { Avatar } from '../../../base/avatar';
import { getSourceNameSignalingFeatureFlag } from '../../../base/config'; import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
import { BottomSheet, isDialogOpen, hideDialog } from '../../../base/dialog'; import { BottomSheet, hideSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { IconArrowDownLarge, IconArrowUpLarge } from '../../../base/icons'; import { IconArrowDownLarge, IconArrowUpLarge } from '../../../base/icons';
@ -87,9 +84,6 @@ type State = {
connectionString: string connectionString: string
}; };
// eslint-disable-next-line prefer-const
let ConnectionStatusComponent_;
/** /**
* Class to implement a popup menu that show the connection statistics. * Class to implement a popup menu that show the connection statistics.
*/ */
@ -126,9 +120,9 @@ class ConnectionStatusComponent extends Component<Props, State> {
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
* @inheritdoc * @inheritdoc
* @returns {React$Node} * @returns {ReactNode}
*/ */
render(): React$Node { render() {
const { t, theme } = this.props; const { t, theme } = this.props;
const { palette } = theme; const { palette } = theme;
@ -402,8 +396,6 @@ class ConnectionStatusComponent extends Component<Props, State> {
} }
} }
_onCancel: () => boolean;
/** /**
* Callback to hide the {@code ConnectionStatusComponent}. * Callback to hide the {@code ConnectionStatusComponent}.
* *
@ -419,17 +411,9 @@ class ConnectionStatusComponent extends Component<Props, State> {
this.props._sourceName, this._onStatsUpdated); this.props._sourceName, this._onStatsUpdated);
} }
if (this.props._isOpen) { this.props.dispatch(hideSheet());
this.props.dispatch(hideDialog(ConnectionStatusComponent_));
return true;
} }
return false;
}
_renderMenuHeader: () => React$Element<any>;
/** /**
* Function to render the menu's header. * Function to render the menu's header.
* *
@ -466,13 +450,10 @@ function _mapStateToProps(state, ownProps) {
const { participantID } = ownProps; const { participantID } = ownProps;
return { return {
_isOpen: isDialogOpen(state, ConnectionStatusComponent_),
_participantDisplayName: getParticipantDisplayName(state, participantID), _participantDisplayName: getParticipantDisplayName(state, participantID),
_sourceNameSignalingEnabled: getSourceNameSignalingFeatureFlag(state), _sourceNameSignalingEnabled: getSourceNameSignalingFeatureFlag(state),
_sourceName: getSourceNameByParticipantId(state, ownProps.participantId) _sourceName: getSourceNameByParticipantId(state, ownProps.participantId)
}; };
} }
ConnectionStatusComponent_ = translate(connect(_mapStateToProps)(withTheme(ConnectionStatusComponent))); export default translate(connect(_mapStateToProps)(withTheme(ConnectionStatusComponent)));
export default ConnectionStatusComponent_;

View File

@ -1,10 +1,8 @@
// @flow
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { Avatar } from '../../../base/avatar'; import { Avatar } from '../../../base/avatar';
import { BottomSheet, isDialogOpen } from '../../../base/dialog'; import { BottomSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { import {
@ -13,7 +11,6 @@ import {
} from '../../../base/participants'; } from '../../../base/participants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import ToggleSelfViewButton from '../../../toolbox/components/native/ToggleSelfViewButton'; import ToggleSelfViewButton from '../../../toolbox/components/native/ToggleSelfViewButton';
import { hideLocalVideoMenu } from '../../actions.native';
import ConnectionStatusButton from './ConnectionStatusButton'; import ConnectionStatusButton from './ConnectionStatusButton';
import styles from './styles'; import styles from './styles';
@ -26,11 +23,6 @@ const AVATAR_SIZE = 24;
type Props = { type Props = {
/**
* True if the menu is currently open, false otherwise.
*/
_isOpen: boolean,
/** /**
* The local participant. * The local participant.
*/ */
@ -52,9 +44,6 @@ type Props = {
t: Function t: Function
} }
// eslint-disable-next-line prefer-const
let LocalVideoMenu_;
/** /**
* Class to implement a popup menu that opens upon long pressing a thumbnail. * Class to implement a popup menu that opens upon long pressing a thumbnail.
*/ */
@ -67,7 +56,6 @@ class LocalVideoMenu extends PureComponent<Props> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this._onCancel = this._onCancel.bind(this);
this._renderMenuHeader = this._renderMenuHeader.bind(this); this._renderMenuHeader = this._renderMenuHeader.bind(this);
} }
@ -79,7 +67,6 @@ class LocalVideoMenu extends PureComponent<Props> {
render() { render() {
const { _participant } = this.props; const { _participant } = this.props;
const buttonProps = { const buttonProps = {
afterClick: this._onCancel,
showLabel: true, showLabel: true,
participantID: _participant.id, participantID: _participant.id,
styles: bottomSheetStyles.buttons styles: bottomSheetStyles.buttons
@ -87,7 +74,6 @@ class LocalVideoMenu extends PureComponent<Props> {
return ( return (
<BottomSheet <BottomSheet
onCancel = { this._onCancel }
renderHeader = { this._renderMenuHeader } renderHeader = { this._renderMenuHeader }
showSlidingView = { true }> showSlidingView = { true }>
<ToggleSelfViewButton { ...buttonProps } /> <ToggleSelfViewButton { ...buttonProps } />
@ -96,26 +82,6 @@ class LocalVideoMenu extends PureComponent<Props> {
); );
} }
_onCancel: () => boolean;
/**
* Callback to hide the {@code RemoteVideoMenu}.
*
* @private
* @returns {boolean}
*/
_onCancel() {
if (this.props._isOpen) {
this.props.dispatch(hideLocalVideoMenu());
return true;
}
return false;
}
_renderMenuHeader: () => React$Element<any>;
/** /**
* Function to render the menu's header. * Function to render the menu's header.
* *
@ -151,12 +117,9 @@ function _mapStateToProps(state) {
const participant = getLocalParticipant(state); const participant = getLocalParticipant(state);
return { return {
_isOpen: isDialogOpen(state, LocalVideoMenu_),
_participant: participant, _participant: participant,
_participantDisplayName: getParticipantDisplayName(state, participant.id) _participantDisplayName: getParticipantDisplayName(state, participant.id)
}; };
} }
LocalVideoMenu_ = translate(connect(_mapStateToProps)(LocalVideoMenu)); export default translate(connect(_mapStateToProps)(LocalVideoMenu));
export default LocalVideoMenu_;

View File

@ -1,11 +1,9 @@
// @flow
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { Divider } from 'react-native-paper'; import { Divider } from 'react-native-paper';
import { Avatar } from '../../../base/avatar'; import { Avatar } from '../../../base/avatar';
import { BottomSheet, isDialogOpen } from '../../../base/dialog'; import { BottomSheet, hideSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { KICK_OUT_ENABLED, getFeatureFlag } from '../../../base/flags'; import { KICK_OUT_ENABLED, getFeatureFlag } from '../../../base/flags';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
@ -16,7 +14,6 @@ import {
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions'; import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions';
import PrivateMessageButton from '../../../chat/components/native/PrivateMessageButton'; import PrivateMessageButton from '../../../chat/components/native/PrivateMessageButton';
import { hideRemoteVideoMenu } from '../../actions.native';
import ConnectionStatusButton from '../native/ConnectionStatusButton'; import ConnectionStatusButton from '../native/ConnectionStatusButton';
import AskUnmuteButton from './AskUnmuteButton'; import AskUnmuteButton from './AskUnmuteButton';
@ -74,11 +71,6 @@ type Props = {
*/ */
_disableGrantModerator: Boolean, _disableGrantModerator: Boolean,
/**
* True if the menu is currently open, false otherwise.
*/
_isOpen: boolean,
/** /**
* Whether the participant is present in the room or not. * Whether the participant is present in the room or not.
*/ */
@ -100,9 +92,6 @@ type Props = {
t: Function t: Function
} }
// eslint-disable-next-line prefer-const
let RemoteVideoMenu_;
/** /**
* Class to implement a popup menu that opens upon long pressing a thumbnail. * Class to implement a popup menu that opens upon long pressing a thumbnail.
*/ */
@ -145,7 +134,6 @@ class RemoteVideoMenu extends PureComponent<Props> {
return ( return (
<BottomSheet <BottomSheet
onCancel = { this._onCancel }
renderHeader = { this._renderMenuHeader } renderHeader = { this._renderMenuHeader }
showSlidingView = { _isParticipantAvailable }> showSlidingView = { _isParticipantAvailable }>
<AskUnmuteButton { ...buttonProps } /> <AskUnmuteButton { ...buttonProps } />
@ -157,7 +145,9 @@ class RemoteVideoMenu extends PureComponent<Props> {
{ !_disableGrantModerator && <GrantModeratorButton { ...buttonProps } /> } { !_disableGrantModerator && <GrantModeratorButton { ...buttonProps } /> }
<PinButton { ...buttonProps } /> <PinButton { ...buttonProps } />
{ !_disablePrivateChat && <PrivateMessageButton { ...buttonProps } /> } { !_disablePrivateChat && <PrivateMessageButton { ...buttonProps } /> }
<ConnectionStatusButton { ...buttonProps } /> <ConnectionStatusButton
{ ...buttonProps }
afterClick = { undefined } />
{_rooms.length > 1 && <> {_rooms.length > 1 && <>
<Divider style = { styles.divider } /> <Divider style = { styles.divider } />
<View style = { styles.contextMenuItem }> <View style = { styles.contextMenuItem }>
@ -175,8 +165,6 @@ class RemoteVideoMenu extends PureComponent<Props> {
); );
} }
_onCancel: () => boolean;
/** /**
* Callback to hide the {@code RemoteVideoMenu}. * Callback to hide the {@code RemoteVideoMenu}.
* *
@ -184,17 +172,9 @@ class RemoteVideoMenu extends PureComponent<Props> {
* @returns {boolean} * @returns {boolean}
*/ */
_onCancel() { _onCancel() {
if (this.props._isOpen) { this.props.dispatch(hideSheet());
this.props.dispatch(hideRemoteVideoMenu());
return true;
} }
return false;
}
_renderMenuHeader: () => React$Element<any>;
/** /**
* Function to render the menu's header. * Function to render the menu's header.
* *
@ -242,13 +222,10 @@ function _mapStateToProps(state, ownProps) {
_disableKick: Boolean(shouldDisableKick), _disableKick: Boolean(shouldDisableKick),
_disableRemoteMute: Boolean(disableRemoteMute), _disableRemoteMute: Boolean(disableRemoteMute),
_disablePrivateChat: Boolean(disablePrivateChat), _disablePrivateChat: Boolean(disablePrivateChat),
_isOpen: isDialogOpen(state, RemoteVideoMenu_),
_isParticipantAvailable: Boolean(isParticipantAvailable), _isParticipantAvailable: Boolean(isParticipantAvailable),
_participantDisplayName: getParticipantDisplayName(state, participantId), _participantDisplayName: getParticipantDisplayName(state, participantId),
_rooms _rooms
}; };
} }
RemoteVideoMenu_ = translate(connect(_mapStateToProps)(RemoteVideoMenu)); export default translate(connect(_mapStateToProps)(RemoteVideoMenu));
export default RemoteVideoMenu_;

View File

@ -5,7 +5,7 @@ import { Text, View } from 'react-native';
import { Divider } from 'react-native-paper'; import { Divider } from 'react-native-paper';
import { Avatar } from '../../../base/avatar'; import { Avatar } from '../../../base/avatar';
import { BottomSheet, isDialogOpen } from '../../../base/dialog'; import { BottomSheet, hideSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles'; import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { import {
getParticipantById, getParticipantById,
@ -13,7 +13,6 @@ import {
} from '../../../base/participants'; } from '../../../base/participants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { SharedVideoButton } from '../../../shared-video/components'; import { SharedVideoButton } from '../../../shared-video/components';
import { hideSharedVideoMenu } from '../../actions.native';
import styles from './styles'; import styles from './styles';
@ -51,9 +50,6 @@ type Props = {
_participantDisplayName: string, _participantDisplayName: string,
} }
// eslint-disable-next-line prefer-const
let SharedVideoMenu_;
/** /**
* Class to implement a popup menu that opens upon long pressing a fake participant thumbnail. * Class to implement a popup menu that opens upon long pressing a fake participant thumbnail.
*/ */
@ -90,7 +86,6 @@ class SharedVideoMenu extends PureComponent<Props> {
return ( return (
<BottomSheet <BottomSheet
onCancel = { this._onCancel }
renderHeader = { this._renderMenuHeader } renderHeader = { this._renderMenuHeader }
showSlidingView = { _isParticipantAvailable }> showSlidingView = { _isParticipantAvailable }>
<Divider style = { styles.divider } /> <Divider style = { styles.divider } />
@ -99,8 +94,6 @@ class SharedVideoMenu extends PureComponent<Props> {
); );
} }
_onCancel: () => boolean;
/** /**
* Callback to hide the {@code SharedVideoMenu}. * Callback to hide the {@code SharedVideoMenu}.
* *
@ -108,17 +101,9 @@ class SharedVideoMenu extends PureComponent<Props> {
* @returns {boolean} * @returns {boolean}
*/ */
_onCancel() { _onCancel() {
if (this.props._isOpen) { this.props.dispatch(hideSheet());
this.props.dispatch(hideSharedVideoMenu());
return true;
} }
return false;
}
_renderMenuHeader: () => React$Element<any>;
/** /**
* Function to render the menu's header. * Function to render the menu's header.
* *
@ -156,12 +141,9 @@ function _mapStateToProps(state, ownProps) {
const isParticipantAvailable = getParticipantById(state, participantId); const isParticipantAvailable = getParticipantById(state, participantId);
return { return {
_isOpen: isDialogOpen(state, SharedVideoMenu_),
_isParticipantAvailable: Boolean(isParticipantAvailable), _isParticipantAvailable: Boolean(isParticipantAvailable),
_participantDisplayName: getParticipantDisplayName(state, participantId) _participantDisplayName: getParticipantDisplayName(state, participantId)
}; };
} }
SharedVideoMenu_ = connect(_mapStateToProps)(SharedVideoMenu); export default connect(_mapStateToProps)(SharedVideoMenu);
export default SharedVideoMenu_;