[RN] Add color scheme support - Components

pull/3883/head jitsi-meet_3543
Bettenbuk Zoltan 7 years ago committed by Zoltan Bettenbuk
parent 2941f5dde4
commit e094b6516a
  1. 14
      react/features/authentication/components/LoginDialog.native.js
  2. 31
      react/features/base/color-scheme/defaultScheme.js
  3. 12
      react/features/base/dialog/components/native/BaseDialog.js
  4. 11
      react/features/base/dialog/components/native/BaseSubmitDialog.js
  5. 30
      react/features/base/dialog/components/native/BottomSheet.js
  6. 20
      react/features/base/dialog/components/native/ConfirmDialog.js
  7. 4
      react/features/base/dialog/components/native/CustomDialog.js
  8. 5
      react/features/base/dialog/components/native/CustomSubmitDialog.js
  9. 18
      react/features/base/dialog/components/native/InputDialog.js
  10. 199
      react/features/base/dialog/components/native/styles.js
  11. 15
      react/features/base/dialog/functions.js
  12. 20
      react/features/base/participants/components/ParticipantView.native.js
  13. 30
      react/features/base/react/components/native/TintedView.js
  14. 5
      react/features/base/react/components/native/styles.js
  15. 1
      react/features/base/styles/components/styles/ColorPalette.js
  16. 14
      react/features/filmstrip/components/native/Thumbnail.js
  17. 49
      react/features/filmstrip/components/styles.js
  18. 30
      react/features/large-video/components/LargeVideo.native.js
  19. 9
      react/features/large-video/components/styles.js
  20. 7
      react/features/recording/components/LiveStream/AbstractStreamKeyForm.js
  21. 16
      react/features/recording/components/LiveStream/native/GoogleSigninForm.js
  22. 38
      react/features/recording/components/LiveStream/native/StreamKeyForm.js
  23. 31
      react/features/recording/components/LiveStream/native/StreamKeyPicker.js
  24. 6
      react/features/recording/components/LiveStream/native/styles.js
  25. 2
      react/features/recording/components/LiveStream/web/StreamKeyForm.js
  26. 23
      react/features/recording/components/Recording/StartRecordingDialogContent.js
  27. 5
      react/features/recording/components/Recording/styles.native.js
  28. 15
      react/features/remote-video-menu/components/native/RemoteVideoMenu.js
  29. 30
      react/features/toolbox/components/native/OverflowMenu.js
  30. 37
      react/features/toolbox/components/native/Toolbox.js
  31. 132
      react/features/toolbox/components/native/styles.js

