feat(welcome/native): settings updates (#11830)

feat(settings/native): feature updates
pull/11919/head jitsi-meet_7589
Calinteodor 2 years ago committed by GitHub
parent e139c6d32d
commit 5ec6581d2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      android/sdk/build.gradle
  2. 1
      android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java
  3. 2
      android/settings.gradle
  4. 6
      ios/Podfile.lock
  5. 6
      lang/main.json
  6. 122
      package-lock.json
  7. 2
      package.json
  8. 34
      react/features/base/settings/components/native/SettingsButton.tsx
  9. 2
      react/features/lobby/components/native/LobbyModeSwitch.js
  10. 15
      react/features/mobile/navigation/components/RootNavigationContainer.js
  11. 9
      react/features/mobile/navigation/components/conference/components/ConferenceNavigationContainer.tsx
  12. 23
      react/features/mobile/navigation/components/settings/SettingsNavigationContainerRef.js
  13. 81
      react/features/mobile/navigation/components/settings/components/SettingsNavigationContainer.js
  14. 4
      react/features/mobile/navigation/components/styles.js
  15. 66
      react/features/mobile/navigation/components/welcome/components/CustomDrawerContent.js
  16. 73
      react/features/mobile/navigation/components/welcome/components/WelcomePageNavigationContainer.js
  17. 62
      react/features/mobile/navigation/components/welcome/components/WelcomePageTabs.js
  18. 2
      react/features/mobile/navigation/components/welcome/functions.js
  19. 2
      react/features/mobile/navigation/rootNavigationContainerRef.js
  20. 17
      react/features/mobile/navigation/routes.js
  21. 124
      react/features/mobile/navigation/screenOptions.js
  22. 2
      react/features/polls/components/native/PollCreate.js
  23. 2
      react/features/settings/components/native/FormRow.js
  24. 11
      react/features/settings/components/native/FormSectionAccordion.js
  25. 18
      react/features/settings/components/native/HelpView.tsx
  26. 15
      react/features/settings/components/native/PrivacyView.tsx
  27. 116
      react/features/settings/components/native/SettingsView.js
  28. 15
      react/features/settings/components/native/TermsView.tsx
  29. 47
      react/features/settings/components/native/styles.js
  30. 4
      react/features/toolbox/components/native/OverflowMenu.js
  31. 150
      react/features/welcome/components/WelcomePage.native.js
  32. 1
      react/features/welcome/components/native/settings/components/index.js
  33. 46
      react/features/welcome/components/styles.js
  34. 12
      react/features/welcome/constants.js

@ -79,7 +79,6 @@ dependencies {
implementation project(':react-native-masked-view_masked-view')
implementation project(':react-native-pager-view')
implementation project(':react-native-performance')
implementation project(':react-native-reanimated')
implementation project(':react-native-safe-area-context')
implementation project(':react-native-screens')
implementation project(':react-native-slider')

@ -117,7 +117,6 @@ class ReactInstanceManagerHolder {
new com.oblador.performance.PerformancePackage(),
new com.reactnativecommunity.slider.ReactSliderPackage(),
new com.brentvatne.react.ReactVideoPackage(),
new com.swmansion.reanimated.ReanimatedPackage(),
new org.reactnative.maskedview.RNCMaskedViewPackage(),
new com.reactnativecommunity.webview.RNCWebViewPackage(),
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),

@ -37,8 +37,6 @@ include ':react-native-pager-view'
project(':react-native-pager-view').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-pager-view/android')
include ':react-native-performance'
project(':react-native-performance').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-performance/android')
include ':react-native-reanimated'
project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-reanimated/android')
include ':react-native-safe-area-context'
project(':react-native-safe-area-context').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-safe-area-context/android')
include ':react-native-screens'

@ -465,8 +465,6 @@ PODS:
- RNGoogleSignin (7.0.4):
- GoogleSignIn (~> 6.0.0)
- React-Core
- RNReanimated (1.13.4):
- React-Core
- RNScreens (3.13.1):
- React-Core
- React-RCTImage
@ -541,7 +539,6 @@ DEPENDENCIES:
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- "RNGoogleSignin (from `../node_modules/@react-native-google-signin/google-signin`)"
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
@ -678,8 +675,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-gesture-handler"
RNGoogleSignin:
:path: "../node_modules/@react-native-google-signin/google-signin"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSound:
@ -766,7 +761,6 @@ SPEC CHECKSUMS:
RNDeviceInfo: 0400a6d0c94186d1120c3cbd97b23abc022187a9
RNGestureHandler: e5c7cab5f214503dcefd6b2b0cefb050e1f51c4a
RNGoogleSignin: c4381751eefd73c552b923ba347a9bfc6f18771c
RNReanimated: c1b56d030d1616239861534d9adb531f8cffab68
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
RNSound: 27e8268bdb0a1f191f219a33267f7e0445e8d62f
RNSVG: ce9d996113475209013317e48b05c21ee988d42e

@ -938,6 +938,7 @@
"insecureRoomNameWarning": "The room name is unsafe. Unwanted participants may join your conference. Consider securing your meeting using the security button."
},
"settings": {
"buttonLabel": "Settings",
"calendar": {
"about": "The {{appName}} calendar integration is used to securely access your calendar so it can read upcoming events.",
"disconnect": "Disconnect",
@ -994,12 +995,17 @@
"displayName": "Display name",
"displayNamePlaceholderText": "Eg: John Doe",
"email": "Email",
"goTo": "Go to",
"header": "Settings",
"help": "Help",
"links": "Links",
"privacy": "Privacy",
"profileSection": "Profile",
"serverURL": "Server URL",
"showAdvanced": "Show advanced settings",
"startWithAudioMuted": "Start with audio muted",
"startWithVideoMuted": "Start with video muted",
"terms": "Terms",
"version": "Version"
},
"share": {

122
package-lock.json generated

@ -46,7 +46,6 @@
"@react-native-google-signin/google-signin": "7.0.4",
"@react-native-masked-view/masked-view": "0.2.6",
"@react-navigation/bottom-tabs": "6.0.9",
"@react-navigation/drawer": "6.1.8",
"@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "6.0.6",
"@react-navigation/native": "6.0.6",
@ -105,7 +104,6 @@
"react-native-pager-view": "5.4.9",
"react-native-paper": "4.11.1",
"react-native-performance": "2.1.0",
"react-native-reanimated": "https://git@github.com/software-mansion/react-native-reanimated#c4a6b6f687ede090f6081064abe83a2ef9a05784",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "3.13.1",
"react-native-sound": "0.11.1",
@ -5091,25 +5089,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/@react-navigation/drawer": {
"version": "6.1.8",
"resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.1.8.tgz",
"integrity": "sha512-kYE2EO5dianUuUcaYmAlYBcgtmvGm2fxWTQ5sn103cgPNidp4KBUR9ClkhF+btfRaHKq+8Ul5M6qvL0mBAv/Lg==",
"dependencies": {
"@react-navigation/elements": "^1.2.1",
"color": "^3.1.3",
"warn-once": "^0.1.0"
},
"peerDependencies": {
"@react-navigation/native": "^6.0.0",
"react": "*",
"react-native": "*",
"react-native-gesture-handler": ">= 1.0.0",
"react-native-reanimated": ">= 1.0.0",
"react-native-safe-area-context": ">= 3.0.0",
"react-native-screens": ">= 3.0.0"
}
},
"node_modules/@react-navigation/elements": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.2.1.tgz",
@ -8261,13 +8240,6 @@
"toggle-selection": "^1.0.6"
}
},
"node_modules/core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.",
"hasInstallScript": true
},
"node_modules/core-js-compat": {
"version": "3.21.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz",
@ -10362,34 +10334,6 @@
"bser": "2.1.1"
}
},
"node_modules/fbjs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz",
"integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==",
"dependencies": {
"core-js": "^2.4.1",
"fbjs-css-vars": "^1.0.0",
"isomorphic-fetch": "^2.1.1",
"loose-envify": "^1.0.0",
"object-assign": "^4.1.0",
"promise": "^7.1.1",
"setimmediate": "^1.0.5",
"ua-parser-js": "^0.7.18"
}
},
"node_modules/fbjs-css-vars": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
"integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
},
"node_modules/fbjs/node_modules/promise": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
"dependencies": {
"asap": "~2.0.3"
}
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -16301,19 +16245,6 @@
"react-native": "*"
}
},
"node_modules/react-native-reanimated": {
"version": "1.13.4",
"resolved": "git+https://git@github.com/software-mansion/react-native-reanimated.git#c4a6b6f687ede090f6081064abe83a2ef9a05784",
"integrity": "sha512-QGeZxvpZj1xv/NQtZ22uosLG99TSfujUlPHASp38AA/AgGzM+f4/P1ciCo1nTeOd3M5Ajh+e1hDy34CeZZeyCw==",
"license": "MIT",
"dependencies": {
"fbjs": "^1.0.0"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-safe-area-context": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-3.3.2.tgz",
@ -24574,16 +24505,6 @@
}
}
},
"@react-navigation/drawer": {
"version": "6.1.8",
"resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.1.8.tgz",
"integrity": "sha512-kYE2EO5dianUuUcaYmAlYBcgtmvGm2fxWTQ5sn103cgPNidp4KBUR9ClkhF+btfRaHKq+8Ul5M6qvL0mBAv/Lg==",
"requires": {
"@react-navigation/elements": "^1.2.1",
"color": "^3.1.3",
"warn-once": "^0.1.0"
}
},
"@react-navigation/elements": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.2.1.tgz",
@ -27014,11 +26935,6 @@
"toggle-selection": "^1.0.6"
}
},
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
},
"core-js-compat": {
"version": "3.21.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz",
@ -28657,36 +28573,6 @@
"bser": "2.1.1"
}
},
"fbjs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz",
"integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==",
"requires": {
"core-js": "^2.4.1",
"fbjs-css-vars": "^1.0.0",
"isomorphic-fetch": "^2.1.1",
"loose-envify": "^1.0.0",
"object-assign": "^4.1.0",
"promise": "^7.1.1",
"setimmediate": "^1.0.5",
"ua-parser-js": "^0.7.18"
},
"dependencies": {
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
"requires": {
"asap": "~2.0.3"
}
}
}
},
"fbjs-css-vars": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
"integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
},
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -33264,14 +33150,6 @@
"resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-2.1.0.tgz",
"integrity": "sha512-Q3dFPN7whBCY7X8nvQe7TBw4F5g1PyB78KwyKDXpJENcDrBodlFtj9/c5T2ZkRwAPb+bxr39b+lq9FyT6WQWtg=="
},
"react-native-reanimated": {
"version": "git+https://git@github.com/software-mansion/react-native-reanimated.git#c4a6b6f687ede090f6081064abe83a2ef9a05784",
"integrity": "sha512-QGeZxvpZj1xv/NQtZ22uosLG99TSfujUlPHASp38AA/AgGzM+f4/P1ciCo1nTeOd3M5Ajh+e1hDy34CeZZeyCw==",
"from": "react-native-reanimated@https://git@github.com/software-mansion/react-native-reanimated#c4a6b6f687ede090f6081064abe83a2ef9a05784",
"requires": {
"fbjs": "^1.0.0"
}
},
"react-native-safe-area-context": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-3.3.2.tgz",

