This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user