@ -9,10 +9,12 @@ import {
CustomSubmitDialog, CustomSubmitDialog,
FIELD_UNDERLINE, FIELD_UNDERLINE,
PLACEHOLDER_COLOR, PLACEHOLDER_COLOR,
_abstractMapStateToProps,
inputDialog as inputDialogStyle inputDialog as inputDialogStyle
} from '../../base/dialog'; } from '../../base/dialog';
import { translate } from '../../base/i18n'; import { translate } from '../../base/i18n';
import { JitsiConnectionErrors } from '../../base/lib-jitsi-meet'; import { JitsiConnectionErrors } from '../../base/lib-jitsi-meet';
import { StyleType } from '../../base/styles';
import { authenticateAndUpgradeRole, cancelLogin } from '../actions'; import { authenticateAndUpgradeRole, cancelLogin } from '../actions';
import styles from './styles'; import styles from './styles';
@ -38,6 +40,11 @@ type Props = {
*/ */
_connecting: boolean, _connecting: boolean,
/**
* The color-schemed stylesheet of the base/dialog feature.
*/
_dialogStyles: StyleType,
/** /**
* The error which occurred during login/authentication. * The error which occurred during login/authentication.
*/ */
@ -134,6 +141,7 @@ class LoginDialog extends Component<Props, State> {
render() { render() {
const { const {
_connecting: connecting, _connecting: connecting,
_dialogStyles,
_error: error, _error: error,
_progress: progress, _progress: progress,
t t
@ -186,7 +194,7 @@ class LoginDialog extends Component<Props, State> {
onChangeText = { this._onUsernameChange } onChangeText = { this._onUsernameChange }
placeholder = { 'user@domain.com' } placeholder = { 'user@domain.com' }
placeholderTextColor = { PLACEHOLDER_COLOR } placeholderTextColor = { PLACEHOLDER_COLOR }
style = { inputDialogStyle.field } style = { _dialogStyles.field }
underlineColorAndroid = { FIELD_UNDERLINE } underlineColorAndroid = { FIELD_UNDERLINE }
value = { this.state.username } /> value = { this.state.username } />
<TextInput <TextInput
@ -195,7 +203,7 @@ class LoginDialog extends Component<Props, State> {
placeholderTextColor = { PLACEHOLDER_COLOR } placeholderTextColor = { PLACEHOLDER_COLOR }
secureTextEntry = { true } secureTextEntry = { true }
style = { [ style = { [
inputDialogStyle.field, _dialogStyles.field,
inputDialogStyle.bottomField inputDialogStyle.bottomField
] } ] }
underlineColorAndroid = { FIELD_UNDERLINE } underlineColorAndroid = { FIELD_UNDERLINE }
@ -289,6 +297,7 @@ class LoginDialog extends Component<Props, State> {
* _conference: JitsiConference, * _conference: JitsiConference,
* _configHosts: Object, * _configHosts: Object,
* _connecting: boolean, * _connecting: boolean,
* _dialogStyles: StyleType,
* _error: Object, * _error: Object,
* _progress: number * _progress: number
* }} * }}
@ -307,6 +316,7 @@ function _mapStateToProps(state) {
} = state['features/base/connection']; } = state['features/base/connection'];
return { return {
..._abstractMapStateToProps(state),
_conference: authRequired, _conference: authRequired,
_configHosts: configHosts, _configHosts: configHosts,
_connecting: Boolean(connecting) || Boolean(thenableWithCancel), _connecting: Boolean(connecting) || Boolean(thenableWithCancel),

@ -1,6 +1,35 @@
// @flow // @flow
import { ColorPalette, getRGBAFormat } from '../styles';
/** /**
* The default color scheme of the application. * The default color scheme of the application.
*/ */
export default {}; export default {
'BottomSheet': {
background: ColorPalette.blackBlue,
icon: ColorPalette.white,
label: ColorPalette.white
},
'Dialog': {
background: ColorPalette.blackBlue,
border: getRGBAFormat(ColorPalette.white, 0.2),
icon: ColorPalette.white,
text: ColorPalette.white
},
'LargeVideo': {
background: ColorPalette.black
},
'Thumbnail': {
activeParticipantHighlight: ColorPalette.blue,
activeParticipantTint: ColorPalette.black,
background: ColorPalette.black
},
'Toolbox': {
button: getRGBAFormat(ColorPalette.white, 0.7),
buttonToggled: getRGBAFormat(ColorPalette.buttonUnderlay, 0.7),
buttonToggledBorder:
getRGBAFormat(ColorPalette.buttonUnderlay, 0.7),
hangup: ColorPalette.red
}
};

@ -8,6 +8,7 @@ import {
} from 'react-native'; } from 'react-native';
import { Icon } from '../../../font-icons'; import { Icon } from '../../../font-icons';
import { StyleType } from '../../../styles';
import AbstractDialog, { import AbstractDialog, {
type Props as AbstractProps, type Props as AbstractProps,
@ -18,6 +19,11 @@ import { brandedDialog as styles } from './styles';
export type Props = { export type Props = {
...AbstractProps, ...AbstractProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
t: Function t: Function
} }
@ -43,7 +49,7 @@ class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { style } = this.props; const { _dialogStyles, style } = this.props;
return ( return (
<View <View
@ -55,7 +61,7 @@ class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
<View <View
pointerEvents = 'box-none' pointerEvents = 'box-none'
style = { [ style = { [
styles.dialog, _dialogStyles.dialog,
this.props.style this.props.style
] }> ] }>
<TouchableOpacity <TouchableOpacity
@ -63,7 +69,7 @@ class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
style = { styles.closeWrapper }> style = { styles.closeWrapper }>
<Icon <Icon
name = 'close' name = 'close'
style = { styles.closeStyle } /> style = { _dialogStyles.closeStyle } />
</TouchableOpacity> </TouchableOpacity>
{ this._renderContent() } { this._renderContent() }
</View> </View>

@ -3,6 +3,8 @@
import React from 'react'; import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native'; import { View, Text, TouchableOpacity } from 'react-native';
import { StyleType } from '../../../styles';
import BaseDialog, { type Props as BaseProps } from './BaseDialog'; import BaseDialog, { type Props as BaseProps } from './BaseDialog';
import { import {
brandedDialog brandedDialog
@ -11,6 +13,11 @@ import {
type Props = { type Props = {
...BaseProps, ...BaseProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
t: Function t: Function
} }
@ -46,7 +53,7 @@ class BaseSubmitDialog<P: Props, S: *> extends BaseDialog<P, S> {
* @inheritdoc * @inheritdoc
*/ */
_renderContent() { _renderContent() {
const { t } = this.props; const { _dialogStyles, t } = this.props;
const additionalButtons = this._renderAdditionalButtons(); const additionalButtons = this._renderAdditionalButtons();
return ( return (
@ -65,7 +72,7 @@ class BaseSubmitDialog<P: Props, S: *> extends BaseDialog<P, S> {
? null : brandedDialog.buttonFarLeft, ? null : brandedDialog.buttonFarLeft,
brandedDialog.buttonFarRight brandedDialog.buttonFarRight
] }> ] }>
<Text style = { brandedDialog.text }> <Text style = { _dialogStyles.text }>
{ t(this._getSubmitButtonKey()) } { t(this._getSubmitButtonKey()) }
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>

@ -2,8 +2,11 @@
import React, { Component, type Node } from 'react'; import React, { Component, type Node } from 'react';
import { TouchableWithoutFeedback, View } from 'react-native'; import { TouchableWithoutFeedback, View } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { Modal } from '../../../react'; import { Modal } from '../../../react';
import { StyleType } from '../../../styles';
import { bottomSheetStyles as styles } from './styles'; import { bottomSheetStyles as styles } from './styles';
@ -12,6 +15,11 @@ import { bottomSheetStyles as styles } from './styles';
*/ */
type Props = { type Props = {
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/** /**
* The children to be displayed within this component. * The children to be displayed within this component.
*/ */
@ -28,7 +36,7 @@ type Props = {
* A component emulating Android's BottomSheet. For all intents and purposes, * A component emulating Android's BottomSheet. For all intents and purposes,
* this component has been designed to work and behave as a {@code Dialog}. * this component has been designed to work and behave as a {@code Dialog}.
*/ */
export default class BottomSheet extends Component<Props> { class BottomSheet extends Component<Props> {
/** /**
* Initializes a new {@code BottomSheet} instance. * Initializes a new {@code BottomSheet} instance.
* *
@ -47,6 +55,8 @@ export default class BottomSheet extends Component<Props> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { _styles } = this.props;
return [ return [
<View <View
key = 'overlay' key = 'overlay'
@ -60,7 +70,7 @@ export default class BottomSheet extends Component<Props> {
onPress = { this._onCancel } > onPress = { this._onCancel } >
<View style = { styles.backdrop } /> <View style = { styles.backdrop } />
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
<View style = { styles.sheet }> <View style = { _styles.sheet }>
{ this.props.children } { this.props.children }
</View> </View>
</View> </View>
@ -82,3 +92,19 @@ export default class BottomSheet extends Component<Props> {
onCancel && onCancel(); onCancel && onCancel();
} }
} }
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @returns {{
* _styles: StyleType
* }}
*/
function _mapStateToProps(state) {
return {
_styles: ColorSchemeRegistry.get(state, 'BottomSheet')
};
}
export default connect(_mapStateToProps)(BottomSheet);

@ -5,6 +5,9 @@ import { Text, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { translate } from '../../../i18n'; import { translate } from '../../../i18n';
import { StyleType } from '../../../styles';
import { _abstractMapStateToProps } from '../../functions';
import { type Props as BaseProps } from './BaseDialog'; import { type Props as BaseProps } from './BaseDialog';
import BaseSubmitDialog from './BaseSubmitDialog'; import BaseSubmitDialog from './BaseSubmitDialog';
@ -13,6 +16,11 @@ import { brandedDialog } from './styles';
type Props = { type Props = {
...BaseProps, ...BaseProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
/** /**
* Untranslated i18n key of the content to be displayed. * Untranslated i18n key of the content to be displayed.
* *
@ -49,7 +57,7 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
* @inheritdoc * @inheritdoc
*/ */
_renderAdditionalButtons() { _renderAdditionalButtons() {
const { t } = this.props; const { _dialogStyles, t } = this.props;
return ( return (
<TouchableOpacity <TouchableOpacity
@ -57,9 +65,9 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
style = { [ style = { [
brandedDialog.button, brandedDialog.button,
brandedDialog.buttonFarLeft, brandedDialog.buttonFarLeft,
brandedDialog.buttonSeparator _dialogStyles.buttonSeparator
] }> ] }>
<Text style = { brandedDialog.text }> <Text style = { _dialogStyles.text }>
{ t('dialog.confirmNo') } { t('dialog.confirmNo') }
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
@ -72,14 +80,14 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
* @inheritdoc * @inheritdoc
*/ */
_renderSubmittable() { _renderSubmittable() {
const { contentKey, t } = this.props; const { _dialogStyles, contentKey, t } = this.props;
const content const content
= typeof contentKey === 'string' = typeof contentKey === 'string'
? t(contentKey) ? t(contentKey)
: this._renderHTML(t(contentKey.key, contentKey.params)); : this._renderHTML(t(contentKey.key, contentKey.params));
return ( return (
<Text style = { brandedDialog.text }> <Text style = { _dialogStyles.text }>
{ content } { content }
</Text> </Text>
); );
@ -88,4 +96,4 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
_renderHTML: string => Object | string _renderHTML: string => Object | string
} }
export default translate(connect()(ConfirmDialog)); export default translate(connect(_abstractMapStateToProps)(ConfirmDialog));

@ -2,6 +2,8 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../functions';
import BaseDialog, { type Props } from './BaseDialog'; import BaseDialog, { type Props } from './BaseDialog';
/** /**
@ -19,4 +21,4 @@ class CustomDialog extends BaseDialog<Props, *> {
} }
} }
export default connect()(CustomDialog); export default connect(_abstractMapStateToProps)(CustomDialog);

@ -4,6 +4,8 @@ import { connect } from 'react-redux';
import { translate } from '../../../i18n'; import { translate } from '../../../i18n';
import { _abstractMapStateToProps } from '../../functions';
import { type Props as BaseProps } from './BaseDialog'; import { type Props as BaseProps } from './BaseDialog';
import BaseSubmitDialog from './BaseSubmitDialog'; import BaseSubmitDialog from './BaseSubmitDialog';
@ -27,4 +29,5 @@ class CustomSubmitDialog extends BaseSubmitDialog<Props, *> {
} }
} }
export default translate(connect()(CustomSubmitDialog)); export default translate(
connect(_abstractMapStateToProps)(CustomSubmitDialog));

@ -5,6 +5,9 @@ import { View, Text, TextInput, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { translate } from '../../../i18n'; import { translate } from '../../../i18n';
import { StyleType } from '../../../styles';
import { _abstractMapStateToProps } from '../../functions';
import { type State as AbstractState } from '../AbstractDialog'; import { type State as AbstractState } from '../AbstractDialog';
@ -18,6 +21,11 @@ import {
type Props = { type Props = {
...BaseProps, ...BaseProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
/** /**
* The untranslated i18n key for the field label on the dialog. * The untranslated i18n key for the field label on the dialog.
*/ */
@ -63,7 +71,7 @@ class InputDialog extends BaseDialog<Props, State> {
* @inheritdoc * @inheritdoc
*/ */
_renderContent() { _renderContent() {
const { okDisabled, t } = this.props; const { _dialogStyles, okDisabled, t } = this.props;
return ( return (
<View> <View>
@ -72,12 +80,12 @@ class InputDialog extends BaseDialog<Props, State> {
brandedDialog.mainWrapper, brandedDialog.mainWrapper,
styles.fieldWrapper styles.fieldWrapper
] }> ] }>
<Text style = { styles.fieldLabel }> <Text style = { _dialogStyles.fieldLabel }>
{ t(this.props.contentKey) } { t(this.props.contentKey) }
</Text> </Text>
<TextInput <TextInput
onChangeText = { this._onChangeText } onChangeText = { this._onChangeText }
style = { styles.field } style = { _dialogStyles.field }
underlineColorAndroid = { FIELD_UNDERLINE } underlineColorAndroid = { FIELD_UNDERLINE }
value = { this.state.fieldValue } value = { this.state.fieldValue }
{ ...this.props.textInputProps } /> { ...this.props.textInputProps } />
@ -91,7 +99,7 @@ class InputDialog extends BaseDialog<Props, State> {
brandedDialog.buttonFarLeft, brandedDialog.buttonFarLeft,
brandedDialog.buttonFarRight brandedDialog.buttonFarRight
] }> ] }>
<Text style = { brandedDialog.text }> <Text style = { _dialogStyles.text }>
{ t('dialog.Ok') } { t('dialog.Ok') }
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
@ -130,4 +138,4 @@ class InputDialog extends BaseDialog<Props, State> {
} }
} }
export default translate(connect()(InputDialog)); export default translate(connect(_abstractMapStateToProps)(InputDialog));

@ -2,12 +2,12 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { ColorSchemeRegistry, schemeColor } from '../../../color-scheme';
import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles'; import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
import { PREFERRED_DIALOG_SIZE } from '../../constants'; import { PREFERRED_DIALOG_SIZE } from '../../constants';
const BORDER_RADIUS = 5; const BORDER_RADIUS = 5;
const DIALOG_BORDER_COLOR = 'rgba(255, 255, 255, 0.2)';
export const FIELD_UNDERLINE = ColorPalette.transparent; export const FIELD_UNDERLINE = ColorPalette.transparent;
@ -22,47 +22,6 @@ export const MD_ITEM_MARGIN_PADDING = 16;
export const PLACEHOLDER_COLOR = ColorPalette.lightGrey; export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
/**
* Default styles for the items of a {@code BottomSheet}-based menu.
*
* These have been implemented as per the Material Design guidelines:
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
*/
const bottomSheetItemStyles = createStyleSheet({
/**
* Container style for a generic item rendered in the menu.
*/
style: {
alignItems: 'center',
flexDirection: 'row',
height: MD_ITEM_HEIGHT
},
/**
* Style for the {@code Icon} element in a generic item of the menu.
*/
iconStyle: {
color: ColorPalette.white,
fontSize: 24
},
/**
* Style for the label in a generic item rendered in the menu.
*/
labelStyle: {
color: ColorPalette.white,
flexShrink: 1,
fontSize: MD_FONT_SIZE,
marginLeft: 32,
opacity: 0.90
}
});
export const bottomSheetItemStylesCombined = {
...bottomSheetItemStyles,
underlayColor: ColorPalette.overflowMenuItemUnderlay
};
/** /**
* The React {@code Component} styles of {@code BottomSheet}. These have * The React {@code Component} styles of {@code BottomSheet}. These have
* been implemented as per the Material Design guidelines: * been implemented as per the Material Design guidelines:
@ -94,16 +53,6 @@ export const bottomSheetStyles = createStyleSheet({
overlay: { overlay: {
...StyleSheet.absoluteFillObject, ...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(127, 127, 127, 0.6)' backgroundColor: 'rgba(127, 127, 127, 0.6)'
},
/**
* Bottom sheet's base style.
*/
sheet: {
backgroundColor: 'rgb(0, 3, 6)',
flex: 1,
paddingHorizontal: MD_ITEM_MARGIN_PADDING,
paddingVertical: 8
} }
}); });
@ -131,38 +80,17 @@ export const brandedDialog = createStyleSheet({
borderBottomRightRadius: BORDER_RADIUS borderBottomRightRadius: BORDER_RADIUS
}, },
buttonSeparator: {
borderRightColor: DIALOG_BORDER_COLOR,
borderRightWidth: 1
},
buttonWrapper: { buttonWrapper: {
alignItems: 'stretch', alignItems: 'stretch',
borderRadius: BORDER_RADIUS, borderRadius: BORDER_RADIUS,
flexDirection: 'row' flexDirection: 'row'
}, },
closeStyle: {
color: ColorPalette.white,
fontSize: MD_FONT_SIZE
},
closeWrapper: { closeWrapper: {
alignSelf: 'flex-end', alignSelf: 'flex-end',
padding: BoxModel.padding padding: BoxModel.padding
}, },
dialog: {
alignItems: 'stretch',
backgroundColor: 'rgb(0, 3, 6)',
borderColor: DIALOG_BORDER_COLOR,
borderRadius: BORDER_RADIUS,
borderWidth: 1,
flex: 1,
flexDirection: 'column',
maxWidth: PREFERRED_DIALOG_SIZE
},
mainWrapper: { mainWrapper: {
alignSelf: 'stretch', alignSelf: 'stretch',
padding: BoxModel.padding * 2, padding: BoxModel.padding * 2,
@ -179,56 +107,135 @@ export const brandedDialog = createStyleSheet({
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'center', justifyContent: 'center',
padding: 30 padding: 30
}
});
/**
* Reusable (colored) style for text in any branded dialogs.
*/
const brandedDialogText = {
color: schemeColor('text'),
fontSize: MD_FONT_SIZE,
textAlign: 'center'
};
export const inputDialog = createStyleSheet({
bottomField: {
marginBottom: 0
}, },
text: { fieldWrapper: {
color: ColorPalette.white, ...brandedDialog.mainWrapper,
fontSize: MD_FONT_SIZE, paddingBottom: BoxModel.padding * 2
textAlign: 'center'
} }
}); });
/** /**
* The React {@code Component} styles of {@code Dialog}. * Default styles for the items of a {@code BottomSheet}-based menu.
*
* These have been implemented as per the Material Design guidelines:
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
*/ */
export const dialog = createStyleSheet({ ColorSchemeRegistry.register('BottomSheet', {
/** /**
* The style of the {@code Text} in a {@code Dialog} button. * Style for the {@code Icon} element in a generic item of the menu.
*/ */
buttonText: { iconStyle: {
color: ColorPalette.blue color: schemeColor('icon'),
fontSize: 24
}, },
/** /**
* The style of the {@code Text} in a {@code Dialog} button which is * Style for the label in a generic item rendered in the menu.
* disabled.
*/ */
disabledButtonText: { labelStyle: {
color: ColorPalette.darkGrey color: schemeColor('label'),
} flexShrink: 1,
fontSize: MD_FONT_SIZE,
marginLeft: 32,
opacity: 0.90
},
/**
* Bottom sheet's base style.
*/
sheet: {
backgroundColor: schemeColor('background'),
flex: 1,
paddingHorizontal: MD_ITEM_MARGIN_PADDING,
paddingVertical: 8
},
/**
* Container style for a generic item rendered in the menu.
*/
style: {
alignItems: 'center',
flexDirection: 'row',
height: MD_ITEM_HEIGHT
},
/**
* Additional style that is not directly used as a style object.
*/
underlayColor: ColorPalette.overflowMenuItemUnderlay
}); });
export const inputDialog = createStyleSheet({ /**
bottomField: { * Color schemed styles for all the component based on the abstract dialog.
marginBottom: 0 */
ColorSchemeRegistry.register('Dialog', {
/**
* Separator line for the buttons in a dialog.
*/
buttonSeparator: {
borderRightColor: schemeColor('border'),
borderRightWidth: 1
}, },
/**
* Style of the close icon on a dialog.
*/
closeStyle: {
color: schemeColor('icon'),
fontSize: MD_FONT_SIZE
},
/**
* Base style of the dialogs.
*/
dialog: {
alignItems: 'stretch',
backgroundColor: schemeColor('background'),
borderColor: schemeColor('border'),
borderRadius: BORDER_RADIUS,
borderWidth: 1,
flex: 1,
flexDirection: 'column',
maxWidth: PREFERRED_DIALOG_SIZE
},
/**
* Field on an input dialog.
*/
field: { field: {
...brandedDialog.text, ...brandedDialogText,
borderBottomWidth: 1, borderBottomWidth: 1,
borderColor: DIALOG_BORDER_COLOR, borderColor: schemeColor('border'),
margin: BoxModel.margin, margin: BoxModel.margin,
textAlign: 'left' textAlign: 'left'
}, },
/**
* Style for the field label on an input dialog.
*/
fieldLabel: { fieldLabel: {
...brandedDialog.text, ...brandedDialogText,
margin: BoxModel.margin, margin: BoxModel.margin,
textAlign: 'left' textAlign: 'left'
}, },
fieldWrapper: { text: {
...brandedDialog.mainWrapper, ...brandedDialogText
paddingBottom: BoxModel.padding * 2
} }
}); });

@ -1,5 +1,6 @@
/* @flow */ /* @flow */
import { ColorSchemeRegistry } from '../color-scheme';
import { toState } from '../redux'; import { toState } from '../redux';
/** /**
@ -15,3 +16,17 @@ import { toState } from '../redux';
export function isDialogOpen(stateful: Function | Object, component: Object) { export function isDialogOpen(stateful: Function | Object, component: Object) {
return toState(stateful)['features/base/dialog'].component === component; return toState(stateful)['features/base/dialog'].component === component;
} }
/**
* Maps part of the Redux state to the props of any Dialog based component.
*
* @param {Object} state - The Redux state.
* @returns {{
* _dialogStyles: StyleType
* }}
*/
export function _abstractMapStateToProps(state: Object): Object {
return {
_dialogStyles: ColorSchemeRegistry.get(state, 'Dialog')
};
}

@ -12,6 +12,7 @@ import {
VideoTrack VideoTrack
} from '../../media'; } from '../../media';
import { Container, TintedView } from '../../react'; import { Container, TintedView } from '../../react';
import { StyleType } from '../../styles';
import { TestHint } from '../../testing/components'; import { TestHint } from '../../testing/components';
import { getTrackByMediaTypeAndParticipant } from '../../tracks'; import { getTrackByMediaTypeAndParticipant } from '../../tracks';
@ -97,6 +98,11 @@ type Props = {
*/ */
tintEnabled: boolean, tintEnabled: boolean,
/**
* The style of the tinting when applied.
*/
tintStyle: StyleType,
/** /**
* The test hint id which can be used to locate the {@code ParticipantView} * The test hint id which can be used to locate the {@code ParticipantView}
* on the jitsi-meet-torture side. If not provided, the * on the jitsi-meet-torture side. If not provided, the
@ -186,11 +192,12 @@ class ParticipantView extends Component<Props> {
*/ */
render() { render() {
const { const {
onPress,
_avatar: avatar, _avatar: avatar,
_connectionStatus: connectionStatus, _connectionStatus: connectionStatus,
_renderVideo: renderVideo, _renderVideo: renderVideo,
_videoTrack: videoTrack _videoTrack: videoTrack,
onPress,
tintStyle
} = this.props; } = this.props;
const waitForVideoStarted = false; const waitForVideoStarted = false;
@ -199,9 +206,10 @@ class ParticipantView extends Component<Props> {
const renderAvatar = Boolean(!renderVideo && avatar); const renderAvatar = Boolean(!renderVideo && avatar);
// If the connection has problems, we will "tint" the video / avatar. // If the connection has problems, we will "tint" the video / avatar.
const connectionProblem
= connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE;
const useTint const useTint
= connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE = connectionProblem || this.props.tintEnabled;
|| this.props.tintEnabled;
const testHintId const testHintId
= this.props.testHintId = this.props.testHintId
@ -238,7 +246,9 @@ class ParticipantView extends Component<Props> {
{ useTint { useTint
// If the connection has problems, tint the video / avatar. // If the connection has problems, tint the video / avatar.
&& <TintedView /> } && <TintedView
style = {
connectionProblem ? undefined : tintStyle } /> }
{ this.props.useConnectivityInfoLabel { this.props.useConnectivityInfoLabel
&& this._renderConnectionInfo(connectionStatus) } && this._renderConnectionInfo(connectionStatus) }

@ -3,7 +3,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native'; import { StyleSheet, View } from 'react-native';
import { ColorPalette } from '../../../styles'; import { TINTED_VIEW_DEFAULT } from './styles';
/** /**
* Base style for the {@code TintedView} component. * Base style for the {@code TintedView} component.
@ -24,16 +24,6 @@ type Props = {
*/ */
children?: React$Node, children?: React$Node,
/**
* Color used as the background of the view. Defaults to
*/
color: string,
/**
* Opacity for the
*/
opacity: number,
/** /**
* Style to override the base style. * Style to override the base style.
*/ */
@ -45,15 +35,6 @@ type Props = {
* the given color and opacity. * the given color and opacity.
*/ */
export default class TintedView extends Component<Props> { export default class TintedView extends Component<Props> {
/**
* Default values for the component's props.
*/
static defaultProps = {
color: ColorPalette.appBackground,
opacity: 0.8,
style: {}
};
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -61,7 +42,7 @@ export default class TintedView extends Component<Props> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { children, color, opacity, style } = this.props; const { children, style } = this.props;
// XXX Don't tint the children, tint the background only. // XXX Don't tint the children, tint the background only.
return ( return (
@ -72,11 +53,8 @@ export default class TintedView extends Component<Props> {
pointerEvents = 'none' pointerEvents = 'none'
style = { [ style = { [
BASE_STYLE, BASE_STYLE,
style, TINTED_VIEW_DEFAULT,
{ style
backgroundColor: color,
opacity
}
] } /> ] } />
<View <View
pointerEvents = 'box-none' pointerEvents = 'box-none'

@ -324,6 +324,11 @@ const SIDEBAR_STYLES = {
} }
}; };
export const TINTED_VIEW_DEFAULT = {
backgroundColor: ColorPalette.appBackground,
opacity: 0.8
};
/** /**
* The styles of the generic React {@code Component}s implemented by the feature * The styles of the generic React {@code Component}s implemented by the feature
* base/react. * base/react.

@ -18,6 +18,7 @@ export const ColorPalette = {
* the sake of consistency. * the sake of consistency.
*/ */
black: BLACK, black: BLACK,
blackBlue: 'rgb(0, 3, 6)',
blue: '#17A0DB', blue: '#17A0DB',
blueHighlight: '#1081b2', blueHighlight: '#1081b2',
buttonUnderlay: '#495258', buttonUnderlay: '#495258',

@ -3,6 +3,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { openDialog } from '../../../base/dialog'; import { openDialog } from '../../../base/dialog';
import { Audio, MEDIA_TYPE } from '../../../base/media'; import { Audio, MEDIA_TYPE } from '../../../base/media';
import { import {
@ -12,6 +13,7 @@ import {
pinParticipant pinParticipant
} from '../../../base/participants'; } from '../../../base/participants';
import { Container } from '../../../base/react'; import { Container } from '../../../base/react';
import { StyleType } from '../../../base/styles';
import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks'; import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
import { RemoteVideoMenu } from '../../../remote-video-menu'; import { RemoteVideoMenu } from '../../../remote-video-menu';
@ -53,6 +55,11 @@ type Props = {
*/ */
_onShowRemoteVideoMenu: ?Function, _onShowRemoteVideoMenu: ?Function,
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/** /**
* The Redux representation of the participant's video track. * The Redux representation of the participant's video track.
*/ */
@ -106,6 +113,7 @@ class Thumbnail extends Component<Props> {
_largeVideo: largeVideo, _largeVideo: largeVideo,
_onClick, _onClick,
_onShowRemoteVideoMenu, _onShowRemoteVideoMenu,
_styles,
_videoTrack: videoTrack, _videoTrack: videoTrack,
disablePin, disablePin,
disableTint, disableTint,
@ -135,7 +143,7 @@ class Thumbnail extends Component<Props> {
style = { [ style = { [
styles.thumbnail, styles.thumbnail,
participant.pinned && !disablePin participant.pinned && !disablePin
? styles.thumbnailPinned : null, ? _styles.thumbnailPinned : null,
this.props.styleOverrides || null this.props.styleOverrides || null
] } ] }
touchFeedback = { false }> touchFeedback = { false }>
@ -148,7 +156,9 @@ class Thumbnail extends Component<Props> {
<ParticipantView <ParticipantView
avatarSize = { AVATAR_SIZE } avatarSize = { AVATAR_SIZE }
participantId = { participantId } participantId = { participantId }
style = { _styles.participantViewStyle }
tintEnabled = { participantInLargeVideo && !disableTint } tintEnabled = { participantInLargeVideo && !disableTint }
tintStyle = { _styles.activeThumbnailTint }
zOrder = { 1 } /> zOrder = { 1 } />
{ participant.role === PARTICIPANT_ROLE.MODERATOR { participant.role === PARTICIPANT_ROLE.MODERATOR
@ -219,6 +229,7 @@ function _mapDispatchToProps(dispatch: Function, ownProps): Object {
* _audioTrack: Track, * _audioTrack: Track,
* _isModerator: boolean, * _isModerator: boolean,
* _largeVideo: Object, * _largeVideo: Object,
* _styles: StyleType,
* _videoTrack: Track * _videoTrack: Track
* }} * }}
*/ */
@ -238,6 +249,7 @@ function _mapStateToProps(state, ownProps) {
_audioTrack: audioTrack, _audioTrack: audioTrack,
_isModerator: isLocalParticipantModerator(state), _isModerator: isLocalParticipantModerator(state),
_largeVideo: largeVideo, _largeVideo: largeVideo,
_styles: ColorSchemeRegistry.get(state, 'Thumbnail'),
_videoTrack: videoTrack _videoTrack: videoTrack
}; };
} }

@ -1,3 +1,6 @@
// @flow
import { ColorSchemeRegistry, schemeColor } from '../../base/color-scheme';
import { ColorPalette } from '../../base/styles'; import { ColorPalette } from '../../base/styles';
import { FILMSTRIP_SIZE } from '../constants'; import { FILMSTRIP_SIZE } from '../constants';
@ -134,19 +137,6 @@ export default {
position: 'absolute' position: 'absolute'
}, },
/**
* Pinned video thumbnail style.
*/
thumbnailPinned: {
borderColor: ColorPalette.blue,
shadowColor: ColorPalette.black,
shadowOffset: {
height: 5,
width: 5
},
shadowRadius: 5
},
tileView: { tileView: {
alignSelf: 'center' alignSelf: 'center'
}, },
@ -160,3 +150,36 @@ export default {
justifyContent: 'center' justifyContent: 'center'
} }
}; };
/**
* Color schemed styles for the @{code Thumbnail} component.
*/
ColorSchemeRegistry.register('Thumbnail', {
/**
* Tinting style of the on-stage participant thumbnail.
*/
activeThumbnailTint: {
backgroundColor: schemeColor('activeParticipantTint')
},
/**
* Coloring if the thumbnail background.
*/
participantViewStyle: {
backgroundColor: schemeColor('background')
},
/**
* Pinned video thumbnail style.
*/
thumbnailPinned: {
borderColor: schemeColor('activeParticipantHighlight'),
shadowColor: schemeColor('activeParticipantHighlight'),
shadowOffset: {
height: 5,
width: 5
},
shadowRadius: 5
}
});

@ -3,27 +3,34 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../base/color-scheme';
import { ParticipantView } from '../../base/participants'; import { ParticipantView } from '../../base/participants';
import { DimensionsDetector } from '../../base/responsive-ui'; import { DimensionsDetector } from '../../base/responsive-ui';
import { StyleType } from '../../base/styles';
import styles, { AVATAR_SIZE } from './styles'; import { AVATAR_SIZE } from './styles';
/** /**
* The type of the React {@link Component} props of {@link LargeVideo}. * The type of the React {@link Component} props of {@link LargeVideo}.
*/ */
type Props = { type Props = {
/**
* Callback to invoke when the {@code LargeVideo} is clicked/pressed.
*/
onClick: Function,
/** /**
* The ID of the participant (to be) depicted by LargeVideo. * The ID of the participant (to be) depicted by LargeVideo.
* *
* @private * @private
*/ */
_participantId: string _participantId: string,
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/**
* Callback to invoke when the {@code LargeVideo} is clicked/pressed.
*/
onClick: Function,
}; };
/** /**
@ -114,6 +121,7 @@ class LargeVideo extends Component<Props, State> {
} = this.state; } = this.state;
const { const {
_participantId, _participantId,
_styles,
onClick onClick
} = this.props; } = this.props;
@ -124,7 +132,7 @@ class LargeVideo extends Component<Props, State> {
avatarSize = { avatarSize } avatarSize = { avatarSize }
onPress = { onClick } onPress = { onClick }
participantId = { _participantId } participantId = { _participantId }
style = { styles.largeVideo } style = { _styles.largeVideo }
testHintId = 'org.jitsi.meet.LargeVideo' testHintId = 'org.jitsi.meet.LargeVideo'
useConnectivityInfoLabel = { useConnectivityInfoLabel } useConnectivityInfoLabel = { useConnectivityInfoLabel }
zOrder = { 0 } zOrder = { 0 }
@ -140,12 +148,14 @@ class LargeVideo extends Component<Props, State> {
* @param {Object} state - Redux state. * @param {Object} state - Redux state.
* @private * @private
* @returns {{ * @returns {{
* _participantId: string * _participantId: string,
* _styles: StyleType
* }} * }}
*/ */
function _mapStateToProps(state) { function _mapStateToProps(state) {
return { return {
_participantId: state['features/large-video'].participantId _participantId: state['features/large-video'].participantId,
_styles: ColorSchemeRegistry.get(state, 'LargeVideo')
}; };
} }

@ -1,13 +1,16 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { ColorPalette, createStyleSheet } from '../../base/styles'; import { ColorSchemeRegistry, schemeColor } from '../../base/color-scheme';
/** /**
* Size for the Avatar. * Size for the Avatar.
*/ */
export const AVATAR_SIZE = 200; export const AVATAR_SIZE = 200;
export default createStyleSheet({ /**
* Color schemed styles for the @{LargeVideo} component.
*/
ColorSchemeRegistry.register('LargeVideo', {
/** /**
* Large video container style. * Large video container style.
@ -15,7 +18,7 @@ export default createStyleSheet({
largeVideo: { largeVideo: {
...StyleSheet.absoluteFillObject, ...StyleSheet.absoluteFillObject,
alignItems: 'stretch', alignItems: 'stretch',
backgroundColor: ColorPalette.appBackground, backgroundColor: schemeColor('background'),
flex: 1, flex: 1,
justifyContent: 'center' justifyContent: 'center'
} }

@ -52,7 +52,8 @@ type State = {
* *
* @extends Component * @extends Component
*/ */
export default class AbstractStreamKeyForm extends Component<Props, State> { export default class AbstractStreamKeyForm<P: Props>
extends Component<P, State> {
helpURL: string; helpURL: string;
_debouncedUpdateValidationErrorVisibility: Function; _debouncedUpdateValidationErrorVisibility: Function;
@ -61,7 +62,7 @@ export default class AbstractStreamKeyForm extends Component<Props, State> {
* *
* @inheritdoc * @inheritdoc
*/ */
constructor(props: Props) { constructor(props: P) {
super(props); super(props);
this.state = { this.state = {
@ -88,7 +89,7 @@ export default class AbstractStreamKeyForm extends Component<Props, State> {
* *
* @inheritdoc * @inheritdoc
*/ */
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: P) {
if (this.props.value !== prevProps.value) { if (this.props.value !== prevProps.value) {
this._debouncedUpdateValidationErrorVisibility(); this._debouncedUpdateValidationErrorVisibility();
} }

@ -4,7 +4,9 @@ import React, { Component } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { StyleType } from '../../../../base/styles';
import { import {
GOOGLE_API_STATES, GOOGLE_API_STATES,
@ -23,6 +25,11 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
*/ */
type Props = { type Props = {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType,
/** /**
* The Redux dispatch Function. * The Redux dispatch Function.
*/ */
@ -102,7 +109,7 @@ class GoogleSigninForm extends Component<Props> {
* @inheritdoc * @inheritdoc
*/ */
render() { render() {
const { t } = this.props; const { _dialogStyles, t } = this.props;
const { googleAPIState, googleResponse } = this.props; const { googleAPIState, googleResponse } = this.props;
const signedInUser = googleResponse const signedInUser = googleResponse
&& googleResponse.user && googleResponse.user
@ -121,7 +128,11 @@ class GoogleSigninForm extends Component<Props> {
return ( return (
<View style = { styles.formWrapper }> <View style = { styles.formWrapper }>
<View style = { styles.helpText }> <View style = { styles.helpText }>
<Text style = { styles.text }> <Text
style = { [
_dialogStyles.text,
styles.text
] }>
{ userInfo } { userInfo }
</Text> </Text>
</View> </View>
@ -225,6 +236,7 @@ function _mapStateToProps(state: Object) {
const { googleAPIState, googleResponse } = state['features/google-api']; const { googleAPIState, googleResponse } = state['features/google-api'];
return { return {
..._abstractMapStateToProps(state),
googleAPIState, googleAPIState,
googleResponse googleResponse
}; };

@ -2,13 +2,24 @@
import React from 'react'; import React from 'react';
import { Linking, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { Linking, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { StyleType } from '../../../../base/styles';
import AbstractStreamKeyForm, { import AbstractStreamKeyForm, {
type Props type Props as AbstractProps
} from '../AbstractStreamKeyForm'; } from '../AbstractStreamKeyForm';
type Props = AbstractProps & {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType
};
import styles, { PLACEHOLDER_COLOR } from './styles'; import styles, { PLACEHOLDER_COLOR } from './styles';
/** /**
@ -16,7 +27,7 @@ import styles, { PLACEHOLDER_COLOR } from './styles';
* *
* @extends Component * @extends Component
*/ */
class StreamKeyForm extends AbstractStreamKeyForm { class StreamKeyForm extends AbstractStreamKeyForm<Props> {
/** /**
* Initializes a new {@code StreamKeyForm} instance. * Initializes a new {@code StreamKeyForm} instance.
* *
@ -37,11 +48,16 @@ class StreamKeyForm extends AbstractStreamKeyForm {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { t } = this.props; const { _dialogStyles, t } = this.props;
return ( return (
<View style = { styles.formWrapper }> <View style = { styles.formWrapper }>
<Text style = { styles.streamKeyInputLabel }> <Text
style = { [
_dialogStyles.text,
styles.text,
styles.streamKeyInputLabel
] }>
{ {
t('dialog.streamKey') t('dialog.streamKey')
} }
@ -56,7 +72,11 @@ class StreamKeyForm extends AbstractStreamKeyForm {
{ {
this.state.showValidationError this.state.showValidationError
? <View style = { styles.formFooterItem }> ? <View style = { styles.formFooterItem }>
<Text style = { styles.warningText }> <Text
style = { [
_dialogStyles.text,
styles.warningText
] }>
{ t('liveStreaming.invalidStreamKey') } { t('liveStreaming.invalidStreamKey') }
</Text> </Text>
</View> </View>
@ -66,7 +86,11 @@ class StreamKeyForm extends AbstractStreamKeyForm {
<TouchableOpacity <TouchableOpacity
onPress = { this._onOpenHelp } onPress = { this._onOpenHelp }
style = { styles.streamKeyHelp } > style = { styles.streamKeyHelp } >
<Text style = { styles.text }> <Text
style = { [
_dialogStyles.text,
styles.text
] }>
{ {
t('liveStreaming.streamIdHelp') t('liveStreaming.streamIdHelp')
} }
@ -98,4 +122,4 @@ class StreamKeyForm extends AbstractStreamKeyForm {
} }
} }
export default translate(StreamKeyForm); export default translate(connect(_abstractMapStateToProps)(StreamKeyForm));

@ -8,8 +8,11 @@ import {
TouchableOpacity, TouchableOpacity,
View View
} from 'react-native'; } from 'react-native';
import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { StyleType } from '../../../../base/styles';
import { YOUTUBE_LIVE_DASHBOARD_URL } from '../constants'; import { YOUTUBE_LIVE_DASHBOARD_URL } from '../constants';
@ -17,6 +20,11 @@ import styles, { ACTIVE_OPACITY, TOUCHABLE_UNDERLAY } from './styles';
type Props = { type Props = {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType,
/** /**
* The list of broadcasts the user can pick from. * The list of broadcasts the user can pick from.
*/ */
@ -74,7 +82,7 @@ class StreamKeyPicker extends Component<Props, State> {
* @inheritdoc * @inheritdoc
*/ */
render() { render() {
const { broadcasts } = this.props; const { _dialogStyles, broadcasts } = this.props;
if (!broadcasts) { if (!broadcasts) {
return null; return null;
@ -85,7 +93,11 @@ class StreamKeyPicker extends Component<Props, State> {
<View style = { styles.formWrapper }> <View style = { styles.formWrapper }>
<TouchableOpacity <TouchableOpacity
onPress = { this._onOpenYoutubeDashboard }> onPress = { this._onOpenYoutubeDashboard }>
<Text style = { styles.warningText }> <Text
style = { [
_dialogStyles.text,
styles.warningText
] }>
{ this.props.t( { this.props.t(
'liveStreaming.getStreamKeyManually') } 'liveStreaming.getStreamKeyManually') }
</Text> </Text>
@ -97,7 +109,11 @@ class StreamKeyPicker extends Component<Props, State> {
return ( return (
<View style = { styles.formWrapper }> <View style = { styles.formWrapper }>
<View style = { styles.streamKeyPickerCta }> <View style = { styles.streamKeyPickerCta }>
<Text style = { styles.text }> <Text
style = { [
_dialogStyles.text,
styles.text
] }>
{ this.props.t('liveStreaming.choose') } { this.props.t('liveStreaming.choose') }
</Text> </Text>
</View> </View>
@ -113,7 +129,11 @@ class StreamKeyPicker extends Component<Props, State> {
? styles.streamKeyPickerItemHighlight : null ? styles.streamKeyPickerItemHighlight : null
] } ] }
underlayColor = { TOUCHABLE_UNDERLAY }> underlayColor = { TOUCHABLE_UNDERLAY }>
<Text style = { styles.text }> <Text
style = { [
_dialogStyles.text,
styles.text
] }>
{ broadcast.title } { broadcast.title }
</Text> </Text>
</TouchableHighlight>)) </TouchableHighlight>))
@ -155,4 +175,5 @@ class StreamKeyPicker extends Component<Props, State> {
} }
} }
export default translate(StreamKeyPicker); export default translate(
connect(_abstractMapStateToProps)(StreamKeyPicker));

@ -99,8 +99,7 @@ export default createStyleSheet({
* Label for the previous field. * Label for the previous field.
*/ */
streamKeyInputLabel: { streamKeyInputLabel: {
alignSelf: 'flex-start', alignSelf: 'flex-start'
color: ColorPalette.white
}, },
/** /**
@ -146,7 +145,8 @@ export default createStyleSheet({
}, },
text: { text: {
color: ColorPalette.white fontSize: 14,
textAlign: 'left'
}, },
/** /**

@ -14,7 +14,7 @@ import AbstractStreamKeyForm, {
* *
* @extends Component * @extends Component
*/ */
class StreamKeyForm extends AbstractStreamKeyForm { class StreamKeyForm extends AbstractStreamKeyForm<Props> {
/** /**
* Initializes a new {@code StreamKeyForm} instance. * Initializes a new {@code StreamKeyForm} instance.

@ -7,7 +7,10 @@ import {
createRecordingDialogEvent, createRecordingDialogEvent,
sendAnalytics sendAnalytics
} from '../../../analytics'; } from '../../../analytics';
import { DialogContent } from '../../../base/dialog'; import {
DialogContent,
_abstractMapStateToProps
} from '../../../base/dialog';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { import {
Container, Container,
@ -15,6 +18,7 @@ import {
Switch, Switch,
Text Text
} from '../../../base/react'; } from '../../../base/react';
import { StyleType } from '../../../base/styles';
import { authorizeDropbox, updateDropboxToken } from '../../../dropbox'; import { authorizeDropbox, updateDropboxToken } from '../../../dropbox';
import styles from './styles'; import styles from './styles';
@ -22,6 +26,11 @@ import { getRecordingDurationEstimation } from '../../functions';
type Props = { type Props = {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType,
/** /**
* The redux dispatch function. * The redux dispatch function.
*/ */
@ -99,7 +108,7 @@ class StartRecordingDialogContent extends Component<Props> {
*/ */
_renderNoIntegrationsContent() { _renderNoIntegrationsContent() {
return ( return (
<DialogContent style = { styles.noIntegrationContent }> <DialogContent style = { this.props._dialogStyles.text }>
{ this.props.t('recording.startRecordingBody') } { this.props.t('recording.startRecordingBody') }
</DialogContent> </DialogContent>
); );
@ -112,7 +121,7 @@ class StartRecordingDialogContent extends Component<Props> {
* @returns {React$Component} * @returns {React$Component}
*/ */
_renderIntegrationsContent() { _renderIntegrationsContent() {
const { isTokenValid, isValidating, t } = this.props; const { _dialogStyles, isTokenValid, isValidating, t } = this.props;
let content = null; let content = null;
@ -135,7 +144,10 @@ class StartRecordingDialogContent extends Component<Props> {
style = { styles.header }> style = { styles.header }>
<Text <Text
className = 'recording-title' className = 'recording-title'
style = { styles.title }> style = { [
_dialogStyles.text,
styles.title
] }>
{ t('recording.authDropboxText') } { t('recording.authDropboxText') }
</Text> </Text>
<Switch <Switch
@ -248,4 +260,5 @@ class StartRecordingDialogContent extends Component<Props> {
} }
} }
export default translate(connect()(StartRecordingDialogContent)); export default translate(
connect(_abstractMapStateToProps)(StartRecordingDialogContent));

@ -28,10 +28,6 @@ export default createStyleSheet({
paddingBottom: _PADDING paddingBottom: _PADDING
}, },
noIntegrationContent: {
color: ColorPalette.white
},
startRecordingText: { startRecordingText: {
paddingBottom: _PADDING paddingBottom: _PADDING
}, },
@ -42,7 +38,6 @@ export default createStyleSheet({
}, },
title: { title: {
color: ColorPalette.white,
fontSize: 16, fontSize: 16,
fontWeight: 'bold' fontWeight: 'bold'
}, },

@ -4,15 +4,16 @@ import React, { Component } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { import {
BottomSheet, BottomSheet
bottomSheetItemStylesCombined
} from '../../../base/dialog'; } from '../../../base/dialog';
import { import {
Avatar, Avatar,
getAvatarURL, getAvatarURL,
getParticipantDisplayName getParticipantDisplayName
} from '../../../base/participants'; } from '../../../base/participants';
import { StyleType } from '../../../base/styles';
import { hideRemoteVideoMenu } from '../../actions'; import { hideRemoteVideoMenu } from '../../actions';
@ -42,6 +43,11 @@ type Props = {
*/ */
_avatarURL: string, _avatarURL: string,
/**
* The color-schemed stylesheet of the BottomSheet.
*/
_bottomSheetStyles: StyleType,
/** /**
* Display name of the participant retreived from Redux. * Display name of the participant retreived from Redux.
*/ */
@ -73,7 +79,7 @@ class RemoteVideoMenu extends Component<Props> {
afterClick: this._onCancel, afterClick: this._onCancel,
showLabel: true, showLabel: true,
participantID: this.props.participant.id, participantID: this.props.participant.id,
styles: bottomSheetItemStylesCombined styles: this.props._bottomSheetStyles
}; };
return ( return (
@ -113,6 +119,7 @@ class RemoteVideoMenu extends Component<Props> {
* @private * @private
* @returns {{ * @returns {{
* _avatarURL: string, * _avatarURL: string,
* _bottomSheetStyles: StyleType,
* _participantDisplayName: string * _participantDisplayName: string
* }} * }}
*/ */
@ -121,6 +128,8 @@ function _mapStateToProps(state, ownProps) {
return { return {
_avatarURL: getAvatarURL(participant), _avatarURL: getAvatarURL(participant),
_bottomSheetStyles:
ColorSchemeRegistry.get(state, 'BottomSheet'),
_participantDisplayName: getParticipantDisplayName( _participantDisplayName: getParticipantDisplayName(
state, participant.id) state, participant.id)
}; };

@ -4,11 +4,12 @@ import React, { Component } from 'react';
import { Platform } from 'react-native'; import { Platform } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { import {
BottomSheet, BottomSheet,
bottomSheetItemStylesCombined,
hideDialog hideDialog
} from '../../../base/dialog'; } from '../../../base/dialog';
import { StyleType } from '../../../base/styles';
import { InviteButton } from '../../../invite'; import { InviteButton } from '../../../invite';
import { AudioRouteButton } from '../../../mobile/audio-mode'; import { AudioRouteButton } from '../../../mobile/audio-mode';
import { LiveStreamButton, RecordButton } from '../../../recording'; import { LiveStreamButton, RecordButton } from '../../../recording';
@ -26,10 +27,15 @@ declare var __DEV__;
*/ */
type Props = { type Props = {
/**
* The color-schemed stylesheet of the dialog feature.
*/
_bottomSheetStyles: StyleType,
/** /**
* Used for hiding the dialog when the selection was completed. * Used for hiding the dialog when the selection was completed.
*/ */
dispatch: Function, dispatch: Function
}; };
/** /**
@ -68,7 +74,7 @@ class OverflowMenu extends Component<Props> {
const buttonProps = { const buttonProps = {
afterClick: this._onCancel, afterClick: this._onCancel,
showLabel: true, showLabel: true,
styles: bottomSheetItemStylesCombined styles: this.props._bottomSheetStyles
}; };
return ( return (
@ -106,6 +112,22 @@ class OverflowMenu extends Component<Props> {
} }
} }
OverflowMenu_ = connect()(OverflowMenu); /**
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @private
* @returns {{
* _bottomSheetStyles: StyleType
* }}
*/
function _mapStateToProps(state) {
return {
_bottomSheetStyles:
ColorSchemeRegistry.get(state, 'BottomSheet')
};
}
OverflowMenu_ = connect(_mapStateToProps)(OverflowMenu);
export default OverflowMenu_; export default OverflowMenu_;

@ -5,21 +5,19 @@ import { View } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Container } from '../../../base/react'; import { Container } from '../../../base/react';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { StyleType } from '../../../base/styles';
import { ChatButton } from '../../../chat'; import { ChatButton } from '../../../chat';
import { isToolboxVisible } from '../../functions'; import { isToolboxVisible } from '../../functions';
import { HANGUP_BUTTON_SIZE } from '../../constants';
import AudioMuteButton from '../AudioMuteButton'; import AudioMuteButton from '../AudioMuteButton';
import HangupButton from '../HangupButton'; import HangupButton from '../HangupButton';
import VideoMuteButton from '../VideoMuteButton';
import OverflowMenuButton from './OverflowMenuButton'; import OverflowMenuButton from './OverflowMenuButton';
import styles, { import styles from './styles';
chatButtonOverride, import VideoMuteButton from '../VideoMuteButton';
hangupButtonStyles,
toolbarButtonStyles,
toolbarToggledButtonStyles
} from './styles';
/** /**
* The number of buttons other than {@link HangupButton} to render in * The number of buttons other than {@link HangupButton} to render in
@ -43,6 +41,11 @@ const _BUTTON_SIZE_FACTOR = 0.85;
*/ */
type Props = { type Props = {
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/** /**
* The indicator which determines whether the toolbox is visible. * The indicator which determines whether the toolbox is visible.
*/ */
@ -111,6 +114,7 @@ class Toolbox extends Component<Props, State> {
* @returns {number} * @returns {number}
*/ */
_calculateButtonSize() { _calculateButtonSize() {
const { _styles } = this.props;
const { width } = this.state; const { width } = this.state;
if (width <= 0) { if (width <= 0) {
@ -118,8 +122,8 @@ class Toolbox extends Component<Props, State> {
return width; return width;
} }
const hangupButtonSize = styles.hangupButton.width; const hangupButtonSize = HANGUP_BUTTON_SIZE;
const { style } = toolbarButtonStyles; const { style } = _styles.buttonStyles;
let buttonSize let buttonSize
= (width = (width
@ -155,12 +159,14 @@ class Toolbox extends Component<Props, State> {
* @returns {Object | Array} * @returns {Object | Array}
*/ */
_getChatButtonToggledStyle(baseStyle) { _getChatButtonToggledStyle(baseStyle) {
const { _styles } = this.props;
if (Array.isArray(baseStyle.style)) { if (Array.isArray(baseStyle.style)) {
return { return {
...baseStyle, ...baseStyle,
style: [ style: [
...baseStyle.style, ...baseStyle.style,
chatButtonOverride.toggled _styles.chatButtonOverride.toggled
] ]
}; };
} }
@ -169,7 +175,7 @@ class Toolbox extends Component<Props, State> {
...baseStyle, ...baseStyle,
style: [ style: [
baseStyle.style, baseStyle.style,
chatButtonOverride.toggled _styles.chatButtonOverride.toggled
] ]
}; };
} }
@ -196,9 +202,9 @@ class Toolbox extends Component<Props, State> {
* @returns {React$Node} * @returns {React$Node}
*/ */
_renderToolbar() { _renderToolbar() {
const { _styles } = this.props;
const buttonSize = this._calculateButtonSize(); const buttonSize = this._calculateButtonSize();
let buttonStyles = toolbarButtonStyles; let { buttonStyles, toggledButtonStyles } = _styles;
let toggledButtonStyles = toolbarToggledButtonStyles;
if (buttonSize > 0) { if (buttonSize > 0) {
const extraButtonStyle = { const extraButtonStyle = {
@ -241,7 +247,8 @@ class Toolbox extends Component<Props, State> {
<AudioMuteButton <AudioMuteButton
styles = { buttonStyles } styles = { buttonStyles }
toggledStyles = { toggledButtonStyles } /> toggledStyles = { toggledButtonStyles } />
<HangupButton styles = { hangupButtonStyles } /> <HangupButton
styles = { _styles.hangupButtonStyles } />
<VideoMuteButton <VideoMuteButton
styles = { buttonStyles } styles = { buttonStyles }
toggledStyles = { toggledButtonStyles } /> toggledStyles = { toggledButtonStyles } />
@ -261,11 +268,13 @@ class Toolbox extends Component<Props, State> {
* {@code Toolbox} props. * {@code Toolbox} props.
* @private * @private
* @returns {{ * @returns {{
* _styles: StyleType,
* _visible: boolean * _visible: boolean
* }} * }}
*/ */
function _mapStateToProps(state: Object): Object { function _mapStateToProps(state: Object): Object {
return { return {
_styles: ColorSchemeRegistry.get(state, 'Toolbox'),
_visible: isToolboxVisible(state) _visible: isToolboxVisible(state)
}; };
} }

@ -1,4 +1,6 @@
// @flow // @flow
import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
import { BoxModel, ColorPalette, createStyleSheet } from '../../../base/styles'; import { BoxModel, ColorPalette, createStyleSheet } from '../../../base/styles';
import { HANGUP_BUTTON_SIZE } from '../../constants'; import { HANGUP_BUTTON_SIZE } from '../../constants';
@ -9,7 +11,7 @@ import { HANGUP_BUTTON_SIZE } from '../../constants';
* The style of toolbar buttons. * The style of toolbar buttons.
*/ */
const toolbarButton = { const toolbarButton = {
backgroundColor: ColorPalette.white, backgroundColor: schemeColor('button'),
borderRadius: 20, borderRadius: 20,
borderWidth: 0, borderWidth: 0,
flex: 0, flex: 0,
@ -20,7 +22,6 @@ const toolbarButton = {
// XXX We probably tested BoxModel.margin and discovered it to be too small // XXX We probably tested BoxModel.margin and discovered it to be too small
// for our taste. // for our taste.
marginHorizontal: 7, marginHorizontal: 7,
opacity: 0.7,
width: 40 width: 40
}; };
@ -33,29 +34,26 @@ const toolbarButtonIcon = {
fontSize: 22 fontSize: 22
}; };
/**
* The style of toolbar buttons which display white icons.
*/
const whiteToolbarButton = {
...toolbarButton,
backgroundColor: schemeColor('buttonToggled')
};
/**
* The icon style of toolbar buttons which display white icons.
*/
const whiteToolbarButtonIcon = {
...toolbarButtonIcon,
color: ColorPalette.white
};
/** /**
* The Toolbox and toolbar related styles. * The Toolbox and toolbar related styles.
*/ */
const styles = createStyleSheet({ const styles = createStyleSheet({
/**
* The style of the toolbar button which hangs the current conference up.
*/
hangupButton: {
...toolbarButton,
backgroundColor: ColorPalette.red,
borderRadius: 30,
height: HANGUP_BUTTON_SIZE,
width: HANGUP_BUTTON_SIZE
},
/**
* The icon style of toolbar buttons which hangs the current conference up.
*/
hangupButtonIcon: {
...toolbarButtonIcon,
color: ColorPalette.white,
fontSize: 24
},
/** /**
* The style of the toolbar. * The style of the toolbar.
@ -69,74 +67,60 @@ const styles = createStyleSheet({
paddingHorizontal: BoxModel.margin paddingHorizontal: BoxModel.margin
}, },
/**
* The style of toolbar buttons.
*/
toolbarButton,
/**
* The icon style of the toolbar buttons.
*/
toolbarButtonIcon,
/** /**
* The style of the root/top-level {@link Container} of {@link Toolbox}. * The style of the root/top-level {@link Container} of {@link Toolbox}.
*/ */
toolbox: { toolbox: {
flexDirection: 'column', flexDirection: 'column',
flexGrow: 0 flexGrow: 0
},
/**
* The style of toolbar buttons which display white icons.
*/
whiteToolbarButton: {
...toolbarButton,
backgroundColor: ColorPalette.buttonUnderlay
},
/**
* The icon style of toolbar buttons which display white icons.
*/
whiteToolbarButtonIcon: {
...toolbarButtonIcon,
color: ColorPalette.white
} }
}); });
export default styles; export default styles;
/** /**
* Styles for the hangup button. * Color schemed styles for the @{Toolbox} component.
*/ */
export const hangupButtonStyles = { ColorSchemeRegistry.register('Toolbox', {
iconStyle: styles.whiteToolbarButtonIcon, /**
style: styles.hangupButton, * Styles for buttons in the toolbar.
underlayColor: ColorPalette.buttonUnderlay */
}; buttonStyles: {
iconStyle: toolbarButtonIcon,
style: toolbarButton
},
/** /**
* Styles for buttons in the toolbar. * Overrides to the standard styles that we apply to the chat button, as
*/ * that behaves slightly differently to other buttons.
export const toolbarButtonStyles = { */
iconStyle: styles.toolbarButtonIcon, chatButtonOverride: {
style: styles.toolbarButton toggled: {
}; backgroundColor: ColorPalette.blue
}
},
/** hangupButtonStyles: {
* Styles for toggled buttons in the toolbar. iconStyle: whiteToolbarButtonIcon,
*/ style: {
export const toolbarToggledButtonStyles = { ...toolbarButton,
iconStyle: styles.whiteToolbarButtonIcon, backgroundColor: schemeColor('hangup'),
style: styles.whiteToolbarButton borderRadius: HANGUP_BUTTON_SIZE / 2,
}; height: HANGUP_BUTTON_SIZE,
width: HANGUP_BUTTON_SIZE
},
underlayColor: ColorPalette.buttonUnderlay
},
/** /**
* Overrides to the standard styles that we apply to the chat button, as that * Styles for toggled buttons in the toolbar.
* behaves slightly differently to other buttons. */
*/ toggledButtonStyles: {
export const chatButtonOverride = createStyleSheet({ iconStyle: whiteToolbarButtonIcon,
toggled: { style: {
backgroundColor: ColorPalette.blue ...whiteToolbarButton,
borderColor: schemeColor('buttonToggledBorder'),
borderWidth: 1
}
} }
}); });

Loading…
Cancel
Save