@ -51,7 +51,6 @@
"@react-native-google-signin/google-signin": "7.0.4",
"@react-native-masked-view/masked-view": "0.2.6",
"@react-navigation/bottom-tabs": "6.0.9",
"@react-navigation/drawer": "6.1.8",
"@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "6.0.6",
"@react-navigation/native": "6.0.6",
@ -110,7 +109,6 @@
"react-native-pager-view": "5.4.9",
"react-native-paper": "4.11.1",
"react-native-performance": "2.1.0",
"react-native-reanimated": "https://git@github.com/software-mansion/react-native-reanimated#c4a6b6f687ede090f6081064abe83a2ef9a05784",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "3.13.1",
"react-native-sound": "0.11.1",

@ -0,0 +1,34 @@
/* eslint-disable lines-around-comment */
// @ts-ignore
import { translate } from '../../../../base/i18n';
// @ts-ignore
import { IconSettings } from '../../../../base/icons';
// @ts-ignore
import { AbstractButton, type AbstractButtonProps } from '../../../../base/toolbox/components';
// @ts-ignore
import { navigate }
// @ts-ignore
from '../../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
// @ts-ignore
import { screen } from '../../../../mobile/navigation/routes';
/**
* Implements an {@link AbstractButton} to open the carmode.
*/
class SettingsButton extends AbstractButton<AbstractButtonProps, any, any> {
accessibilityLabel = 'toolbar.accessibilityLabel.Settings';
icon = IconSettings;
label = 'settings.buttonLabel';
/**
* Handles clicking / pressing the button, and opens the carmode mode.
*
* @private
* @returns {void}
*/
_handleClick() {
return navigate(screen.settings.main);
}
}
export default translate(SettingsButton);

@ -9,7 +9,7 @@ import {
DISABLED_TRACK_COLOR,
ENABLED_TRACK_COLOR,
THUMB_COLOR
} from '../../../welcome/components/native/settings/components/styles';
} from '../../../settings/components/native/styles';
import styles from './styles';

