Compare commits

...

12 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé 9fedbab80a fix(android) exclude the Giphy SDK from the libre build
Fixes: https://github.com/jitsi/jitsi-meet/issues/11759
2022-07-21 12:54:05 +02:00
Calin-Teodor 2039feae94 feat(base): TERTIARY type rework 2022-07-08 13:49:39 +03:00
Calin-Teodor 2842d3acef feat(conf/gifs/participants): created ParticipantsPaneFooter and updated comments 2022-07-08 13:49:31 +03:00
Calin-Teodor 00e1a1d79d feat(base): fixed height for buttons 2022-07-08 13:49:22 +03:00
Calinteodor 1843516ec7 feat(mobile/navigation): revert to stack navigator (#11811)
* feat(mobile/navigation): replaced native stack with stack navigator and other ui fixes
2022-07-07 18:15:49 +03:00
Calinteodor 7f34818cd4 feat(base/native): button abstractions (#11795)
* feat(base): created Button.tsx and IconButton.tsx
2022-07-07 18:15:41 +03:00
Calin-Teodor c8229a590c feat(gifs/native): fixed linter 2022-07-07 18:15:31 +03:00
Calin-Teodor e339325afc feat(gifs/native): created GifsMenuFooter 2022-07-07 18:15:22 +03:00
Calin-Teodor 2aecbcaab1 feat(conference/native): created CarModeFooter 2022-07-07 18:15:13 +03:00
Calin-Teodor f8037966f4 feat(base): removed PagedList because it is not used anymore 2022-07-07 18:15:04 +03:00
Calin-Teodor 057dceb178 feat(etherpad): ui fixes 2022-07-07 18:14:47 +03:00
Saúl Ibarra Corretgé f8917b2d3f chore(rn,versions) bump appp and sdk versions 2022-07-06 23:01:17 +02:00
67 changed files with 894 additions and 1218 deletions

View File

@ -26,5 +26,5 @@ android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
android.bundle.enableUncompressedNativeLibs=false android.bundle.enableUncompressedNativeLibs=false
appVersion=22.3.0 appVersion=22.4.0
sdkVersion=5.2.0 sdkVersion=6.0.0

View File

@ -51,15 +51,10 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.6'
implementation "androidx.startup:startup-runtime:1.1.0" implementation "androidx.startup:startup-runtime:1.1.0"
if (rootProject.ext.libreBuild) { // Only add these packages if we are NOT doing a LIBRE_BUILD
implementation(project(':react-native-device-info')) { if (!rootProject.ext.libreBuild) {
exclude group: 'com.google.firebase'
exclude group: 'com.google.android.gms'
exclude group: 'com.android.installreferrer'
}
} else {
implementation project(':react-native-amplitude') implementation project(':react-native-amplitude')
implementation project(':react-native-device-info') implementation project(':react-native-giphy')
implementation(project(":react-native-google-signin")) { implementation(project(":react-native-google-signin")) {
exclude group: 'com.google.android.gms' exclude group: 'com.google.android.gms'
exclude group: 'androidx' exclude group: 'androidx'
@ -72,9 +67,13 @@ dependencies {
implementation project(':react-native-community_clipboard') implementation project(':react-native-community_clipboard')
implementation project(':react-native-community_netinfo') implementation project(':react-native-community_netinfo')
implementation project(':react-native-default-preference') implementation project(':react-native-default-preference')
implementation(project(':react-native-device-info')) {
exclude group: 'com.google.firebase'
exclude group: 'com.google.android.gms'
exclude group: 'com.android.installreferrer'
}
implementation project(':react-native-gesture-handler') implementation project(':react-native-gesture-handler')
implementation project(':react-native-get-random-values') implementation project(':react-native-get-random-values')
implementation project(':react-native-giphy')
implementation project(':react-native-immersive') implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake') implementation project(':react-native-keep-awake')
implementation project(':react-native-masked-view_masked-view') implementation project(':react-native-masked-view_masked-view')

View File

@ -46,6 +46,8 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
class ReactInstanceManagerHolder { class ReactInstanceManagerHolder {
private static final String TAG = ReactInstanceManagerHolder.class.getSimpleName();
/** /**
* FIXME (from linter): Do not place Android context classes in static * FIXME (from linter): Do not place Android context classes in static
* fields (static reference to ReactInstanceManager which has field * fields (static reference to ReactInstanceManager which has field
@ -110,7 +112,6 @@ class ReactInstanceManagerHolder {
new com.corbt.keepawake.KCKeepAwakePackage(), new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(), new com.facebook.react.shell.MainReactPackage(),
new com.reactnativecommunity.clipboard.ClipboardPackage(), new com.reactnativecommunity.clipboard.ClipboardPackage(),
new com.giphyreactnativesdk.GiphyReactNativeSdkPackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(), new com.reactnativecommunity.netinfo.NetInfoPackage(),
new com.reactnativepagerview.PagerViewPackage(), new com.reactnativepagerview.PagerViewPackage(),
new com.oblador.performance.PerformancePackage(), new com.oblador.performance.PerformancePackage(),
@ -146,6 +147,17 @@ class ReactInstanceManagerHolder {
packages.add((ReactPackage)constructor.newInstance()); packages.add((ReactPackage)constructor.newInstance());
} catch (Exception e) { } catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled. // Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
Log.d(TAG, "Not loading AmplitudeReactNativePackage");
}
// GiphyReactNativeSdkPackage
try {
Class<?> giphyPackageClass = Class.forName("com.giphyreactnativesdk.GiphyReactNativeSdkPackage");
Constructor constructor = giphyPackageClass.getConstructor();
packages.add((ReactPackage)constructor.newInstance());
} catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
Log.d(TAG, "Not loading GiphyReactNativeSdkPackage");
} }
// RNGoogleSignInPackage // RNGoogleSignInPackage
@ -155,6 +167,7 @@ class ReactInstanceManagerHolder {
packages.add((ReactPackage)constructor.newInstance()); packages.add((ReactPackage)constructor.newInstance());
} catch (Exception e) { } catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled. // Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
Log.d(TAG, "Not loading RNGoogleSignInPackage");
} }
return packages; return packages;
@ -240,7 +253,7 @@ class ReactInstanceManagerHolder {
return; return;
} }
Log.d(ReactInstanceManagerHolder.class.getCanonicalName(), "initializing RN with Application"); Log.d(TAG, "initializing RN with Application");
reactInstanceManager reactInstanceManager
= ReactInstanceManager.builder() = ReactInstanceManager.builder()

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>22.3.0</string> <string>22.4.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>NSExtension</key> <key>NSExtension</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>22.3.0</string> <string>22.4.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>22.3.0</string> <string>22.4.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>XPC!</string> <string>XPC!</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>22.3.0</string> <string>22.4.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>CLKComplicationPrincipalClass</key> <key>CLKComplicationPrincipalClass</key>

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>5.2.0</string> <string>6.0.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>

141
package-lock.json generated
View File

@ -49,7 +49,7 @@
"@react-navigation/elements": "1.2.1", "@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "6.0.6", "@react-navigation/material-top-tabs": "6.0.6",
"@react-navigation/native": "6.0.6", "@react-navigation/native": "6.0.6",
"@react-navigation/native-stack": "6.6.2", "@react-navigation/stack": "6.2.2",
"@svgr/webpack": "4.3.2", "@svgr/webpack": "4.3.2",
"@tensorflow/tfjs-backend-wasm": "3.13.0", "@tensorflow/tfjs-backend-wasm": "3.13.0",
"@tensorflow/tfjs-core": "3.13.0", "@tensorflow/tfjs-core": "3.13.0",
@ -5026,33 +5026,6 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/@react-navigation/native-stack": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.6.2.tgz",
"integrity": "sha512-pFMuzhxbPml5MBvJVAzHWoaUkQaefAOKpuUnAs/AxNQuHQwwnxRmDit1PQLuIPo7g7DlfwFXagDHE1R0tbnS8Q==",
"dependencies": {
"@react-navigation/elements": "^1.3.3",
"warn-once": "^0.1.0"
},
"peerDependencies": {
"@react-navigation/native": "^6.0.0",
"react": "*",
"react-native": "*",
"react-native-safe-area-context": ">= 3.0.0",
"react-native-screens": ">= 3.0.0"
}
},
"node_modules/@react-navigation/native-stack/node_modules/@react-navigation/elements": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.3.tgz",
"integrity": "sha512-Lv2lR7si5gNME8dRsqz57d54m4FJtrwHRjNQLOyQO546ZxO+g864cSvoLC6hQedQU0+IJnPTsZiEI2hHqfpEpw==",
"peerDependencies": {
"@react-navigation/native": "^6.0.0",
"react": "*",
"react-native": "*",
"react-native-safe-area-context": ">= 3.0.0"
}
},
"node_modules/@react-navigation/routers": { "node_modules/@react-navigation/routers": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz", "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz",
@ -5061,6 +5034,63 @@
"nanoid": "^3.1.23" "nanoid": "^3.1.23"
} }
}, },
"node_modules/@react-navigation/stack": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.2.2.tgz",
"integrity": "sha512-P9ZfmluOXNmbs7YdG1UWS1fAh87Yse9aX8TgqOz4FlHEm5q7g5eaM35QgWByt+wif3UiqE40D8wXpqRQvMgPWg==",
"dependencies": {
"@react-navigation/elements": "^1.3.4",
"color": "^4.2.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-safe-area-context": ">= 3.0.0",
"react-native-screens": ">= 3.0.0"
}
},
"node_modules/@react-navigation/stack/node_modules/@react-navigation/elements": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.4.tgz",
"integrity": "sha512-O0jICpjn3jskVo4yiWzZozmj7DZy1ZBbn3O7dbenuUjZSj/cscjwaapmZZFGcI/IMmjmx8UTKsybhCFEIbGf3g==",
"peerDependencies": {
"@react-navigation/native": "^6.0.0",
"react": "*",
"react-native": "*",
"react-native-safe-area-context": ">= 3.0.0"
}
},
"node_modules/@react-navigation/stack/node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/@react-navigation/stack/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/@react-navigation/stack/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/@sideway/address": { "node_modules/@sideway/address": {
"version": "4.1.4", "version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
@ -23766,22 +23796,6 @@
"nanoid": "^3.1.23" "nanoid": "^3.1.23"
} }
}, },
"@react-navigation/native-stack": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.6.2.tgz",
"integrity": "sha512-pFMuzhxbPml5MBvJVAzHWoaUkQaefAOKpuUnAs/AxNQuHQwwnxRmDit1PQLuIPo7g7DlfwFXagDHE1R0tbnS8Q==",
"requires": {
"@react-navigation/elements": "^1.3.3",
"warn-once": "^0.1.0"
},
"dependencies": {
"@react-navigation/elements": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.3.tgz",
"integrity": "sha512-Lv2lR7si5gNME8dRsqz57d54m4FJtrwHRjNQLOyQO546ZxO+g864cSvoLC6hQedQU0+IJnPTsZiEI2hHqfpEpw=="
}
}
},
"@react-navigation/routers": { "@react-navigation/routers": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz", "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz",
@ -23790,6 +23804,45 @@
"nanoid": "^3.1.23" "nanoid": "^3.1.23"
} }
}, },
"@react-navigation/stack": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.2.2.tgz",
"integrity": "sha512-P9ZfmluOXNmbs7YdG1UWS1fAh87Yse9aX8TgqOz4FlHEm5q7g5eaM35QgWByt+wif3UiqE40D8wXpqRQvMgPWg==",
"requires": {
"@react-navigation/elements": "^1.3.4",
"color": "^4.2.3",
"warn-once": "^0.1.0"
},
"dependencies": {
"@react-navigation/elements": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.4.tgz",
"integrity": "sha512-O0jICpjn3jskVo4yiWzZozmj7DZy1ZBbn3O7dbenuUjZSj/cscjwaapmZZFGcI/IMmjmx8UTKsybhCFEIbGf3g=="
},
"color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"requires": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"@sideway/address": { "@sideway/address": {
"version": "4.1.4", "version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",

View File

@ -54,7 +54,7 @@
"@react-navigation/elements": "1.2.1", "@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "6.0.6", "@react-navigation/material-top-tabs": "6.0.6",
"@react-navigation/native": "6.0.6", "@react-navigation/native": "6.0.6",
"@react-navigation/native-stack": "6.6.2", "@react-navigation/stack": "6.2.2",
"@svgr/webpack": "4.3.2", "@svgr/webpack": "4.3.2",
"@tensorflow/tfjs-backend-wasm": "3.13.0", "@tensorflow/tfjs-backend-wasm": "3.13.0",
"@tensorflow/tfjs-core": "3.13.0", "@tensorflow/tfjs-core": "3.13.0",

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import { Platform, StyleSheet, View } from 'react-native'; import { Platform, StyleSheet, View } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import { FullWindowOverlay } from 'react-native-screens';
import SplashScreen from 'react-native-splash-screen'; import SplashScreen from 'react-native-splash-screen';
import { DialogContainer } from '../../base/dialog'; import { DialogContainer } from '../../base/dialog';
@ -24,7 +23,6 @@ import '../reducers';
declare var __DEV__; declare var __DEV__;
const DialogContainerWrapper = Platform.select({ const DialogContainerWrapper = Platform.select({
ios: FullWindowOverlay,
default: View default: View
}); });

View File

@ -19,6 +19,7 @@ export function _cleanupConfig(config: Object) {
delete config.analytics?.googleAnalyticsTrackingId; delete config.analytics?.googleAnalyticsTrackingId;
delete config.callStatsID; delete config.callStatsID;
delete config.callStatsSecret; delete config.callStatsSecret;
config.giphy = { enabled: false };
} }
} }

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { getDefaultHeaderHeight } from '@react-navigation/elements'; import { useHeaderHeight } from '@react-navigation/elements';
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { import {
Keyboard, Keyboard,
@ -8,7 +8,7 @@ import {
Platform, Platform,
StatusBar StatusBar
} from 'react-native'; } from 'react-native';
import { useSafeAreaFrame, useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { StyleType } from '../../styles'; import { StyleType } from '../../styles';
@ -34,11 +34,6 @@ type Props = {
*/ */
hasTabNavigator: boolean, hasTabNavigator: boolean,
/**
* Is the screen presented as a modal?
*/
isModalPresentation: boolean,
/** /**
* Additional style to be appended to the KeyboardAvoidingView. * Additional style to be appended to the KeyboardAvoidingView.
*/ */
@ -51,33 +46,26 @@ const JitsiKeyboardAvoidingView = (
contentContainerStyle, contentContainerStyle,
hasTabNavigator, hasTabNavigator,
hasBottomTextInput, hasBottomTextInput,
isModalPresentation,
style style
}: Props) => { }: Props) => {
const frame = useSafeAreaFrame(); const headerHeight = useHeaderHeight();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const [ bottomPadding, setBottomPadding ] = useState(insets.bottom); const [ bottomPadding, setBottomPadding ] = useState(insets.bottom);
const [ topPadding, setTopPadding ] = useState(insets.top);
useEffect(() => { useEffect(() => {
// This useEffect is needed because insets are undefined at first for some reason // This useEffect is needed because insets are undefined at first for some reason
// https://github.com/th3rdwave/react-native-safe-area-context/issues/54 // https://github.com/th3rdwave/react-native-safe-area-context/issues/54
setBottomPadding(insets.bottom); setBottomPadding(insets.bottom);
setTopPadding(insets.top); }, [ insets.bottom ]);
}, [ insets.bottom, insets.top ]);
const headerHeight = getDefaultHeaderHeight(frame, isModalPresentation, topPadding);
// Notch devices have in general a header height between 103 and 106px
const topNotchDevice = headerHeight > 100;
const deviceHeight = topNotchDevice ? headerHeight - 50 : headerHeight;
const tabNavigatorPadding const tabNavigatorPadding
= hasTabNavigator ? deviceHeight : 0; = hasTabNavigator ? headerHeight : 0;
const noNotchDevicePadding = bottomPadding || 10; const noNotchDevicePadding = bottomPadding || 10;
const iosVerticalOffset const iosVerticalOffset
= deviceHeight + noNotchDevicePadding + tabNavigatorPadding; = headerHeight + noNotchDevicePadding + tabNavigatorPadding;
const androidVerticalOffset = hasBottomTextInput const androidVerticalOffset = hasBottomTextInput
? deviceHeight + StatusBar.currentHeight : deviceHeight; ? headerHeight + StatusBar.currentHeight : headerHeight;
// Tells the view what to do with taps // Tells the view what to do with taps
const shouldSetResponse = useCallback(() => true); const shouldSetResponse = useCallback(() => true);

View File

@ -37,11 +37,6 @@ type Props = {
*/ */
hasTabNavigator?: boolean, hasTabNavigator?: boolean,
/**
* Is the screen presented as a modal?
*/
isModalPresentation?: boolean,
/** /**
* Insets for the SafeAreaView. * Insets for the SafeAreaView.
*/ */
@ -59,7 +54,6 @@ const JitsiScreen = ({
footerComponent, footerComponent,
hasTabNavigator = false, hasTabNavigator = false,
hasBottomTextInput = false, hasBottomTextInput = false,
isModalPresentation = true,
safeAreaInsets = [ 'left', 'right' ], safeAreaInsets = [ 'left', 'right' ],
style style
}: Props) => ( }: Props) => (
@ -69,7 +63,6 @@ const JitsiScreen = ({
contentContainerStyle = { contentContainerStyle } contentContainerStyle = { contentContainerStyle }
hasBottomTextInput = { hasBottomTextInput } hasBottomTextInput = { hasBottomTextInput }
hasTabNavigator = { hasTabNavigator } hasTabNavigator = { hasTabNavigator }
isModalPresentation = { isModalPresentation }
style = { style }> style = { style }>
<SafeAreaView <SafeAreaView
edges = { safeAreaInsets } edges = { safeAreaInsets }

View File

@ -1,44 +0,0 @@
/* @flow */
import React, { Component } from 'react';
import { Text, TouchableOpacity } from 'react-native';
type Props = {
/**
* React Elements to display within the component.
*/
children: React$Node | Object,
/**
* Handler called when the user presses the button.
*/
onValueChange: Function,
/**
* The component's external style.
*/
style: Object
};
/**
* Renders a button.
*/
export default class ButtonImpl extends Component<Props> {
/**
* Implements React's {@link Component#render()}, renders the button.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<TouchableOpacity
onPress = { this.props.onValueChange } >
<Text style = { this.props.style }>
{ this.props.children }
</Text>
</TouchableOpacity>
);
}
}

View File

@ -0,0 +1,99 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
Button as NativePaperButton,
Text,
TouchableRipple
} from 'react-native-paper';
import BaseTheme from '../../../ui/components/BaseTheme.native';
import styles from './styles';
import { BUTTON_MODES, BUTTON_TYPES } from '../../constants';
import { ButtonProps } from '../../types';
const Button: React.FC<ButtonProps> = ({
accessibilityLabel,
color: buttonColor,
disabled,
icon,
label,
labelStyle,
onPress,
style,
type
}: ButtonProps) => {
const { t } = useTranslation();
const { CONTAINED } = BUTTON_MODES;
const { DESTRUCTIVE, PRIMARY, SECONDARY, TERTIARY } = BUTTON_TYPES;
let buttonLabelStyles;
let buttonStyles;
let color;
let mode;
if (type === PRIMARY) {
buttonLabelStyles = styles.buttonLabelPrimary;
color = BaseTheme.palette.action01;
mode = CONTAINED
} else if (type === SECONDARY) {
buttonLabelStyles = styles.buttonLabelSecondary;
color = BaseTheme.palette.action02;
mode = CONTAINED
} else if (type === DESTRUCTIVE) {
color = BaseTheme.palette.actionDanger;
buttonLabelStyles = styles.buttonLabelDestructive;
mode = CONTAINED
} else {
color = buttonColor;
buttonLabelStyles = styles.buttonLabel;
}
if (disabled) {
buttonLabelStyles = styles.buttonLabelDisabled;
buttonStyles = styles.buttonDisabled;
} else {
buttonStyles = styles.button;
}
if ( type === TERTIARY) {
return (
<TouchableRipple
accessibilityLabel = { accessibilityLabel }
disabled = { disabled }
onPress = { onPress }
rippleColor = 'transparent'
style = { [
buttonStyles,
style
] }>
<Text
style = { [
buttonLabelStyles,
labelStyle
] }>{ t(label) }</Text>
</TouchableRipple>
);
}
return (
<NativePaperButton
accessibilityLabel = { t(accessibilityLabel) }
children = { t(label) }
color = { color }
disabled = { disabled }
icon = { icon }
labelStyle = { [
buttonLabelStyles,
labelStyle
] }
mode = { mode }
onPress = { onPress }
style = { [
buttonStyles,
style
] } />
);
};
export default Button;

View File

@ -0,0 +1,64 @@
import React from 'react';
import { TouchableRipple } from 'react-native-paper';
import { Icon } from '../../../icons';
import BaseTheme from '../../../ui/components/BaseTheme.native';
import styles from './styles';
import { BUTTON_TYPES } from '../../constants';
import { IconButtonProps } from '../../types';
const IconButton: React.FC<IconButtonProps> = ({
accessibilityLabel,
color: iconColor,
disabled,
onPress,
size,
src,
style,
tapColor,
type
}: IconButtonProps) => {
const { PRIMARY, SECONDARY, TERTIARY } = BUTTON_TYPES;
let color;
let rippleColor;
let iconButtonContainerStyles;
if (type === PRIMARY) {
color = BaseTheme.palette.icon01;
iconButtonContainerStyles = styles.iconButtonContainerPrimary;
rippleColor = BaseTheme.palette.action01;
} else if (type === SECONDARY) {
color = BaseTheme.palette.icon02;
iconButtonContainerStyles = styles.iconButtonContainerSecondary;
rippleColor = BaseTheme.palette.action02;
} else if ( type === TERTIARY) {
color = BaseTheme.palette.icon01;
iconButtonContainerStyles = styles.iconButtonContainer;
rippleColor = BaseTheme.palette.action03;
} else {
color = iconColor;
rippleColor = tapColor;
}
return (
<TouchableRipple
accessibilityLabel = { accessibilityLabel }
disabled = { disabled }
onPress = { onPress }
rippleColor = { rippleColor }
style = { [
iconButtonContainerStyles,
style
] }>
<Icon
color = { color }
size = { 20 || size }
src = { src } />
</TouchableRipple>
);
};
export default IconButton;

View File

@ -1,296 +0,0 @@
// @flow
import React, { Component } from 'react';
import { SafeAreaView, Text, TouchableOpacity, View } from 'react-native';
import { Icon } from '../../../icons';
import { connect } from '../../../redux';
import styles from './styles';
/**
* The type of the React {@code Component} props of {@link PagedList}.
*/
type Props = {
/**
* The zero-based index of the page that should be rendered (selected) by
* default.
*/
defaultPage: number,
/**
* Indicates if the list is disabled or not.
*/
disabled: boolean,
/**
* The Redux dispatch function.
*/
dispatch: Function,
/**
* Callback to execute on page change.
*/
onSelectPage: ?Function,
/**
* The pages of the PagedList component to be rendered.
*
* NOTE 1: An element's {@code component} may be {@code undefined} and then
* it won't need to be rendered.
*
* NOTE 2: There must be at least one page available and enabled.
*/
pages: Array<{
component: ?Object,
icon: string | number,
title: string
}>
};
/**
* The type of the React {@code Component} state of {@link PagedList}.
*/
type State = {
/**
* The currently selected page.
*/
pageIndex: number
};
/**
* A component that renders a paged list.
*
* @augments PagedList
*/
class PagedList extends Component<Props, State> {
/**
* Initializes a new {@code PagedList} instance.
*
* @inheritdoc
*/
constructor(props: Props) {
super(props);
this.state = {
pageIndex: this._validatePageIndex(props.defaultPage)
};
// Bind event handlers so they are only bound once per instance.
this._maybeRefreshSelectedPage
= this._maybeRefreshSelectedPage.bind(this);
}
/**
* Renders the component.
*
* @inheritdoc
*/
render() {
const { disabled } = this.props;
const pages = this.props.pages.filter(({ component }) => component);
let children;
if (pages.length > 1) {
children = this._renderPagedList(disabled);
} else {
children = React.createElement(
// $FlowExpectedError
/* type */ pages[0].component,
/* props */ {
disabled,
style: styles.pagedList
});
}
return (
<View
style = { [
styles.pagedListContainer,
disabled ? styles.pagedListContainerDisabled : null
] }>
{
// $FlowExpectedError
children
}
</View>
);
}
/**
* Constructs the style of an indicator.
*
* @param {number} indicatorIndex - The index of the indicator.
* @private
* @returns {Object}
*/
_getIndicatorStyle(indicatorIndex) {
if (this.state.pageIndex === indicatorIndex) {
return styles.pageIndicatorActive;
}
return null;
}
_maybeRefreshSelectedPage: ?boolean => void;
/**
* Components that this PagedList displays may have a refresh function to
* refresh its content when displayed (or based on custom logic). This
* function invokes this logic if it's present.
*
* @private
* @param {boolean} isInteractive - If true this refresh was caused by
* direct user interaction, false otherwise.
* @returns {void}
*/
_maybeRefreshSelectedPage(isInteractive: boolean = true) {
const selectedPage = this.props.pages[this.state.pageIndex];
let component;
if (selectedPage && (component = selectedPage.component)) {
// react-i18n / react-redux wrap components and thus we cannot access
// the wrapped component's static methods directly.
const component_ = component.WrappedComponent || component;
const { refresh } = component_;
refresh.call(component, this.props.dispatch, isInteractive);
}
}
/**
* Sets the selected page.
*
* @param {number} pageIndex - The index of the selected page.
* @protected
* @returns {void}
*/
_onSelectPage(pageIndex: number) {
return () => {
// eslint-disable-next-line no-param-reassign
pageIndex = this._validatePageIndex(pageIndex);
const { onSelectPage } = this.props;
onSelectPage && onSelectPage(pageIndex);
this.setState({ pageIndex }, this._maybeRefreshSelectedPage);
};
}
/**
* Renders a single page of the page list.
*
* @private
* @param {Object} page - The page to render.
* @param {boolean} disabled - Renders the page disabled.
* @returns {React$Node}
*/
_renderPage(page, disabled) {
if (!page.component) {
return null;
}
return (
<View style = { styles.pageContainer }>
{
React.createElement(
page.component,
{
disabled
})
}
</View>
);
}
/**
* Renders the paged list if multiple pages are to be rendered.
*
* @param {boolean} disabled - True if the rendered lists should be
* disabled.
* @returns {ReactElement}
*/
_renderPagedList(disabled) {
const { pages } = this.props;
const { pageIndex } = this.state;
return (
<View style = { styles.pagedListContainer }>
{
this._renderPage(pages[pageIndex], disabled)
}
<SafeAreaView style = { styles.pageIndicatorContainer }>
{
pages.map((page, index) => this._renderPageIndicator(
page, index, disabled
))
}
</SafeAreaView>
</View>
);
}
/**
* Renders a page indicator (icon) for the page.
*
* @private
* @param {Object} page - The page the indicator is rendered for.
* @param {number} index - The index of the page the indicator is rendered
* for.
* @param {boolean} disabled - Renders the indicator disabled.
* @returns {React$Node}
*/
_renderPageIndicator(page, index, disabled) {
if (!page.component) {
return null;
}
return (
<TouchableOpacity
disabled = { disabled }
key = { index }
onPress = { this._onSelectPage(index) }
style = { styles.pageIndicator } >
<View style = { styles.pageIndicatorContent }>
<Icon
src = { page.icon }
style = { [
styles.pageIndicatorIcon,
this._getIndicatorStyle(index)
] } />
<Text
style = { [
styles.pageIndicatorText,
this._getIndicatorStyle(index)
] }>
{ page.title }
</Text>
</View>
</TouchableOpacity>
);
}
/**
* Validates the requested page index and returns a safe value.
*
* @private
* @param {number} pageIndex - The requested page index.
* @returns {number}
*/
_validatePageIndex(pageIndex) {
// pageIndex may point to a non-existing page if some of the pages are
// disabled (their component property is undefined).
const maxPageIndex
= this.props.pages.filter(({ component }) => component).length - 1;
return Math.max(0, Math.min(maxPageIndex, pageIndex));
}
}
export default connect()(PagedList);

View File

@ -2,7 +2,6 @@
export { default as AvatarListItem } from './AvatarListItem'; export { default as AvatarListItem } from './AvatarListItem';
export { default as BaseIndicator } from './BaseIndicator'; export { default as BaseIndicator } from './BaseIndicator';
export { default as Button } from './Button';
export { default as Container } from './Container'; export { default as Container } from './Container';
export { default as Image } from './Image'; export { default as Image } from './Image';
export { default as Link } from './Link'; export { default as Link } from './Link';
@ -15,7 +14,6 @@ export { default as NavigateSectionListItem }
from './NavigateSectionListItem'; from './NavigateSectionListItem';
export { default as NavigateSectionListSectionHeader } export { default as NavigateSectionListSectionHeader }
from './NavigateSectionListSectionHeader'; from './NavigateSectionListSectionHeader';
export { default as PagedList } from './PagedList';
export { default as Pressable } from './Pressable'; export { default as Pressable } from './Pressable';
export { default as SectionList } from './SectionList'; export { default as SectionList } from './SectionList';
export { default as SlidingView } from './SlidingView'; export { default as SlidingView } from './SlidingView';

View File

@ -5,93 +5,12 @@ import BaseTheme from '../../../ui/components/BaseTheme.native';
const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)'; const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)';
const SECONDARY_ACTION_BUTTON_SIZE = 30; const SECONDARY_ACTION_BUTTON_SIZE = 30;
const BUTTON_HEIGHT = BaseTheme.spacing[7];
const BUTTON_WIDTH = BaseTheme.spacing[7];
export const AVATAR_SIZE = 65; export const AVATAR_SIZE = 65;
export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)'; export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)';
/**
* Style classes of the PagedList-based components.
*/
const PAGED_LIST_STYLES = {
/**
* Outermost container of a page in {@code PagedList}.
*/
pageContainer: {
flex: 1
},
/**
* Style of the page indicator (Android).
*/
pageIndicator: {
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'center',
padding: BoxModel.padding / 2
},
/**
* Additional style for the active indicator icon (Android).
*/
pageIndicatorActive: {
color: ColorPalette.white
},
/**
* Container for the page indicators (Android).
*/
pageIndicatorContainer: {
alignItems: 'center',
backgroundColor: ColorPalette.blue,
flexDirection: 'row',
justifyContent: 'space-around'
},
pageIndicatorContent: {
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'center'
},
/**
* Icon of the page indicator (Android).
*/
pageIndicatorIcon: {
color: ColorPalette.blueHighlight,
fontSize: 24
},
/**
* Label of the page indicator (Android).
*/
pageIndicatorText: {
color: ColorPalette.blueHighlight
},
/**
* Top level style of the paged list.
*/
pagedList: {
flex: 1
},
/**
* The paged list container View.
*/
pagedListContainer: {
flex: 1,
flexDirection: 'column'
},
/**
* Disabled style for the container.
*/
pagedListContainerDisabled: {
opacity: 0.2
}
};
const SECTION_LIST_STYLES = { const SECTION_LIST_STYLES = {
/** /**
* The style of the avatar container that makes the avatar rounded. * The style of the avatar container that makes the avatar rounded.
@ -217,11 +136,82 @@ export const BASE_INDICATOR = {
justifyContent: 'center' justifyContent: 'center'
}; };
const button = {
borderRadius: BaseTheme.shape.borderRadius,
height: BUTTON_HEIGHT
};
const buttonLabel = {
...BaseTheme.typography.bodyShortBold,
padding: 6,
textTransform: 'capitalize'
};
const iconButtonContainer = {
alignItems: 'center',
display: 'flex',
justifyContent: 'center',
borderRadius: BaseTheme.shape.borderRadius,
height: BUTTON_HEIGHT,
width: BUTTON_WIDTH
};
/** /**
* The styles of the generic React {@code Component}s implemented by the feature * The styles of the generic React {@code Component}s implemented by the feature
* base/react. * base/react.
*/ */
export default { export default {
...PAGED_LIST_STYLES, ...SECTION_LIST_STYLES,
...SECTION_LIST_STYLES
button: {
...button
},
buttonLabel: {
...buttonLabel
},
buttonLabelDisabled: {
...buttonLabel,
color: BaseTheme.palette.text03
},
buttonDisabled: {
...button,
backgroundColor: BaseTheme.palette.actionDisabled
},
buttonLabelPrimary: {
...buttonLabel,
color: BaseTheme.palette.text01
},
buttonLabelSecondary: {
...buttonLabel,
color: BaseTheme.palette.text02
},
buttonLabelDestructive: {
...buttonLabel,
color: BaseTheme.palette.text01
},
buttonLabelTertiary: {
...buttonLabel,
color: BaseTheme.palette.text01
},
iconButtonContainer: {
...iconButtonContainer
},
iconButtonContainerPrimary: {
...iconButtonContainer,
backgroundColor: BaseTheme.palette.action01
},
iconButtonContainerSecondary: {
...iconButtonContainer,
backgroundColor: BaseTheme.palette.action02
}
}; };

View File

@ -5,3 +5,20 @@
* everything, such as modal-type of components, or dialogs. * everything, such as modal-type of components, or dialogs.
*/ */
export const OVERLAY_Z_INDEX = 1000; export const OVERLAY_Z_INDEX = 1000;
/**
* The types of the buttons.
*/
export const BUTTON_TYPES = {
PRIMARY: 'primary',
SECONDARY: 'secondary',
TERTIARY: 'tertiary',
DESTRUCTIVE: 'destructive'
};
/**
* The modes of the buttons.
*/
export const BUTTON_MODES = {
CONTAINED: 'contained'
};

View File

@ -0,0 +1,23 @@
export interface ButtonProps {
accessibilityLabel?: string;
color?: string;
disabled?: boolean;
icon?: JSX.Element;
label?: string;
labelStyle?: Object|undefined;
onPress?: Function;
style?: Object|undefined;
type?: string;
}
export interface IconButtonProps {
accessibilityLabel?: string;
color?: string;
disabled?: boolean;
onPress?: Function;
size?: number|string;
src?: Function;
style?: Object|undefined;
tapColor?: string;
type?: string;
}

View File

@ -89,6 +89,8 @@ export const colorMap = {
// Status bar // Status bar
status01Bar: 'primary11', status01Bar: 'primary11',
actionDisabled: 'surface09',
// Hover state for primary buttons // Hover state for primary buttons
action01Hover: 'primary06', action01Hover: 'primary06',
@ -102,7 +104,7 @@ export const colorMap = {
action01Disabled: 'primary02', action01Disabled: 'primary02',
// Secondary buttons // Secondary buttons
action02: 'surface04', action02: 'surface10',
// Hover state for secondary buttons // Hover state for secondary buttons
action02Hover: 'surface05', action02Hover: 'surface05',
@ -156,7 +158,7 @@ export const colorMap = {
text01: 'surface11', text01: 'surface11',
// Secondary text with medium contrast // Secondary text with medium contrast
text02: 'surface09', text02: 'surface01',
// Tertiary text with low contrast placeholders, disabled actions, label for disabled buttons // Tertiary text with low contrast placeholders, disabled actions, label for disabled buttons
text03: 'surface07', text03: 'surface07',
@ -180,7 +182,7 @@ export const colorMap = {
icon01: 'surface11', icon01: 'surface11',
// Secondary color for input fields // Secondary color for input fields
icon02: 'surface09', icon02: 'surface01',
// Tertiary color for disabled actions // Tertiary color for disabled actions
icon03: 'surface07', icon03: 'surface07',

View File

@ -35,11 +35,3 @@ export const SMALL_WIDTH_THRESHOLD = 580;
* Lobby message type. * Lobby message type.
*/ */
export const LOBBY_CHAT_MESSAGE = 'LOBBY_CHAT_MESSAGE'; export const LOBBY_CHAT_MESSAGE = 'LOBBY_CHAT_MESSAGE';
/**
* The modes of the buttons of the chat and polls tabs.
*/
export const BUTTON_MODES = {
CONTAINED: 'contained',
TEXT: 'text'
};

View File

@ -1,10 +1,12 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Text, TouchableOpacity, View } from 'react-native'; import { Text, View } from 'react-native';
import { getFeatureFlag, INVITE_ENABLED } from '../../../base/flags'; import { getFeatureFlag, INVITE_ENABLED } from '../../../base/flags';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { Icon, IconAddPeople } from '../../../base/icons'; import { Icon, IconAddPeople } from '../../../base/icons';
import { getParticipantCountWithFake } from '../../../base/participants'; import { getParticipantCountWithFake } from '../../../base/participants';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { isInBreakoutRoom } from '../../../breakout-rooms/functions'; import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native'; import { doInvitePeople } from '../../../invite/actions.native';
@ -57,6 +59,19 @@ class LonelyMeetingExperience extends PureComponent<Props> {
this._onPress = this._onPress.bind(this); this._onPress = this._onPress.bind(this);
} }
/**
* Renders the "add people" icon.
*
* @returns {ReactElement}
*/
_renderAddPeopleIcon() {
return (
<Icon
size = { 20 }
src = { IconAddPeople } />
);
}
/** /**
* Implements {@code PureComponent#render}. * Implements {@code PureComponent#render}.
* *
@ -80,17 +95,13 @@ class LonelyMeetingExperience extends PureComponent<Props> {
{ t('lonelyMeetingExperience.youAreAlone') } { t('lonelyMeetingExperience.youAreAlone') }
</Text> </Text>
{ !_isInviteFunctionsDiabled && !_isInBreakoutRoom && ( { !_isInviteFunctionsDiabled && !_isInBreakoutRoom && (
<TouchableOpacity <Button
accessibilityLabel = 'lonelyMeetingExperience.button'
icon = { this._renderAddPeopleIcon }
label = 'lonelyMeetingExperience.button'
onPress = { this._onPress } onPress = { this._onPress }
style = { styles.lonelyButton }> style = { styles.lonelyButton }
<Icon type = { BUTTON_TYPES.PRIMARY } />
size = { 24 }
src = { IconAddPeople }
style = { styles.lonelyButtonComponents } />
<Text style = { styles.lonelyButtonComponents }>
{ t('lonelyMeetingExperience.button') }
</Text>
</TouchableOpacity>
) } ) }
</View> </View>
); );

View File

@ -1,6 +1,5 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { View } from 'react-native';
import { Text, View } from 'react-native';
import { withSafeAreaInsets } from 'react-native-safe-area-context'; import { withSafeAreaInsets } from 'react-native-safe-area-context';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
@ -12,20 +11,18 @@ import { setIsCarmode } from '../../../../video-layout/actions';
import ConferenceTimer from '../../ConferenceTimer'; import ConferenceTimer from '../../ConferenceTimer';
import { isConnecting } from '../../functions'; import { isConnecting } from '../../functions';
import EndMeetingButton from './EndMeetingButton'; import CarModeFooter from './CarModeFooter';
import MicrophoneButton from './MicrophoneButton'; import MicrophoneButton from './MicrophoneButton';
import SoundDeviceButton from './SoundDeviceButton';
import TitleBar from './TitleBar'; import TitleBar from './TitleBar';
import styles from './styles'; import styles from './styles';
/** /**
* Implements the carmode tab. * Implements the carmode component.
* *
* @returns { JSX.Element} - The carmode tab. * @returns { JSX.Element} - The carmode component.
*/ */
const CarmodeTab = (): JSX.Element => { const CarMode = (): JSX.Element => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { t } = useTranslation();
const connecting = useSelector(isConnecting); const connecting = useSelector(isConnecting);
const isSharing = useSelector(isLocalVideoTrackDesktop); const isSharing = useSelector(isLocalVideoTrackDesktop);
@ -42,7 +39,9 @@ const CarmodeTab = (): JSX.Element => {
}, []); }, []);
return ( return (
<JitsiScreen style = { styles.conference }> <JitsiScreen
footerComponent = { CarModeFooter }
style = { styles.conference }>
{/* {/*
* The activity/loading indicator goes above everything, except * The activity/loading indicator goes above everything, except
* the toolbox/toolbars and the dialogs. * the toolbox/toolbars and the dialogs.
@ -66,17 +65,8 @@ const CarmodeTab = (): JSX.Element => {
style = { styles.microphoneContainer }> style = { styles.microphoneContainer }>
<MicrophoneButton /> <MicrophoneButton />
</View> </View>
<View
pointerEvents = 'box-none'
style = { styles.bottomContainer }>
<Text style = { styles.videoStoppedLabel }>
{t('carmode.labels.videoStopped')}
</Text>
<SoundDeviceButton />
<EndMeetingButton />
</View>
</JitsiScreen> </JitsiScreen>
); );
}; };
export default withSafeAreaInsets(CarmodeTab); export default withSafeAreaInsets(CarMode);

View File

@ -0,0 +1,30 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import EndMeetingButton from './EndMeetingButton';
import SoundDeviceButton from './SoundDeviceButton';
import styles from './styles';
/**
* Implements the car mode footer component.
*
* @returns { JSX.Element} - The car mode footer component.
*/
const CarModeFooter = (): JSX.Element => {
const { t } = useTranslation();
return (
<View
pointerEvents = 'box-none'
style = { styles.bottomContainer }>
<Text style = { styles.videoStoppedLabel }>
{t('carmode.labels.videoStopped')}
</Text>
<SoundDeviceButton />
<EndMeetingButton />
</View>
);
};
export default CarModeFooter;

View File

@ -1,10 +1,10 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createToolbarEvent, sendAnalytics } from '../../../../analytics'; import { createToolbarEvent, sendAnalytics } from '../../../../analytics';
import { appNavigate } from '../../../../app/actions'; import { appNavigate } from '../../../../app/actions';
import Button from '../../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../../base/react/constants';
import EndMeetingIcon from './EndMeetingIcon'; import EndMeetingIcon from './EndMeetingIcon';
import styles from './styles'; import styles from './styles';
@ -15,7 +15,6 @@ import styles from './styles';
* @returns {JSX.Element} - The end meeting button. * @returns {JSX.Element} - The end meeting button.
*/ */
const EndMeetingButton = () : JSX.Element => { const EndMeetingButton = () : JSX.Element => {
const { t } = useTranslation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const onSelect = useCallback(() => { const onSelect = useCallback(() => {
@ -26,13 +25,12 @@ const EndMeetingButton = () : JSX.Element => {
return ( return (
<Button <Button
accessibilityLabel = { t('carmode.actions.leaveMeeting') } accessibilityLabel = 'carmode.actions.leaveMeeting'
children = { t('carmode.actions.leaveMeeting') }
icon = { EndMeetingIcon } icon = { EndMeetingIcon }
labelStyle = { styles.endMeetingButtonLabel } label = 'carmode.actions.leaveMeeting'
mode = 'contained'
onPress = { onSelect } onPress = { onSelect }
style = { styles.endMeetingButton } /> style = { styles.endMeetingButton }
type = { BUTTON_TYPES.DESTRUCTIVE } />
); );
}; };

View File

@ -1,9 +1,9 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { openSheet } from '../../../../base/dialog/actions'; import { openSheet } from '../../../../base/dialog/actions';
import Button from '../../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../../base/react/constants';
import AudioRoutePickerDialog from '../../../../mobile/audio-mode/components/AudioRoutePickerDialog'; import AudioRoutePickerDialog from '../../../../mobile/audio-mode/components/AudioRoutePickerDialog';
import AudioIcon from './AudioIcon'; import AudioIcon from './AudioIcon';
@ -15,7 +15,6 @@ import styles from './styles';
* @returns {JSX.Element} - The sound device button. * @returns {JSX.Element} - The sound device button.
*/ */
const SelectSoundDevice = () : JSX.Element => { const SelectSoundDevice = () : JSX.Element => {
const { t } = useTranslation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const onSelect = useCallback(() => const onSelect = useCallback(() =>
@ -24,13 +23,12 @@ const SelectSoundDevice = () : JSX.Element => {
return ( return (
<Button <Button
accessibilityLabel = { t('carmode.actions.selectSoundDevice') } accessibilityLabel = 'carmode.actions.selectSoundDevice'
children = { t('carmode.actions.selectSoundDevice') }
icon = { AudioIcon } icon = { AudioIcon }
labelStyle = { styles.soundDeviceButtonLabel } label = 'carmode.actions.selectSoundDevice'
mode = 'contained'
onPress = { onSelect } onPress = { onSelect }
style = { styles.soundDeviceButton } /> style = { styles.soundDeviceButton }
type = { BUTTON_TYPES.SECONDARY } />
); );
}; };

View File

@ -5,29 +5,6 @@ import BaseTheme from '../../../../base/ui/components/BaseTheme.native';
*/ */
const MICROPHONE_SIZE = 180; const MICROPHONE_SIZE = 180;
/**
* Base button style.
*/
const baseButton = {
borderRadius: BaseTheme.shape.borderRadius,
height: BaseTheme.spacing[7],
marginTop: BaseTheme.spacing[3],
marginLeft: BaseTheme.spacing[10],
marginRight: BaseTheme.spacing[10],
display: 'flex',
justifyContent: 'space-around',
width: 300
};
/**
* Base label style.
*/
const baseLabel = {
display: 'flex',
fontSize: 16,
textTransform: 'capitalize'
};
/** /**
* The styles of the safe area view that contains the title bar. * The styles of the safe area view that contains the title bar.
*/ */
@ -47,7 +24,7 @@ export default {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
alignItems: 'center', alignItems: 'center',
bottom: 0, bottom: BaseTheme.spacing[8],
left: 0, left: 0,
right: 0, right: 0,
position: 'absolute' position: 'absolute'
@ -106,10 +83,8 @@ export default {
}, },
roomTimer: { roomTimer: {
color: BaseTheme.palette.text01,
...BaseTheme.typography.bodyShortBold, ...BaseTheme.typography.bodyShortBold,
paddingHorizontal: 8, color: BaseTheme.palette.text01,
paddingVertical: 6,
textAlign: 'center' textAlign: 'center'
}, },
@ -129,25 +104,13 @@ export default {
color: BaseTheme.palette.text02 color: BaseTheme.palette.text02
}, },
soundDeviceButtonLabel: {
...baseLabel,
color: BaseTheme.palette.text06
},
soundDeviceButton: { soundDeviceButton: {
...baseButton, marginBottom: BaseTheme.spacing[3],
backgroundColor: BaseTheme.palette.section01 width: 240
}, },
endMeetingButton: { endMeetingButton: {
...baseButton, width: 240
backgroundColor: BaseTheme.palette.actionDanger,
marginBottom: 60
},
endMeetingButtonLabel: {
...baseLabel,
color: BaseTheme.palette.text01
}, },
headerLabels: { headerLabels: {
@ -196,13 +159,14 @@ export default {
}, },
titleBar: { titleBar: {
alignSelf: 'center' alignSelf: 'center',
marginTop: BaseTheme.spacing[1]
}, },
videoStoppedLabel: { videoStoppedLabel: {
...BaseTheme.typography.bodyShortRegularLarge,
color: BaseTheme.palette.text01, color: BaseTheme.palette.text01,
marginBottom: 32, marginBottom: BaseTheme.spacing[3]
...BaseTheme.typography.bodyShortRegularLarge
}, },
connectionIndicatorIcon: { connectionIndicatorIcon: {

View File

@ -41,14 +41,20 @@ export default {
width: BaseTheme.spacing[6] width: BaseTheme.spacing[6]
}, },
headerNavigationIcon: {
marginLeft: 12
},
headerNavigationText: { headerNavigationText: {
color: BaseTheme.palette.text01, color: BaseTheme.palette.text01,
marginLeft: BaseTheme.spacing[3],
fontSize: HEADER_ACTION_BUTTON_SIZE fontSize: HEADER_ACTION_BUTTON_SIZE
}, },
headerNavigationTextBold: { headerNavigationTextBold: {
...BaseTheme.typography.labelButton, ...BaseTheme.typography.labelButton,
color: BaseTheme.palette.text01, color: BaseTheme.palette.text01,
marginRight: BaseTheme.spacing[3],
fontSize: HEADER_ACTION_BUTTON_SIZE fontSize: HEADER_ACTION_BUTTON_SIZE
}, },
@ -79,18 +85,8 @@ export default {
}, },
lonelyButton: { lonelyButton: {
alignItems: 'center', borderRadius: BaseTheme.spacing[4],
backgroundColor: BaseTheme.palette.action01, paddingHorizontal: BaseTheme.spacing[1]
borderRadius: 24,
flexDirection: 'row',
height: BaseTheme.spacing[6],
justifyContent: 'space-around',
paddingHorizontal: 12
},
lonelyButtonComponents: {
color: BaseTheme.palette.text01,
marginHorizontal: 6
}, },
lonelyMeetingContainer: { lonelyMeetingContainer: {
@ -170,7 +166,7 @@ export default {
}, },
roomTimerView: { roomTimerView: {
backgroundColor: BaseTheme.palette.action02, backgroundColor: BaseTheme.palette.ui03,
borderRadius: 3, borderRadius: 3,
justifyContent: 'center', justifyContent: 'center',
minWidth: 50 minWidth: 50

View File

@ -59,9 +59,11 @@ class SharedDocument extends PureComponent<Props> {
addHeaderHeightValue = { true } addHeaderHeightValue = { true }
style = { styles.sharedDocContainer }> style = { styles.sharedDocContainer }>
<WebView <WebView
hideKeyboardAccessoryView = { true }
renderLoading = { this._renderLoading } renderLoading = { this._renderLoading }
source = {{ uri: _documentUrl }} source = {{ uri: _documentUrl }}
startInLoadingState = { true } /> startInLoadingState = { true }
style = { styles.sharedDoc } />
</JitsiScreen> </JitsiScreen>
); );
} }

View File

@ -1,22 +1,29 @@
// @flow // @flow
import { ColorPalette } from '../../../base/styles'; import BaseTheme from '../../../base/ui/components/BaseTheme.native';
export const INDICATOR_COLOR = ColorPalette.lightGrey;
export const INDICATOR_COLOR = BaseTheme.palette.indicatorColor;
export default { export default {
indicatorWrapper: { indicatorWrapper: {
alignItems: 'center', alignItems: 'center',
backgroundColor: ColorPalette.white, backgroundColor: BaseTheme.palette.ui12,
height: '100%', height: '100%',
justifyContent: 'center' justifyContent: 'center'
}, },
sharedDocContainer: { sharedDocContainer: {
flex: 1 backgroundColor: BaseTheme.palette.ui12,
flex: 1,
paddingRight: BaseTheme.spacing[3]
},
sharedDoc: {
marginBottom: BaseTheme.spacing[3]
}, },
webView: { webView: {
backgroundColor: 'rgb(242, 242, 242)' backgroundColor: BaseTheme.palette.ui12
} }
}; };

View File

@ -1,7 +1,6 @@
import { GiphyContent, GiphyGridView, GiphyMediaType } from '@giphy/react-native-sdk'; import { GiphyContent, GiphyGridView, GiphyMediaType } from '@giphy/react-native-sdk';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Image, Text, View } from 'react-native';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createGifSentEvent, sendAnalytics } from '../../../analytics'; import { createGifSentEvent, sendAnalytics } from '../../../analytics';
@ -11,6 +10,7 @@ import { goBack } from '../../../mobile/navigation/components/conference/Confere
import ClearableInput from '../../../participants-pane/components/native/ClearableInput'; import ClearableInput from '../../../participants-pane/components/native/ClearableInput';
import { formatGifUrlMessage, getGifUrl } from '../../functions'; import { formatGifUrlMessage, getGifUrl } from '../../functions';
import GifsMenuFooter from './GifsMenuFooter';
import styles from './styles'; import styles from './styles';
const GifsMenu = () => { const GifsMenu = () => {
@ -34,19 +34,9 @@ const GifsMenu = () => {
goBack(); goBack();
}, []); }, []);
const footerComponent = () => (
<View style = { styles.credit }>
<Text
style = { styles.creditText }>Powered by</Text>
<Image source = { require('../../../../../images/GIPHY_logo.png') } />
</View>
);
return ( return (
<JitsiScreen <JitsiScreen
/* eslint-disable-next-line react/jsx-no-bind */ footerComponent = { GifsMenuFooter }
footerComponent = { footerComponent }
style = { styles.container }> style = { styles.container }>
<ClearableInput <ClearableInput
customStyles = { styles.clearableInput } customStyles = { styles.clearableInput }

View File

@ -0,0 +1,26 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Image, Text, View } from 'react-native';
import styles from './styles';
/**
* Implements the gifs menu footer component.
*
* @returns { JSX.Element} - The gifs menu footer component.
*/
const GifsMenuFooter = (): JSX.Element => {
const { t } = useTranslation();
return(
<View style={ styles.credit }>
<Text
style={ styles.creditText }>{ t('poweredby') }</Text>
<Image
source = { require('../../../../../images/GIPHY_logo.png') } />
</View>
)
};
export default GifsMenuFooter;

View File

@ -12,7 +12,9 @@ export default {
marginTop: BaseTheme.spacing[3] marginTop: BaseTheme.spacing[3]
}, },
input: { textAlign: 'left' } input: {
textAlign: 'left'
}
}, },
grid: { grid: {
@ -34,7 +36,7 @@ export default {
}, },
creditText: { creditText: {
color: 'white', color: BaseTheme.palette.text01,
fontWeight: 'bold' fontWeight: 'bold'
} }
}; };

View File

@ -1,11 +1,13 @@
// @flow // @flow
import React from 'react'; import React from 'react';
import { Text, View, TouchableOpacity, TextInput } from 'react-native'; import { Text, View, TextInput } from 'react-native';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import JitsiScreen from '../../../base/modal/components/JitsiScreen'; import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { LoadingIndicator } from '../../../base/react'; import { LoadingIndicator } from '../../../base/react';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui'; import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui';
import BaseTheme from '../../../base/ui/components/BaseTheme'; import BaseTheme from '../../../base/ui/components/BaseTheme';
@ -22,7 +24,6 @@ import AbstractLobbyScreen, {
import styles from './styles'; import styles from './styles';
type Props = AbstractProps & { type Props = AbstractProps & {
/** /**
@ -185,31 +186,21 @@ class LobbyScreen extends AbstractLobbyScreen<Props> {
* @inheritdoc * @inheritdoc
*/ */
_renderPasswordJoinButtons() { _renderPasswordJoinButtons() {
const { t } = this.props;
return ( return (
<View style = { styles.passwordJoinButtonsWrapper }> <View style = { styles.passwordJoinButtonsWrapper }>
<TouchableOpacity <Button
accessibilityLabel = 'lobby.backToKnockModeButton'
label = 'lobby.backToKnockModeButton'
onPress = { this._onSwitchToKnockMode } onPress = { this._onSwitchToKnockMode }
style = { [ style = { styles.lobbyButton }
styles.button, type = { BUTTON_TYPES.PRIMARY } />
styles.primaryButton <Button
] }> accessibilityLabel = 'lobby.passwordJoinButton'
<Text style = { styles.primaryButtonText }>
{ t('lobby.backToKnockModeButton') }
</Text>
</TouchableOpacity>
<TouchableOpacity
disabled = { !this.state.password } disabled = { !this.state.password }
label = 'lobby.passwordJoinButton'
onPress = { this._onJoinWithPassword } onPress = { this._onJoinWithPassword }
style = { [ style = { styles.lobbyButton }
styles.button, type = { BUTTON_TYPES.PRIMARY } />
styles.primaryButton
] }>
<Text style = { styles.primaryButtonText }>
{ t('lobby.passwordJoinButton') }
</Text>
</TouchableOpacity>
</View> </View>
); );
} }
@ -245,44 +236,39 @@ class LobbyScreen extends AbstractLobbyScreen<Props> {
* @inheritdoc * @inheritdoc
*/ */
_renderStandardButtons() { _renderStandardButtons() {
const { _knocking, _renderPassword, _isLobbyChatActive, t } = this.props; const { _knocking, _renderPassword, _isLobbyChatActive } = this.props;
const { displayName } = this.state; const { displayName } = this.state;
const askToJoinButtonStyles
= displayName ? styles.primaryButton : styles.primaryButtonDisabled;
return ( return (
<View style = { styles.standardButtonWrapper }> <View style = { styles.standardButtonWrapper }>
{ _knocking && _isLobbyChatActive && <TouchableOpacity {
_knocking && _isLobbyChatActive
&& <Button
accessibilityLabel = 'toolbar.openChat'
label = 'toolbar.openChat'
onPress = { this._onNavigateToLobbyChat } onPress = { this._onNavigateToLobbyChat }
style = { [ style = { styles.lobbyButton }
styles.button, type = { BUTTON_TYPES.PRIMARY } />
styles.primaryButton }
] }> {
<Text style = { styles.primaryButtonText }> _knocking
{ t('toolbar.openChat') } || <Button
</Text> accessibilityLabel = 'lobby.knockButton'
</TouchableOpacity>}
{ _knocking || <TouchableOpacity
disabled = { !displayName } disabled = { !displayName }
label = 'lobby.knockButton'
onPress = { this._onAskToJoin } onPress = { this._onAskToJoin }
style = { [ style = { styles.lobbyButton }
styles.button, type = { BUTTON_TYPES.PRIMARY } />
askToJoinButtonStyles }
] }> {
<Text style = { styles.primaryButtonText }> _renderPassword
{ t('lobby.knockButton') } && <Button
</Text> accessibilityLabel = 'lobby.enterPasswordButton'
</TouchableOpacity> } label = 'lobby.enterPasswordButton'
{ _renderPassword && <TouchableOpacity
onPress = { this._onSwitchToPasswordMode } onPress = { this._onSwitchToPasswordMode }
style = { [ style = { styles.enterPasswordButton }
styles.button, type = { BUTTON_TYPES.PRIMARY } />
styles.primaryButton }
] }>
<Text style = { styles.primaryButtonText }>
{ t('lobby.enterPasswordButton') }
</Text>
</TouchableOpacity> }
</View> </View>
); );
} }

View File

@ -5,13 +5,6 @@ import BaseTheme from '../../../base/ui/components/BaseTheme.native';
const SECONDARY_COLOR = BaseTheme.palette.border04; const SECONDARY_COLOR = BaseTheme.palette.border04;
export default { export default {
button: {
alignItems: 'center',
borderRadius: BaseTheme.shape.borderRadius,
padding: BaseTheme.spacing[2],
height: BaseTheme.spacing[7],
width: '100%'
},
buttonStylesBorderless: { buttonStylesBorderless: {
iconStyle: { iconStyle: {
@ -137,7 +130,7 @@ export default {
color: BaseTheme.palette.text06, color: BaseTheme.palette.text06,
height: BaseTheme.spacing[7], height: BaseTheme.spacing[7],
marginTop: BaseTheme.spacing[3], marginTop: BaseTheme.spacing[3],
marginHorizontal: 12, marginHorizontal: BaseTheme.spacing[3],
padding: BaseTheme.spacing[2], padding: BaseTheme.spacing[2],
textAlign: 'center' textAlign: 'center'
}, },
@ -155,8 +148,7 @@ export default {
}, },
standardButtonWrapper: { standardButtonWrapper: {
alignSelf: 'stretch', alignSelf: 'stretch'
marginHorizontal: 12
}, },
joiningMessage: { joiningMessage: {
@ -185,26 +177,13 @@ export default {
paddingVertical: 12 paddingVertical: 12
}, },
primaryButton: { lobbyButton: {
backgroundColor: BaseTheme.palette.action01,
marginTop: BaseTheme.spacing[3] marginTop: BaseTheme.spacing[3]
}, },
primaryButtonDisabled: { enterPasswordButton: {
backgroundColor: BaseTheme.palette.action03Disabled, marginHorizontal: BaseTheme.spacing[3],
marginTop: BaseTheme.spacing[3] marginTop: BaseTheme.spacing[6]
},
primaryButtonText: {
...BaseTheme.typography.labelButtonLarge,
color: BaseTheme.palette.text01,
lineHeight: 30
},
primaryText: {
color: BaseTheme.palette.text01,
margin: 'auto',
textAlign: 'center'
}, },
// KnockingParticipantList // KnockingParticipantList

View File

@ -61,7 +61,8 @@ const HeaderNavigationButton
styles.headerNavigationButton ] } > styles.headerNavigationButton ] } >
<Icon <Icon
size = { 24 } size = { 24 }
src = { src } /> src = { src }
style = { styles.headerNavigationIcon } />
</TouchableRipple> </TouchableRipple>
) : ( ) : (
<TouchableRipple <TouchableRipple

View File

@ -1,5 +1,5 @@
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createStackNavigator } from '@react-navigation/stack';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
@ -24,7 +24,7 @@ import ConferenceNavigationContainer
import WelcomePageNavigationContainer import WelcomePageNavigationContainer
from './welcome/components/WelcomePageNavigationContainer'; from './welcome/components/WelcomePageNavigationContainer';
const RootStack = createNativeStackNavigator(); const RootStack = createStackNavigator();
type Props = { type Props = {

View File

@ -1,5 +1,5 @@
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createStackNavigator } from '@react-navigation/stack';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
@ -7,7 +7,7 @@ import { useSelector } from 'react-redux';
import { Chat, ChatAndPolls } from '../../../../../chat'; import { Chat, ChatAndPolls } from '../../../../../chat';
import Conference from '../../../../../conference/components/native/Conference'; import Conference from '../../../../../conference/components/native/Conference';
import CarmodeTab from '../../../../../conference/components/native/carmode/Conference'; import CarMode from '../../../../../conference/components/native/carmode/CarMode';
import { getDisablePolls } from '../../../../../conference/functions'; import { getDisablePolls } from '../../../../../conference/functions';
import { SharedDocument } from '../../../../../etherpad'; import { SharedDocument } from '../../../../../etherpad';
import { GifsMenu } from '../../../../../gifs/components'; import { GifsMenu } from '../../../../../gifs/components';
@ -46,7 +46,7 @@ import {
conferenceNavigationRef conferenceNavigationRef
} from '../ConferenceNavigationContainerRef'; } from '../ConferenceNavigationContainerRef';
const ConferenceStack = createNativeStackNavigator(); const ConferenceStack = createStackNavigator();
const ConferenceNavigationContainer = () => { const ConferenceNavigationContainer = () => {
const isPollsDisabled = useSelector(getDisablePolls); const isPollsDisabled = useSelector(getDisablePolls);
@ -147,7 +147,7 @@ const ConferenceNavigationContainer = () => {
title: t('documentSharing.title') title: t('documentSharing.title')
}} /> }} />
<ConferenceStack.Screen <ConferenceStack.Screen
component = { CarmodeTab } component = { CarMode }
name = { screen.conference.carmode } name = { screen.conference.carmode }
options = {{ options = {{
...carmodeScreenOptions, ...carmodeScreenOptions,

View File

@ -1,5 +1,5 @@
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createStackNavigator } from '@react-navigation/stack';
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
@ -12,7 +12,7 @@ import {
} from '../../../screenOptions'; } from '../../../screenOptions';
import { lobbyNavigationContainerRef } from '../LobbyNavigationContainerRef'; import { lobbyNavigationContainerRef } from '../LobbyNavigationContainerRef';
const LobbyStack = createNativeStackNavigator(); const LobbyStack = createStackNavigator();
const LobbyNavigationContainer = () => { const LobbyNavigationContainer = () => {

View File

@ -1,3 +1,4 @@
import { TransitionPresets } from '@react-navigation/stack';
import React from 'react'; import React from 'react';
import { Platform } from 'react-native'; import { Platform } from 'react-native';
@ -16,6 +17,23 @@ import { lobbyScreenHeaderCloseButton, screenHeaderCloseButton } from './functio
import { goBack as goBackToWelcomeScreen } from './rootNavigationContainerRef'; 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. * Navigation container theme.
*/ */
@ -29,7 +47,7 @@ export const navigationContainerTheme = {
* Drawer navigator screens options and transition types. * Drawer navigator screens options and transition types.
*/ */
export const drawerNavigatorScreenOptions = { export const drawerNavigatorScreenOptions = {
animation: 'default', ...TransitionPresets.ModalTransition,
gestureEnabled: true, gestureEnabled: true,
headerShown: false headerShown: false
}; };
@ -39,16 +57,12 @@ export const drawerNavigatorScreenOptions = {
* Drawer screen options and transition types. * Drawer screen options and transition types.
*/ */
export const drawerScreenOptions = { export const drawerScreenOptions = {
animation: 'default', ...TransitionPresets.ModalTransition,
gestureEnabled: true, gestureEnabled: true,
headerShown: true, headerShown: true,
headerStyle: { headerStyle: {
backgroundColor: BaseTheme.palette.screen02Header backgroundColor: BaseTheme.palette.screen02Header
}, }
orientation: Platform.select({
ios: 'default',
android: 'all'
})
}; };
/** /**
@ -57,7 +71,7 @@ export const drawerScreenOptions = {
export const drawerContentOptions = { export const drawerContentOptions = {
drawerActiveBackgroundColor: BaseTheme.palette.uiBackground, drawerActiveBackgroundColor: BaseTheme.palette.uiBackground,
drawerActiveTintColor: BaseTheme.palette.screen01Header, drawerActiveTintColor: BaseTheme.palette.screen01Header,
drawerInactiveTintColor: BaseTheme.palette.text02, drawerInactiveTintColor: BaseTheme.palette.text01,
drawerLabelStyle: { drawerLabelStyle: {
marginLeft: BaseTheme.spacing[2] marginLeft: BaseTheme.spacing[2]
}, },
@ -75,7 +89,7 @@ export const welcomeScreenOptions = {
...drawerScreenOptions, ...drawerScreenOptions,
drawerIcon: ({ focused }) => ( drawerIcon: ({ focused }) => (
<Icon <Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon02 } color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 } size = { 20 }
src = { IconHome } /> src = { IconHome } />
), ),
@ -94,7 +108,7 @@ export const settingsScreenOptions = {
...drawerScreenOptions, ...drawerScreenOptions,
drawerIcon: ({ focused }) => ( drawerIcon: ({ focused }) => (
<Icon <Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon02 } color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 } size = { 20 }
src = { IconSettings } /> src = { IconSettings } />
), ),
@ -110,7 +124,7 @@ export const termsAndPrivacyScreenOptions = {
...drawerScreenOptions, ...drawerScreenOptions,
drawerIcon: ({ focused }) => ( drawerIcon: ({ focused }) => (
<Icon <Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon02 } color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 } size = { 20 }
src = { IconInfo } /> src = { IconInfo } />
), ),
@ -126,7 +140,7 @@ export const helpScreenOptions = {
...drawerScreenOptions, ...drawerScreenOptions,
drawerIcon: ({ focused }) => ( drawerIcon: ({ focused }) => (
<Icon <Icon
color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon02 } color = { focused ? BaseTheme.palette.screen01Header : BaseTheme.palette.icon01 }
size = { 20 } size = { 20 }
src = { IconHelp } /> src = { IconHelp } />
), ),
@ -138,15 +152,7 @@ export const helpScreenOptions = {
/** /**
* Screen options for conference. * Screen options for conference.
*/ */
export const conferenceScreenOptions = { export const conferenceScreenOptions = fullScreenOptions;
animation: 'default',
gestureEnabled: false,
headerShown: false,
orientation: Platform.select({
ios: 'default',
android: 'all'
})
};
/** /**
* Tab bar options for chat screen. * Tab bar options for chat screen.
@ -172,6 +178,7 @@ export const chatTabBarOptions = {
* Screen options for presentation type modals. * Screen options for presentation type modals.
*/ */
export const presentationScreenOptions = { export const presentationScreenOptions = {
...modalPresentation,
headerBackTitleVisible: false, headerBackTitleVisible: false,
headerLeft: () => screenHeaderCloseButton(goBack), headerLeft: () => screenHeaderCloseButton(goBack),
headerStatusBarHeight: 0, headerStatusBarHeight: 0,
@ -180,20 +187,13 @@ export const presentationScreenOptions = {
}, },
headerTitleStyle: { headerTitleStyle: {
color: BaseTheme.palette.text01 color: BaseTheme.palette.text01
}, }
orientation: Platform.select({
ios: 'default',
android: 'all'
})
}; };
/** /**
* Screen options for car mode. * Screen options for car mode.
*/ */
export const carmodeScreenOptions = { export const carmodeScreenOptions = presentationScreenOptions;
...presentationScreenOptions,
orientation: 'portrait'
};
/** /**
* Screen options for chat. * Screen options for chat.
@ -205,7 +205,6 @@ export const chatScreenOptions = presentationScreenOptions;
*/ */
export const dialInSummaryScreenOptions = { export const dialInSummaryScreenOptions = {
...presentationScreenOptions, ...presentationScreenOptions,
animation: 'slide_from_bottom',
headerLeft: () => screenHeaderCloseButton(goBackToWelcomeScreen) headerLeft: () => screenHeaderCloseButton(goBackToWelcomeScreen)
}; };

View File

@ -1,16 +1,15 @@
// @flow // @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import Button from '../../../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../../../base/react/constants';
import { createBreakoutRoom } from '../../../../../breakout-rooms/actions'; import { createBreakoutRoom } from '../../../../../breakout-rooms/actions';
import styles from './styles'; import styles from './styles';
const AddBreakoutRoomButton = () => { const AddBreakoutRoomButton = () => {
const { t } = useTranslation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const onAdd = useCallback(() => const onAdd = useCallback(() =>
@ -19,12 +18,11 @@ const AddBreakoutRoomButton = () => {
return ( return (
<Button <Button
accessibilityLabel = { t('breakoutRooms.actions.add') } accessibilityLabel = 'breakoutRooms.actions.add'
children = { t('breakoutRooms.actions.add') } label = 'breakoutRooms.actions.add'
labelStyle = { styles.addButtonLabel }
mode = 'contained'
onPress = { onAdd } onPress = { onAdd }
style = { styles.addButton } /> style = { styles.addButton }
type = { BUTTON_TYPES.SECONDARY } />
); );
}; };

View File

@ -1,16 +1,16 @@
// @flow // @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import Button from '../../../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../../../base/react/constants';
import { autoAssignToBreakoutRooms } from '../../../../../breakout-rooms/actions'; import { autoAssignToBreakoutRooms } from '../../../../../breakout-rooms/actions';
import styles from './styles'; import styles from './styles';
const AutoAssignButton = () => { const AutoAssignButton = () => {
const { t } = useTranslation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const onAutoAssign = useCallback(() => { const onAutoAssign = useCallback(() => {
@ -19,12 +19,12 @@ const AutoAssignButton = () => {
return ( return (
<Button <Button
accessibilityLabel = { t('breakoutRooms.actions.autoAssign') } accessibilityLabel = 'breakoutRooms.actions.autoAssign'
children = { t('breakoutRooms.actions.autoAssign') } label = 'breakoutRooms.actions.autoAssign'
labelStyle = { styles.autoAssignLabel } labelStyle = { styles.autoAssignLabel }
mode = 'contained'
onPress = { onAutoAssign } onPress = { onAutoAssign }
style = { styles.transparentButton } /> style = { styles.autoAssignButton }
type = { BUTTON_TYPES.TERTIARY } />
); );
}; };

View File

@ -19,14 +19,10 @@ const baseLabel = {
*/ */
export default { export default {
addButtonLabel: {
...baseLabel,
color: BaseTheme.palette.text01
},
addButton: { addButton: {
...baseButton, marginTop: BaseTheme.spacing[3],
backgroundColor: BaseTheme.palette.ui03 marginLeft: BaseTheme.spacing[3],
marginRight: BaseTheme.spacing[3]
}, },
collapsibleRoom: { collapsibleRoom: {
@ -70,18 +66,18 @@ export default {
marginLeft: BaseTheme.spacing[2] marginLeft: BaseTheme.spacing[2]
}, },
transparentButton: {
backgroundColor: 'transparent',
marginTop: BaseTheme.spacing[3]
},
leaveButtonLabel: { leaveButtonLabel: {
...baseLabel, ...baseLabel,
color: BaseTheme.palette.textError color: BaseTheme.palette.textError
}, },
autoAssignLabel: { autoAssignLabel: {
...baseLabel,
color: BaseTheme.palette.link01 color: BaseTheme.palette.link01
},
autoAssignButton: {
alignSelf: 'center',
justifyContent: 'center',
marginTop: BaseTheme.spacing[3]
} }
}; };

View File

@ -1,10 +0,0 @@
// @flow
import React from 'react';
import { Icon, IconHorizontalPoints } from '../../../base/icons';
const HorizontalDotsIcon = () => (<Icon
size = { 20 }
src = { IconHorizontalPoints } />);
export default HorizontalDotsIcon;

View File

@ -1,11 +1,11 @@
// @flow // @flow
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { hasRaisedHand } from '../../../base/participants'; import { hasRaisedHand } from '../../../base/participants';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { approveKnockingParticipant } from '../../../lobby/actions.native'; import { approveKnockingParticipant } from '../../../lobby/actions.native';
import { showContextMenuReject } from '../../actions.native'; import { showContextMenuReject } from '../../actions.native';
import { MEDIA_STATE } from '../../constants'; import { MEDIA_STATE } from '../../constants';
@ -25,7 +25,6 @@ export const LobbyParticipantItem = ({ participant: p }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const admit = useCallback(() => dispatch(approveKnockingParticipant(p.id), [ dispatch ])); const admit = useCallback(() => dispatch(approveKnockingParticipant(p.id), [ dispatch ]));
const openContextMenuReject = useCallback(() => dispatch(showContextMenuReject(p), [ dispatch ])); const openContextMenuReject = useCallback(() => dispatch(showContextMenuReject(p), [ dispatch ]));
const { t } = useTranslation();
return ( return (
<ParticipantItem <ParticipantItem
@ -39,12 +38,11 @@ export const LobbyParticipantItem = ({ participant: p }: Props) => {
raisedHand = { hasRaisedHand(p) } raisedHand = { hasRaisedHand(p) }
videoMediaState = { MEDIA_STATE.NONE }> videoMediaState = { MEDIA_STATE.NONE }>
<Button <Button
children = { t('lobby.admit') } accessibilityLabel = 'lobby.admit'
contentStyle = { styles.participantActionsButtonContent } label = 'lobby.admit'
labelStyle = { styles.participantActionsButtonText }
mode = 'contained'
onPress = { admit } onPress = { admit }
style = { styles.participantActionsButtonAdmit } /> style = { styles.participantActionsButtonAdmit }
type = { BUTTON_TYPES.PRIMARY } />
</ParticipantItem> </ParticipantItem>
); );
}; };

View File

@ -3,9 +3,10 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ScrollView, Text, View } from 'react-native'; import { ScrollView, Text, View } from 'react-native';
import { Button, withTheme } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { admitMultiple } from '../../../lobby/actions.native'; import { admitMultiple } from '../../../lobby/actions.native';
import { getKnockingParticipants, getLobbyEnabled } from '../../../lobby/functions'; import { getKnockingParticipants, getLobbyEnabled } from '../../../lobby/functions';
@ -13,15 +14,8 @@ import CollapsibleList from './CollapsibleList';
import { LobbyParticipantItem } from './LobbyParticipantItem'; import { LobbyParticipantItem } from './LobbyParticipantItem';
import styles from './styles'; import styles from './styles';
type Props = {
/** const LobbyParticipantList = () => {
* Theme used for styles.
*/
theme: Object
};
const LobbyParticipantList = ({ theme }: Props) => {
const lobbyEnabled = useSelector(getLobbyEnabled); const lobbyEnabled = useSelector(getLobbyEnabled);
const participants = useSelector(getKnockingParticipants); const participants = useSelector(getKnockingParticipants);
@ -30,11 +24,11 @@ const LobbyParticipantList = ({ theme }: Props) => {
dispatch(admitMultiple(participants)), dispatch(admitMultiple(participants)),
[ dispatch, participants ]); [ dispatch, participants ]);
const { t } = useTranslation(); const { t } = useTranslation();
const { palette } = theme;
if (!lobbyEnabled || !participants.length) { if (!lobbyEnabled || !participants.length) {
return null; return null;
} }
const title = ( const title = (
<View style = { styles.lobbyListDetails } > <View style = { styles.lobbyListDetails } >
<Text style = { styles.lobbyListDescription }> <Text style = { styles.lobbyListDescription }>
@ -44,12 +38,11 @@ const LobbyParticipantList = ({ theme }: Props) => {
{ {
participants.length > 1 && ( participants.length > 1 && (
<Button <Button
color = { palette.action02 } accessibilityLabel = 'lobby.admitAll'
labelStyle = { styles.admitAllParticipantsActionButtonLabel } label = 'lobby.admitAll'
mode = 'text' labelStyle = { styles.admitAllButtonLabel }
onPress = { admitAll }> onPress = { admitAll }
{t('lobby.admitAll')} type = { BUTTON_TYPES.TERTIARY } />
</Button>
) )
} }
</View> </View>
@ -78,4 +71,4 @@ const LobbyParticipantList = ({ theme }: Props) => {
); );
}; };
export default withTheme(LobbyParticipantList); export default LobbyParticipantList;

View File

@ -2,12 +2,15 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { FlatList } from 'react-native'; import { FlatList } from 'react-native';
import { Button, withTheme } from 'react-native-paper';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { Icon, IconInviteMore } from '../../../base/icons'; import { Icon, IconInviteMore } from '../../../base/icons';
import { getLocalParticipant, getParticipantCountWithFake, getRemoteParticipants } from '../../../base/participants'; import { getLocalParticipant, getParticipantCountWithFake, getRemoteParticipants } from '../../../base/participants';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions'; import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native'; import { doInvitePeople } from '../../../invite/actions.native';
import { participantMatchesSearch, shouldRenderInviteButton } from '../../functions'; import { participantMatchesSearch, shouldRenderInviteButton } from '../../functions';
@ -83,12 +86,7 @@ type Props = {
/** /**
* Translation function. * Translation function.
*/ */
t: Function, t: Function
/**
* Theme used for styles.
*/
theme: Object
} }
/** /**
@ -230,17 +228,17 @@ class MeetingParticipantList extends PureComponent<Props> {
{ {
_showInviteButton _showInviteButton
&& <Button && <Button
children = { t('participantsPane.actions.invite') } accessibilityLabel = 'participantsPane.actions.invite'
icon = { this._renderInviteMoreIcon } icon = { this._renderInviteMoreIcon }
labelStyle = { styles.inviteLabel } label = 'participantsPane.actions.invite'
mode = 'contained'
onPress = { this._onInvite } onPress = { this._onInvite }
style = { styles.inviteButton } /> style = { styles.inviteButton }
type = { BUTTON_TYPES.PRIMARY } />
} }
<ClearableInput <ClearableInput
onChange = { this._onSearchStringChange } onChange = { this._onSearchStringChange }
placeholder = { t('participantsPane.search') } placeholder = { t('participantsPane.search') }
selectionColor = { this.props.theme.palette.text01 } /> selectionColor = { BaseTheme.palette.text01 } />
<FlatList <FlatList
bounces = { false } bounces = { false }
data = { [ _localParticipant?.id, ..._sortedRemoteParticipants ] } data = { [ _localParticipant?.id, ..._sortedRemoteParticipants ] }
@ -280,4 +278,4 @@ function _mapStateToProps(state): Object {
}; };
} }
export default translate(connect(_mapStateToProps)(withTheme(MeetingParticipantList))); export default translate(connect(_mapStateToProps)(MeetingParticipantList));

View File

@ -1,12 +1,8 @@
// @flow // @flow
import React, { useCallback, useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux';
import { View } from 'react-native';
import { Button } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux';
import { openDialog, openSheet } from '../../../base/dialog';
import JitsiScreen from '../../../base/modal/components/JitsiScreen'; import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { isLocalParticipantModerator } from '../../../base/participants'; import { isLocalParticipantModerator } from '../../../base/participants';
import { equals } from '../../../base/redux'; import { equals } from '../../../base/redux';
@ -18,9 +14,6 @@ import {
isInBreakoutRoom isInBreakoutRoom
} from '../../../breakout-rooms/functions'; } from '../../../breakout-rooms/functions';
import { getKnockingParticipants } from '../../../lobby/functions'; import { getKnockingParticipants } from '../../../lobby/functions';
import MuteEveryoneDialog
from '../../../video-menu/components/native/MuteEveryoneDialog';
import { isMoreActionsVisible, isMuteAllVisible } from '../../functions';
import { import {
AddBreakoutRoomButton, AddBreakoutRoomButton,
AutoAssignButton, AutoAssignButton,
@ -28,26 +21,20 @@ import {
} from '../breakout-rooms/components/native'; } from '../breakout-rooms/components/native';
import { CollapsibleRoom } from '../breakout-rooms/components/native/CollapsibleRoom'; import { CollapsibleRoom } from '../breakout-rooms/components/native/CollapsibleRoom';
import { ContextMenuMore } from './ContextMenuMore';
import HorizontalDotsIcon from './HorizontalDotsIcon';
import LobbyParticipantList from './LobbyParticipantList'; import LobbyParticipantList from './LobbyParticipantList';
import MeetingParticipantList from './MeetingParticipantList'; import MeetingParticipantList from './MeetingParticipantList';
import ParticipantsPaneFooter from './ParticipantsPaneFooter';
import styles from './styles'; import styles from './styles';
/** /**
* Participant pane. * Participants pane.
* *
* @returns {React$Element<any>} * @returns {React$Element<any>}
*/ */
const ParticipantsPane = () => { const ParticipantsPane = () => {
const dispatch = useDispatch();
const [ searchString, setSearchString ] = useState(''); const [ searchString, setSearchString ] = useState('');
const openMoreMenu = useCallback(() => dispatch(openSheet(ContextMenuMore)), [ dispatch ]);
const isLocalModerator = useSelector(isLocalParticipantModerator); const isLocalModerator = useSelector(isLocalParticipantModerator);
const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)),
[ dispatch ]);
const { t } = useTranslation();
const { conference } = useSelector(state => state['features/base/conference']); const { conference } = useSelector(state => state['features/base/conference']);
const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported(); const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
const currentRoomId = useSelector(getCurrentRoomId); const currentRoomId = useSelector(getCurrentRoomId);
@ -57,12 +44,12 @@ const ParticipantsPane = () => {
const inBreakoutRoom = useSelector(isInBreakoutRoom); const inBreakoutRoom = useSelector(isInBreakoutRoom);
const showAddBreakoutRoom = useSelector(isAddBreakoutRoomButtonVisible); const showAddBreakoutRoom = useSelector(isAddBreakoutRoomButtonVisible);
const showAutoAssign = useSelector(isAutoAssignParticipantsVisible); const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
const showMoreActions = useSelector(isMoreActionsVisible);
const showMuteAll = useSelector(isMuteAllVisible);
const lobbyParticipants = useSelector(getKnockingParticipants); const lobbyParticipants = useSelector(getKnockingParticipants);
return ( return (
<JitsiScreen style = { styles.participantsPaneContainer }> <JitsiScreen
footerComponent = { isLocalModerator && ParticipantsPaneFooter }
style = { styles.participantsPaneContainer }>
<LobbyParticipantList /> <LobbyParticipantList />
<MeetingParticipantList <MeetingParticipantList
breakoutRooms = { rooms } breakoutRooms = { rooms }
@ -86,31 +73,6 @@ const ParticipantsPane = () => {
{ {
showAddBreakoutRoom && <AddBreakoutRoomButton /> showAddBreakoutRoom && <AddBreakoutRoomButton />
} }
{
isLocalModerator
&& <View style = { styles.participantsPaneFooter }>
{
showMuteAll && (
<Button
children = { t('participantsPane.actions.muteAll') }
labelStyle = { styles.muteAllLabel }
mode = 'contained'
onPress = { muteAll }
style = { styles.muteAllMoreButton } />
)
}
{
showMoreActions && (
<Button
icon = { HorizontalDotsIcon }
labelStyle = { styles.moreIcon }
mode = 'contained'
onPress = { openMoreMenu }
style = { styles.moreButton } />
)
}
</View>
}
</JitsiScreen> </JitsiScreen>
); );
}; };

View File

@ -0,0 +1,55 @@
import React, { useCallback } from 'react';
import { View } from 'react-native';
import { useDispatch, useSelector} from "react-redux";
import { openDialog, openSheet } from '../../../base/dialog';
import { IconHorizontalPoints } from '../../../base/icons';
import Button from '../../../base/react/components/native/Button';
import IconButton from '../../../base/react/components/native/IconButton';
import { BUTTON_TYPES } from '../../../base/react/constants';
import MuteEveryoneDialog
from '../../../video-menu/components/native/MuteEveryoneDialog';
import { isMoreActionsVisible, isMuteAllVisible } from '../../functions';
import { ContextMenuMore } from './ContextMenuMore';
import styles from './styles';
/**
* Implements the participants pane footer component.
*
* @returns { JSX.Element} - The participants pane footer component.
*/
const ParticipantsPaneFooter = (): JSX.Element => {
const dispatch = useDispatch();
const openMoreMenu = useCallback(() => dispatch(openSheet(ContextMenuMore)), [ dispatch ]);
const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)),
[ dispatch ]);
const showMoreActions = useSelector(isMoreActionsVisible);
const showMuteAll = useSelector(isMuteAllVisible);
return(
<View style = { styles.participantsPaneFooter }>
{
showMuteAll && (
<Button
accessibilityLabel = 'participantsPane.actions.muteAll'
label = 'participantsPane.actions.muteAll'
onPress = { muteAll }
type = { BUTTON_TYPES.SECONDARY } />
)
}
{
showMoreActions && (
<IconButton
onPress = { openMoreMenu }
src = { IconHorizontalPoints }
style = { styles.moreButton }
type = { BUTTON_TYPES.SECONDARY } />
)
}
</View>
)
};
export default ParticipantsPaneFooter;

View File

@ -35,39 +35,8 @@ const contextMenuItemText = {
* The style of the participants pane buttons. * The style of the participants pane buttons.
*/ */
export const button = { export const button = {
backgroundColor: BaseTheme.palette.action02,
borderRadius: BaseTheme.shape.borderRadius,
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'center',
minWidth: 0
};
/**
* Small buttons.
*/
const smallButton = {
...button,
height: BaseTheme.spacing[7],
width: BaseTheme.spacing[7]
};
/**
* Mute all button.
*/
const muteAllButton = {
...button,
marginLeft: 'auto'
};
/**
* The style of the participants pane buttons description.
*/
const buttonContent = {
...BaseTheme.typography.labelButton,
alignContent: 'center',
color: BaseTheme.palette.text01,
display: 'flex',
justifyContent: 'center' justifyContent: 'center'
}; };
@ -88,34 +57,15 @@ const contextMenuItem = {
export default { export default {
participantActionsButtonAdmit: { participantActionsButtonAdmit: {
backgroundColor: BaseTheme.palette.action01,
borderRadius: BaseTheme.shape.borderRadius,
flexDirection: 'row',
height: BaseTheme.spacing[6],
marginRight: BaseTheme.spacing[3], marginRight: BaseTheme.spacing[3],
position: 'absolute', position: 'absolute',
right: 0, right: 0
zIndex: 1
}, },
participantActionsButtonContent: { admitAllButtonLabel: {
alignItems: 'center',
display: 'flex',
height: BaseTheme.spacing[5],
top: BaseTheme.spacing[1]
},
participantActionsButtonText: {
color: BaseTheme.palette.text01,
textTransform: 'capitalize'
},
admitAllParticipantsActionButtonLabel: {
...BaseTheme.typography.heading6,
color: BaseTheme.palette.link01, color: BaseTheme.palette.link01,
textTransform: 'capitalize', marginRight: BaseTheme.spacing[6],
marginRight: BaseTheme.spacing[5], marginTop: 14
marginTop: BaseTheme.spacing[3]
}, },
participantContainer: { participantContainer: {
@ -263,49 +213,13 @@ export default {
}, },
inviteButton: { inviteButton: {
backgroundColor: BaseTheme.palette.action01,
borderRadius: BaseTheme.shape.borderRadius,
height: BaseTheme.spacing[7],
marginLeft: BaseTheme.spacing[3], marginLeft: BaseTheme.spacing[3],
marginRight: BaseTheme.spacing[3], marginRight: BaseTheme.spacing[3],
marginVertical: BaseTheme.spacing[3] marginVertical: BaseTheme.spacing[3]
}, },
inviteLabel: {
fontSize: 15,
lineHeight: 30,
textTransform: 'capitalize'
},
moreButton: { moreButton: {
...smallButton, marginLeft: BaseTheme.spacing[2]
marginLeft: BaseTheme.spacing[3]
},
moreIcon: {
...buttonContent,
height: BaseTheme.spacing[5],
marginLeft: 'auto'
},
muteAllButton: {
...muteAllButton
},
muteAllMoreButton: {
...muteAllButton
},
muteAllLabel: {
...BaseTheme.typography.labelButtonLarge,
color: BaseTheme.palette.text01,
height: BaseTheme.spacing[7],
marginVertical: BaseTheme.spacing[0],
marginHorizontal: BaseTheme.spacing[0],
paddingTop: 12,
paddingBottom: 12,
textTransform: 'capitalize',
width: 94
}, },
contextMenuItem: { contextMenuItem: {

View File

@ -2,12 +2,12 @@
import React from 'react'; import React from 'react';
import { Switch, Text, View } from 'react-native'; import { Switch, Text, View } from 'react-native';
import { Button } from 'react-native-paper';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { getLocalParticipant } from '../../../base/participants'; import { getLocalParticipant } from '../../../base/participants';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import BaseTheme from '../../../base/ui/components/BaseTheme.native'; import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import { BUTTON_MODES } from '../../../chat/constants';
import { isSubmitAnswerDisabled } from '../../functions'; import { isSubmitAnswerDisabled } from '../../functions';
import AbstractPollAnswer from '../AbstractPollAnswer'; import AbstractPollAnswer from '../AbstractPollAnswer';
import type { AbstractProps } from '../AbstractPollAnswer'; import type { AbstractProps } from '../AbstractPollAnswer';
@ -27,6 +27,7 @@ const PollAnswer = (props: AbstractProps) => {
} = props; } = props;
const { changingVote } = poll; const { changingVote } = poll;
const localParticipant = useSelector(getLocalParticipant); const localParticipant = useSelector(getLocalParticipant);
const { PRIMARY, SECONDARY } = BUTTON_TYPES;
return ( return (
<> <>
@ -51,26 +52,18 @@ const PollAnswer = (props: AbstractProps) => {
</View> </View>
<View style = { chatStyles.buttonRow }> <View style = { chatStyles.buttonRow }>
<Button <Button
color = { BaseTheme.palette.action02 } accessibilityLabel = 'polls.answer.skip'
labelStyle = { chatStyles.pollButtonLabel } label = 'polls.answer.skip'
mode = { BUTTON_MODES.CONTAINED }
onPress = { changingVote ? skipChangeVote : skipAnswer } onPress = { changingVote ? skipChangeVote : skipAnswer }
style = { chatStyles.pollCreateButton } > style = { chatStyles.pollCreateButton }
{ t('polls.answer.skip') } type = { SECONDARY } />
</Button>
<Button <Button
color = { BaseTheme.palette.action01 } accessibilityLabel = 'polls.answer.submit'
disabled = { isSubmitAnswerDisabled(checkBoxStates) } disabled = { isSubmitAnswerDisabled(checkBoxStates) }
labelStyle = { label = 'polls.answer.submit'
isSubmitAnswerDisabled(checkBoxStates)
? chatStyles.pollSendDisabledLabel
: chatStyles.pollSendLabel
}
mode = { BUTTON_MODES.CONTAINED }
onPress = { submitAnswer } onPress = { submitAnswer }
style = { chatStyles.pollCreateButton } > style = { chatStyles.pollCreateButton }
{ t('polls.answer.submit') } type = { PRIMARY } />
</Button>
</View> </View>
</> </>

View File

@ -1,11 +1,12 @@
// @flow // @flow
import React, { useCallback, useEffect, useRef, useState } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { View, Text, TextInput, FlatList } from 'react-native'; import { View, Text, TextInput, FlatList, Platform } from 'react-native';
import { Button, Divider, TouchableRipple } from 'react-native-paper'; import { Divider, TouchableRipple } from 'react-native-paper';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import BaseTheme from '../../../base/ui/components/BaseTheme.native'; import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import { BUTTON_MODES } from '../../../chat/constants';
import styles import styles
from '../../../welcome/components/native/settings/components/styles'; from '../../../welcome/components/native/settings/components/styles';
import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants'; import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants';
@ -16,8 +17,6 @@ import { chatStyles, dialogStyles } from './styles';
const PollCreate = (props: AbstractProps) => { const PollCreate = (props: AbstractProps) => {
const { const {
addAnswer, addAnswer,
answers, answers,
@ -56,6 +55,7 @@ const PollCreate = (props: AbstractProps) => {
* about whether a newly created input field has been rendered yet or not. * about whether a newly created input field has been rendered yet or not.
*/ */
const [ lastFocus, requestFocus ] = useState(null); const [ lastFocus, requestFocus ] = useState(null);
const { PRIMARY, SECONDARY } = BUTTON_TYPES;
useEffect(() => { useEffect(() => {
if (lastFocus === null) { if (lastFocus === null) {
@ -127,6 +127,8 @@ const PollCreate = (props: AbstractProps) => {
} }
</View> </View>
); );
const buttonRowStyles = Platform.OS === 'android'
? chatStyles.buttonRowAndroid : chatStyles.buttonRowIos;
return ( return (
<View style = { chatStyles.pollCreateContainer }> <View style = { chatStyles.pollCreateContainer }>
@ -156,47 +158,36 @@ const PollCreate = (props: AbstractProps) => {
renderItem = { renderListItem } /> renderItem = { renderListItem } />
<View style = { chatStyles.pollCreateButtonsContainer }> <View style = { chatStyles.pollCreateButtonsContainer }>
<Button <Button
color = { BaseTheme.palette.action02 } accessibilityLabel = 'polls.create.addOption'
disabled = { answers.length >= ANSWERS_LIMIT } disabled = { answers.length >= ANSWERS_LIMIT }
labelStyle = { chatStyles.pollButtonLabel } label = 'polls.create.addOption'
mode = { BUTTON_MODES.CONTAINED }
onPress = { () => { onPress = { () => {
// adding and answer // adding and answer
addAnswer(); addAnswer();
requestFocus(answers.length); requestFocus(answers.length);
} } } }
style = { chatStyles.pollCreateAddButton }> style = { chatStyles.pollCreateAddButton }
{ t('polls.create.addOption') } type = { SECONDARY } />
</Button>
<View <View
style = { chatStyles.buttonRow }> style = { buttonRowStyles }>
<Button <Button
color = { BaseTheme.palette.action02 } accessibilityLabel = 'polls.create.cancel'
labelStyle = { chatStyles.pollButtonLabel } label = 'polls.create.cancel'
mode = { BUTTON_MODES.CONTAINED }
onPress = { () => setCreateMode(false) } onPress = { () => setCreateMode(false) }
style = { chatStyles.pollCreateButton } > style = { chatStyles.pollCreateButton }
{ t('polls.create.cancel') } type = { SECONDARY } />
</Button>
<Button <Button
color = { BaseTheme.palette.action01 } accessibilityLabel = 'polls.create.send'
disabled = { isSubmitDisabled } disabled = { isSubmitDisabled }
labelStyle = { label = 'polls.create.send'
isSubmitDisabled
? chatStyles.pollSendDisabledLabel
: chatStyles.pollSendLabel
}
mode = { BUTTON_MODES.CONTAINED }
onPress = { onSubmit } onPress = { onSubmit }
style = { chatStyles.pollCreateButton } > style = { chatStyles.pollCreateButton }
{ t('polls.create.send') } type = { PRIMARY } />
</Button>
</View> </View>
</View> </View>
</View> </View>
</View> </View>
); );
}; };
/* /*

View File

@ -3,11 +3,11 @@
import { useNavigation, useIsFocused } from '@react-navigation/native'; import { useNavigation, useIsFocused } from '@react-navigation/native';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Button, useTheme } from 'react-native-paper';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import JitsiScreen from '../../../base/modal/components/JitsiScreen'; import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { BUTTON_MODES } from '../../../chat/constants'; import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { getUnreadPollCount } from '../../functions'; import { getUnreadPollCount } from '../../functions';
import AbstractPollsPane from '../AbstractPollsPane'; import AbstractPollsPane from '../AbstractPollsPane';
import type { AbstractProps } from '../AbstractPollsPane'; import type { AbstractProps } from '../AbstractPollsPane';
@ -22,7 +22,6 @@ const PollsPane = (props: AbstractProps) => {
const isPollsScreenFocused = useIsFocused(); const isPollsScreenFocused = useIsFocused();
const navigation = useNavigation(); const navigation = useNavigation();
const nbUnreadPolls = useSelector(getUnreadPollCount); const nbUnreadPolls = useSelector(getUnreadPollCount);
const { palette } = useTheme();
const nrUnreadPolls = !isPollsScreenFocused && nbUnreadPolls > 0 const nrUnreadPolls = !isPollsScreenFocused && nbUnreadPolls > 0
? `(${nbUnreadPolls})` ? `(${nbUnreadPolls})`
@ -47,13 +46,11 @@ const PollsPane = (props: AbstractProps) => {
} }
{ {
!createMode && <Button !createMode && <Button
color = { palette.action01 } accessibilityLabel = 'polls.create.create'
labelStyle = { chatStyles.pollButtonLabel } label = 'polls.create.create'
mode = { BUTTON_MODES.CONTAINED }
onPress = { onCreate } onPress = { onCreate }
style = { chatStyles.createPollButton } > style = { chatStyles.createPollButton }
{t('polls.create.create')} type = { BUTTON_TYPES.PRIMARY } />
</Button>
} }
</JitsiScreen> </JitsiScreen>
); );

View File

@ -167,7 +167,6 @@ export const chatStyles = createStyleSheet({
pollCreateButton: { pollCreateButton: {
flex: 1, flex: 1,
padding: 4,
marginHorizontal: BaseTheme.spacing[2] marginHorizontal: BaseTheme.spacing[2]
}, },
@ -185,6 +184,15 @@ export const chatStyles = createStyleSheet({
flexDirection: 'row' flexDirection: 'row'
}, },
buttonRowAndroid: {
flexDirection: 'row',
marginBottom: BaseTheme.spacing[3]
},
buttonRowIos: {
flexDirection: 'row'
},
answerContent: { answerContent: {
paddingBottom: 8 paddingBottom: 8
}, },
@ -200,13 +208,8 @@ export const chatStyles = createStyleSheet({
marginLeft: BaseTheme.spacing[2] marginLeft: BaseTheme.spacing[2]
}, },
pollButtonLabel: {
textTransform: 'capitalize'
},
pollCreateAddButton: { pollCreateAddButton: {
margin: BaseTheme.spacing[2], margin: BaseTheme.spacing[2]
padding: BaseTheme.spacing[1]
}, },
toggleText: { toggleText: {
@ -215,7 +218,6 @@ export const chatStyles = createStyleSheet({
}, },
createPollButton: { createPollButton: {
padding: 4,
marginHorizontal: BaseTheme.spacing[4], marginHorizontal: BaseTheme.spacing[4],
marginVertical: '8%' marginVertical: '8%'
}, },

View File

@ -2,9 +2,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
BackHandler, BackHandler,
Text,
View, View,
TouchableOpacity,
TextInput, TextInput,
Platform Platform
} from 'react-native'; } from 'react-native';
@ -17,6 +15,8 @@ import { IconClose } from '../../base/icons';
import JitsiScreen from '../../base/modal/components/JitsiScreen'; import JitsiScreen from '../../base/modal/components/JitsiScreen';
import { getLocalParticipant } from '../../base/participants'; import { getLocalParticipant } from '../../base/participants';
import { getFieldValue } from '../../base/react'; import { getFieldValue } from '../../base/react';
import Button from '../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../base/react/constants';
import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui'; import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui';
import { updateSettings } from '../../base/settings'; import { updateSettings } from '../../base/settings';
import BaseTheme from '../../base/ui/components/BaseTheme.native'; import BaseTheme from '../../base/ui/components/BaseTheme.native';
@ -28,15 +28,11 @@ import { screen } from '../../mobile/navigation/routes';
import AudioMuteButton from '../../toolbox/components/AudioMuteButton'; import AudioMuteButton from '../../toolbox/components/AudioMuteButton';
import VideoMuteButton from '../../toolbox/components/VideoMuteButton'; import VideoMuteButton from '../../toolbox/components/VideoMuteButton';
import { isDisplayNameRequired } from '../functions'; import { isDisplayNameRequired } from '../functions';
import { PrejoinProps } from '../types';
import styles from './styles'; import styles from './styles';
interface Props { const Prejoin: React.FC<PrejoinProps> = ({ navigation }: PrejoinProps) => {
navigation: any;
}
const Prejoin: ({ navigation }: Props) => JSX.Element = ({ navigation }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const aspectRatio = useSelector( const aspectRatio = useSelector(
@ -88,9 +84,8 @@ const Prejoin: ({ navigation }: Props) => JSX.Element = ({ navigation }: Props)
); );
}, []); }, []);
const { PRIMARY, SECONDARY } = BUTTON_TYPES;
const joinButtonDisabled = !displayName && isDisplayNameMandatory; const joinButtonDisabled = !displayName && isDisplayNameMandatory;
const joinButtonStyles = joinButtonDisabled
? styles.primaryButtonDisabled : styles.primaryButton;
useEffect(() => { useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', goBack); BackHandler.addEventListener('hardwareBackPress', goBack);
@ -122,6 +117,7 @@ const Prejoin: ({ navigation }: Props) => JSX.Element = ({ navigation }: Props)
toolboxContainerStyles = styles.toolboxContainerWide; toolboxContainerStyles = styles.toolboxContainerWide;
} }
return ( return (
<JitsiScreen <JitsiScreen
safeAreaInsets = { [ 'left' ] } safeAreaInsets = { [ 'left' ] }
@ -138,27 +134,19 @@ const Prejoin: ({ navigation }: Props) => JSX.Element = ({ navigation }: Props)
placeholderTextColor = { BaseTheme.palette.text03 } placeholderTextColor = { BaseTheme.palette.text03 }
style = { styles.field } style = { styles.field }
value = { displayName } /> value = { displayName } />
<TouchableOpacity <Button
accessibilityLabel = 'prejoin.joinMeeting'
disabled = { joinButtonDisabled } disabled = { joinButtonDisabled }
label = 'prejoin.joinMeeting'
onPress = { onJoin } onPress = { onJoin }
style = { [ style = { styles.prejoinButton }
styles.button, type = { PRIMARY } />
joinButtonStyles <Button
] }> accessibilityLabel = 'prejoin.joinMeetingInLowBandwidthMode'
<Text style = { styles.primaryButtonText }> label = 'prejoin.joinMeetingInLowBandwidthMode'
{ t('prejoin.joinMeeting') }
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress = { onJoinLowBandwidth } onPress = { onJoinLowBandwidth }
style = { [ style = { styles.prejoinButton }
styles.button, type = { SECONDARY } />
styles.secondaryButton
] }>
<Text style = { styles.secondaryButtonText }>
{ t('prejoin.joinMeetingInLowBandwidthMode') }
</Text>
</TouchableOpacity>
</View> </View>
<View style = { toolboxContainerStyles }> <View style = { toolboxContainerStyles }>
<AudioMuteButton <AudioMuteButton

View File

@ -1,47 +1,13 @@
import BaseTheme from '../../base/ui/components/BaseTheme.native'; import BaseTheme from '../../base/ui/components/BaseTheme.native';
const SECONDARY_COLOR = BaseTheme.palette.border04; const SECONDARY_COLOR = BaseTheme.palette.border04;
const btn = {
marginTop: BaseTheme.spacing[4]
};
const btnText = {
...BaseTheme.typography.labelButtonLarge,
color: BaseTheme.palette.text01,
lineHeight: 30
};
export default { export default {
button: { prejoinButton: {
alignItems: 'center',
borderRadius: BaseTheme.shape.borderRadius,
padding: BaseTheme.spacing[2],
height: BaseTheme.spacing[7]
},
primaryButton: {
...btn,
backgroundColor: BaseTheme.palette.action01
},
primaryButtonDisabled: {
backgroundColor: BaseTheme.palette.action03Disabled,
marginTop: BaseTheme.spacing[4] marginTop: BaseTheme.spacing[4]
}, },
primaryButtonText: {
...btnText
},
secondaryButton: {
...btn,
backgroundColor: BaseTheme.palette.action02
},
secondaryButtonText: {
...btnText
},
buttonStylesBorderless: { buttonStylesBorderless: {
iconStyle: { iconStyle: {
color: BaseTheme.palette.icon01, color: BaseTheme.palette.icon01,

View File

@ -0,0 +1,3 @@
interface PrejoinProps {
navigation: Object;
}

View File

@ -1,14 +1,13 @@
// @flow // @flow
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Text, TouchableHighlight, View } from 'react-native'; import { Text } from 'react-native-paper';
import { type Dispatch } from 'redux'; import { type Dispatch } from 'redux';
import { import {
createToolbarEvent, createToolbarEvent,
sendAnalytics sendAnalytics
} from '../../../analytics'; } from '../../../analytics';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { RAISE_HAND_ENABLED, getFeatureFlag } from '../../../base/flags'; import { RAISE_HAND_ENABLED, getFeatureFlag } from '../../../base/flags';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { import {
@ -16,10 +15,12 @@ import {
hasRaisedHand, hasRaisedHand,
raiseHand raiseHand
} from '../../../base/participants'; } from '../../../base/participants';
import Button from '../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../base/react/constants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { type AbstractButtonProps } from '../../../base/toolbox/components'; import { type AbstractButtonProps } from '../../../base/toolbox/components';
import { type ReactionStyles } from './ReactionButton'; import styles from './styles';
/** /**
* The type of the React {@code Component} props of {@link RaiseHandButton}. * The type of the React {@code Component} props of {@link RaiseHandButton}.
@ -54,12 +55,7 @@ type Props = AbstractButtonProps & {
/** /**
* Used to close the overflow menu after raise hand is clicked. * Used to close the overflow menu after raise hand is clicked.
*/ */
onCancel: Function, onCancel: Function
/**
* Styles for the button.
*/
_styles: ReactionStyles
}; };
/** /**
@ -127,6 +123,17 @@ class RaiseHandButton extends Component<Props, *> {
return t(_raisedHand ? this.toggledLabel : this.label); return t(_raisedHand ? this.toggledLabel : this.label);
} }
/**
* Renders the "raise hand" emoji.
*
* @returns {ReactElement}
*/
_renderRaiseHandEmoji() {
return (
<Text></Text>
);
}
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -134,24 +141,20 @@ class RaiseHandButton extends Component<Props, *> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { _enabled, _styles, t } = this.props; const { _enabled } = this.props;
if (!_enabled) { if (!_enabled) {
return null; return null;
} }
return ( return (
<TouchableHighlight <Button
accessibilityLabel = { t(this.accessibilityLabel) } accessibilityLabel = { this.accessibilityLabel }
accessibilityRole = 'button' icon = { this._renderRaiseHandEmoji }
label = { this._getLabel() }
onPress = { this._onClick } onPress = { this._onClick }
style = { _styles.style } style = { styles.raiseHandButton }
underlayColor = { _styles.underlayColor }> type = { BUTTON_TYPES.SECONDARY } />
<View style = { _styles.container }>
<Text style = { _styles.emoji }></Text>
<Text style = { _styles.text }>{this._getLabel()}</Text>
</View>
</TouchableHighlight>
); );
} }
} }
@ -170,8 +173,7 @@ function _mapStateToProps(state): Object {
return { return {
_enabled: enabled, _enabled: enabled,
_localParticipant, _localParticipant,
_raisedHand: hasRaisedHand(_localParticipant), _raisedHand: hasRaisedHand(_localParticipant)
_styles: ColorSchemeRegistry.get(state, 'Toolbox').raiseHandButton
}; };
} }

View File

@ -49,13 +49,16 @@ function ReactionMenu({
return ( return (
<View style = { overflowMenu ? _styles.overflowReactionMenu : _styles.reactionMenu }> <View style = { overflowMenu ? _styles.overflowReactionMenu : _styles.reactionMenu }>
<View style = { _styles.reactionRow }> <View style = { _styles.reactionRow }>
{Object.keys(REACTIONS).map(key => ( {
Object.keys(REACTIONS).map(key => (
<ReactionButton <ReactionButton
key = { key } key = { key }
reaction = { key } reaction = { key }
styles = { _styles.reactionButton } /> styles = { _styles.reactionButton } />
))} ))
{gifEnabled && ( }
{
gifEnabled && (
<ReactionButton <ReactionButton
onClick = { openGifMenu } onClick = { openGifMenu }
styles = { _styles.reactionButton }> styles = { _styles.reactionButton }>
@ -63,7 +66,8 @@ function ReactionMenu({
height = { 22 } height = { 22 }
source = { require('../../../../../images/GIPHY_icon.png') } /> source = { require('../../../../../images/GIPHY_icon.png') } />
</ReactionButton> </ReactionButton>
)} )
}
</View> </View>
<RaiseHandButton onCancel = { onCancel } /> <RaiseHandButton onCancel = { onCancel } />
</View> </View>

View File

@ -0,0 +1,11 @@
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
/**
* The styles of the native components of the feature {@code reactions}.
*/
export default {
raiseHandButton: {
marginVertical: BaseTheme.spacing[3],
width: 240
}
};

View File

@ -1,10 +1,11 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { Button } from 'react-native-paper';
import { useDispatch, batch } from 'react-redux'; import { useDispatch, batch } from 'react-redux';
import { BottomSheet, hideSheet } from '../../../../base/dialog'; import { BottomSheet, hideSheet } from '../../../../base/dialog';
import Button from '../../../../base/react/components/native/Button';
import { BUTTON_TYPES } from '../../../../base/react/constants';
import { highlightMeetingMoment } from '../../../actions.any'; import { highlightMeetingMoment } from '../../../actions.any';
import styles from '../styles.native'; import styles from '../styles.native';
@ -28,20 +29,16 @@ const HighlightDialog = () => {
</Text> </Text>
<View style = { styles.highlightDialogButtonsContainer } > <View style = { styles.highlightDialogButtonsContainer } >
<Button <Button
accessibilityLabel = { t('dialog.Cancel') } accessibilityLabel = 'dialog.Cancel'
children = { t('dialog.Cancel') } label = 'dialog.Cancel'
labelStyle = { styles.highlightDialogCancelLabel }
mode = 'contained'
onPress = { closeDialog } onPress = { closeDialog }
style = { styles.highlightDialogCancelButton } /> type = { BUTTON_TYPES.SECONDARY } />
<View style = { styles.highlightDialogButtonsSpace } /> <View style = { styles.highlightDialogButtonsSpace } />
<Button <Button
accessibilityLabel = { t('recording.highlight') } accessibilityLabel = 'recording.highlight'
children = { t('recording.highlight') } label = 'recording.highlight'
labelStyle = { styles.highlightDialogHighlighLabel }
mode = 'contained'
onPress = { highlightMoment } onPress = { highlightMoment }
style = { styles.highlightDialogHighlightButton } /> type = { BUTTON_TYPES.PRIMARY } />
</View> </View>
</View> </View>
</BottomSheet> </BottomSheet>

View File

@ -39,18 +39,6 @@ const title = {
paddingLeft: BoxModel.padding paddingLeft: BoxModel.padding
}; };
const baseHighlightDialogButton = {
borderRadius: BaseTheme.shape.borderRadius,
height: BaseTheme.spacing[7],
flex: 1,
justifyContent: 'space-around'
};
const baseHighlightDialogLabel = {
...BaseTheme.typography.bodyShortBoldLarge,
textTransform: 'none'
};
export default { export default {
/** /**
* Container for the StartRecordingDialog screen. * Container for the StartRecordingDialog screen.
@ -104,22 +92,6 @@ export default {
display: 'flex', display: 'flex',
flexDirection: 'column-reverse' flexDirection: 'column-reverse'
}, },
highlightDialogCancelButton: {
...baseHighlightDialogButton,
backgroundColor: BaseTheme.palette.section01
},
highlightDialogHighlightButton: {
...baseHighlightDialogButton,
backgroundColor: BaseTheme.palette.action01
},
highlightDialogCancelLabel: {
...baseHighlightDialogLabel,
color: BaseTheme.palette.field01
},
highlightDialogHighlighLabel: {
...baseHighlightDialogLabel,
color: BaseTheme.palette.text01
},
highlightDialogButtonsSpace: { highlightDialogButtonsSpace: {
height: 16, height: 16,
width: '100%' width: '100%'

View File

@ -161,8 +161,7 @@ ColorSchemeRegistry.register('Toolbox', {
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
width: '100%', width: '100%'
marginBottom: 16
}, },
reactionButton: { reactionButton: {
@ -172,28 +171,6 @@ ColorSchemeRegistry.register('Toolbox', {
emoji: reactionEmoji emoji: reactionEmoji
}, },
raiseHandButton: {
style: {
...reactionButton,
backgroundColor: BaseTheme.palette.ui13,
width: '100%',
borderRadius: 6
},
underlayColor: BaseTheme.palette.ui13,
emoji: reactionEmoji,
text: {
color: BaseTheme.palette.text01,
fontWeight: '600',
marginLeft: 8,
lineHeight: 24
},
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
}
},
emojiAnimation: { emojiAnimation: {
color: BaseTheme.palette.icon01, color: BaseTheme.palette.icon01,
position: 'absolute', position: 'absolute',

View File

@ -103,7 +103,7 @@ export default {
* Global {@code Text} color for the components. * Global {@code Text} color for the components.
*/ */
text: { text: {
color: BaseTheme.palette.text02 color: BaseTheme.palette.text01
}, },
/** /**