diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 637e69f66..48784f20f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -749,4 +749,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: bef1335067eaa4e8c558b1248f8ab3948de855bc -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/react/features/app/components/App.native.js b/react/features/app/components/App.native.js index b374d38b5..4c2f1e707 100644 --- a/react/features/app/components/App.native.js +++ b/react/features/app/components/App.native.js @@ -1,10 +1,11 @@ // @flow -import React from 'react'; +import React, { Fragment } from 'react'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import SplashScreen from 'react-native-splash-screen'; import { DialogContainer } from '../../base/dialog'; +import BottomSheetContainer from '../../base/dialog/components/native/BottomSheetContainer'; import { updateFlags } from '../../base/flags/actions'; import { CALL_INTEGRATION_ENABLED, SERVER_URL_CHANGE_ENABLED } from '../../base/flags/constants'; import { getFeatureFlag } from '../../base/flags/functions'; @@ -240,7 +241,10 @@ export class App extends AbstractApp { */ _renderDialogContainer() { return ( - + + + + ); } } diff --git a/react/features/base/dialog/actionTypes.ts b/react/features/base/dialog/actionTypes.ts index 365f98061..266fea5bb 100644 --- a/react/features/base/dialog/actionTypes.ts +++ b/react/features/base/dialog/actionTypes.ts @@ -7,6 +7,15 @@ */ 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. * @@ -18,3 +27,15 @@ export const HIDE_DIALOG = 'HIDE_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'; diff --git a/react/features/base/dialog/actions.js b/react/features/base/dialog/actions.js index 31075f028..8ec133466 100644 --- a/react/features/base/dialog/actions.js +++ b/react/features/base/dialog/actions.js @@ -2,7 +2,12 @@ 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'; /** @@ -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. * @@ -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 * is not already open. If it is open, then Dialog is signaled to close its diff --git a/react/features/base/dialog/components/native/BottomSheet.js b/react/features/base/dialog/components/native/BottomSheet.js index 055278527..5dfa1e5a8 100644 --- a/react/features/base/dialog/components/native/BottomSheet.js +++ b/react/features/base/dialog/components/native/BottomSheet.js @@ -2,6 +2,8 @@ import React, { PureComponent, type Node } from 'react'; import { SafeAreaView, ScrollView, View } from 'react-native'; import { SlidingView } from '../../../react'; +import { connect } from '../../../redux'; +import { hideSheet } from '../../actions'; import { bottomSheetStyles as styles } from './styles'; @@ -20,6 +22,11 @@ type Props = { */ children: Node, + /** + * Redux Dispatch function. + */ + dispatch: Function, + /** * Handler for the cancel event, which happens when the user dismisses * the sheet. @@ -61,6 +68,31 @@ class BottomSheet extends PureComponent { 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()}. * @@ -80,7 +112,7 @@ class BottomSheet extends PureComponent { { } } -export default BottomSheet; +export default connect()(BottomSheet); diff --git a/react/features/base/dialog/components/native/BottomSheetContainer.tsx b/react/features/base/dialog/components/native/BottomSheetContainer.tsx new file mode 100644 index 000000000..35cc80caa --- /dev/null +++ b/react/features/base/dialog/components/native/BottomSheetContainer.tsx @@ -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 ( + + { React.createElement(sheet, sheetProps) } + + ); +} + +export default BottomSheetContainer; diff --git a/react/features/base/dialog/reducer.js b/react/features/base/dialog/reducer.js index cafde62be..56b47911b 100644 --- a/react/features/base/dialog/reducer.js +++ b/react/features/base/dialog/reducer.js @@ -1,8 +1,11 @@ -/* @flow */ - 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. @@ -32,6 +35,18 @@ ReducerRegistry.register('features/base/dialog', (state = {}, action) => { component: action.component, 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; diff --git a/react/features/conference/components/native/carmode/SoundDeviceButton.tsx b/react/features/conference/components/native/carmode/SoundDeviceButton.tsx index 96921f19b..8ac3fc553 100644 --- a/react/features/conference/components/native/carmode/SoundDeviceButton.tsx +++ b/react/features/conference/components/native/carmode/SoundDeviceButton.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { Button } from 'react-native-paper'; 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 AudioIcon from './AudioIcon'; @@ -19,7 +19,7 @@ const SelectSoundDevice = () : JSX.Element => { const dispatch = useDispatch(); const onSelect = useCallback(() => - dispatch(openDialog(AudioRoutePickerDialog)) + dispatch(openSheet(AudioRoutePickerDialog)) , [ dispatch ]); return ( diff --git a/react/features/mobile/audio-mode/components/AudioDeviceToggleButton.js b/react/features/mobile/audio-mode/components/AudioDeviceToggleButton.js index eeb30f581..a229c89f5 100644 --- a/react/features/mobile/audio-mode/components/AudioDeviceToggleButton.js +++ b/react/features/mobile/audio-mode/components/AudioDeviceToggleButton.js @@ -1,7 +1,6 @@ -// @flow import type { Dispatch } from 'redux'; -import { openDialog } from '../../../base/dialog'; +import { openSheet } from '../../../base/dialog'; import { translate } from '../../../base/i18n'; import { IconVolumeEmpty } from '../../../base/icons'; import { connect } from '../../../base/redux'; @@ -32,7 +31,7 @@ class AudioDeviceToggleButton extends AbstractButton { * @returns {void} */ _handleClick() { - this.props.dispatch(openDialog(AudioRoutePickerDialog)); + this.props.dispatch(openSheet(AudioRoutePickerDialog)); } } diff --git a/react/features/mobile/audio-mode/components/AudioRoutePickerDialog.js b/react/features/mobile/audio-mode/components/AudioRoutePickerDialog.js index 3d0b01f91..ea8029c4f 100644 --- a/react/features/mobile/audio-mode/components/AudioRoutePickerDialog.js +++ b/react/features/mobile/audio-mode/components/AudioRoutePickerDialog.js @@ -1,10 +1,8 @@ -// @flow - import _ from 'lodash'; import React, { Component } from 'react'; 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 { translate } from '../../../base/i18n'; 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 * is required to join a conference. @@ -218,36 +211,10 @@ class AudioRoutePickerDialog extends Component { constructor(props: Props) { super(props); - // Bind event handlers so they are only bound once per instance. - this._onCancel = this._onCancel.bind(this); - // Trigger an initial update. 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 * on the sheet. The selected device will be used by {@code AudioMode}. @@ -258,7 +225,7 @@ class AudioRoutePickerDialog extends Component { */ _onSelectDeviceFn(device: Device) { return () => { - this._hide(); + this.props.dispatch(hideSheet()); AudioMode.setAudioDevice(device.uid || device.type); }; } @@ -329,7 +296,7 @@ class AudioRoutePickerDialog extends Component { } return ( - + { content } ); @@ -348,6 +315,4 @@ function _mapStateToProps(state) { }; } -AudioRoutePickerDialog_ = translate(connect(_mapStateToProps)(AudioRoutePickerDialog)); - -export default AudioRoutePickerDialog_; +export default translate(connect(_mapStateToProps)(AudioRoutePickerDialog)); diff --git a/react/features/participants-pane/actions.native.js b/react/features/participants-pane/actions.native.js index 13355b6ec..b145c9c0f 100644 --- a/react/features/participants-pane/actions.native.js +++ b/react/features/participants-pane/actions.native.js @@ -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 { LocalVideoMenu } from '../video-menu/components/native'; import ConnectionStatusComponent @@ -20,7 +20,7 @@ export * from './actions.any'; * @returns {Function} */ export function showContextMenuReject(participant: Object) { - return openDialog(ContextMenuLobbyParticipantReject, { participant }); + return openSheet(ContextMenuLobbyParticipantReject, { participant }); } @@ -31,7 +31,7 @@ export function showContextMenuReject(participant: Object) { * @returns {Function} */ 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']; if (local) { - dispatch(openDialog(LocalVideoMenu)); + dispatch(openSheet(LocalVideoMenu)); } 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} */ export function showSharedVideoMenu(participantId: string) { - return openDialog(SharedVideoMenu, { participantId }); + return openSheet(SharedVideoMenu, { participantId }); } /** diff --git a/react/features/participants-pane/components/breakout-rooms/components/native/BreakoutRoomContextMenu.js b/react/features/participants-pane/components/breakout-rooms/components/native/BreakoutRoomContextMenu.js index ba1b1ee05..dd3deb6ca 100644 --- a/react/features/participants-pane/components/breakout-rooms/components/native/BreakoutRoomContextMenu.js +++ b/react/features/participants-pane/components/breakout-rooms/components/native/BreakoutRoomContextMenu.js @@ -1,5 +1,3 @@ -// @flow - import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { TouchableOpacity } from 'react-native'; @@ -7,7 +5,7 @@ import { Text } from 'react-native-paper'; import { useDispatch, useSelector } from 'react-redux'; 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 { Icon, @@ -29,7 +27,6 @@ type Props = { const BreakoutRoomContextMenu = ({ room }: Props) => { const dispatch = useDispatch(); - const closeDialog = useCallback(() => dispatch(hideDialog()), [ dispatch ]); const isLocalModerator = useSelector(isLocalParticipantModerator); const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig); const { t } = useTranslation(); @@ -37,23 +34,22 @@ const BreakoutRoomContextMenu = ({ room }: Props) => { const onJoinRoom = useCallback(() => { sendAnalytics(createBreakoutRoomsEvent('join')); dispatch(moveToRoom(room.jid)); - closeDialog(); + dispatch(hideSheet()); }, [ dispatch, room ]); const onRemoveBreakoutRoom = useCallback(() => { dispatch(removeBreakoutRoom(room.jid)); - closeDialog(); + dispatch(hideSheet()); }, [ dispatch, room ]); const onCloseBreakoutRoom = useCallback(() => { dispatch(closeBreakoutRoom(room.id)); - closeDialog(); + dispatch(hideSheet()); }, [ dispatch, room ]); return ( { !hideJoinRoomButton && ( diff --git a/react/features/participants-pane/components/breakout-rooms/components/native/CollapsibleRoom.js b/react/features/participants-pane/components/breakout-rooms/components/native/CollapsibleRoom.js index 273a4a39d..2fdc50be8 100644 --- a/react/features/participants-pane/components/breakout-rooms/components/native/CollapsibleRoom.js +++ b/react/features/participants-pane/components/breakout-rooms/components/native/CollapsibleRoom.js @@ -1,11 +1,9 @@ -// @flow - import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { FlatList } from 'react-native'; import { useDispatch } from 'react-redux'; -import { openDialog } from '../../../../../base/dialog'; +import { openSheet } from '../../../../../base/dialog'; import { participantMatchesSearch } from '../../../../functions'; import CollapsibleList from '../../../native/CollapsibleList'; import styles from '../../../native/styles'; @@ -41,7 +39,7 @@ export const CollapsibleRoom = ({ room, searchString }: Props) => { const dispatch = useDispatch(); const { t } = useTranslation(); const _openContextMenu = useCallback(() => { - dispatch(openDialog(BreakoutRoomContextMenu, { room })); + dispatch(openSheet(BreakoutRoomContextMenu, { room })); }, [ room ]); const roomParticipantsNr = Object.values(room.participants || {}).length; const title diff --git a/react/features/participants-pane/components/native/ContextMenuLobbyParticipantReject.js b/react/features/participants-pane/components/native/ContextMenuLobbyParticipantReject.js index b92850f92..a861a911d 100644 --- a/react/features/participants-pane/components/native/ContextMenuLobbyParticipantReject.js +++ b/react/features/participants-pane/components/native/ContextMenuLobbyParticipantReject.js @@ -1,5 +1,3 @@ -// @flow - import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { TouchableOpacity, View } from 'react-native'; @@ -7,7 +5,6 @@ import { Text } from 'react-native-paper'; import { useDispatch, useSelector } from 'react-redux'; import { Avatar } from '../../../base/avatar'; -import { hideDialog } from '../../../base/dialog'; import BottomSheet from '../../../base/dialog/components/native/BottomSheet'; import { Icon, IconClose @@ -16,6 +13,7 @@ import { setKnockingParticipantApproval } from '../../../lobby/actions.native'; import { getKnockingParticipantsById } from '../../../lobby/functions'; import styles from './styles'; + type Props = { /** @@ -28,7 +26,6 @@ const ContextMenuLobbyParticipantReject = ({ participant: p }: Props) => { const dispatch = useDispatch(); const knockParticipantsIDArr = useSelector(getKnockingParticipantsById); const knockParticipantIsAvailable = knockParticipantsIDArr.find(knockPartId => knockPartId === p.id); - const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]); const displayName = p.name; const reject = useCallback(() => dispatch(setKnockingParticipantApproval(p.id, false), [ dispatch ])); const { t } = useTranslation(); @@ -50,7 +47,6 @@ const ContextMenuLobbyParticipantReject = ({ participant: p }: Props) => { return ( { const dispatch = useDispatch(); - const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]); - const muteAllVideo = useCallback(() => - dispatch(openDialog(MuteEveryonesVideoDialog)), - [ dispatch ]); + const muteAllVideo = useCallback(() => { + dispatch(openDialog(MuteEveryonesVideoDialog)); + dispatch(hideSheet()); + }, [ dispatch ]); const { t } = useTranslation(); const isModerationSupported = useSelector(isAvModerationSupported); @@ -54,7 +52,6 @@ export const ContextMenuMore = () => { return ( { const dispatch = useDispatch(); const [ searchString, setSearchString ] = useState(''); - const openMoreMenu = useCallback(() => dispatch(openDialog(ContextMenuMore)), [ dispatch ]); + const openMoreMenu = useCallback(() => dispatch(openSheet(ContextMenuMore)), [ dispatch ]); const isLocalModerator = useSelector(isLocalParticipantModerator); const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)), [ dispatch ]); diff --git a/react/features/recent-list/components/RecentList.native.js b/react/features/recent-list/components/RecentList.native.js index 9dd36a9c4..c43b49e46 100644 --- a/react/features/recent-list/components/RecentList.native.js +++ b/react/features/recent-list/components/RecentList.native.js @@ -1,11 +1,9 @@ -// @flow - import React from 'react'; import { TouchableWithoutFeedback, View } from 'react-native'; import type { Dispatch } from 'redux'; import { getDefaultURL } from '../../app/functions'; -import { openDialog } from '../../base/dialog/actions'; +import { openSheet } from '../../base/dialog/actions'; import { translate } from '../../base/i18n'; import { NavigateSectionList, type Section } from '../../base/react'; import { connect } from '../../base/redux'; @@ -56,9 +54,6 @@ type Props = { * */ class RecentList extends AbstractRecentList { - _getRenderListEmptyComponent: () => React$Node; - _onPress: string => {}; - /** * Initializes a new {@code RecentList} instance. * @@ -105,8 +100,6 @@ class RecentList extends AbstractRecentList { ); } - _onLongPress: (Object) => void; - /** * Handles the list's navigate action. * @@ -115,7 +108,7 @@ class RecentList extends AbstractRecentList { * @returns {void} */ _onLongPress(item) { - this.props.dispatch(openDialog(RecentListItemMenu, { item })); + this.props.dispatch(openSheet(RecentListItemMenu, { item })); } } diff --git a/react/features/recent-list/components/RecentListItemMenu.native.js b/react/features/recent-list/components/RecentListItemMenu.native.js index 6d1d65c2d..fe2ab330a 100644 --- a/react/features/recent-list/components/RecentListItemMenu.native.js +++ b/react/features/recent-list/components/RecentListItemMenu.native.js @@ -1,9 +1,7 @@ -// @flow - import React, { PureComponent } from 'react'; 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 { type Item } from '../../base/react/Types'; import { connect } from '../../base/redux'; @@ -22,17 +20,9 @@ type Props = { /** * Item being rendered in this menu. */ - item: Item, - - /** - * True if the menu is currently open, false otherwise. - */ - _isOpen: boolean + item: Item } -// eslint-disable-next-line prefer-const -let RecentListItemMenu_; - /** * Class to implement a popup menu that opens upon long pressing a recent list item. */ @@ -65,7 +55,6 @@ class RecentListItemMenu extends PureComponent { return ( @@ -73,8 +62,6 @@ class RecentListItemMenu extends PureComponent { ); } - _onCancel: () => boolean; - /** * Callback to hide this menu. * @@ -82,17 +69,9 @@ class RecentListItemMenu extends PureComponent { * @returns {boolean} */ _onCancel() { - if (this.props._isOpen) { - this.props.dispatch(hideDialog(RecentListItemMenu_)); - - return true; - } - - return false; + this.props.dispatch(hideSheet()); } - _renderMenuHeader: () => React$Element; - /** * Function to render the menu's header. * @@ -118,19 +97,4 @@ class RecentListItemMenu extends PureComponent { } } -/** - * 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_; +export default connect()(RecentListItemMenu); diff --git a/react/features/recording/actions.native.js b/react/features/recording/actions.native.js index e1a02cd2e..2338565ee 100644 --- a/react/features/recording/actions.native.js +++ b/react/features/recording/actions.native.js @@ -1,6 +1,4 @@ -// @flow - -import { openDialog } from '../base/dialog'; +import { openSheet } from '../base/dialog'; import JitsiMeetJS from '../base/lib-jitsi-meet'; import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications'; @@ -15,7 +13,7 @@ export * from './actions.any'; */ export function openHighlightDialog() { return (dispatch: Function) => { - dispatch(openDialog(HighlightDialog)); + dispatch(openSheet(HighlightDialog)); }; } diff --git a/react/features/recording/components/Recording/native/HighlightDialog.js b/react/features/recording/components/Recording/native/HighlightDialog.js index 2384d1fd5..99679300b 100644 --- a/react/features/recording/components/Recording/native/HighlightDialog.js +++ b/react/features/recording/components/Recording/native/HighlightDialog.js @@ -1,27 +1,26 @@ -// @flow import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { Text, View } from 'react-native'; import { Button } from 'react-native-paper'; import { useDispatch, batch } from 'react-redux'; -import { hideDialog, BottomSheet } from '../../../../base/dialog'; +import { BottomSheet, hideSheet } from '../../../../base/dialog'; import { highlightMeetingMoment } from '../../../actions.any'; import styles from '../styles.native'; const HighlightDialog = () => { const dispatch = useDispatch(); const { t } = useTranslation(); - const closeDialog = useCallback(() => dispatch(hideDialog()), [ dispatch ]); + const closeDialog = useCallback(() => dispatch(hideSheet()), [ dispatch ]); const highlightMoment = useCallback(() => { batch(() => { dispatch(highlightMeetingMoment()); - dispatch(hideDialog()); + dispatch(hideSheet()); }); }, [ dispatch ]); return ( - + { `${t('recording.highlightMoment')}?` } diff --git a/react/features/toolbox/components/native/OverflowMenu.js b/react/features/toolbox/components/native/OverflowMenu.js index 8db04d9d6..9153dd7ad 100644 --- a/react/features/toolbox/components/native/OverflowMenu.js +++ b/react/features/toolbox/components/native/OverflowMenu.js @@ -3,7 +3,7 @@ import React, { PureComponent } from 'react'; 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 { connect } from '../../../base/redux'; import { SharedDocumentButton } from '../../../etherpad'; @@ -73,15 +73,6 @@ type State = { 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 * those in the toolbar. @@ -139,7 +130,6 @@ class OverflowMenu extends PureComponent { return ( @@ -167,26 +157,16 @@ class OverflowMenu extends PureComponent { ); } - _onCancel: () => boolean; - /** * Hides this {@code OverflowMenu}. * * @private - * @returns {boolean} + * @returns {void} */ _onCancel() { - if (this.props._isOpen) { - this.props.dispatch(hideDialog(OverflowMenu_)); - - return true; - } - - return false; + this.props.dispatch(hideSheet()); } - _renderReactionMenu: () => React$Element; - /** * 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']; return { - _isOpen: isDialogOpen(state, OverflowMenu_), _reactionsEnabled: isReactionsEnabled(state), _selfViewHidden: Boolean(disableSelfView), _width: state['features/base/responsive-ui'].clientWidth }; } -OverflowMenu_ = connect(_mapStateToProps)(OverflowMenu); - -export default OverflowMenu_; +export default connect(_mapStateToProps)(OverflowMenu); diff --git a/react/features/toolbox/components/native/OverflowMenuButton.js b/react/features/toolbox/components/native/OverflowMenuButton.js index 40e02f617..b803556c4 100644 --- a/react/features/toolbox/components/native/OverflowMenuButton.js +++ b/react/features/toolbox/components/native/OverflowMenuButton.js @@ -1,6 +1,4 @@ -// @flow - -import { openDialog } from '../../../base/dialog'; +import { openSheet } from '../../../base/dialog'; import { getFeatureFlag, OVERFLOW_MENU_ENABLED } from '../../../base/flags'; import { translate } from '../../../base/i18n'; import { IconHorizontalPoints } from '../../../base/icons'; @@ -35,7 +33,7 @@ class OverflowMenuButton extends AbstractButton { * @returns {void} */ _handleClick() { - this.props.dispatch(openDialog(OverflowMenu)); + this.props.dispatch(openSheet(OverflowMenu)); } } diff --git a/react/features/video-menu/actions.native.js b/react/features/video-menu/actions.native.js index bf0ac7209..02b37d475 100644 --- a/react/features/video-menu/actions.native.js +++ b/react/features/video-menu/actions.native.js @@ -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'; diff --git a/react/features/video-menu/components/native/ConnectionStatusButton.js b/react/features/video-menu/components/native/ConnectionStatusButton.js index 3614d5793..851e76ce7 100644 --- a/react/features/video-menu/components/native/ConnectionStatusButton.js +++ b/react/features/video-menu/components/native/ConnectionStatusButton.js @@ -1,6 +1,4 @@ -// @flow - -import { openDialog } from '../../../base/dialog'; +import { openSheet } from '../../../base/dialog'; import { translate } from '../../../base/i18n'; import { IconInfo } from '../../../base/icons'; import { connect } from '../../../base/redux'; @@ -42,7 +40,7 @@ class ConnectionStatusButton extends AbstractButton { _handleClick() { const { dispatch, participantID } = this.props; - dispatch(openDialog(ConnectionStatusComponent, { + dispatch(openSheet(ConnectionStatusComponent, { participantID })); } diff --git a/react/features/video-menu/components/native/ConnectionStatusComponent.js b/react/features/video-menu/components/native/ConnectionStatusComponent.js index dd4dc1c8c..8d65980de 100644 --- a/react/features/video-menu/components/native/ConnectionStatusComponent.js +++ b/react/features/video-menu/components/native/ConnectionStatusComponent.js @@ -1,13 +1,10 @@ -// @flow - import React, { Component } from 'react'; import { Text, View } from 'react-native'; import { withTheme } from 'react-native-paper'; - import { Avatar } from '../../../base/avatar'; 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 { translate } from '../../../base/i18n'; import { IconArrowDownLarge, IconArrowUpLarge } from '../../../base/icons'; @@ -87,9 +84,6 @@ type State = { connectionString: string }; -// eslint-disable-next-line prefer-const -let ConnectionStatusComponent_; - /** * Class to implement a popup menu that show the connection statistics. */ @@ -126,9 +120,9 @@ class ConnectionStatusComponent extends Component { * Implements React's {@link Component#render()}. * * @inheritdoc - * @returns {React$Node} + * @returns {ReactNode} */ - render(): React$Node { + render() { const { t, theme } = this.props; const { palette } = theme; @@ -402,8 +396,6 @@ class ConnectionStatusComponent extends Component { } } - _onCancel: () => boolean; - /** * Callback to hide the {@code ConnectionStatusComponent}. * @@ -419,17 +411,9 @@ class ConnectionStatusComponent extends Component { this.props._sourceName, this._onStatsUpdated); } - if (this.props._isOpen) { - this.props.dispatch(hideDialog(ConnectionStatusComponent_)); - - return true; - } - - return false; + this.props.dispatch(hideSheet()); } - _renderMenuHeader: () => React$Element; - /** * Function to render the menu's header. * @@ -466,13 +450,10 @@ function _mapStateToProps(state, ownProps) { const { participantID } = ownProps; return { - _isOpen: isDialogOpen(state, ConnectionStatusComponent_), _participantDisplayName: getParticipantDisplayName(state, participantID), _sourceNameSignalingEnabled: getSourceNameSignalingFeatureFlag(state), _sourceName: getSourceNameByParticipantId(state, ownProps.participantId) }; } -ConnectionStatusComponent_ = translate(connect(_mapStateToProps)(withTheme(ConnectionStatusComponent))); - -export default ConnectionStatusComponent_; +export default translate(connect(_mapStateToProps)(withTheme(ConnectionStatusComponent))); diff --git a/react/features/video-menu/components/native/LocalVideoMenu.js b/react/features/video-menu/components/native/LocalVideoMenu.js index ecd56df30..33347eb8e 100644 --- a/react/features/video-menu/components/native/LocalVideoMenu.js +++ b/react/features/video-menu/components/native/LocalVideoMenu.js @@ -1,10 +1,8 @@ -// @flow - import React, { PureComponent } from 'react'; import { Text, View } from 'react-native'; 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 { translate } from '../../../base/i18n'; import { @@ -13,7 +11,6 @@ import { } from '../../../base/participants'; import { connect } from '../../../base/redux'; import ToggleSelfViewButton from '../../../toolbox/components/native/ToggleSelfViewButton'; -import { hideLocalVideoMenu } from '../../actions.native'; import ConnectionStatusButton from './ConnectionStatusButton'; import styles from './styles'; @@ -26,11 +23,6 @@ const AVATAR_SIZE = 24; type Props = { - /** - * True if the menu is currently open, false otherwise. - */ - _isOpen: boolean, - /** * The local participant. */ @@ -52,9 +44,6 @@ type Props = { t: Function } -// eslint-disable-next-line prefer-const -let LocalVideoMenu_; - /** * Class to implement a popup menu that opens upon long pressing a thumbnail. */ @@ -67,7 +56,6 @@ class LocalVideoMenu extends PureComponent { constructor(props: Props) { super(props); - this._onCancel = this._onCancel.bind(this); this._renderMenuHeader = this._renderMenuHeader.bind(this); } @@ -79,7 +67,6 @@ class LocalVideoMenu extends PureComponent { render() { const { _participant } = this.props; const buttonProps = { - afterClick: this._onCancel, showLabel: true, participantID: _participant.id, styles: bottomSheetStyles.buttons @@ -87,7 +74,6 @@ class LocalVideoMenu extends PureComponent { return ( @@ -96,26 +82,6 @@ class LocalVideoMenu extends PureComponent { ); } - _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; - /** * Function to render the menu's header. * @@ -151,12 +117,9 @@ function _mapStateToProps(state) { const participant = getLocalParticipant(state); return { - _isOpen: isDialogOpen(state, LocalVideoMenu_), _participant: participant, _participantDisplayName: getParticipantDisplayName(state, participant.id) }; } -LocalVideoMenu_ = translate(connect(_mapStateToProps)(LocalVideoMenu)); - -export default LocalVideoMenu_; +export default translate(connect(_mapStateToProps)(LocalVideoMenu)); diff --git a/react/features/video-menu/components/native/RemoteVideoMenu.js b/react/features/video-menu/components/native/RemoteVideoMenu.js index e2109458a..5128d9448 100644 --- a/react/features/video-menu/components/native/RemoteVideoMenu.js +++ b/react/features/video-menu/components/native/RemoteVideoMenu.js @@ -1,11 +1,9 @@ -// @flow - import React, { PureComponent } from 'react'; import { Text, View } from 'react-native'; import { Divider } from 'react-native-paper'; 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 { KICK_OUT_ENABLED, getFeatureFlag } from '../../../base/flags'; import { translate } from '../../../base/i18n'; @@ -16,7 +14,6 @@ import { import { connect } from '../../../base/redux'; import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions'; import PrivateMessageButton from '../../../chat/components/native/PrivateMessageButton'; -import { hideRemoteVideoMenu } from '../../actions.native'; import ConnectionStatusButton from '../native/ConnectionStatusButton'; import AskUnmuteButton from './AskUnmuteButton'; @@ -74,11 +71,6 @@ type Props = { */ _disableGrantModerator: Boolean, - /** - * True if the menu is currently open, false otherwise. - */ - _isOpen: boolean, - /** * Whether the participant is present in the room or not. */ @@ -100,9 +92,6 @@ type Props = { t: Function } -// eslint-disable-next-line prefer-const -let RemoteVideoMenu_; - /** * Class to implement a popup menu that opens upon long pressing a thumbnail. */ @@ -145,7 +134,6 @@ class RemoteVideoMenu extends PureComponent { return ( @@ -157,7 +145,9 @@ class RemoteVideoMenu extends PureComponent { { !_disableGrantModerator && } { !_disablePrivateChat && } - + {_rooms.length > 1 && <> @@ -175,8 +165,6 @@ class RemoteVideoMenu extends PureComponent { ); } - _onCancel: () => boolean; - /** * Callback to hide the {@code RemoteVideoMenu}. * @@ -184,17 +172,9 @@ class RemoteVideoMenu extends PureComponent { * @returns {boolean} */ _onCancel() { - if (this.props._isOpen) { - this.props.dispatch(hideRemoteVideoMenu()); - - return true; - } - - return false; + this.props.dispatch(hideSheet()); } - _renderMenuHeader: () => React$Element; - /** * Function to render the menu's header. * @@ -242,13 +222,10 @@ function _mapStateToProps(state, ownProps) { _disableKick: Boolean(shouldDisableKick), _disableRemoteMute: Boolean(disableRemoteMute), _disablePrivateChat: Boolean(disablePrivateChat), - _isOpen: isDialogOpen(state, RemoteVideoMenu_), _isParticipantAvailable: Boolean(isParticipantAvailable), _participantDisplayName: getParticipantDisplayName(state, participantId), _rooms }; } -RemoteVideoMenu_ = translate(connect(_mapStateToProps)(RemoteVideoMenu)); - -export default RemoteVideoMenu_; +export default translate(connect(_mapStateToProps)(RemoteVideoMenu)); diff --git a/react/features/video-menu/components/native/SharedVideoMenu.js b/react/features/video-menu/components/native/SharedVideoMenu.js index c6e015d85..18a6cdb7b 100644 --- a/react/features/video-menu/components/native/SharedVideoMenu.js +++ b/react/features/video-menu/components/native/SharedVideoMenu.js @@ -5,7 +5,7 @@ import { Text, View } from 'react-native'; import { Divider } from 'react-native-paper'; 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 { getParticipantById, @@ -13,7 +13,6 @@ import { } from '../../../base/participants'; import { connect } from '../../../base/redux'; import { SharedVideoButton } from '../../../shared-video/components'; -import { hideSharedVideoMenu } from '../../actions.native'; import styles from './styles'; @@ -51,9 +50,6 @@ type Props = { _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. */ @@ -90,7 +86,6 @@ class SharedVideoMenu extends PureComponent { return ( @@ -99,8 +94,6 @@ class SharedVideoMenu extends PureComponent { ); } - _onCancel: () => boolean; - /** * Callback to hide the {@code SharedVideoMenu}. * @@ -108,17 +101,9 @@ class SharedVideoMenu extends PureComponent { * @returns {boolean} */ _onCancel() { - if (this.props._isOpen) { - this.props.dispatch(hideSharedVideoMenu()); - - return true; - } - - return false; + this.props.dispatch(hideSheet()); } - _renderMenuHeader: () => React$Element; - /** * Function to render the menu's header. * @@ -156,12 +141,9 @@ function _mapStateToProps(state, ownProps) { const isParticipantAvailable = getParticipantById(state, participantId); return { - _isOpen: isDialogOpen(state, SharedVideoMenu_), _isParticipantAvailable: Boolean(isParticipantAvailable), _participantDisplayName: getParticipantDisplayName(state, participantId) }; } -SharedVideoMenu_ = connect(_mapStateToProps)(SharedVideoMenu); - -export default SharedVideoMenu_; +export default connect(_mapStateToProps)(SharedVideoMenu);