This commit is contained in:
1
react/features/mobile/navigation/actionTypes.ts
Normal file
1
react/features/mobile/navigation/actionTypes.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const _ROOT_NAVIGATION_READY = '_ROOT_NAVIGATION_READY';
|
||||
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SafeAreaView, Text, View, ViewStyle } from 'react-native';
|
||||
|
||||
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
|
||||
import LoadingIndicator from '../../../base/react/components/native/LoadingIndicator';
|
||||
|
||||
import { TEXT_COLOR, navigationStyles } from './styles';
|
||||
|
||||
|
||||
const ConnectingPage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<JitsiScreen style = { navigationStyles.connectingScreenContainer }>
|
||||
<View style = { navigationStyles.connectingScreenContent as ViewStyle }>
|
||||
<SafeAreaView>
|
||||
<LoadingIndicator
|
||||
color = { TEXT_COLOR }
|
||||
size = 'large' />
|
||||
<Text style = { navigationStyles.connectingScreenText }>
|
||||
{ t('connectingOverlay.joiningRoom') }
|
||||
</Text>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</JitsiScreen>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectingPage;
|
||||
@@ -0,0 +1,103 @@
|
||||
import React from 'react';
|
||||
import { GestureResponderEvent } from 'react-native';
|
||||
|
||||
import { StyleType } from '../../../base/styles/functions.native';
|
||||
import Button from '../../../base/ui/components/native/Button';
|
||||
import IconButton from '../../../base/ui/components/native/IconButton';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
|
||||
import { navigationStyles } from './styles';
|
||||
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Icon button color.
|
||||
*/
|
||||
color?: string;
|
||||
|
||||
/**
|
||||
* Is the button disabled?
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* ID of the header navigation button.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* Label of the button.
|
||||
*/
|
||||
label?: string;
|
||||
|
||||
/**
|
||||
* Callback to invoke when the {@code HeaderNavigationButton} is clicked/pressed.
|
||||
*/
|
||||
onPress?: (e?: GestureResponderEvent | React.MouseEvent) => void;
|
||||
|
||||
/**
|
||||
* The ImageSource to be rendered as image.
|
||||
*/
|
||||
src?: any;
|
||||
|
||||
/**
|
||||
* Style of the button.
|
||||
*/
|
||||
style?: StyleType;
|
||||
|
||||
/**
|
||||
* Header has two actions.
|
||||
*/
|
||||
twoActions?: boolean;
|
||||
}
|
||||
|
||||
const HeaderNavigationButton = ({ color, id, disabled, label, onPress, src, style, twoActions }: IProps) => {
|
||||
|
||||
let btnStyle;
|
||||
let labelStyle;
|
||||
|
||||
if (disabled) {
|
||||
btnStyle = navigationStyles.headerNavigationButtonDisabled;
|
||||
labelStyle = twoActions
|
||||
? navigationStyles.headerNavigationButtonLabelBoldDisabled
|
||||
: navigationStyles.headerNavigationButtonLabelDisabled;
|
||||
} else {
|
||||
btnStyle = navigationStyles.headerNavigationButton;
|
||||
labelStyle = twoActions
|
||||
? navigationStyles.headerNavigationButtonLabelBold
|
||||
: navigationStyles.headerNavigationButtonLabel;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
src ? (
|
||||
<IconButton
|
||||
color = { color }
|
||||
id = { id }
|
||||
onPress = { onPress }
|
||||
size = { 24 }
|
||||
src = { src }
|
||||
style = { [
|
||||
navigationStyles.headerNavigationButtonIcon,
|
||||
style
|
||||
] } />
|
||||
) : (
|
||||
<Button
|
||||
disabled = { disabled }
|
||||
id = { id }
|
||||
labelKey = { label }
|
||||
labelStyle = { labelStyle }
|
||||
onClick = { onPress }
|
||||
style = { [
|
||||
btnStyle,
|
||||
style
|
||||
] }
|
||||
type = { BUTTON_TYPES.TERTIARY } />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeaderNavigationButton;
|
||||
@@ -0,0 +1,136 @@
|
||||
import { NavigationContainer, Theme } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import React, { useCallback } from 'react';
|
||||
import { StatusBar } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState, IStore } from '../../../app/types';
|
||||
import DialInSummary from '../../../invite/components/dial-in-summary/native/DialInSummary';
|
||||
import Prejoin from '../../../prejoin/components/native/Prejoin';
|
||||
import UnsafeRoomWarning from '../../../prejoin/components/native/UnsafeRoomWarning';
|
||||
import { isUnsafeRoomWarningEnabled } from '../../../prejoin/functions';
|
||||
import VisitorsQueue from '../../../visitors/components/native/VisitorsQueue';
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
import WelcomePage from '../../../welcome/components/WelcomePage';
|
||||
import { isWelcomePageEnabled } from '../../../welcome/functions';
|
||||
import { _ROOT_NAVIGATION_READY } from '../actionTypes';
|
||||
import { rootNavigationRef } from '../rootNavigationContainerRef';
|
||||
import { screen } from '../routes';
|
||||
import {
|
||||
conferenceNavigationContainerScreenOptions,
|
||||
connectingScreenOptions,
|
||||
dialInSummaryScreenOptions,
|
||||
navigationContainerTheme,
|
||||
preJoinScreenOptions,
|
||||
unsafeMeetingScreenOptions,
|
||||
visitorsScreenOptions,
|
||||
welcomeScreenOptions
|
||||
} from '../screenOptions';
|
||||
|
||||
import ConnectingPage from './ConnectingPage';
|
||||
import ConferenceNavigationContainer
|
||||
from './conference/components/ConferenceNavigationContainer';
|
||||
|
||||
const RootStack = createStackNavigator();
|
||||
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Redux dispatch function.
|
||||
*/
|
||||
dispatch: IStore['dispatch'];
|
||||
|
||||
/**
|
||||
* Is unsafe room warning available?
|
||||
*/
|
||||
isUnsafeRoomWarningAvailable: boolean;
|
||||
|
||||
/**
|
||||
* Is welcome page available?
|
||||
*/
|
||||
isWelcomePageAvailable: boolean;
|
||||
}
|
||||
|
||||
|
||||
const RootNavigationContainer = ({ dispatch, isUnsafeRoomWarningAvailable, isWelcomePageAvailable }: IProps) => {
|
||||
const initialRouteName = isWelcomePageAvailable
|
||||
? screen.welcome.main : screen.connecting;
|
||||
const onReady = useCallback(() => {
|
||||
dispatch({
|
||||
type: _ROOT_NAVIGATION_READY,
|
||||
ready: true
|
||||
});
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
independent = { true }
|
||||
onReady = { onReady }
|
||||
ref = { rootNavigationRef }
|
||||
theme = { navigationContainerTheme as Theme }>
|
||||
<StatusBar
|
||||
animated = { true }
|
||||
backgroundColor = 'transparent'
|
||||
barStyle = { 'light-content' }
|
||||
translucent = { true } />
|
||||
<RootStack.Navigator
|
||||
initialRouteName = { initialRouteName }>
|
||||
{
|
||||
isWelcomePageAvailable
|
||||
&& <>
|
||||
<RootStack.Screen // @ts-ignore
|
||||
component = { WelcomePage }
|
||||
name = { screen.welcome.main }
|
||||
options = { welcomeScreenOptions } />
|
||||
<RootStack.Screen
|
||||
|
||||
// @ts-ignore
|
||||
component = { DialInSummary }
|
||||
name = { screen.dialInSummary }
|
||||
options = { dialInSummaryScreenOptions } />
|
||||
</>
|
||||
}
|
||||
<RootStack.Screen
|
||||
component = { ConnectingPage }
|
||||
name = { screen.connecting }
|
||||
options = { connectingScreenOptions } />
|
||||
<RootStack.Screen
|
||||
component = { Prejoin }
|
||||
name = { screen.preJoin }
|
||||
options = { preJoinScreenOptions } />
|
||||
{
|
||||
isUnsafeRoomWarningAvailable
|
||||
&& <RootStack.Screen
|
||||
component = { UnsafeRoomWarning }
|
||||
name = { screen.unsafeRoomWarning }
|
||||
options = { unsafeMeetingScreenOptions } />
|
||||
}
|
||||
<RootStack.Screen
|
||||
component = { VisitorsQueue }
|
||||
name = { screen.visitorsQueue }
|
||||
options = { visitorsScreenOptions } />
|
||||
<RootStack.Screen
|
||||
component = { ConferenceNavigationContainer }
|
||||
name = { screen.conference.root }
|
||||
options = { conferenceNavigationContainerScreenOptions } />
|
||||
</RootStack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps part of the Redux store to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
isUnsafeRoomWarningAvailable: isUnsafeRoomWarningEnabled(state),
|
||||
isWelcomePageAvailable: isWelcomePageEnabled(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(RootNavigationContainer);
|
||||
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import { StyleProp, Text, TextStyle, View } from 'react-native';
|
||||
|
||||
import { navigationStyles } from './styles';
|
||||
|
||||
interface ITabBarLabelCounterProps {
|
||||
activeUnreadNr: boolean;
|
||||
isFocused: boolean;
|
||||
label: string;
|
||||
nbUnread?: number;
|
||||
}
|
||||
|
||||
export const TabBarLabelCounter = ({ activeUnreadNr, isFocused, label, nbUnread }: ITabBarLabelCounterProps) => {
|
||||
const labelStyles = isFocused
|
||||
? navigationStyles.unreadCounterDescriptionFocused
|
||||
: navigationStyles.unreadCounterDescription;
|
||||
|
||||
return (
|
||||
<View
|
||||
style = {
|
||||
navigationStyles.unreadCounterContainer as StyleProp<TextStyle> }>
|
||||
<Text
|
||||
style = { labelStyles }>
|
||||
{ label && label }
|
||||
</Text>
|
||||
{
|
||||
activeUnreadNr && (
|
||||
<View
|
||||
style = { navigationStyles.unreadCounterCircle as StyleProp<TextStyle> }>
|
||||
<Text
|
||||
style = { navigationStyles.unreadCounter as StyleProp<TextStyle> }>
|
||||
{ nbUnread }
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable lines-around-comment */
|
||||
|
||||
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../../../app/types';
|
||||
import {
|
||||
getClientHeight,
|
||||
getClientWidth
|
||||
} from '../../../../../base/modal/components/functions';
|
||||
import { setFocusedTab } from '../../../../../chat/actions.any';
|
||||
import Chat from '../../../../../chat/components/native/Chat';
|
||||
import { ChatTabs } from '../../../../../chat/constants';
|
||||
import { resetNbUnreadPollsMessages } from '../../../../../polls/actions';
|
||||
import PollsPane from '../../../../../polls/components/native/PollsPane';
|
||||
import { screen } from '../../../routes';
|
||||
import { chatTabBarOptions } from '../../../screenOptions';
|
||||
|
||||
const ChatTab = createMaterialTopTabNavigator();
|
||||
|
||||
const ChatAndPolls = () => {
|
||||
const clientHeight = useSelector(getClientHeight);
|
||||
const clientWidth = useSelector(getClientWidth);
|
||||
const dispatch = useDispatch();
|
||||
const { focusedTab } = useSelector((state: IReduxState) => state['features/chat']);
|
||||
const initialRouteName = focusedTab === ChatTabs.POLLS
|
||||
? screen.conference.chatandpolls.tab.polls
|
||||
: screen.conference.chatandpolls.tab.chat;
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<ChatTab.Navigator
|
||||
backBehavior = 'none'
|
||||
initialLayout = {{
|
||||
height: clientHeight,
|
||||
width: clientWidth
|
||||
}}
|
||||
initialRouteName = { initialRouteName }
|
||||
screenOptions = { chatTabBarOptions }>
|
||||
<ChatTab.Screen
|
||||
component = { Chat }
|
||||
listeners = {{
|
||||
tabPress: () => {
|
||||
dispatch(setFocusedTab(ChatTabs.CHAT));
|
||||
}
|
||||
}}
|
||||
name = { screen.conference.chatandpolls.tab.chat } />
|
||||
<ChatTab.Screen
|
||||
component = { PollsPane }
|
||||
listeners = {{
|
||||
tabPress: () => {
|
||||
dispatch(setFocusedTab(ChatTabs.POLLS));
|
||||
dispatch(resetNbUnreadPollsMessages);
|
||||
}
|
||||
}}
|
||||
name = { screen.conference.chatandpolls.tab.polls } />
|
||||
</ChatTab.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatAndPolls;
|
||||
@@ -0,0 +1,35 @@
|
||||
import { NavigationContainerRef } from '@react-navigation/native';
|
||||
import React from 'react';
|
||||
|
||||
export const conferenceNavigationRef = React.createRef<NavigationContainerRef<any>>();
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @param {string} name - Destination name of the route that has been defined somewhere.
|
||||
* @param {Object} params - Params to pass to the destination route.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function navigate(name: string, params?: Object) {
|
||||
return conferenceNavigationRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function goBack() {
|
||||
return conferenceNavigationRef.current?.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @param {Object} params - Params to pass to the destination route.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setParams(params: Object) {
|
||||
return conferenceNavigationRef.current?.setParams(params);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/* eslint-disable lines-around-comment */
|
||||
|
||||
import { NavigationContainer, Theme } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import BreakoutRooms
|
||||
// @ts-ignore
|
||||
from '../../../../../breakout-rooms/components/native/BreakoutRooms';
|
||||
// @ts-ignore
|
||||
import Chat from '../../../../../chat/components/native/Chat';
|
||||
// @ts-ignore
|
||||
import Conference from '../../../../../conference/components/native/Conference';
|
||||
// @ts-ignore
|
||||
import CarMode from '../../../../../conference/components/native/carmode/CarMode';
|
||||
// @ts-ignore
|
||||
import { arePollsDisabled } from '../../../../../conference/functions';
|
||||
// @ts-ignore
|
||||
import SharedDocument from '../../../../../etherpad/components/native/SharedDocument';
|
||||
// @ts-ignore
|
||||
import GifsMenu from '../../../../../gifs/components/native/GifsMenu';
|
||||
import AddPeopleDialog
|
||||
// @ts-ignore
|
||||
from '../../../../../invite/components/add-people-dialog/native/AddPeopleDialog';
|
||||
// @ts-ignore
|
||||
import ParticipantsPane from '../../../../../participants-pane/components/native/ParticipantsPane';
|
||||
// @ts-ignore
|
||||
import StartLiveStreamDialog from '../../../../../recording/components/LiveStream/native/StartLiveStreamDialog';
|
||||
import StartRecordingDialog
|
||||
// @ts-ignore
|
||||
from '../../../../../recording/components/Recording/native/StartRecordingDialog';
|
||||
import SalesforceLinkDialog
|
||||
// @ts-ignore
|
||||
from '../../../../../salesforce/components/native/SalesforceLinkDialog';
|
||||
import SecurityDialog
|
||||
// @ts-ignore
|
||||
from '../../../../../security/components/security-dialog/native/SecurityDialog';
|
||||
import SpeakerStats
|
||||
// @ts-ignore
|
||||
from '../../../../../speaker-stats/components/native/SpeakerStats';
|
||||
import LanguageSelectorDialog
|
||||
// @ts-ignore
|
||||
from '../../../../../subtitles/components/native/LanguageSelectorDialog';
|
||||
import Whiteboard from '../../../../../whiteboard/components/native/Whiteboard';
|
||||
// @ts-ignore
|
||||
import { screen } from '../../../routes';
|
||||
import {
|
||||
breakoutRoomsScreenOptions,
|
||||
carmodeScreenOptions,
|
||||
chatScreenOptions,
|
||||
conferenceScreenOptions,
|
||||
gifsMenuOptions,
|
||||
inviteScreenOptions,
|
||||
liveStreamScreenOptions,
|
||||
lobbyNavigationContainerScreenOptions,
|
||||
navigationContainerTheme,
|
||||
participantsScreenOptions,
|
||||
recordingScreenOptions,
|
||||
salesforceScreenOptions,
|
||||
securityScreenOptions,
|
||||
settingsNavigationContainerScreenOptions,
|
||||
sharedDocumentScreenOptions,
|
||||
speakerStatsScreenOptions,
|
||||
subtitlesScreenOptions,
|
||||
whiteboardScreenOptions
|
||||
// @ts-ignore
|
||||
} from '../../../screenOptions';
|
||||
// @ts-ignore
|
||||
import ChatAndPollsNavigator from '../../chat/components/ChatAndPollsNavigator';
|
||||
// @ts-ignore
|
||||
import LobbyNavigationContainer from '../../lobby/components/LobbyNavigationContainer';
|
||||
// @ts-ignore
|
||||
import SettingsNavigationContainer from '../../settings/components/SettingsNavigationContainer';
|
||||
import {
|
||||
conferenceNavigationRef
|
||||
// @ts-ignore
|
||||
} from '../ConferenceNavigationContainerRef';
|
||||
|
||||
|
||||
const ConferenceStack = createStackNavigator();
|
||||
|
||||
|
||||
const ConferenceNavigationContainer = () => {
|
||||
const isPollsDisabled = useSelector(arePollsDisabled);
|
||||
let ChatScreen;
|
||||
let chatScreenName;
|
||||
let chatTitleString;
|
||||
|
||||
if (isPollsDisabled) {
|
||||
ChatScreen = Chat;
|
||||
chatScreenName = screen.conference.chat;
|
||||
chatTitleString = 'chat.title';
|
||||
} else {
|
||||
ChatScreen = ChatAndPollsNavigator;
|
||||
chatScreenName = screen.conference.chatandpolls.main;
|
||||
chatTitleString = 'chat.titleWithPolls';
|
||||
}
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
independent = { true }
|
||||
ref = { conferenceNavigationRef }
|
||||
theme = { navigationContainerTheme as Theme }>
|
||||
<ConferenceStack.Navigator
|
||||
screenOptions = {{
|
||||
presentation: 'modal'
|
||||
}}>
|
||||
<ConferenceStack.Screen
|
||||
component = { Conference }
|
||||
name = { screen.conference.main }
|
||||
options = { conferenceScreenOptions } />
|
||||
<ConferenceStack.Screen
|
||||
component = { ChatScreen }
|
||||
name = { chatScreenName }
|
||||
options = {{
|
||||
...chatScreenOptions,
|
||||
title: t(chatTitleString)
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { ParticipantsPane }
|
||||
name = { screen.conference.participants }
|
||||
options = {{
|
||||
...participantsScreenOptions,
|
||||
title: t('participantsPane.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { SecurityDialog }
|
||||
name = { screen.conference.security }
|
||||
options = {{
|
||||
...securityScreenOptions,
|
||||
title: t('security.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { StartRecordingDialog }
|
||||
name = { screen.conference.recording }
|
||||
options = {{
|
||||
...recordingScreenOptions,
|
||||
title: t('recording.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { StartLiveStreamDialog }
|
||||
name = { screen.conference.liveStream }
|
||||
options = {{
|
||||
...liveStreamScreenOptions,
|
||||
title: t('liveStreaming.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { SpeakerStats }
|
||||
name = { screen.conference.speakerStats }
|
||||
options = {{
|
||||
...speakerStatsScreenOptions,
|
||||
title: t('speakerStats.speakerStats')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { SalesforceLinkDialog }
|
||||
name = { screen.conference.salesforce }
|
||||
options = {{
|
||||
...salesforceScreenOptions,
|
||||
title: t('notify.linkToSalesforce')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { GifsMenu }
|
||||
name = { screen.conference.gifsMenu }
|
||||
options = {{
|
||||
...gifsMenuOptions,
|
||||
title: t('notify.gifsMenu')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { LobbyNavigationContainer }
|
||||
name = { screen.lobby.root }
|
||||
options = {{
|
||||
...lobbyNavigationContainerScreenOptions,
|
||||
title: t('lobby.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { AddPeopleDialog }
|
||||
name = { screen.conference.invite }
|
||||
options = {{
|
||||
...inviteScreenOptions,
|
||||
title: t('addPeople.add')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { SharedDocument }
|
||||
name = { screen.conference.sharedDocument }
|
||||
options = {{
|
||||
...sharedDocumentScreenOptions,
|
||||
title: t('documentSharing.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
// @ts-ignore
|
||||
component = { SettingsNavigationContainer }
|
||||
name = { screen.settings.main }
|
||||
options = { settingsNavigationContainerScreenOptions } />
|
||||
<ConferenceStack.Screen
|
||||
// @ts-ignore
|
||||
component = { CarMode }
|
||||
name = { screen.conference.carmode }
|
||||
options = {{
|
||||
...carmodeScreenOptions,
|
||||
title: t('carmode.labels.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { LanguageSelectorDialog }
|
||||
name = { screen.conference.subtitles }
|
||||
options = {{
|
||||
...subtitlesScreenOptions,
|
||||
title: t('transcribing.subtitles')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
component = { BreakoutRooms }
|
||||
name = { screen.conference.breakoutRooms }
|
||||
options = {{
|
||||
...breakoutRoomsScreenOptions,
|
||||
title: t('breakoutRooms.title')
|
||||
}} />
|
||||
<ConferenceStack.Screen
|
||||
// @ts-ignore
|
||||
component = { Whiteboard }
|
||||
name = { screen.conference.whiteboard }
|
||||
options = {{
|
||||
...whiteboardScreenOptions,
|
||||
title: t('whiteboard.screenTitle')
|
||||
}} />
|
||||
</ConferenceStack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConferenceNavigationContainer;
|
||||
@@ -0,0 +1,24 @@
|
||||
import { NavigationContainerRef } from '@react-navigation/native';
|
||||
import React from 'react';
|
||||
|
||||
export const lobbyNavigationContainerRef = React.createRef<NavigationContainerRef<any>>();
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @param {string} name - Destination name of the route that has been defined somewhere.
|
||||
* @param {Object} params - Params to pass to the destination route.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function navigate(name: string, params?: Object) {
|
||||
return lobbyNavigationContainerRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function goBack() {
|
||||
return lobbyNavigationContainerRef.current?.goBack();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../../../app/types';
|
||||
import LobbyChatScreen from '../../../../../lobby/components/native/LobbyChatScreen';
|
||||
import LobbyScreen from '../../../../../lobby/components/native/LobbyScreen';
|
||||
import { screen } from '../../../routes';
|
||||
import {
|
||||
lobbyChatScreenOptions,
|
||||
lobbyScreenOptions,
|
||||
navigationContainerTheme
|
||||
} from '../../../screenOptions';
|
||||
import { lobbyNavigationContainerRef } from '../LobbyNavigationContainerRef';
|
||||
|
||||
const LobbyStack = createStackNavigator();
|
||||
|
||||
|
||||
const LobbyNavigationContainer = () => {
|
||||
const { isLobbyChatActive }
|
||||
= useSelector((state: IReduxState) => state['features/chat']);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
independent = { true }
|
||||
ref = { lobbyNavigationContainerRef }
|
||||
|
||||
// @ts-ignore
|
||||
theme = { navigationContainerTheme }>
|
||||
<LobbyStack.Navigator
|
||||
screenOptions = {{
|
||||
presentation: 'modal'
|
||||
}}>
|
||||
<LobbyStack.Screen
|
||||
component = { LobbyScreen }
|
||||
name = { screen.lobby.main }
|
||||
options = { lobbyScreenOptions } />
|
||||
{
|
||||
isLobbyChatActive
|
||||
&& <LobbyStack.Screen
|
||||
component = { LobbyChatScreen }
|
||||
name = { screen.lobby.chat }
|
||||
options = { lobbyChatScreenOptions } />
|
||||
}
|
||||
</LobbyStack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
export default LobbyNavigationContainer;
|
||||
@@ -0,0 +1,24 @@
|
||||
import { NavigationContainerRef } from '@react-navigation/native';
|
||||
import React from 'react';
|
||||
|
||||
export const settingsNavigationContainerRef = React.createRef<NavigationContainerRef<any>>();
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @param {string} name - Destination name of the route that has been defined somewhere.
|
||||
* @param {Object} params - Params to pass to the destination route.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function navigate(name: string, params?: Object) {
|
||||
return settingsNavigationContainerRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function goBack() {
|
||||
return settingsNavigationContainerRef.current?.goBack();
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { NavigationContainer, Theme } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import LanguageSelectView from '../../../../../settings/components/native/LanguageSelectView';
|
||||
import ProfileView from '../../../../../settings/components/native/ProfileView';
|
||||
import SettingsView
|
||||
from '../../../../../settings/components/native/SettingsView';
|
||||
import { screen } from '../../../routes';
|
||||
import {
|
||||
languageSelectScreenOptions,
|
||||
navigationContainerTheme,
|
||||
profileSettingsScreenOptions,
|
||||
settingsScreenOptions,
|
||||
welcomeScreenOptions
|
||||
} from '../../../screenOptions';
|
||||
import {
|
||||
settingsNavigationContainerRef
|
||||
} from '../SettingsNavigationContainerRef';
|
||||
|
||||
const SettingsStack = createStackNavigator();
|
||||
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link SettingsNavigationContainer}.
|
||||
*/
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Is the navigator part of Welcome page?
|
||||
*/
|
||||
isInWelcomePage?: boolean | undefined;
|
||||
}
|
||||
|
||||
|
||||
const SettingsNavigationContainer = ({ isInWelcomePage }: IProps) => {
|
||||
const baseSettingsScreenOptions = isInWelcomePage ? welcomeScreenOptions : settingsScreenOptions;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const SettingsScreen = useCallback(() =>
|
||||
(
|
||||
<SettingsView
|
||||
isInWelcomePage = { isInWelcomePage } />
|
||||
), []);
|
||||
|
||||
const ProfileScreen = useCallback(() =>
|
||||
(<ProfileView
|
||||
isInWelcomePage = { isInWelcomePage } />)
|
||||
, []);
|
||||
|
||||
const LanguageSelectScreen = useCallback(() =>
|
||||
(<LanguageSelectView
|
||||
isInWelcomePage = { isInWelcomePage } />)
|
||||
, []);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
independent = { true }
|
||||
ref = { settingsNavigationContainerRef }
|
||||
theme = { navigationContainerTheme as Theme }>
|
||||
<SettingsStack.Navigator
|
||||
initialRouteName = { screen.settings.main }>
|
||||
<SettingsStack.Screen
|
||||
name = { screen.settings.main }
|
||||
options = {{
|
||||
...baseSettingsScreenOptions,
|
||||
title: t('settings.title')
|
||||
}}>
|
||||
{ SettingsScreen }
|
||||
</SettingsStack.Screen>
|
||||
<SettingsStack.Screen
|
||||
component = { ProfileScreen }
|
||||
name = { screen.settings.profile }
|
||||
options = {{
|
||||
...profileSettingsScreenOptions,
|
||||
title: t('settingsView.profileSection')
|
||||
}} />
|
||||
<SettingsStack.Screen
|
||||
component = { LanguageSelectScreen }
|
||||
name = { screen.settings.language }
|
||||
options = {{
|
||||
...languageSelectScreenOptions,
|
||||
title: t('settings.language')
|
||||
}} />
|
||||
</SettingsStack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsNavigationContainer;
|
||||
114
react/features/mobile/navigation/components/styles.ts
Normal file
114
react/features/mobile/navigation/components/styles.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { BoxModel } from '../../../base/styles/components/styles/BoxModel';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
|
||||
|
||||
export const TEXT_COLOR = BaseTheme.palette.text01;
|
||||
|
||||
const unreadCounterDescription = {
|
||||
...BaseTheme.typography.bodyShortBoldLarge,
|
||||
color: BaseTheme.palette.text03
|
||||
};
|
||||
|
||||
const HEADER_ACTION_BUTTON_SIZE = 16;
|
||||
|
||||
const headerNavigationButtonLabel = {
|
||||
color: BaseTheme.palette.link01,
|
||||
fontSize: HEADER_ACTION_BUTTON_SIZE,
|
||||
lineHeight: BaseTheme.spacing[3]
|
||||
};
|
||||
|
||||
const headerNavigationButton = {
|
||||
borderRadius: BaseTheme.shape.borderRadius,
|
||||
height: BaseTheme.spacing[6],
|
||||
marginLeft: BaseTheme.spacing[3]
|
||||
};
|
||||
|
||||
/**
|
||||
* Styles of the navigation feature.
|
||||
*/
|
||||
export const navigationStyles = {
|
||||
|
||||
connectingScreenContainer: {
|
||||
backgroundColor: BaseTheme.palette.uiBackground,
|
||||
flex: 1
|
||||
},
|
||||
|
||||
connectingScreenContent: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
|
||||
connectingScreenIndicator: {
|
||||
margin: BoxModel.margin
|
||||
},
|
||||
|
||||
connectingScreenText: {
|
||||
color: TEXT_COLOR
|
||||
},
|
||||
|
||||
headerNavigationButton: {
|
||||
...headerNavigationButton
|
||||
},
|
||||
|
||||
headerNavigationButtonIcon: {
|
||||
...headerNavigationButton,
|
||||
padding: BaseTheme.spacing[2]
|
||||
},
|
||||
|
||||
headerNavigationButtonDisabled: {
|
||||
backgroundColor: 'transparent',
|
||||
marginLeft: BaseTheme.spacing[2]
|
||||
},
|
||||
|
||||
headerNavigationButtonLabel: {
|
||||
...headerNavigationButtonLabel
|
||||
},
|
||||
|
||||
headerNavigationButtonLabelDisabled: {
|
||||
...headerNavigationButtonLabel,
|
||||
color: BaseTheme.palette.text03
|
||||
},
|
||||
|
||||
headerNavigationButtonLabelBold: {
|
||||
...headerNavigationButtonLabel,
|
||||
...BaseTheme.typography.bodyShortRegularLarge
|
||||
},
|
||||
|
||||
headerNavigationButtonLabelBoldDisabled: {
|
||||
...headerNavigationButtonLabel,
|
||||
...BaseTheme.typography.bodyShortRegularLarge,
|
||||
color: BaseTheme.palette.text03
|
||||
},
|
||||
|
||||
unreadCounterContainer: {
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
|
||||
unreadCounterDescription: {
|
||||
...unreadCounterDescription
|
||||
},
|
||||
|
||||
unreadCounterDescriptionFocused: {
|
||||
...unreadCounterDescription,
|
||||
color: BaseTheme.palette.text01
|
||||
},
|
||||
|
||||
unreadCounterCircle: {
|
||||
backgroundColor: BaseTheme.palette.warning01,
|
||||
borderRadius: BaseTheme.spacing[4] / 2,
|
||||
height: BaseTheme.spacing[4],
|
||||
justifyContent: 'center',
|
||||
marginLeft: BaseTheme.spacing[2],
|
||||
width: BaseTheme.spacing[4]
|
||||
},
|
||||
|
||||
unreadCounter: {
|
||||
...BaseTheme.typography.bodyShortBold,
|
||||
alignSelf: 'center',
|
||||
color: BaseTheme.palette.text04
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,120 @@
|
||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { GestureResponderEvent } from 'react-native';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import CalendarList from '../../../../../calendar-sync/components/CalendarList.native';
|
||||
import { isCalendarEnabled } from '../../../../../calendar-sync/functions.native';
|
||||
import RecentList from '../../../../../recent-list/components/RecentList.native';
|
||||
import {
|
||||
calendarListTabBarOptions,
|
||||
recentListTabBarOptions,
|
||||
settingsTabBarOptions,
|
||||
tabBarOptions
|
||||
} from '../../../../../welcome/constants';
|
||||
import { screen } from '../../../routes';
|
||||
import SettingsNavigationContainer
|
||||
from '../../settings/components/SettingsNavigationContainer';
|
||||
|
||||
const WelcomePage = createBottomTabNavigator();
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link WelcomePageTabs}.
|
||||
*/
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Renders the lists disabled.
|
||||
*/
|
||||
disabled: boolean;
|
||||
|
||||
/**
|
||||
* Callback to be invoked when pressing the list container.
|
||||
*/
|
||||
onListContainerPress?: (e?: GestureResponderEvent) => void;
|
||||
|
||||
/**
|
||||
* Callback to be invoked when settings screen is focused.
|
||||
*/
|
||||
onSettingsScreenFocused: Function;
|
||||
}
|
||||
|
||||
|
||||
const WelcomePageTabs = ({ disabled, onListContainerPress, onSettingsScreenFocused }: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
const RecentListScreen = useCallback(() =>
|
||||
(
|
||||
<RecentList
|
||||
disabled = { disabled }
|
||||
onListContainerPress = { onListContainerPress } />
|
||||
), []);
|
||||
|
||||
const calendarEnabled = useSelector(isCalendarEnabled);
|
||||
|
||||
const CalendarListScreen = useCallback(() =>
|
||||
(
|
||||
<CalendarList
|
||||
disabled = { disabled } />
|
||||
), []);
|
||||
|
||||
const SettingsScreen = useCallback(() =>
|
||||
(
|
||||
<SettingsNavigationContainer
|
||||
isInWelcomePage = { true } />
|
||||
), []);
|
||||
|
||||
return (
|
||||
<WelcomePage.Navigator
|
||||
backBehavior = { 'none' }
|
||||
screenOptions = {{
|
||||
...tabBarOptions,
|
||||
headerShown: false
|
||||
}}>
|
||||
<WelcomePage.Screen
|
||||
listeners = {{
|
||||
tabPress: () => {
|
||||
onSettingsScreenFocused(false);
|
||||
}
|
||||
}}
|
||||
name = { screen.welcome.tabs.recent }
|
||||
options = {{
|
||||
...recentListTabBarOptions,
|
||||
title: t('welcomepage.recentList')
|
||||
}}>
|
||||
{ RecentListScreen }
|
||||
</WelcomePage.Screen>
|
||||
{
|
||||
calendarEnabled
|
||||
&& <WelcomePage.Screen
|
||||
listeners = {{
|
||||
tabPress: () => {
|
||||
onSettingsScreenFocused(false);
|
||||
}
|
||||
}}
|
||||
name = { screen.welcome.tabs.calendar }
|
||||
options = {{
|
||||
...calendarListTabBarOptions,
|
||||
title: t('welcomepage.calendar')
|
||||
}}>
|
||||
{ CalendarListScreen }
|
||||
</WelcomePage.Screen>
|
||||
}
|
||||
<WelcomePage.Screen
|
||||
listeners = {{
|
||||
tabPress: () => {
|
||||
onSettingsScreenFocused(true);
|
||||
}
|
||||
}}
|
||||
name = { screen.settings.main }
|
||||
options = {{
|
||||
...settingsTabBarOptions,
|
||||
title: t('welcomepage.settings')
|
||||
}}>
|
||||
{ SettingsScreen }
|
||||
</WelcomePage.Screen>
|
||||
</WelcomePage.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
export default WelcomePageTabs;
|
||||
88
react/features/mobile/navigation/functions.tsx
Normal file
88
react/features/mobile/navigation/functions.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { GestureResponderEvent, Platform } from 'react-native';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
|
||||
import { appNavigate } from '../../app/actions.native';
|
||||
import { IStateful } from '../../base/app/types';
|
||||
import { PREJOIN_PAGE_ENABLED } from '../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../base/flags/functions';
|
||||
import { IconCloseLarge } from '../../base/icons/svg';
|
||||
import { toState } from '../../base/redux/functions';
|
||||
import { cancelKnocking } from '../../lobby/actions.native';
|
||||
import { isPrejoinEnabledInConfig } from '../../prejoin/functions.native';
|
||||
|
||||
import HeaderNavigationButton from './components/HeaderNavigationButton';
|
||||
|
||||
|
||||
/**
|
||||
* Close icon/text button based on platform.
|
||||
*
|
||||
* @param {Function} goBack - Goes back to the previous screen function.
|
||||
* @returns {React.Component}
|
||||
*/
|
||||
export function screenHeaderCloseButton(goBack: (e?: GestureResponderEvent | React.MouseEvent) => void) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
id = { 'close-screen-button' }
|
||||
label = { t('dialog.close') }
|
||||
onPress = { goBack } />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
id = { 'close-screen-button' }
|
||||
onPress = { goBack }
|
||||
src = { IconCloseLarge } />
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the {@code Prejoin page} is enabled by the app itself
|
||||
* (e.g. Programmatically via the Jitsi Meet SDK for Android and iOS).
|
||||
*
|
||||
* @param {Function|Object} stateful - The redux state or {@link getState}
|
||||
* function.
|
||||
* @returns {boolean} If the {@code Prejoin} is enabled by the app, then
|
||||
* {@code true}; otherwise, {@code false}.
|
||||
*/
|
||||
export function isPrejoinPageEnabled(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
|
||||
return getFeatureFlag(state, PREJOIN_PAGE_ENABLED, isPrejoinEnabledInConfig(state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Close icon/text button for lobby screen based on platform.
|
||||
*
|
||||
* @returns {React.Component}
|
||||
*/
|
||||
export function lobbyScreenHeaderCloseButton() {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const goBack = useCallback(() => {
|
||||
dispatch(cancelKnocking());
|
||||
dispatch(appNavigate(undefined));
|
||||
}, [ dispatch ]);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
id = { 'close-screen-button' }
|
||||
label = { t('dialog.close') }
|
||||
onPress = { goBack } />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
id = { 'close-screen-button' }
|
||||
onPress = { goBack }
|
||||
src = { IconCloseLarge } />
|
||||
);
|
||||
}
|
||||
38
react/features/mobile/navigation/middleware.ts
Normal file
38
react/features/mobile/navigation/middleware.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { appNavigate } from '../../app/actions.native';
|
||||
import { IStore } from '../../app/types';
|
||||
import { CONFERENCE_FAILED } from '../../base/conference/actionTypes';
|
||||
import { JitsiConferenceErrors } from '../../base/lib-jitsi-meet';
|
||||
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
|
||||
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
|
||||
case CONFERENCE_FAILED:
|
||||
return _conferenceFailed(store, next, action);
|
||||
}
|
||||
|
||||
return next(action);
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to handle the conference failed event and navigate the user to the lobby screen
|
||||
* based on the failure reason.
|
||||
*
|
||||
* @param {Object} store - The Redux store.
|
||||
* @param {Function} next - The Redux next function.
|
||||
* @param {Object} action - The Redux action.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function _conferenceFailed({ dispatch }: IStore, next: Function, action: AnyAction) {
|
||||
const { error } = action;
|
||||
|
||||
// We need to cover the case where knocking participant
|
||||
// is rejected from entering the conference
|
||||
if (error.name === JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED) {
|
||||
dispatch(appNavigate(undefined));
|
||||
}
|
||||
|
||||
return next(action);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { NavigationContainerRef } from '@react-navigation/native';
|
||||
import React from 'react';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { IStateful } from '../../base/app/types';
|
||||
import { toState } from '../../base/redux/functions';
|
||||
import { isWelcomePageEnabled } from '../../welcome/functions';
|
||||
import { _sendReadyToClose } from '../external-api/functions';
|
||||
|
||||
import { screen } from './routes';
|
||||
|
||||
export const rootNavigationRef = React.createRef<NavigationContainerRef<any>>();
|
||||
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @param {string} name - Destination name of the route that has been defined somewhere.
|
||||
* @param {Object} params - Params to pass to the destination route.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function navigateRoot(name: string, params?: Object) {
|
||||
return rootNavigationRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined navigation action included inside the reference to the container.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function goBack() {
|
||||
return rootNavigationRef.current?.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates back to Welcome page, if it's available.
|
||||
*
|
||||
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
|
||||
* @param {Function} dispatch - Redux dispatch function.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function goBackToRoot(stateful: IStateful, dispatch: IStore['dispatch']) {
|
||||
const state = toState(stateful);
|
||||
|
||||
if (isWelcomePageEnabled(state)) {
|
||||
navigateRoot(screen.welcome.main);
|
||||
} else {
|
||||
// For JitsiSDK, WelcomePage is not available
|
||||
_sendReadyToClose(dispatch);
|
||||
}
|
||||
}
|
||||
55
react/features/mobile/navigation/routes.ts
Normal file
55
react/features/mobile/navigation/routes.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
export const screen = {
|
||||
conference: {
|
||||
breakoutRooms: 'Breakout Rooms',
|
||||
carmode: 'Car Mode',
|
||||
chat: 'Chat',
|
||||
chatandpolls: {
|
||||
main: 'Chat and Polls',
|
||||
tab: {
|
||||
chat: 'Chat',
|
||||
polls: 'Polls'
|
||||
}
|
||||
},
|
||||
container: 'Conference container',
|
||||
gifsMenu: 'GIPHY',
|
||||
invite: 'Invite',
|
||||
liveStream: 'Live stream',
|
||||
main: 'Conference',
|
||||
participants: 'Participants',
|
||||
root: 'Conference root',
|
||||
recording: 'Recording',
|
||||
salesforce: 'Link to Salesforce',
|
||||
security: 'Security Options',
|
||||
sharedDocument: 'Shared document',
|
||||
speakerStats: 'Speaker Stats',
|
||||
subtitles: 'Subtitles',
|
||||
whiteboard: 'Whiteboard'
|
||||
},
|
||||
connecting: 'Connecting',
|
||||
dialInSummary: 'Dial-In Info',
|
||||
preJoin: 'Pre-Join',
|
||||
lobby: {
|
||||
chat: 'Lobby chat',
|
||||
main: 'Lobby',
|
||||
root: 'Lobby root'
|
||||
},
|
||||
settings: {
|
||||
language: 'Language',
|
||||
links: {
|
||||
help: 'Help',
|
||||
privacy: 'Privacy',
|
||||
terms: 'Terms'
|
||||
},
|
||||
main: 'Settings',
|
||||
profile: 'Profile'
|
||||
},
|
||||
unsafeRoomWarning: 'Unsafe Room Warning',
|
||||
visitorsQueue: 'Visitors Queue',
|
||||
welcome: {
|
||||
main: 'Welcome',
|
||||
tabs: {
|
||||
calendar: 'Calendar',
|
||||
recent: 'Recent'
|
||||
}
|
||||
}
|
||||
};
|
||||
260
react/features/mobile/navigation/screenOptions.ts
Normal file
260
react/features/mobile/navigation/screenOptions.ts
Normal file
@@ -0,0 +1,260 @@
|
||||
import { TransitionPresets } from '@react-navigation/stack';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
import BaseTheme from '../../base/ui/components/BaseTheme.native';
|
||||
|
||||
import { goBack } from './components/conference/ConferenceNavigationContainerRef';
|
||||
import { goBack as goBackToLobbyScreen } from './components/lobby/LobbyNavigationContainerRef';
|
||||
import { lobbyScreenHeaderCloseButton, screenHeaderCloseButton } from './functions';
|
||||
import { goBack as goBackToWelcomeScreen } from './rootNavigationContainerRef';
|
||||
|
||||
|
||||
/**
|
||||
* Default modal transition for the current platform.
|
||||
*/
|
||||
export const modalPresentation = Platform.select({
|
||||
ios: TransitionPresets.ModalPresentationIOS,
|
||||
default: TransitionPresets.DefaultTransition
|
||||
});
|
||||
|
||||
/**
|
||||
* Screen options and transition types.
|
||||
*/
|
||||
export const fullScreenOptions = {
|
||||
...TransitionPresets.ModalTransition,
|
||||
gestureEnabled: false,
|
||||
headerShown: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigation container theme.
|
||||
*/
|
||||
export const navigationContainerTheme = {
|
||||
colors: {
|
||||
background: BaseTheme.palette.uiBackground
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for welcome page.
|
||||
*/
|
||||
export const welcomeScreenOptions = {
|
||||
...TransitionPresets.ModalTransition,
|
||||
gestureEnabled: false,
|
||||
headerShown: true,
|
||||
headerStyle: {
|
||||
backgroundColor: BaseTheme.palette.ui01
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: BaseTheme.palette.text01
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for conference.
|
||||
*/
|
||||
export const conferenceScreenOptions = fullScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for visitors queue.
|
||||
*/
|
||||
export const visitorsScreenOptions = fullScreenOptions;
|
||||
|
||||
/**
|
||||
* Tab bar options for chat screen.
|
||||
*/
|
||||
export const chatTabBarOptions = {
|
||||
swipeEnabled: false,
|
||||
tabBarIndicatorStyle: {
|
||||
backgroundColor: BaseTheme.palette.link01Active
|
||||
},
|
||||
tabBarStyle: {
|
||||
backgroundColor: BaseTheme.palette.ui01,
|
||||
borderBottomColor: BaseTheme.palette.ui06,
|
||||
borderBottomWidth: 0.4
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for presentation type modals.
|
||||
*/
|
||||
export const presentationScreenOptions = {
|
||||
...modalPresentation,
|
||||
headerBackTitleVisible: false,
|
||||
headerLeft: () => screenHeaderCloseButton(goBack),
|
||||
headerStatusBarHeight: 0,
|
||||
headerStyle: {
|
||||
backgroundColor: BaseTheme.palette.ui01
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: BaseTheme.palette.text01
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for breakout rooms screen.
|
||||
*/
|
||||
export const breakoutRoomsScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for car mode.
|
||||
*/
|
||||
export const carmodeScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for chat.
|
||||
*/
|
||||
export const chatScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Dial-IN Info screen options and transition types.
|
||||
*/
|
||||
export const dialInSummaryScreenOptions = {
|
||||
...presentationScreenOptions,
|
||||
headerLeft: () => screenHeaderCloseButton(goBackToWelcomeScreen)
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for invite modal.
|
||||
*/
|
||||
export const inviteScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for live stream modal.
|
||||
*/
|
||||
export const liveStreamScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for participants modal.
|
||||
*/
|
||||
export const participantsScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for speaker stats modal.
|
||||
*/
|
||||
export const speakerStatsScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for security options modal.
|
||||
*/
|
||||
export const securityScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for recording modal.
|
||||
*/
|
||||
export const recordingScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for subtitles modal.
|
||||
*/
|
||||
export const subtitlesScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for lobby modal.
|
||||
*/
|
||||
export const lobbyScreenOptions = {
|
||||
...presentationScreenOptions,
|
||||
headerLeft: () => lobbyScreenHeaderCloseButton()
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for lobby chat modal.
|
||||
*/
|
||||
export const lobbyChatScreenOptions = {
|
||||
...presentationScreenOptions,
|
||||
headerLeft: () => screenHeaderCloseButton(goBackToLobbyScreen)
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for salesforce link modal.
|
||||
*/
|
||||
export const salesforceScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for GIPHY integration modal.
|
||||
*/
|
||||
export const gifsMenuOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for shared document.
|
||||
*/
|
||||
export const sharedDocumentScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for settings modal.
|
||||
*/
|
||||
export const settingsScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for connecting screen.
|
||||
*/
|
||||
export const connectingScreenOptions = {
|
||||
gestureEnabled: false,
|
||||
headerShown: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for the whiteboard screen.
|
||||
*/
|
||||
export const whiteboardScreenOptions = presentationScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for pre-join screen.
|
||||
*/
|
||||
export const preJoinScreenOptions = {
|
||||
gestureEnabled: false,
|
||||
headerStyle: {
|
||||
backgroundColor: BaseTheme.palette.ui01
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: BaseTheme.palette.text01
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for profile setting.
|
||||
*/
|
||||
export const profileSettingsScreenOptions = {
|
||||
headerStyle: {
|
||||
backgroundColor: BaseTheme.palette.ui01
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: BaseTheme.palette.text01
|
||||
},
|
||||
headerBackTitleVisible: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for language select screen.
|
||||
*/
|
||||
export const languageSelectScreenOptions = profileSettingsScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for pre-join screen.
|
||||
*/
|
||||
export const unsafeMeetingScreenOptions = preJoinScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for conference navigation container screen.
|
||||
*/
|
||||
export const conferenceNavigationContainerScreenOptions = {
|
||||
gestureEnabled: false,
|
||||
headerShown: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for lobby navigation container screen.
|
||||
*/
|
||||
export const lobbyNavigationContainerScreenOptions = {
|
||||
gestureEnabled: false,
|
||||
headerShown: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for settings navigation container screen.
|
||||
*/
|
||||
export const settingsNavigationContainerScreenOptions = {
|
||||
...modalPresentation,
|
||||
gestureEnabled: true,
|
||||
headerShown: false
|
||||
};
|
||||
Reference in New Issue
Block a user