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.bundle.enableUncompressedNativeLibs=false
appVersion=22.3.0
sdkVersion=5.2.0
appVersion=22.4.0
sdkVersion=6.0.0

View File

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

View File

@ -46,6 +46,8 @@ import java.util.Arrays;
import java.util.List;
class ReactInstanceManagerHolder {
private static final String TAG = ReactInstanceManagerHolder.class.getSimpleName();
/**
* FIXME (from linter): Do not place Android context classes in static
* fields (static reference to ReactInstanceManager which has field
@ -110,7 +112,6 @@ class ReactInstanceManagerHolder {
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.reactnativecommunity.clipboard.ClipboardPackage(),
new com.giphyreactnativesdk.GiphyReactNativeSdkPackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),
new com.reactnativepagerview.PagerViewPackage(),
new com.oblador.performance.PerformancePackage(),
@ -146,6 +147,17 @@ class ReactInstanceManagerHolder {
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 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
@ -155,6 +167,7 @@ class ReactInstanceManagerHolder {
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 RNGoogleSignInPackage");
}
return packages;
@ -240,7 +253,7 @@ class ReactInstanceManagerHolder {
return;
}
Log.d(ReactInstanceManagerHolder.class.getCanonicalName(), "initializing RN with Application");
Log.d(TAG, "initializing RN with Application");
reactInstanceManager
= ReactInstanceManager.builder()

View File

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

View File

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

View File

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

View File

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

View File

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

141
package-lock.json generated
View File

@ -49,7 +49,7 @@
"@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "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",
"@tensorflow/tfjs-backend-wasm": "3.13.0",
"@tensorflow/tfjs-core": "3.13.0",
@ -5026,33 +5026,6 @@
"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": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz",
@ -5061,6 +5034,63 @@
"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": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
@ -23766,22 +23796,6 @@
"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": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz",
@ -23790,6 +23804,45 @@
"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": {
"version": "4.1.4",
"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/material-top-tabs": "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",
"@tensorflow/tfjs-backend-wasm": "3.13.0",
"@tensorflow/tfjs-core": "3.13.0",

View File

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

View File

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

View File

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

View File

@ -37,11 +37,6 @@ type Props = {
*/
hasTabNavigator?: boolean,
/**
* Is the screen presented as a modal?
*/
isModalPresentation?: boolean,
/**
* Insets for the SafeAreaView.
*/
@ -59,7 +54,6 @@ const JitsiScreen = ({
footerComponent,
hasTabNavigator = false,
hasBottomTextInput = false,
isModalPresentation = true,
safeAreaInsets = [ 'left', 'right' ],
style
}: Props) => (
@ -69,7 +63,6 @@ const JitsiScreen = ({
contentContainerStyle = { contentContainerStyle }
hasBottomTextInput = { hasBottomTextInput }
hasTabNavigator = { hasTabNavigator }
isModalPresentation = { isModalPresentation }
style = { style }>
<SafeAreaView
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 BaseIndicator } from './BaseIndicator';
export { default as Button } from './Button';
export { default as Container } from './Container';
export { default as Image } from './Image';
export { default as Link } from './Link';
@ -15,7 +14,6 @@ export { default as NavigateSectionListItem }
from './NavigateSectionListItem';
export { default as NavigateSectionListSectionHeader }
from './NavigateSectionListSectionHeader';
export { default as PagedList } from './PagedList';
export { default as Pressable } from './Pressable';
export { default as SectionList } from './SectionList';
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 SECONDARY_ACTION_BUTTON_SIZE = 30;
const BUTTON_HEIGHT = BaseTheme.spacing[7];
const BUTTON_WIDTH = BaseTheme.spacing[7];
export const AVATAR_SIZE = 65;
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 = {
/**
* The style of the avatar container that makes the avatar rounded.
@ -217,11 +136,82 @@ export const BASE_INDICATOR = {
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
* base/react.
*/
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.
*/
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
status01Bar: 'primary11',
actionDisabled: 'surface09',
// Hover state for primary buttons
action01Hover: 'primary06',
@ -102,7 +104,7 @@ export const colorMap = {
action01Disabled: 'primary02',
// Secondary buttons
action02: 'surface04',
action02: 'surface10',
// Hover state for secondary buttons
action02Hover: 'surface05',
@ -156,7 +158,7 @@ export const colorMap = {
text01: 'surface11',
// Secondary text with medium contrast
text02: 'surface09',
text02: 'surface01',
// Tertiary text with low contrast placeholders, disabled actions, label for disabled buttons
text03: 'surface07',
@ -180,7 +182,7 @@ export const colorMap = {
icon01: 'surface11',
// Secondary color for input fields
icon02: 'surface09',
icon02: 'surface01',
// Tertiary color for disabled actions
icon03: 'surface07',

View File

@ -35,11 +35,3 @@ export const SMALL_WIDTH_THRESHOLD = 580;
* Lobby message type.
*/
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 { Text, TouchableOpacity, View } from 'react-native';
import { Text, View } from 'react-native';
import { getFeatureFlag, INVITE_ENABLED } from '../../../base/flags';
import { translate } from '../../../base/i18n';
import { Icon, IconAddPeople } from '../../../base/icons';
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 { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native';
@ -57,6 +59,19 @@ class LonelyMeetingExperience extends PureComponent<Props> {
this._onPress = this._onPress.bind(this);
}
/**
* Renders the "add people" icon.
*
* @returns {ReactElement}
*/
_renderAddPeopleIcon() {
return (
<Icon
size = { 20 }
src = { IconAddPeople } />
);
}
/**
* Implements {@code PureComponent#render}.
*
@ -80,17 +95,13 @@ class LonelyMeetingExperience extends PureComponent<Props> {
{ t('lonelyMeetingExperience.youAreAlone') }
</Text>
{ !_isInviteFunctionsDiabled && !_isInBreakoutRoom && (
<TouchableOpacity
<Button
accessibilityLabel = 'lonelyMeetingExperience.button'
icon = { this._renderAddPeopleIcon }
label = 'lonelyMeetingExperience.button'
onPress = { this._onPress }
style = { styles.lonelyButton }>
<Icon
size = { 24 }
src = { IconAddPeople }
style = { styles.lonelyButtonComponents } />
<Text style = { styles.lonelyButtonComponents }>
{ t('lonelyMeetingExperience.button') }
</Text>
</TouchableOpacity>
style = { styles.lonelyButton }
type = { BUTTON_TYPES.PRIMARY } />
) }
</View>
);

View File

@ -1,6 +1,5 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import { View } from 'react-native';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import { useDispatch, useSelector } from 'react-redux';
@ -12,20 +11,18 @@ import { setIsCarmode } from '../../../../video-layout/actions';
import ConferenceTimer from '../../ConferenceTimer';
import { isConnecting } from '../../functions';
import EndMeetingButton from './EndMeetingButton';
import CarModeFooter from './CarModeFooter';
import MicrophoneButton from './MicrophoneButton';
import SoundDeviceButton from './SoundDeviceButton';
import TitleBar from './TitleBar';
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 { t } = useTranslation();
const connecting = useSelector(isConnecting);
const isSharing = useSelector(isLocalVideoTrackDesktop);
@ -42,7 +39,9 @@ const CarmodeTab = (): JSX.Element => {
}, []);
return (
<JitsiScreen style = { styles.conference }>
<JitsiScreen
footerComponent = { CarModeFooter }
style = { styles.conference }>
{/*
* The activity/loading indicator goes above everything, except
* the toolbox/toolbars and the dialogs.
@ -66,17 +65,8 @@ const CarmodeTab = (): JSX.Element => {
style = { styles.microphoneContainer }>
<MicrophoneButton />
</View>
<View
pointerEvents = 'box-none'
style = { styles.bottomContainer }>
<Text style = { styles.videoStoppedLabel }>
{t('carmode.labels.videoStopped')}
</Text>
<SoundDeviceButton />
<EndMeetingButton />
</View>
</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 { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux';
import { createToolbarEvent, sendAnalytics } from '../../../../analytics';
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 styles from './styles';
@ -15,7 +15,6 @@ import styles from './styles';
* @returns {JSX.Element} - The end meeting button.
*/
const EndMeetingButton = () : JSX.Element => {
const { t } = useTranslation();
const dispatch = useDispatch();
const onSelect = useCallback(() => {
@ -26,13 +25,12 @@ const EndMeetingButton = () : JSX.Element => {
return (
<Button
accessibilityLabel = { t('carmode.actions.leaveMeeting') }
children = { t('carmode.actions.leaveMeeting') }
accessibilityLabel = 'carmode.actions.leaveMeeting'
icon = { EndMeetingIcon }
labelStyle = { styles.endMeetingButtonLabel }
mode = 'contained'
label = 'carmode.actions.leaveMeeting'
onPress = { onSelect }
style = { styles.endMeetingButton } />
style = { styles.endMeetingButton }
type = { BUTTON_TYPES.DESTRUCTIVE } />
);
};

View File

@ -1,9 +1,9 @@
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux';
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 AudioIcon from './AudioIcon';
@ -15,7 +15,6 @@ import styles from './styles';
* @returns {JSX.Element} - The sound device button.
*/
const SelectSoundDevice = () : JSX.Element => {
const { t } = useTranslation();
const dispatch = useDispatch();
const onSelect = useCallback(() =>
@ -24,13 +23,12 @@ const SelectSoundDevice = () : JSX.Element => {
return (
<Button
accessibilityLabel = { t('carmode.actions.selectSoundDevice') }
children = { t('carmode.actions.selectSoundDevice') }
accessibilityLabel = 'carmode.actions.selectSoundDevice'
icon = { AudioIcon }
labelStyle = { styles.soundDeviceButtonLabel }
mode = 'contained'
label = 'carmode.actions.selectSoundDevice'
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;
/**
* 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.
*/
@ -47,7 +24,7 @@ export default {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
bottom: 0,
bottom: BaseTheme.spacing[8],
left: 0,
right: 0,
position: 'absolute'
@ -106,10 +83,8 @@ export default {
},
roomTimer: {
color: BaseTheme.palette.text01,
...BaseTheme.typography.bodyShortBold,
paddingHorizontal: 8,
paddingVertical: 6,
color: BaseTheme.palette.text01,
textAlign: 'center'
},
@ -129,25 +104,13 @@ export default {
color: BaseTheme.palette.text02
},
soundDeviceButtonLabel: {
...baseLabel,
color: BaseTheme.palette.text06
},
soundDeviceButton: {
...baseButton,
backgroundColor: BaseTheme.palette.section01
marginBottom: BaseTheme.spacing[3],
width: 240
},
endMeetingButton: {
...baseButton,
backgroundColor: BaseTheme.palette.actionDanger,
marginBottom: 60
},
endMeetingButtonLabel: {
...baseLabel,
color: BaseTheme.palette.text01
width: 240
},
headerLabels: {
@ -196,13 +159,14 @@ export default {
},
titleBar: {
alignSelf: 'center'
alignSelf: 'center',
marginTop: BaseTheme.spacing[1]
},
videoStoppedLabel: {
...BaseTheme.typography.bodyShortRegularLarge,
color: BaseTheme.palette.text01,
marginBottom: 32,
...BaseTheme.typography.bodyShortRegularLarge
marginBottom: BaseTheme.spacing[3]
},
connectionIndicatorIcon: {

View File

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

View File

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

View File

@ -1,22 +1,29 @@
// @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 {
indicatorWrapper: {
alignItems: 'center',
backgroundColor: ColorPalette.white,
backgroundColor: BaseTheme.palette.ui12,
height: '100%',
justifyContent: 'center'
},
sharedDocContainer: {
flex: 1
backgroundColor: BaseTheme.palette.ui12,
flex: 1,
paddingRight: BaseTheme.spacing[3]
},
sharedDoc: {
marginBottom: BaseTheme.spacing[3]
},
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 React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Image, Text, View } from 'react-native';
import { useDispatch } from 'react-redux';
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 { formatGifUrlMessage, getGifUrl } from '../../functions';
import GifsMenuFooter from './GifsMenuFooter';
import styles from './styles';
const GifsMenu = () => {
@ -34,19 +34,9 @@ const GifsMenu = () => {
goBack();
}, []);
const footerComponent = () => (
<View style = { styles.credit }>
<Text
style = { styles.creditText }>Powered by</Text>
<Image source = { require('../../../../../images/GIPHY_logo.png') } />
</View>
);
return (
<JitsiScreen
/* eslint-disable-next-line react/jsx-no-bind */
footerComponent = { footerComponent }
footerComponent = { GifsMenuFooter }
style = { styles.container }>
<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]
},
input: { textAlign: 'left' }
input: {
textAlign: 'left'
}
},
grid: {
@ -34,7 +36,7 @@ export default {
},
creditText: {
color: 'white',
color: BaseTheme.palette.text01,
fontWeight: 'bold'
}
};

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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 { connect } from '../../../base/redux';
@ -24,7 +24,7 @@ import ConferenceNavigationContainer
import WelcomePageNavigationContainer
from './welcome/components/WelcomePageNavigationContainer';
const RootStack = createNativeStackNavigator();
const RootStack = createStackNavigator();
type Props = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,14 +19,10 @@ const baseLabel = {
*/
export default {
addButtonLabel: {
...baseLabel,
color: BaseTheme.palette.text01
},
addButton: {
...baseButton,
backgroundColor: BaseTheme.palette.ui03
marginTop: BaseTheme.spacing[3],
marginLeft: BaseTheme.spacing[3],
marginRight: BaseTheme.spacing[3]
},
collapsibleRoom: {
@ -70,18 +66,18 @@ export default {
marginLeft: BaseTheme.spacing[2]
},
transparentButton: {
backgroundColor: 'transparent',
marginTop: BaseTheme.spacing[3]
},
leaveButtonLabel: {
...baseLabel,
color: BaseTheme.palette.textError
},
autoAssignLabel: {
...baseLabel,
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
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux';
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 { showContextMenuReject } from '../../actions.native';
import { MEDIA_STATE } from '../../constants';
@ -25,7 +25,6 @@ export const LobbyParticipantItem = ({ participant: p }: Props) => {
const dispatch = useDispatch();
const admit = useCallback(() => dispatch(approveKnockingParticipant(p.id), [ dispatch ]));
const openContextMenuReject = useCallback(() => dispatch(showContextMenuReject(p), [ dispatch ]));
const { t } = useTranslation();
return (
<ParticipantItem
@ -39,12 +38,11 @@ export const LobbyParticipantItem = ({ participant: p }: Props) => {
raisedHand = { hasRaisedHand(p) }
videoMediaState = { MEDIA_STATE.NONE }>
<Button
children = { t('lobby.admit') }
contentStyle = { styles.participantActionsButtonContent }
labelStyle = { styles.participantActionsButtonText }
mode = 'contained'
accessibilityLabel = 'lobby.admit'
label = 'lobby.admit'
onPress = { admit }
style = { styles.participantActionsButtonAdmit } />
style = { styles.participantActionsButtonAdmit }
type = { BUTTON_TYPES.PRIMARY } />
</ParticipantItem>
);
};

View File

@ -3,9 +3,10 @@
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { ScrollView, Text, View } from 'react-native';
import { Button, withTheme } from 'react-native-paper';
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 { getKnockingParticipants, getLobbyEnabled } from '../../../lobby/functions';
@ -13,15 +14,8 @@ import CollapsibleList from './CollapsibleList';
import { LobbyParticipantItem } from './LobbyParticipantItem';
import styles from './styles';
type Props = {
/**
* Theme used for styles.
*/
theme: Object
};
const LobbyParticipantList = ({ theme }: Props) => {
const LobbyParticipantList = () => {
const lobbyEnabled = useSelector(getLobbyEnabled);
const participants = useSelector(getKnockingParticipants);
@ -30,11 +24,11 @@ const LobbyParticipantList = ({ theme }: Props) => {
dispatch(admitMultiple(participants)),
[ dispatch, participants ]);
const { t } = useTranslation();
const { palette } = theme;
if (!lobbyEnabled || !participants.length) {
return null;
}
const title = (
<View style = { styles.lobbyListDetails } >
<Text style = { styles.lobbyListDescription }>
@ -44,12 +38,11 @@ const LobbyParticipantList = ({ theme }: Props) => {
{
participants.length > 1 && (
<Button
color = { palette.action02 }
labelStyle = { styles.admitAllParticipantsActionButtonLabel }
mode = 'text'
onPress = { admitAll }>
{t('lobby.admitAll')}
</Button>
accessibilityLabel = 'lobby.admitAll'
label = 'lobby.admitAll'
labelStyle = { styles.admitAllButtonLabel }
onPress = { admitAll }
type = { BUTTON_TYPES.TERTIARY } />
)
}
</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 { FlatList } from 'react-native';
import { Button, withTheme } from 'react-native-paper';
import { translate } from '../../../base/i18n';
import { Icon, IconInviteMore } from '../../../base/icons';
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 BaseTheme from '../../../base/ui/components/BaseTheme.native';
import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native';
import { participantMatchesSearch, shouldRenderInviteButton } from '../../functions';
@ -83,12 +86,7 @@ type Props = {
/**
* Translation function.
*/
t: Function,
/**
* Theme used for styles.
*/
theme: Object
t: Function
}
/**
@ -230,17 +228,17 @@ class MeetingParticipantList extends PureComponent<Props> {
{
_showInviteButton
&& <Button
children = { t('participantsPane.actions.invite') }
accessibilityLabel = 'participantsPane.actions.invite'
icon = { this._renderInviteMoreIcon }
labelStyle = { styles.inviteLabel }
mode = 'contained'
label = 'participantsPane.actions.invite'
onPress = { this._onInvite }
style = { styles.inviteButton } />
style = { styles.inviteButton }
type = { BUTTON_TYPES.PRIMARY } />
}
<ClearableInput
onChange = { this._onSearchStringChange }
placeholder = { t('participantsPane.search') }
selectionColor = { this.props.theme.palette.text01 } />
selectionColor = { BaseTheme.palette.text01 } />
<FlatList
bounces = { false }
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
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { View } from 'react-native';
import { Button } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux';
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import { openDialog, openSheet } from '../../../base/dialog';
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { isLocalParticipantModerator } from '../../../base/participants';
import { equals } from '../../../base/redux';
@ -18,9 +14,6 @@ import {
isInBreakoutRoom
} from '../../../breakout-rooms/functions';
import { getKnockingParticipants } from '../../../lobby/functions';
import MuteEveryoneDialog
from '../../../video-menu/components/native/MuteEveryoneDialog';
import { isMoreActionsVisible, isMuteAllVisible } from '../../functions';
import {
AddBreakoutRoomButton,
AutoAssignButton,
@ -28,26 +21,20 @@ import {
} from '../breakout-rooms/components/native';
import { CollapsibleRoom } from '../breakout-rooms/components/native/CollapsibleRoom';
import { ContextMenuMore } from './ContextMenuMore';
import HorizontalDotsIcon from './HorizontalDotsIcon';
import LobbyParticipantList from './LobbyParticipantList';
import MeetingParticipantList from './MeetingParticipantList';
import ParticipantsPaneFooter from './ParticipantsPaneFooter';
import styles from './styles';
/**
* Participant pane.
* Participants pane.
*
* @returns {React$Element<any>}
*/
const ParticipantsPane = () => {
const dispatch = useDispatch();
const [ searchString, setSearchString ] = useState('');
const openMoreMenu = useCallback(() => dispatch(openSheet(ContextMenuMore)), [ dispatch ]);
const isLocalModerator = useSelector(isLocalParticipantModerator);
const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)),
[ dispatch ]);
const { t } = useTranslation();
const { conference } = useSelector(state => state['features/base/conference']);
const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
const currentRoomId = useSelector(getCurrentRoomId);
@ -57,12 +44,12 @@ const ParticipantsPane = () => {
const inBreakoutRoom = useSelector(isInBreakoutRoom);
const showAddBreakoutRoom = useSelector(isAddBreakoutRoomButtonVisible);
const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
const showMoreActions = useSelector(isMoreActionsVisible);
const showMuteAll = useSelector(isMuteAllVisible);
const lobbyParticipants = useSelector(getKnockingParticipants);
return (
<JitsiScreen style = { styles.participantsPaneContainer }>
<JitsiScreen
footerComponent = { isLocalModerator && ParticipantsPaneFooter }
style = { styles.participantsPaneContainer }>
<LobbyParticipantList />
<MeetingParticipantList
breakoutRooms = { rooms }
@ -86,31 +73,6 @@ const ParticipantsPane = () => {
{
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>
);
};

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.
*/
export const button = {
backgroundColor: BaseTheme.palette.action02,
borderRadius: BaseTheme.shape.borderRadius,
display: 'flex',
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'
};
@ -88,34 +57,15 @@ const contextMenuItem = {
export default {
participantActionsButtonAdmit: {
backgroundColor: BaseTheme.palette.action01,
borderRadius: BaseTheme.shape.borderRadius,
flexDirection: 'row',
height: BaseTheme.spacing[6],
marginRight: BaseTheme.spacing[3],
position: 'absolute',
right: 0,
zIndex: 1
right: 0
},
participantActionsButtonContent: {
alignItems: 'center',
display: 'flex',
height: BaseTheme.spacing[5],
top: BaseTheme.spacing[1]
},
participantActionsButtonText: {
color: BaseTheme.palette.text01,
textTransform: 'capitalize'
},
admitAllParticipantsActionButtonLabel: {
...BaseTheme.typography.heading6,
admitAllButtonLabel: {
color: BaseTheme.palette.link01,
textTransform: 'capitalize',
marginRight: BaseTheme.spacing[5],
marginTop: BaseTheme.spacing[3]
marginRight: BaseTheme.spacing[6],
marginTop: 14
},
participantContainer: {
@ -263,49 +213,13 @@ export default {
},
inviteButton: {
backgroundColor: BaseTheme.palette.action01,
borderRadius: BaseTheme.shape.borderRadius,
height: BaseTheme.spacing[7],
marginLeft: BaseTheme.spacing[3],
marginRight: BaseTheme.spacing[3],
marginVertical: BaseTheme.spacing[3]
},
inviteLabel: {
fontSize: 15,
lineHeight: 30,
textTransform: 'capitalize'
},
moreButton: {
...smallButton,
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
marginLeft: BaseTheme.spacing[2]
},
contextMenuItem: {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,47 +1,13 @@
import BaseTheme from '../../base/ui/components/BaseTheme.native';
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 {
button: {
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,
prejoinButton: {
marginTop: BaseTheme.spacing[4]
},
primaryButtonText: {
...btnText
},
secondaryButton: {
...btn,
backgroundColor: BaseTheme.palette.action02
},
secondaryButtonText: {
...btnText
},
buttonStylesBorderless: {
iconStyle: {
color: BaseTheme.palette.icon01,

View File

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

View File

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

View File

@ -49,21 +49,25 @@ function ReactionMenu({
return (
<View style = { overflowMenu ? _styles.overflowReactionMenu : _styles.reactionMenu }>
<View style = { _styles.reactionRow }>
{Object.keys(REACTIONS).map(key => (
<ReactionButton
key = { key }
reaction = { key }
styles = { _styles.reactionButton } />
))}
{gifEnabled && (
<ReactionButton
onClick = { openGifMenu }
styles = { _styles.reactionButton }>
<Image
height = { 22 }
source = { require('../../../../../images/GIPHY_icon.png') } />
</ReactionButton>
)}
{
Object.keys(REACTIONS).map(key => (
<ReactionButton
key = { key }
reaction = { key }
styles = { _styles.reactionButton } />
))
}
{
gifEnabled && (
<ReactionButton
onClick = { openGifMenu }
styles = { _styles.reactionButton }>
<Image
height = { 22 }
source = { require('../../../../../images/GIPHY_icon.png') } />
</ReactionButton>
)
}
</View>
<RaiseHandButton onCancel = { onCancel } />
</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 { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import { Button } from 'react-native-paper';
import { useDispatch, batch } from 'react-redux';
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 styles from '../styles.native';
@ -28,20 +29,16 @@ const HighlightDialog = () => {
</Text>
<View style = { styles.highlightDialogButtonsContainer } >
<Button
accessibilityLabel = { t('dialog.Cancel') }
children = { t('dialog.Cancel') }
labelStyle = { styles.highlightDialogCancelLabel }
mode = 'contained'
accessibilityLabel = 'dialog.Cancel'
label = 'dialog.Cancel'
onPress = { closeDialog }
style = { styles.highlightDialogCancelButton } />
type = { BUTTON_TYPES.SECONDARY } />
<View style = { styles.highlightDialogButtonsSpace } />
<Button
accessibilityLabel = { t('recording.highlight') }
children = { t('recording.highlight') }
labelStyle = { styles.highlightDialogHighlighLabel }
mode = 'contained'
accessibilityLabel = 'recording.highlight'
label = 'recording.highlight'
onPress = { highlightMoment }
style = { styles.highlightDialogHighlightButton } />
type = { BUTTON_TYPES.PRIMARY } />
</View>
</View>
</BottomSheet>

View File

@ -39,18 +39,6 @@ const title = {
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 {
/**
* Container for the StartRecordingDialog screen.
@ -104,22 +92,6 @@ export default {
display: 'flex',
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: {
height: 16,
width: '100%'

View File

@ -161,8 +161,7 @@ ColorSchemeRegistry.register('Toolbox', {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
marginBottom: 16
width: '100%'
},
reactionButton: {
@ -172,28 +171,6 @@ ColorSchemeRegistry.register('Toolbox', {
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: {
color: BaseTheme.palette.icon01,
position: 'absolute',

View File

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