[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:
parent
f973a695d8
commit
e7aff1d8e1
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue