[RN] Group the secondary toobar buttons

Rearrange the ToolbarButtons in the secondary Toolbar in order to mostly
group the media-related ones such as the AudioRouteButton, the
switchCamera button, and the audio-only mode button.
This commit is contained in:
Lyubo Marinov 2017-11-14 14:18:16 -06:00
parent f973a695d8
commit e7aff1d8e1
7 changed files with 92 additions and 94 deletions

View File

@ -9,7 +9,7 @@ import { LoadingIndicator } from '../../react';
import { set } from '../../redux'; import { set } from '../../redux';
import AbstractDialog from './AbstractDialog'; import AbstractDialog from './AbstractDialog';
import styles from './styles'; import { dialog as styles } from './styles';
/** /**
* The value of the style property {@link _TAG_KEY} which identifies the * The value of the style property {@link _TAG_KEY} which identifies the

View File

@ -12,7 +12,7 @@ import { connect } from 'react-redux';
import { Icon } from '../../font-icons'; import { Icon } from '../../font-icons';
import { bottomSheet as styles } from './styles'; import { simpleBottomSheet as styles } from './styles';
/** /**
* Underlay color for the buttons on the sheet. * Underlay color for the buttons on the sheet.

View File

@ -1,9 +1,9 @@
import { ColorPalette, createStyleSheet } from '../../styles'; import { ColorPalette, createStyleSheet } from '../../styles';
/** /**
* The React {@code Component} styles of the feature base/dialog. * The React {@code Component} styles of {@code Dialog}.
*/ */
export default createStyleSheet({ export const dialog = createStyleSheet({
/** /**
* The style of the {@code Text} in a {@code Dialog} button. * The style of the {@code Text} in a {@code Dialog} button.
*/ */
@ -21,11 +21,11 @@ export default createStyleSheet({
}); });
/** /**
* The React {@code Component} styles for {@code SimpleBottomSheet}. * The React {@code Component} styles of {@code SimpleBottomSheet}. These have
* These styles have been implemented as per the Material Design guidelines: * been implemented as per the Material Design guidelines:
* https://material.io/guidelines/components/bottom-sheets.html * {@link https://material.io/guidelines/components/bottom-sheets.html}.
*/ */
export const bottomSheet = createStyleSheet({ export const simpleBottomSheet = createStyleSheet({
/** /**
* Style for the container of the sheet. * Style for the container of the sheet.
*/ */

View File

@ -7,11 +7,30 @@ import { connect } from 'react-redux';
import { hideDialog, SimpleBottomSheet } from '../../../base/dialog'; import { hideDialog, SimpleBottomSheet } from '../../../base/dialog';
const AudioMode = NativeModules.AudioMode; /**
* {@code PasswordRequiredPrompt}'s React {@code Component} prop types.
*/
type Props = {
/**
* Used for hiding the dialog when the selection was completed.
*/
dispatch: Function
};
type State = {
/**
* Array of available devices.
*/
devices: Array<string>
};
const { AudioMode } = NativeModules;
/** /**
* Maps each device type to a display name and icon. * Maps each device type to a display name and icon.
* TODO: internationalization. * TODO i18n
*/ */
const deviceInfoMap = { const deviceInfoMap = {
BLUETOOTH: { BLUETOOTH: {
@ -37,30 +56,11 @@ const deviceInfoMap = {
}; };
/** /**
* Variable to hold the reference to the exported component. This dialog is only * The exported React {@code Component}. {@code AudioRoutePickerDialog} is
* exported if the {@code AudioMode} module has the capability to get / set * exported only if the {@code AudioMode} module has the capability to get / set
* audio devices. * audio devices.
*/ */
let DialogType; let AudioRoutePickerDialog_;
/**
* {@code PasswordRequiredPrompt}'s React {@code Component} prop types.
*/
type Props = {
/**
* Used for hiding the dialog when the selection was completed.
*/
dispatch: Function
};
type State = {
/**
* Array of available devices.
*/
devices: Array<string>
};
/** /**
* Implements a React {@code Component} which prompts the user when a password * Implements a React {@code Component} which prompts the user when a password
@ -68,7 +68,10 @@ type State = {
*/ */
class AudioRoutePickerDialog extends Component<Props, State> { class AudioRoutePickerDialog extends Component<Props, State> {
state = { state = {
// Available audio devices, it will be set in componentWillMount. /**
* Available audio devices, it will be set in
* {@link #componentWillMount()}.
*/
devices: [] devices: []
}; };
@ -87,7 +90,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
} }
/** /**
* Initializes the device list by querying the {@code AudioMode} module. * Initializes the device list by querying {@code AudioMode}.
* *
* @inheritdoc * @inheritdoc
*/ */
@ -107,8 +110,10 @@ class AudioRoutePickerDialog extends Component<Props, State> {
} }
if (audioDevices) { if (audioDevices) {
// Make sure devices is alphabetically sorted // Make sure devices is alphabetically sorted.
this.setState({ devices: _.sortBy(audioDevices, 'text') }); this.setState({
devices: _.sortBy(audioDevices, 'text')
});
} }
}); });
} }
@ -119,7 +124,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
* @returns {void} * @returns {void}
*/ */
_hide() { _hide() {
this.props.dispatch(hideDialog(DialogType)); this.props.dispatch(hideDialog(AudioRoutePickerDialog_));
} }
_onCancel: () => void; _onCancel: () => void;
@ -156,7 +161,9 @@ class AudioRoutePickerDialog extends Component<Props, State> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
if (!this.state.devices.length) { const { devices } = this.state;
if (!devices.length) {
return null; return null;
} }
@ -164,7 +171,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
<SimpleBottomSheet <SimpleBottomSheet
onCancel = { this._onCancel } onCancel = { this._onCancel }
onSubmit = { this._onSubmit } onSubmit = { this._onSubmit }
options = { this.state.devices } /> options = { devices } />
); );
} }
} }
@ -172,7 +179,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
// Only export the dialog if we have support for getting / setting audio devices // Only export the dialog if we have support for getting / setting audio devices
// in AudioMode. // in AudioMode.
if (AudioMode.getAudioDevices && AudioMode.setAudioDevice) { if (AudioMode.getAudioDevices && AudioMode.setAudioDevice) {
DialogType = connect()(AudioRoutePickerDialog); AudioRoutePickerDialog_ = connect()(AudioRoutePickerDialog);
} }
export default DialogType; export default AudioRoutePickerDialog_;

View File

@ -3,8 +3,8 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import {
findNodeHandle, findNodeHandle,
requireNativeComponent,
NativeModules, NativeModules,
requireNativeComponent,
View View
} from 'react-native'; } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -15,17 +15,15 @@ import { AudioRoutePickerDialog } from '../../mobile/audio-mode';
import ToolbarButton from './ToolbarButton'; import ToolbarButton from './ToolbarButton';
/** /**
* Define the {@code MPVolumeView} React component. It will only be available * The {@code MPVolumeView} React {@code Component}. It will only be available
* on iOS. * on iOS.
*/ */
let MPVolumeView; const MPVolumeView
= NativeModules.MPVolumeViewManager
if (NativeModules.MPVolumeViewManager) { && requireNativeComponent('MPVolumeView', null);
MPVolumeView = requireNativeComponent('MPVolumeView', null);
}
/** /**
* Style required to hide the {@code MPVolumeView} view, since it's displayed * The style required to hide the {@code MPVolumeView}, since it's displayed
* programmatically. * programmatically.
*/ */
const HIDE_VIEW_STYLE = { display: 'none' }; const HIDE_VIEW_STYLE = { display: 'none' };
@ -33,7 +31,8 @@ const HIDE_VIEW_STYLE = { display: 'none' };
type Props = { type Props = {
/** /**
* Used to show the {@code AudioRoutePickerDialog}. * The redux {@code dispatch} function used to open/show the
* {@code AudioRoutePickerDialog}.
*/ */
dispatch: Function, dispatch: Function,
@ -48,12 +47,12 @@ type Props = {
iconStyle: Object, iconStyle: Object,
/** /**
* {@code AudioRouteButton} styles. * The style(s) of {@code AudioRouteButton}.
*/ */
style: Array<*> | Object, style: Array<*> | Object,
/** /**
* The color underlying the button. * The color underlaying the button.
*/ */
underlayColor: string underlayColor: string
}; };
@ -64,16 +63,6 @@ type Props = {
class AudioRouteButton extends Component<Props> { class AudioRouteButton extends Component<Props> {
_volumeComponent: ?Object; _volumeComponent: ?Object;
/**
* Indicates if there is support for audio device selection via this button.
*
* @returns {boolean} - True if audio device selection is supported, false
* otherwise.
*/
static supported() {
return Boolean(MPVolumeView || AudioRoutePickerDialog);
}
/** /**
* Initializes a new {@code AudioRouteButton} instance. * Initializes a new {@code AudioRouteButton} instance.
* *
@ -108,27 +97,13 @@ class AudioRouteButton extends Component<Props> {
*/ */
_onClick() { _onClick() {
if (MPVolumeView) { if (MPVolumeView) {
const handle = findNodeHandle(this._volumeComponent); NativeModules.MPVolumeViewManager.show(
findNodeHandle(this._volumeComponent));
NativeModules.MPVolumeViewManager.show(handle);
} else if (AudioRoutePickerDialog) { } else if (AudioRoutePickerDialog) {
this.props.dispatch(openDialog(AudioRoutePickerDialog)); this.props.dispatch(openDialog(AudioRoutePickerDialog));
} }
} }
_setVolumeComponent: (?Object) => void;
/**
* Sets the internal reference to the React Component wrapping the
* {@code MPVolumeView} component.
*
* @param {ReactComponent} component - React Component.
* @returns {void}
*/
_setVolumeComponent(component) {
this._volumeComponent = component;
}
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -155,6 +130,21 @@ class AudioRouteButton extends Component<Props> {
</View> </View>
); );
} }
_setVolumeComponent: (?Object) => void;
/**
* Sets the internal reference to the React Component wrapping the
* {@code MPVolumeView} component.
*
* @param {ReactComponent} component - React Component.
* @private
* @returns {void}
*/
_setVolumeComponent(component) {
this._volumeComponent = component;
}
} }
export default connect()(AudioRouteButton); export default (MPVolumeView || AudioRoutePickerDialog)
&& connect()(AudioRouteButton);

View File

@ -47,8 +47,9 @@ class ToolbarButton extends AbstractToolbarButton {
return React.createElement(TouchableHighlight, props, children); return React.createElement(TouchableHighlight, props, children);
} }
// eslint-disable-next-line valid-jsdoc
/** /**
* Renders the icon of this {@code ToolbarButton}.
*
* @inheritdoc * @inheritdoc
*/ */
_renderIcon() { _renderIcon() {

View File

@ -282,6 +282,14 @@ class Toolbox extends Component {
<View <View
key = 'secondaryToolbar' key = 'secondaryToolbar'
style = { styles.secondaryToolbar }> style = { styles.secondaryToolbar }>
{
AudioRouteButton
&& <AudioRouteButton
iconName = { 'volume' }
iconStyle = { iconStyle }
style = { style }
underlayColor = { underlayColor } />
}
<ToolbarButton <ToolbarButton
disabled = { audioOnly || videoMuted } disabled = { audioOnly || videoMuted }
iconName = 'switch-camera' iconName = 'switch-camera'
@ -289,6 +297,12 @@ class Toolbox extends Component {
onClick = { this.props._onToggleCameraFacingMode } onClick = { this.props._onToggleCameraFacingMode }
style = { style } style = { style }
underlayColor = { underlayColor } /> underlayColor = { underlayColor } />
<ToolbarButton
iconName = { audioOnly ? 'visibility-off' : 'visibility' }
iconStyle = { iconStyle }
onClick = { this.props._onToggleAudioOnly }
style = { style }
underlayColor = { underlayColor } />
<ToolbarButton <ToolbarButton
iconName = { iconName = {
this.props._locked ? 'security-locked' : 'security' this.props._locked ? 'security-locked' : 'security'
@ -297,12 +311,6 @@ class Toolbox extends Component {
onClick = { this.props._onRoomLock } onClick = { this.props._onRoomLock }
style = { style } style = { style }
underlayColor = { underlayColor } /> underlayColor = { underlayColor } />
<ToolbarButton
iconName = { audioOnly ? 'visibility-off' : 'visibility' }
iconStyle = { iconStyle }
onClick = { this.props._onToggleAudioOnly }
style = { style }
underlayColor = { underlayColor } />
{ {
_SHARE_ROOM_TOOLBAR_BUTTON _SHARE_ROOM_TOOLBAR_BUTTON
&& <ToolbarButton && <ToolbarButton
@ -312,14 +320,6 @@ class Toolbox extends Component {
style = { style } style = { style }
underlayColor = { underlayColor } /> underlayColor = { underlayColor } />
} }
{
AudioRouteButton.supported()
&& <AudioRouteButton
iconName = { 'volume' }
iconStyle = { iconStyle }
style = { style }
underlayColor = { underlayColor } />
}
</View> </View>
); );