@ -5,6 +5,7 @@ import React, { useCallback } from 'react';
import { connect } from '../../../base/redux';
import { DialInSummary } from '../../../invite';
import Prejoin from '../../../prejoin/components/Prejoin.native';
import WelcomePage from '../../../welcome/components/WelcomePage';
import { isWelcomePageEnabled } from '../../../welcome/functions';
import { _ROOT_NAVIGATION_READY } from '../actionTypes';
import { rootNavigationRef } from '../rootNavigationContainerRef';
@ -13,16 +14,14 @@ import {
conferenceNavigationContainerScreenOptions,
connectingScreenOptions,
dialInSummaryScreenOptions,
drawerNavigatorScreenOptions,
navigationContainerTheme,
preJoinScreenOptions
preJoinScreenOptions,
welcomeScreenOptions
} from '../screenOptions';
import ConnectingPage from './ConnectingPage';
import ConferenceNavigationContainer
from './conference/components/ConferenceNavigationContainer';
import WelcomePageNavigationContainer
from './welcome/components/WelcomePageNavigationContainer';
const RootStack = createStackNavigator();
@ -43,7 +42,7 @@ type Props = {
const RootNavigationContainer = ({ dispatch, isWelcomePageAvailable }: Props) => {
const initialRouteName = isWelcomePageAvailable
? screen.root : screen.connecting;
? screen.welcome.main : screen.connecting;
const onReady = useCallback(() => {
dispatch({
type: _ROOT_NAVIGATION_READY,
@ -63,9 +62,9 @@ const RootNavigationContainer = ({ dispatch, isWelcomePageAvailable }: Props) =>
isWelcomePageAvailable
&& <>
<RootStack.Screen
component = { WelcomePageNavigationContainer }
name = { screen.root }
options = { drawerNavigatorScreenOptions } />
component = { WelcomePage }
name = { screen.welcome.main }
options = { welcomeScreenOptions } />
<RootStack.Screen
component = { DialInSummary }
name = { screen.dialInSummary }

@ -50,6 +50,7 @@ import {
recordingScreenOptions,
salesforceScreenOptions,
securityScreenOptions,
settingsNavigationContainerScreenOptions,
sharedDocumentScreenOptions,
speakerStatsScreenOptions
// @ts-ignore
@ -57,6 +58,9 @@ import {
import LobbyNavigationContainer
// @ts-ignore
from '../../lobby/components/LobbyNavigationContainer';
import SettingsNavigationContainer
// @ts-ignore
from '../../settings/components/SettingsNavigationContainer';
import {
conferenceNavigationRef
// @ts-ignore
@ -64,6 +68,7 @@ import {
const ConferenceStack = createStackNavigator();
const ConferenceNavigationContainer = () => {
const isPollsDisabled = useSelector(getDisablePolls);
let ChatScreen;
@ -162,6 +167,10 @@ const ConferenceNavigationContainer = () => {
...sharedDocumentScreenOptions,
title: t('documentSharing.title')
}} />
<ConferenceStack.Screen
component = { SettingsNavigationContainer }
name = { screen.settings.main }
options = { settingsNavigationContainerScreenOptions } />
<ConferenceStack.Screen
component = { CarMode }
name = { screen.conference.carmode }

@ -0,0 +1,23 @@
import React from 'react';
export const settingsNavigationContainerRef = React.createRef();
/**
* 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,81 @@
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import React from 'react';
import { useTranslation } from 'react-i18next';
import HelpView from '../../../../../settings/components/native/HelpView';
import PrivacyView from '../../../../../settings/components/native/PrivacyView';
import SettingsView
from '../../../../../settings/components/native/SettingsView';
import TermsView from '../../../../../settings/components/native/TermsView';
import { screen } from '../../../routes';
import {
linkScreenOptions,
navigationContainerTheme,
settingsScreenOptions,
welcomeScreenOptions
} from '../../../screenOptions';
import {
settingsNavigationContainerRef
} from '../SettingsNavigationContainerRef';
const SettingsStack = createStackNavigator();
/**
* The type of the React {@code Component} props of {@link SettingsNavigationContainer}.
*/
type Props = {
/**
* Is the navigator part of Welcome page?
*/
isInWelcomePage: boolean
};
const SettingsNavigationContainer = ({ isInWelcomePage }: Props) => {
const baseSettingsScreenOptions = isInWelcomePage ? welcomeScreenOptions : settingsScreenOptions;
const { t } = useTranslation();
return (
<NavigationContainer
independent = { true }
ref = { settingsNavigationContainerRef }
theme = { navigationContainerTheme }>
<SettingsStack.Navigator
initialRouteName = { screen.settings.main }>
<SettingsStack.Screen
component = { SettingsView }
name = { screen.settings.main }
options = {{
...baseSettingsScreenOptions,
title: t('settings.title')
}} />
<SettingsStack.Screen
component = { HelpView }
name = { screen.settings.links.help }
options = {{
...linkScreenOptions,
title: t('helpView.header')
}} />
<SettingsStack.Screen
component = { TermsView }
name = { screen.settings.links.terms }
options = {{
...linkScreenOptions,
title: t('termsView.header')
}} />
<SettingsStack.Screen
component = { PrivacyView }
name = { screen.settings.links.privacy }
options = {{
...linkScreenOptions,
title: t('privacyView.header')
}} />
</SettingsStack.Navigator>
</NavigationContainer>
);
};
export default SettingsNavigationContainer;

@ -9,10 +9,6 @@ export const TEXT_COLOR = BaseTheme.palette.text01;
*/
export const navigationStyles = {
arrowBackStyle: {
marginLeft: 14
},
connectingScreenContainer: {
backgroundColor: BaseTheme.palette.uiBackground,
flex: 1

@ -1,66 +0,0 @@
// @flow
import { DrawerItemList } from '@react-navigation/drawer';
import React from 'react';
import { ScrollView, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Avatar } from '../../../../../base/avatar';
import {
getLocalParticipant, getParticipantDisplayName
} from '../../../../../base/participants';
import { connect } from '../../../../../base/redux';
import styles, { DRAWER_AVATAR_SIZE } from '../../../../../welcome/components/styles';
type Props = {
/**
* Local participant name to be displayed.
*/
displayName: string,
/**
* The ID of the local participant.
*/
localParticipantId: string
};
const CustomDrawerContent = (props: Props) => (
<ScrollView bounces = { false }>
<View style = { styles.drawerHeader }>
<Avatar
participantId = { props.localParticipantId }
size = { DRAWER_AVATAR_SIZE } />
<Text style = { styles.displayName }>
{ props.displayName }
</Text>
</View>
<SafeAreaView
edges = { [
'left',
'right'
] }>
<DrawerItemList { ...props } />
</SafeAreaView>
</ScrollView>
);
/**
* Maps (parts of) the redux state to the React {@code Component} props.
*
* @param {Object} state - The redux state.
* @protected
* @returns {Props}
*/
function mapStateToProps(state: Object) {
const localParticipant = getLocalParticipant(state);
const localParticipantId = localParticipant?.id;
const displayName = localParticipant && getParticipantDisplayName(state, localParticipantId);
return {
displayName,
localParticipantId
};
}
export default connect(mapStateToProps)(CustomDrawerContent);

@ -1,73 +0,0 @@
// @flow
import { createDrawerNavigator } from '@react-navigation/drawer';
import React from 'react';
import { useTranslation } from 'react-i18next';
import WelcomePage from '../../../../../welcome/components/WelcomePage';
import HelpView from '../../../../../welcome/components/native/HelpView';
import PrivacyView from '../../../../../welcome/components/native/PrivacyView';
import TermsView from '../../../../../welcome/components/native/TermsView';
import SettingsView
from '../../../../../welcome/components/native/settings/components/SettingsView';
import { screen } from '../../../routes';
import {
drawerContentOptions,
helpScreenOptions,
settingsScreenOptions,
termsAndPrivacyScreenOptions,
welcomeScreenOptions
} from '../../../screenOptions';
import CustomDrawerContent from './CustomDrawerContent';
const DrawerStack = createDrawerNavigator();
const WelcomePageNavigationContainer = () => {
const { t } = useTranslation();
return (
<DrawerStack.Navigator
/* eslint-disable-next-line react/jsx-no-bind */
drawerContent = { props => <CustomDrawerContent { ...props } /> }
screenOptions = { drawerContentOptions }>
<DrawerStack.Screen
component = { WelcomePage }
name = { screen.welcome.main }
options = { welcomeScreenOptions } />
<DrawerStack.Screen
component = { SettingsView }
name = { screen.welcome.settings }
options = {{
...settingsScreenOptions,
title: t('settingsView.header')
}} />
<DrawerStack.Screen
component = { TermsView }
name = { screen.welcome.terms }
options = {{
...termsAndPrivacyScreenOptions,
title: t('termsView.header')
}} />
<DrawerStack.Screen
component = { PrivacyView }
name = { screen.welcome.privacy }
options = {{
...termsAndPrivacyScreenOptions,
title: t('privacyView.header')
}} />
<DrawerStack.Screen
component = { HelpView }
name = { screen.welcome.help }
options = {{
...helpScreenOptions,
title: t('helpView.header')
}} />
</DrawerStack.Navigator>
);
};
export default WelcomePageNavigationContainer;

@ -1,5 +1,3 @@
// @flow
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import React, { useCallback } from 'react';
import { useSelector } from 'react-redux';
@ -9,12 +7,16 @@ import { RecentList } from '../../../../../recent-list';
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}.
*/
@ -28,30 +30,53 @@ type Props = {
/**
* Callback to be invoked when pressing the list container.
*/
onListContainerPress?: Function
onListContainerPress?: Function,
/**
* Callback to be invoked when settings screen is focused.
*/
onSettingsScreenFocused: Function
};
const WelcomePageTabs = ({ disabled, onListContainerPress }: Props) => {
const WelcomePageTabs = ({ disabled, onListContainerPress, onSettingsScreenFocused }: Props) => {
const RecentListScreen = useCallback(() =>
(<RecentList
disabled = { disabled }
onListContainerPress = { onListContainerPress } />)
(
<RecentList
disabled = { disabled }
onListContainerPress = { onListContainerPress } />
)
);
const calendarEnabled = useSelector(isCalendarEnabled);
const CalendarListScreen = useCallback(() =>
(<CalendarList
disabled = { disabled } />)
(
<CalendarList
disabled = { disabled } />
)
);
const SettingsScreen = useCallback(() =>
(
<SettingsNavigationContainer
isInWelcomePage = { true } />
)
);
return (
<WelcomePage.Navigator
initialRouteName = { screen.welcome.tabs.recent }
screenOptions = {{
headerShown: false,
...tabBarOptions
...tabBarOptions,
headerShown: false
}}>
<WelcomePage.Screen
listeners = {{
tabPress: () => {
onSettingsScreenFocused(false);
}
}}
name = { screen.welcome.tabs.recent }
options = { recentListTabBarOptions }>
{ RecentListScreen }
@ -59,11 +84,26 @@ const WelcomePageTabs = ({ disabled, onListContainerPress }: Props) => {
{
calendarEnabled
&& <WelcomePage.Screen
listeners = {{
tabPress: () => {
onSettingsScreenFocused(false);
}
}}
name = { screen.welcome.tabs.calendar }
options = { calendarListTabBarOptions }>
{ CalendarListScreen }
</WelcomePage.Screen>
}
<WelcomePage.Screen
listeners = {{
tabPress: () => {
onSettingsScreenFocused(true);
}
}}
name = { screen.settings.main }
options = { settingsTabBarOptions }>
{ SettingsScreen }
</WelcomePage.Screen>
</WelcomePage.Navigator>
);
};

@ -5,7 +5,6 @@ import React from 'react';
import { IconArrowBack } from '../../../../base/icons';
import HeaderNavigationButton
from '../HeaderNavigationButton';
import { navigationStyles } from '../styles';
/**
@ -18,7 +17,6 @@ import { navigationStyles } from '../styles';
export function renderArrowBackButton(onPress: Function) {
return (
<HeaderNavigationButton
buttonStyle = { navigationStyles.arrowBackStyle }
onPress = { onPress }
src = { IconArrowBack } />
);

@ -40,7 +40,7 @@ export function goBackToRoot(stateful: Function | Object, dispatch: Function) {
const state = toState(stateful);
if (isWelcomePageEnabled(state)) {
navigateRoot(screen.root);
navigateRoot(screen.welcome.main);
} else {
// For JitsiSDK, WelcomePage is not available
_sendReadyToClose(dispatch);

@ -1,15 +1,10 @@
export const screen = {
root: 'Main root',
welcome: {
main: 'Home',
main: 'Welcome',
tabs: {
recent: 'Recent',
calendar: 'Calendar'
},
settings: 'Settings',
terms: 'Terms',
privacy: 'Privacy',
help: 'Help'
}
},
dialInSummary: 'Dial-In Info',
connecting: 'Connecting',
@ -41,5 +36,13 @@ export const screen = {
root: 'Lobby root',
main: 'Lobby',
chat: 'Lobby chat'
},
settings: {
main: 'Settings',
links: {
help: 'Help',
privacy: 'Privacy',
terms: 'Terms'
}
}
};

@ -1,14 +1,6 @@
import { TransitionPresets } from '@react-navigation/stack';
import React from 'react';
import { Platform } from 'react-native';
import {
Icon,
IconHelp,
IconHome,
IconInfo,
IconSettings
} from '../../base/icons';
import BaseTheme from '../../base/ui/components/BaseTheme.native';
import { goBack } from './components/conference/ConferenceNavigationContainerRef';
@ -34,51 +26,20 @@ export const fullScreenOptions = {
headerShown: false
};
/**
* Navigation container theme.
*/
export const navigationContainerTheme = {
colors: {
background: BaseTheme.palette.uiBackground
}
};
/**
* Drawer navigator screens options and transition types.
*/
export const drawerNavigatorScreenOptions = {
...TransitionPresets.ModalTransition,
gestureEnabled: true,
headerShown: false
};
/**
* Drawer screen options and transition types.
*/
export const drawerScreenOptions = {
...TransitionPresets.ModalTransition,
export const linkScreenOptions = {
gestureEnabled: true,
headerShown: true,
headerStyle: {
backgroundColor: BaseTheme.palette.screen02Header
headerTitleStyle: {
color: BaseTheme.palette.text01
}
};
/**
* Drawer content options.
* Navigation container theme.
*/
export const drawerContentOptions = {
drawerActiveBackgroundColor: BaseTheme.palette.uiBackground,
drawerActiveTintColor: BaseTheme.palette.screen01Header,
drawerInactiveTintColor: BaseTheme.palette.text01,
drawerLabelStyle: {
marginLeft: BaseTheme.spacing[2]
},
drawerStyle: {
backgroundColor: BaseTheme.palette.uiBackground,
maxWidth: 400,
width: '75%'
export const navigationContainerTheme = {
colors: {
background: BaseTheme.palette.uiBackground
}
};
@ -86,13 +47,9 @@ export const drawerContentOptions = {
* Screen options for welcome page.
*/
export const welcomeScreenOptions = {
...drawerScreenOptions,
drawerIcon: ({ focused }) => (
<Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 }
src = { IconHome } />
),
...TransitionPresets.ModalTransition,
gestureEnabled: false,
headerShown: true,
headerStyle: {
backgroundColor: BaseTheme.palette.screen01Header
},
@ -101,54 +58,6 @@ export const welcomeScreenOptions = {
}
};
/**
* Screen options for settings screen.
*/
export const settingsScreenOptions = {
...drawerScreenOptions,
drawerIcon: ({ focused }) => (
<Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 }
src = { IconSettings } />
),
headerTitleStyle: {
color: BaseTheme.palette.text01
}
};
/**
* Screen options for terms/privacy screens.
*/
export const termsAndPrivacyScreenOptions = {
...drawerScreenOptions,
drawerIcon: ({ focused }) => (
<Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 }
src = { IconInfo } />
),
headerTitleStyle: {
color: BaseTheme.palette.text01
}
};
/**
* Screen options for help screen.
*/
export const helpScreenOptions = {
...drawerScreenOptions,
drawerIcon: ({ focused }) => (
<Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 }
src = { IconHelp } />
),
headerTitleStyle: {
color: BaseTheme.palette.text01
}
};
/**
* Screen options for conference.
*/
@ -269,6 +178,11 @@ export const gifsMenuOptions = presentationScreenOptions;
*/
export const sharedDocumentScreenOptions = presentationScreenOptions;
/**
* Screen options for settings modal.
*/
export const settingsScreenOptions = presentationScreenOptions;
/**
* Screen options for connecting screen.
*/
@ -303,3 +217,11 @@ export const lobbyNavigationContainerScreenOptions = {
gestureEnabled: false,
headerShown: false
};
/**
* Screen options for settings navigation container screen.
*/
export const settingsNavigationContainerScreenOptions = {
gestureEnabled: true,
headerShown: false
};

@ -8,7 +8,7 @@ import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import Button from '../../../base/ui/components/native/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants';
import styles
from '../../../welcome/components/native/settings/components/styles';
from '../../../settings/components/native/styles';
import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants';
import AbstractPollCreate from '../AbstractPollCreate';
import type { AbstractProps } from '../AbstractPollCreate';

@ -3,7 +3,7 @@
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { translate } from '../../../../../base/i18n';
import { translate } from '../../../base/i18n';
import styles, { ANDROID_UNDERLINE_COLOR, PLACEHOLDER_COLOR } from './styles';

@ -3,9 +3,8 @@
import React, { useCallback, useState } from 'react';
import { List } from 'react-native-paper';
import { translate } from '../../../../../base/i18n';
import { Icon, IconArrowDown, IconArrowUp } from '../../../../../base/icons';
import BaseTheme from '../../../../../base/ui/components/BaseTheme.native';
import { translate } from '../../../base/i18n';
import { Icon, IconArrowDown, IconArrowUp } from '../../../base/icons';
import styles from './styles';
@ -66,11 +65,15 @@ function FormSectionAccordion({ accordion, children, expandable, label, style, t
{ ...props }
src = { expandSection ? IconArrowUp : IconArrowDown }
style = { styles.section } /> }
rippleColor = { BaseTheme.palette.uiBackground }
style = { [
styles.formSectionTitle,
style
] }
theme = {{
colors: {
background: 'transparent'
}
}}
title = { t(label) }
titleStyle = { styles.formSectionTitleText }>
{ children }

@ -1,14 +1,20 @@
// @flow
/* eslint-disable lines-around-comment */
import React, { PureComponent } from 'react';
// @ts-ignore
import JitsiScreenWebView from '../../../base/modal/components/JitsiScreenWebView';
// @ts-ignore
import JitsiStatusBar from '../../../base/modal/components/JitsiStatusBar';
// @ts-ignore
import { connect } from '../../../base/redux';
// @ts-ignore
import { renderArrowBackButton }
// @ts-ignore
from '../../../mobile/navigation/components/welcome/functions';
import { screen } from '../../../mobile/navigation/routes';
import styles from '../styles';
// @ts-ignore
import styles from './styles';
const DEFAULT_HELP_CENTRE_URL = 'https://web-cdn.jitsi.net/faq/meet-faq.html';
@ -42,10 +48,12 @@ class HelpView extends PureComponent<Props> {
navigation
} = this.props;
// @ts-ignore
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
navigation.navigate(screen.welcome.main))
// @ts-ignore
navigation.goBack())
});
}
@ -73,7 +81,7 @@ class HelpView extends PureComponent<Props> {
* @param {Object} state - The Redux state.
* @returns {Props}
*/
function _mapStateToProps(state) {
function _mapStateToProps(state: any) {
return {
_url: state['features/base/config'].helpCentreURL || DEFAULT_HELP_CENTRE_URL
};

@ -1,13 +1,18 @@
// @flow
/* eslint-disable lines-around-comment */
import React, { useEffect } from 'react';
// @ts-ignore
import JitsiScreenWebView from '../../../base/modal/components/JitsiScreenWebView';
// @ts-ignore
import JitsiStatusBar from '../../../base/modal/components/JitsiStatusBar';
// @ts-ignore
import { renderArrowBackButton }
// @ts-ignore
from '../../../mobile/navigation/components/welcome/functions';
import { screen } from '../../../mobile/navigation/routes';
import styles from '../styles';
// @ts-ignore
import styles from './styles';
type Props = {
@ -26,10 +31,12 @@ const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
const PrivacyView = ({ navigation }: Props) => {
useEffect(() => {
// @ts-ignore
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
navigation.navigate(screen.welcome.main))
// @ts-ignore
navigation.goBack())
});
});

@ -1,27 +1,37 @@
// @flow
import { Link } from '@react-navigation/native';
import React from 'react';
import {
Alert,
NativeModules,
Platform,
ScrollView,
Text
Text, View
} from 'react-native';
import { Divider, Switch, TextInput, withTheme } from 'react-native-paper';
import { translate } from '../../../../../base/i18n';
import JitsiScreen from '../../../../../base/modal/components/JitsiScreen';
import { connect } from '../../../../../base/redux';
import { renderArrowBackButton }
from '../../../../../mobile/navigation/components/welcome/functions';
import { screen } from '../../../../../mobile/navigation/routes';
import {
Divider,
Switch,
TextInput,
withTheme
} from 'react-native-paper';
import { Avatar } from '../../../base/avatar';
import { translate } from '../../../base/i18n';
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import {
getLocalParticipant,
getParticipantDisplayName
} from '../../../base/participants';
import { connect } from '../../../base/redux';
import { screen } from '../../../mobile/navigation/routes';
import { AVATAR_SIZE } from '../../../welcome/components/styles';
import { normalizeUserInputURL, isServerURLChangeEnabled } from '../../functions';
import {
AbstractSettingsView,
_mapStateToProps as _abstractMapStateToProps,
type Props as AbstractProps
} from '../../../../../settings/components/AbstractSettingsView';
import { normalizeUserInputURL, isServerURLChangeEnabled } from '../../../../../settings/functions';
} from '../AbstractSettingsView';
import FormRow from './FormRow';
import FormSectionAccordion from './FormSectionAccordion';
@ -31,11 +41,13 @@ import styles, {
THUMB_COLOR
} from './styles';
/**
* Application information module.
*/
const { AppInfo } = NativeModules;
type State = {
/**
@ -92,11 +104,26 @@ type Props = AbstractProps & {
*/
_serverURLChangeEnabled: boolean,
/**
* Avatar label.
*/
avatarLabel: string,
/**
* The ID of the local participant.
*/
localParticipantId: string,
/**
* Default prop for navigating between screen components(React Navigation).
*/
navigation: Object,
/**
* Callback to be invoked when settings screen is focused.
*/
onSettingsScreenFocused: Function,
/**
* Theme used for styles.
*/
@ -112,6 +139,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
_urlField: Object;
/**
*
* Initializes a new {@code SettingsView} instance.
*
* @inheritdoc
@ -150,27 +178,6 @@ class SettingsView extends AbstractSettingsView<Props, State> {
this._showURLAlert = this._showURLAlert.bind(this);
}
/**
* Implements React's {@link Component#componentDidMount()}. Invoked
* immediately after mounting occurs.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount() {
const {
navigation,
t
} = this.props;
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
navigation.navigate(screen.welcome.main)),
headerTitle: t('settings.screenTitle')
});
}
/**
* Implements React's {@link Component#render()}, renders the settings page.
*
@ -202,11 +209,18 @@ class SettingsView extends AbstractSettingsView<Props, State> {
return (
<JitsiScreen
safeAreaInsets = { [ 'bottom', 'left', 'right' ] }
style = { styles.settingsViewContainer }>
<ScrollView>
<View style = { styles.avatarContainer }>
<Avatar
participantId = { this.props.localParticipantId }
size = { AVATAR_SIZE } />
<Text style = { styles.avatarLabel }>
{ this.props.avatarLabel }
</Text>
</View>
<FormSectionAccordion
accordion = { false }
expandable = { false }
label = 'settingsView.profileSection'>
<TextInput
autoCorrect = { false }
@ -235,8 +249,6 @@ class SettingsView extends AbstractSettingsView<Props, State> {
value = { email } />
</FormSectionAccordion>
<FormSectionAccordion
accordion = { false }
expandable = { false }
label = 'settingsView.conferenceSection'>
<TextInput
autoCapitalize = 'none'
@ -278,8 +290,26 @@ class SettingsView extends AbstractSettingsView<Props, State> {
</FormRow>
</FormSectionAccordion>
<FormSectionAccordion
accordion = { false }
expandable = { false }
label = 'settingsView.links'>
<Link
style = { styles.sectionLink }
to = {{ screen: screen.settings.links.help }}>
{ this.props.t('settingsView.help') }
</Link>
<Divider style = { styles.fieldSeparator } />
<Link
style = { styles.sectionLink }
to = {{ screen: screen.settings.links.terms }}>
{ this.props.t('settingsView.terms') }
</Link>
<Divider style = { styles.fieldSeparator } />
<Link
style = { styles.sectionLink }
to = {{ screen: screen.settings.links.privacy }}>
{ this.props.t('settingsView.privacy') }
</Link>
</FormSectionAccordion>
<FormSectionAccordion
label = 'settingsView.buildInfoSection'>
<FormRow
label = 'settingsView.version'>
@ -289,8 +319,6 @@ class SettingsView extends AbstractSettingsView<Props, State> {
</FormRow>
</FormSectionAccordion>
<FormSectionAccordion
accordion = { true }
expandable = { true }
label = 'settingsView.advanced'>
{ Platform.OS === 'android' && (
<>
@ -589,9 +617,15 @@ class SettingsView extends AbstractSettingsView<Props, State> {
* @returns {Props}
*/
function _mapStateToProps(state) {
const localParticipant = getLocalParticipant(state);
const localParticipantId = localParticipant?.id;
const avatarLabel = localParticipant && getParticipantDisplayName(state, localParticipantId);
return {
..._abstractMapStateToProps(state),
_serverURLChangeEnabled: isServerURLChangeEnabled(state)
_serverURLChangeEnabled: isServerURLChangeEnabled(state),
avatarLabel,
localParticipantId
};
}

@ -1,13 +1,18 @@
// @flow
/* eslint-disable lines-around-comment */
import React, { useEffect } from 'react';
// @ts-ignore
import JitsiScreenWebView from '../../../base/modal/components/JitsiScreenWebView';
// @ts-ignore
import JitsiStatusBar from '../../../base/modal/components/JitsiStatusBar';
// @ts-ignore
import { renderArrowBackButton }
// @ts-ignore
from '../../../mobile/navigation/components/welcome/functions';
import { screen } from '../../../mobile/navigation/routes';
import styles from '../styles';
// @ts-ignore
import styles from './styles';
type Props = {
@ -26,10 +31,12 @@ const TERMS_URL = 'https://jitsi.org/meet/terms';
const TermsView = ({ navigation }: Props) => {
useEffect(() => {
// @ts-ignore
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
navigation.navigate(screen.welcome.main))
// @ts-ignore
navigation.goBack())
});
});

@ -1,4 +1,6 @@
import BaseTheme from '../../../../../base/ui/components/BaseTheme.native';
import { BoxModel } from '../../../base/styles';
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
export const ANDROID_UNDERLINE_COLOR = 'transparent';
export const PLACEHOLDER_COLOR = BaseTheme.palette.focus01;
export const ENABLED_TRACK_COLOR = BaseTheme.palette.switch01Enabled;
@ -7,11 +9,30 @@ export const THUMB_COLOR = BaseTheme.palette.field02;
const TEXT_SIZE = 14;
/**
* The styles of the native components of the feature {@code settings}.
*/
export default {
avatarContainer: {
alignItems: 'center',
flexDirection: 'column',
height: 180,
justifyContent: 'center'
},
/**
* The style of the display name label.
*/
avatarLabel: {
color: BaseTheme.palette.text01,
fontSize: 16,
marginTop: BoxModel.margin,
textAlign: 'center'
},
/**
* Style for screen container.
*/
@ -99,6 +120,23 @@ export default {
fontSize: 14
},
sectionLink: {
...BaseTheme.typography.bodyShortBoldLarge,
color: BaseTheme.palette.link01,
margin: BaseTheme.spacing[3],
textAlign: 'center'
},
sectionLinkContainer: {
margin: BaseTheme.spacing[3]
},
sectionLinkText: {
...BaseTheme.typography.bodyShortBoldLarge,
color: BaseTheme.palette.link01,
textAlign: 'center'
},
/**
* Global {@code Text} color for the components.
*/
@ -136,5 +174,12 @@ export default {
marginVertical: 5,
paddingVertical: 3,
textAlign: 'left'
},
/**
* Style for screen container.
*/
screenContainer: {
flex: 1
}
};

@ -6,6 +6,7 @@ import { Divider } from 'react-native-paper';
import { BottomSheet, hideSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { connect } from '../../../base/redux';
import SettingsButton from '../../../base/settings/components/native/SettingsButton';
import { SharedDocumentButton } from '../../../etherpad';
import { ParticipantsPaneButton } from '../../../participants-pane/components/native';
import { ReactionMenu } from '../../../reactions/components';
@ -19,7 +20,6 @@ import { ClosedCaptionButton } from '../../../subtitles';
import { TileViewButton } from '../../../video-layout';
import styles from '../../../video-menu/components/native/styles';
import { getMovableButtons } from '../../functions.native';
import HelpButton from '../HelpButton';
import AudioOnlyButton from './AudioOnlyButton';
import LinkToSalesforceButton from './LinkToSalesforceButton';
@ -153,7 +153,7 @@ class OverflowMenu extends PureComponent<Props, State> {
<Divider style = { styles.divider } />
<ClosedCaptionButton { ...buttonProps } />
<SharedDocumentButton { ...buttonProps } />
<HelpButton { ...buttonProps } />
<SettingsButton { ...buttonProps } />
</BottomSheet>
);
}

@ -1,20 +1,18 @@
// @flow
import { DrawerActions } from '@react-navigation/native';
import React from 'react';
import {
Animated,
SafeAreaView,
TextInput,
TouchableHighlight,
TouchableOpacity,
View
} from 'react-native';
import { getName } from '../../app/functions';
import { ColorSchemeRegistry } from '../../base/color-scheme';
import { translate } from '../../base/i18n';
import { Icon, IconMenu, IconWarning } from '../../base/icons';
import { Icon, IconWarning } from '../../base/icons';
import JitsiStatusBar from '../../base/modal/components/JitsiStatusBar';
import { LoadingIndicator, Text } from '../../base/react';
import { connect } from '../../base/redux';
@ -62,10 +60,12 @@ class WelcomePage extends AbstractWelcomePage<*> {
constructor(props: Props) {
super(props);
// $FlowExpectedError
this.state._fieldFocused = false;
// $FlowExpectedError
this.state.isSettingsScreenFocused = false;
this.state.roomNameInputAnimation = new Animated.Value(1);
this.state.hintBoxAnimation = new Animated.Value(0);
// Bind event handlers so they are only bound once per instance.
@ -75,6 +75,7 @@ class WelcomePage extends AbstractWelcomePage<*> {
// Specially bind functions to avoid function definition on render.
this._onFieldBlur = this._onFieldFocusChange.bind(this, false);
this._onFieldFocus = this._onFieldFocusChange.bind(this, true);
this._onSettingsScreenFocused = this._onSettingsScreenFocused.bind(this);
}
_onFieldBlur: () => void;
@ -99,25 +100,11 @@ class WelcomePage extends AbstractWelcomePage<*> {
super.componentDidMount();
const {
_headerStyles,
navigation,
t
} = this.props;
navigation.setOptions({
headerLeft: () => (
<TouchableOpacity
/* eslint-disable-next-line react/jsx-no-bind */
onPress = { () =>
navigation.dispatch(DrawerActions.openDrawer())
}
style = { styles.drawerNavigationIcon }>
<Icon
size = { 24 }
src = { IconMenu }
style = { _headerStyles.headerButtonIcon } />
</TouchableOpacity>
),
headerTitle: t('welcomepage.headerTitle')
});
@ -195,7 +182,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
styles.messageContainer,
styles.hintContainer,
{
// $FlowExpectedError
opacity: this.state.hintBoxAnimation
}
];
@ -214,7 +200,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
_onFieldFocusChange(focused) {
if (focused) {
// Stop placeholder animation.
// $FlowExpectedError
this._clearTimeouts();
this.setState({
_fieldFocused: true,
@ -227,10 +212,8 @@ class WelcomePage extends AbstractWelcomePage<*> {
Animated.timing(
// $FlowExpectedError
this.state.hintBoxAnimation,
// $FlowExpectedError
{
duration: 300,
toValue: focused ? 1 : 0,
@ -238,16 +221,42 @@ class WelcomePage extends AbstractWelcomePage<*> {
})
.start(animationState =>
// $FlowExpectedError
animationState.finished
// $FlowExpectedError
&& !focused
&& this.setState({
_fieldFocused: false
}));
}
_onSettingsScreenFocused: boolean => void;
/**
* Callback for when the settings screen is focused.
*
* @private
* @param {boolean} focused - The focused state of the screen.
* @returns {void}
*/
_onSettingsScreenFocused(focused) {
this.setState({
isSettingsScreenFocused: focused
});
this.props.navigation.setOptions({
headerShown: !focused
});
Animated.timing(
this.state.roomNameInputAnimation,
{
toValue: focused ? 0 : 1,
duration: 500,
useNativeDriver: true
})
.start();
}
_renderHintBox: () => React$Element<any>;
/**
@ -259,7 +268,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
_renderHintBox() {
const { t } = this.props;
// $FlowExpectedError
if (this.state._fieldFocused) {
return (
<Animated.View style = { this._getHintBoxStyle() }>
@ -321,55 +329,71 @@ class WelcomePage extends AbstractWelcomePage<*> {
}
/**
* Renders the full welcome page.
* Renders the room name input.
*
* @private
* @returns {ReactElement}
*/
_renderFullUI() {
_renderRoomNameInput() {
const roomnameAccLabel = 'welcomepage.accessibilityLabel.roomname';
const { t } = this.props;
const { isSettingsScreenFocused } = this.state;
return (
<Animated.View
style = { [
isSettingsScreenFocused && styles.roomNameInputContainer,
{ opacity: this.state.roomNameInputAnimation }
] }>
<SafeAreaView style = { styles.roomContainer }>
<View style = { styles.joinControls } >
<Text style = { styles.enterRoomText }>
{ t('welcomepage.roomname') }
</Text>
<TextInput
accessibilityLabel = { t(roomnameAccLabel) }
autoCapitalize = { 'none' }
autoComplete = { 'off' }
autoCorrect = { false }
autoFocus = { false }
onBlur = { this._onFieldBlur }
onChangeText = { this._onRoomChange }
onFocus = { this._onFieldFocus }
onSubmitEditing = { this._onJoin }
placeholder = { this.state.roomPlaceholder }
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
returnKeyType = { 'go' }
spellCheck = { false }
style = { styles.textInput }
underlineColorAndroid = 'transparent'
value = { this.state.room } />
{
this._renderInsecureRoomNameWarning()
}
{
this._renderHintBox()
}
</View>
</SafeAreaView>
</Animated.View>
);
}
/**
* Renders the full welcome page.
*
* @returns {ReactElement}
*/
_renderFullUI() {
return (
<>
<JitsiStatusBar />
{ this._renderRoomNameInput() }
<View style = { styles.welcomePage }>
<SafeAreaView style = { styles.roomContainer } >
<View style = { styles.joinControls } >
<Text style = { styles.enterRoomText }>
{ t('welcomepage.roomname') }
</Text>
{/* // $FlowExpectedError*/}
<TextInput
accessibilityLabel = { t(roomnameAccLabel) }
autoCapitalize = { 'none' }
autoComplete = { 'off' }
autoCorrect = { false }
autoFocus = { false }
onBlur = { this._onFieldBlur }
onChangeText = { this._onRoomChange }
onFocus = { this._onFieldFocus }
onSubmitEditing = { this._onJoin }
placeholder = { this.state.roomPlaceholder }
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
returnKeyType = { 'go' }
spellCheck = { false }
style = { styles.textInput }
underlineColorAndroid = 'transparent'
value = { this.state.room } />
{
// $FlowExpectedError
this._renderInsecureRoomNameWarning()
}
{
this._renderHintBox()
}
</View>
</SafeAreaView>
{/* // $FlowExpectedError*/}
<WelcomePageTabs
disabled = { this.state._fieldFocused }
onListContainerPress = { this._onFieldBlur } />
onListContainerPress = { this._onFieldBlur }
onSettingsScreenFocused = { this._onSettingsScreenFocused } />
</View>
</>
);

@ -1 +0,0 @@
export { default as SettingsView } from './SettingsView';

@ -7,13 +7,7 @@ import BaseTheme from '../../base/ui/components/BaseTheme.native';
export const PLACEHOLDER_TEXT_COLOR = BaseTheme.palette.text01;
export const DRAWER_AVATAR_SIZE = 104;
const DRAWER_HEADER_HEIGHT = 220;
export const SWITCH_THUMB_COLOR = BaseTheme.palette.action04;
export const SWITCH_UNDER_COLOR = BaseTheme.palette.video01Disabled;
export const AVATAR_SIZE = 104;
/**
* The default color of text on the WelcomePage.
@ -65,16 +59,6 @@ export default {
fontSize: 14
},
/**
* The style of the display name label in the side bar.
*/
displayName: {
color: BaseTheme.palette.text01,
fontSize: 16,
marginTop: BoxModel.margin,
textAlign: 'center'
},
enterRoomText: {
color: TEXT_COLOR,
fontSize: 18,
@ -136,6 +120,10 @@ export default {
paddingVertical: 2 * BoxModel.padding
},
roomNameInputContainer: {
height: '0%'
},
/**
* Top-level screen style.
*/
@ -168,23 +156,6 @@ export default {
marginHorizontal: BaseTheme.spacing[2]
},
/**
* The style of the side bar header.
*/
drawerHeader: {
alignItems: 'center',
backgroundColor: BaseTheme.palette.screen01Header,
flexDirection: 'column',
height: DRAWER_HEADER_HEIGHT,
justifyContent: 'center'
},
drawerNavigationIcon: {
height: BaseTheme.spacing[6],
marginLeft: BaseTheme.spacing[3],
width: BaseTheme.spacing[6]
},
/**
* The container of the label of the audio-video switch.
*/
@ -254,12 +225,5 @@ export default {
flex: 1,
opacity: 0.8,
overflow: 'hidden'
},
/**
* Style for screen container.
*/
screenContainer: {
flex: 1
}
};

@ -2,7 +2,7 @@
import React from 'react';
import { IconEventNote, IconRestore } from '../base/icons';
import { IconEventNote, IconRestore, IconSettings } from '../base/icons';
import BaseTheme from '../base/ui/components/BaseTheme';
import TabIcon from './components/TabIcon';
@ -21,7 +21,6 @@ export const tabBarOptions = {
};
export const recentListTabBarOptions = {
// $FlowExpectedError
tabBarIcon: ({ focused }) => (
<TabIcon
focused = { focused }
@ -30,10 +29,17 @@ export const recentListTabBarOptions = {
};
export const calendarListTabBarOptions = {
// $FlowExpectedError
tabBarIcon: ({ focused }) => (
<TabIcon
focused = { focused }
src = { IconEventNote } />
)
};
export const settingsTabBarOptions = {
tabBarIcon: ({ focused }) => (
<TabIcon
focused = { focused }
src = { IconSettings } />
)
};

Loading…
Cancel
Save