[RN] Make feature dialogs branded: recording

This commit is contained in:
Bettenbuk Zoltan 2018-10-18 10:32:12 +02:00 committed by Saúl Ibarra Corretgé
parent 4bc09dd8b9
commit 62e7fd7e8e
23 changed files with 285 additions and 217 deletions

View File

@ -3,6 +3,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Container, Text } from '../../react'; import { Container, Text } from '../../react';
import { type StyleType } from '../../styles';
import styles from './styles'; import styles from './styles';
@ -11,7 +12,9 @@ type Props = {
/** /**
* Children of the component. * Children of the component.
*/ */
children: string | React$Node children: string | React$Node,
style: ?StyleType
}; };
/** /**
@ -25,10 +28,10 @@ export default class DialogContent extends Component<Props> {
* @inheritdoc * @inheritdoc
*/ */
render() { render() {
const { children } = this.props; const { children, style } = this.props;
const childrenComponent = typeof children === 'string' const childrenComponent = typeof children === 'string'
? <Text>{ children }</Text> ? <Text style = { style }>{ children }</Text>
: children; : children;
return ( return (

View File

@ -38,6 +38,7 @@ export default createStyleSheet({
borderColor: ColorPalette.lightGrey, borderColor: ColorPalette.lightGrey,
borderRadius: 3, borderRadius: 3,
borderWidth: 1, borderWidth: 1,
color: ColorPalette.white,
height: BUTTON_HEIGHT, height: BUTTON_HEIGHT,
justifyContent: 'center' justifyContent: 'center'
}, },

View File

@ -1,12 +1,11 @@
// @flow // @flow
import React, { Component } from 'react'; import { Component } from 'react';
import { import {
createRecordingDialogEvent, createRecordingDialogEvent,
sendAnalytics sendAnalytics
} from '../../../analytics'; } from '../../../analytics';
import { Dialog } from '../../../base/dialog';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
/** /**
@ -140,27 +139,6 @@ export default class AbstractStartLiveStreamDialog<P: Props>
this._isMounted = false; this._isMounted = false;
} }
/**
* Implements {@code Component}'s render.
*
* @inheritdoc
*/
render() {
return (
<Dialog
cancelTitleKey = 'dialog.Cancel'
okTitleKey = 'dialog.startLiveStreaming'
onCancel = { this._onCancel }
onSubmit = { this._onSubmit }
titleKey = 'liveStreaming.start'
width = { 'small' }>
{
this._renderDialogContent()
}
</Dialog>
);
}
_onCancel: () => boolean; _onCancel: () => boolean;
/** /**
@ -257,13 +235,6 @@ export default class AbstractStartLiveStreamDialog<P: Props>
this.setState(newState); this.setState(newState);
} }
} }
/**
* Renders the platform specific dialog content.
*
* @returns {React$Component}
*/
_renderDialogContent: () => React$Component<*>
} }
/** /**

View File

@ -1,8 +1,7 @@
// @flow // @flow
import React, { Component } from 'react'; import { Component } from 'react';
import { Dialog } from '../../../base/dialog';
import { import {
createRecordingDialogEvent, createRecordingDialogEvent,
sendAnalytics sendAnalytics
@ -53,24 +52,6 @@ export default class AbstractStopLiveStreamDialog extends Component<Props> {
this._onSubmit = this._onSubmit.bind(this); this._onSubmit = this._onSubmit.bind(this);
} }
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<Dialog
okTitleKey = 'dialog.stopLiveStreaming'
onSubmit = { this._onSubmit }
titleKey = 'dialog.liveStreaming'
width = 'small'>
{ this._renderDialogContent() }
</Dialog>
);
}
_onSubmit: () => boolean; _onSubmit: () => boolean;
/** /**
@ -90,14 +71,6 @@ export default class AbstractStopLiveStreamDialog extends Component<Props> {
return true; return true;
} }
/**
* Function to be implemented by the platform specific implementations.
*
* @private
* @returns {React$Component<*>}
*/
_renderDialogContent: () => React$Component<*>
} }
/** /**

View File

@ -126,14 +126,16 @@ class GoogleSigninForm extends Component<Props> {
return null; return null;
} }
const userInfo = signedInUser
? `${t('liveStreaming.signedInAs')} ${signedInUser}`
: t('liveStreaming.signInCTA');
return ( return (
<View style = { styles.formWrapper }> <View style = { styles.formWrapper }>
<View style = { styles.helpText }> <View style = { styles.helpText }>
{ signedInUser ? <Text> <Text style = { styles.text }>
{ `${t('liveStreaming.signedInAs')} ${signedInUser}` } { userInfo }
</Text> : <Text> </Text>
{ t('liveStreaming.signInCTA') }
</Text> }
</View> </View>
<GoogleSignInButton <GoogleSignInButton
onClick = { this._onGoogleButtonPress } onClick = { this._onGoogleButtonPress }

View File

@ -4,6 +4,7 @@ import React from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { CustomSubmitDialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { googleApi } from '../../../../google-api'; import { googleApi } from '../../../../google-api';
@ -36,9 +37,39 @@ class StartLiveStreamDialog extends AbstractStartLiveStreamDialog<Props> {
= this._onStreamKeyChangeNative.bind(this); = this._onStreamKeyChangeNative.bind(this);
this._onStreamKeyPick = this._onStreamKeyPick.bind(this); this._onStreamKeyPick = this._onStreamKeyPick.bind(this);
this._onUserChanged = this._onUserChanged.bind(this); this._onUserChanged = this._onUserChanged.bind(this);
this._renderDialogContent = this._renderDialogContent.bind(this);
} }
/**
* Implements {@code Component}'s render.
*
* @inheritdoc
*/
render() {
return (
<CustomSubmitDialog
okTitleKey = 'dialog.startLiveStreaming'
onCancel = { this._onCancel }
onSubmit = { this._onSubmit } >
<View style = { styles.startDialogWrapper }>
<GoogleSigninForm
onUserChanged = { this._onUserChanged } />
<StreamKeyPicker
broadcasts = { this.state.broadcasts }
onChange = { this._onStreamKeyPick } />
<StreamKeyForm
onChange = { this._onStreamKeyChangeNative }
value = {
this.state.streamKey || this.props._streamKey
} />
</View>
</CustomSubmitDialog>
);
}
_onCancel: () => boolean;
_onSubmit: () => boolean;
_onStreamKeyChange: string => void _onStreamKeyChange: string => void
_onStreamKeyChangeNative: string => void; _onStreamKeyChangeNative: string => void;
@ -102,29 +133,6 @@ class StartLiveStreamDialog extends AbstractStartLiveStreamDialog<Props> {
}); });
} }
} }
_renderDialogContent: () => React$Component<*>
/**
* Renders the platform specific dialog content.
*
* @returns {React$Component}
*/
_renderDialogContent() {
return (
<View style = { styles.startDialogWrapper }>
<GoogleSigninForm
onUserChanged = { this._onUserChanged } />
<StreamKeyPicker
broadcasts = { this.state.broadcasts }
onChange = { this._onStreamKeyPick } />
<StreamKeyForm
onChange = { this._onStreamKeyChangeNative }
value = { this.state.streamKey || this.props._streamKey } />
</View>
);
}
} }
export default translate(connect(_mapStateToProps)(StartLiveStreamDialog)); export default translate(connect(_mapStateToProps)(StartLiveStreamDialog));

View File

@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { DialogContent } from '../../../../base/dialog'; import { ConfirmDialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import AbstractStopLiveStreamDialog, { import AbstractStopLiveStreamDialog, {
@ -19,19 +19,20 @@ import AbstractStopLiveStreamDialog, {
class StopLiveStreamDialog extends AbstractStopLiveStreamDialog { class StopLiveStreamDialog extends AbstractStopLiveStreamDialog {
/** /**
* Renders the platform specific {@code Dialog} content. * Implements React's {@link Component#render()}.
* *
* @inheritdoc * @inheritdoc
* @returns {ReactElement}
*/ */
_renderDialogContent() { render() {
return ( return (
<DialogContent> <ConfirmDialog
{ contentKey = 'dialog.stopStreamingWarning'
this.props.t('dialog.stopStreamingWarning') onSubmit = { this._onSubmit } />
}
</DialogContent>
); );
} }
_onSubmit: () => boolean
} }
export default translate(connect(_mapStateToProps)(StopLiveStreamDialog)); export default translate(connect(_mapStateToProps)(StopLiveStreamDialog));

View File

@ -9,7 +9,7 @@ import AbstractStreamKeyForm, {
type Props type Props
} from '../AbstractStreamKeyForm'; } from '../AbstractStreamKeyForm';
import styles from './styles'; import styles, { PLACEHOLDER_COLOR } from './styles';
/** /**
* A React Component for entering a key for starting a YouTube live stream. * A React Component for entering a key for starting a YouTube live stream.
@ -49,12 +49,13 @@ class StreamKeyForm extends AbstractStreamKeyForm {
<TextInput <TextInput
onChangeText = { this._onInputChange } onChangeText = { this._onInputChange }
placeholder = { t('liveStreaming.enterStreamKey') } placeholder = { t('liveStreaming.enterStreamKey') }
placeholderTextColor = { PLACEHOLDER_COLOR }
style = { styles.streamKeyInput } style = { styles.streamKeyInput }
value = { this.props.value } /> value = { this.props.value } />
<TouchableOpacity <TouchableOpacity
onPress = { this._onOpenHelp } onPress = { this._onOpenHelp }
style = { styles.streamKeyHelp } > style = { styles.streamKeyHelp } >
<Text> <Text style = { styles.text }>
{ {
t('liveStreaming.streamIdHelp') t('liveStreaming.streamIdHelp')
} }

View File

@ -74,7 +74,7 @@ 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> <Text style = { styles.text }>
{ this.props.t('liveStreaming.choose') } { this.props.t('liveStreaming.choose') }
</Text> </Text>
</View> </View>
@ -90,7 +90,7 @@ class StreamKeyPicker extends Component<Props, State> {
? styles.streamKeyPickerItemHighlight : null ? styles.streamKeyPickerItemHighlight : null
] } ] }
underlayColor = { TOUCHABLE_UNDERLAY }> underlayColor = { TOUCHABLE_UNDERLAY }>
<Text style = { styles.streamKeyPickerItemText }> <Text style = { styles.text }>
{ broadcast.title } { broadcast.title }
</Text> </Text>
</TouchableHighlight>)) </TouchableHighlight>))

View File

@ -11,6 +11,11 @@ import {
*/ */
export const ACTIVE_OPACITY = 0.3; export const ACTIVE_OPACITY = 0.3;
/**
* Color for the key input field placeholder.
*/
export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
/** /**
* Underlay of the TouchableHighlight. * Underlay of the TouchableHighlight.
*/ */
@ -69,14 +74,19 @@ export default createStyleSheet({
*/ */
streamKeyInput: { streamKeyInput: {
alignSelf: 'stretch', alignSelf: 'stretch',
height: 50 borderColor: ColorPalette.lightGrey,
borderBottomWidth: 1,
color: ColorPalette.white,
height: 40,
marginBottom: 5
}, },
/** /**
* Label for the previous field. * Label for the previous field.
*/ */
streamKeyInputLabel: { streamKeyInputLabel: {
alignSelf: 'flex-start' alignSelf: 'flex-start',
color: ColorPalette.white
}, },
/** /**
@ -108,7 +118,7 @@ export default createStyleSheet({
* Additional style for the selected item. * Additional style for the selected item.
*/ */
streamKeyPickerItemHighlight: { streamKeyPickerItemHighlight: {
backgroundColor: ColorPalette.lighterGrey backgroundColor: ColorPalette.darkGrey
}, },
/** /**
@ -119,6 +129,10 @@ export default createStyleSheet({
borderRadius: 3, borderRadius: 3,
borderWidth: 1, borderWidth: 1,
flexDirection: 'column' flexDirection: 'column'
},
text: {
color: ColorPalette.white
} }
}); });

View File

@ -4,6 +4,7 @@ import Spinner from '@atlaskit/spinner';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Dialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { import {
@ -59,8 +60,6 @@ class StartLiveStreamDialog
this._onRequestGoogleSignIn = this._onRequestGoogleSignIn.bind(this); this._onRequestGoogleSignIn = this._onRequestGoogleSignIn.bind(this);
this._onYouTubeBroadcastIDSelected this._onYouTubeBroadcastIDSelected
= this._onYouTubeBroadcastIDSelected.bind(this); = this._onYouTubeBroadcastIDSelected.bind(this);
this._renderDialogContent = this._renderDialogContent.bind(this);
} }
/** /**
@ -78,6 +77,39 @@ class StartLiveStreamDialog
} }
} }
/**
* Implements {@code Component}'s render.
*
* @inheritdoc
*/
render() {
const { _googleApiApplicationClientID } = this.props;
return (
<Dialog
cancelTitleKey = 'dialog.Cancel'
okTitleKey = 'dialog.startLiveStreaming'
onCancel = { this._onCancel }
onSubmit = { this._onSubmit }
titleKey = 'liveStreaming.start'
width = { 'small' }>
<div className = 'live-stream-dialog'>
{ _googleApiApplicationClientID
? this._renderYouTubePanel() : null }
<StreamKeyForm
onChange = { this._onStreamKeyChange }
value = {
this.state.streamKey || this.props._streamKey
} />
</div>
</Dialog>
);
}
_onCancel: () => boolean;
_onSubmit: () => boolean;
_onInitializeGoogleApi: () => Promise<*>; _onInitializeGoogleApi: () => Promise<*>;
/** /**
@ -221,27 +253,6 @@ class StartLiveStreamDialog
}); });
} }
_renderDialogContent: () => React$Component<*>
/**
* Renders the platform specific dialog content.
*
* @returns {React$Component}
*/
_renderDialogContent() {
const { _googleApiApplicationClientID } = this.props;
return (
<div className = 'live-stream-dialog'>
{ _googleApiApplicationClientID
? this._renderYouTubePanel() : null }
<StreamKeyForm
onChange = { this._onStreamKeyChange }
value = { this.state.streamKey || this.props._streamKey } />
</div>
);
}
/** /**
* Renders a React Element for authenticating with the Google web client. * Renders a React Element for authenticating with the Google web client.
* *

View File

@ -1,7 +1,9 @@
// @flow // @flow
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Dialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import AbstractStopLiveStreamDialog, { import AbstractStopLiveStreamDialog, {
@ -17,13 +19,24 @@ import AbstractStopLiveStreamDialog, {
class StopLiveStreamDialog extends AbstractStopLiveStreamDialog { class StopLiveStreamDialog extends AbstractStopLiveStreamDialog {
/** /**
* Renders the platform specific {@code Dialog} content. * Implements React's {@link Component#render()}.
* *
* @inheritdoc * @inheritdoc
* @returns {ReactElement}
*/ */
_renderDialogContent() { render() {
return this.props.t('dialog.stopStreamingWarning'); return (
<Dialog
okTitleKey = 'dialog.stopLiveStreaming'
onSubmit = { this._onSubmit }
titleKey = 'dialog.liveStreaming'
width = 'small'>
{ this.props.t('dialog.stopStreamingWarning') }
</Dialog>
);
} }
_onSubmit: () => boolean;
} }
export default translate(connect(_mapStateToProps)(StopLiveStreamDialog)); export default translate(connect(_mapStateToProps)(StopLiveStreamDialog));

View File

@ -18,8 +18,7 @@ import {
import { getActiveSession } from '../../functions'; import { getActiveSession } from '../../functions';
import StartRecordingDialog from './StartRecordingDialog'; import { StartRecordingDialog, StopRecordingDialog } from './_';
import { StopRecordingDialog } from './_';
/** /**
* The type of the React {@code Component} props of * The type of the React {@code Component} props of

View File

@ -1,21 +1,17 @@
// @flow // @flow
import React, { Component } from 'react'; import { Component } from 'react';
import { connect } from 'react-redux';
import { import {
createRecordingDialogEvent, createRecordingDialogEvent,
sendAnalytics sendAnalytics
} from '../../../analytics'; } from '../../../analytics';
import { Dialog } from '../../../base/dialog';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { import {
getDropboxData, getDropboxData,
isEnabled as isDropboxEnabled isEnabled as isDropboxEnabled
} from '../../../dropbox'; } from '../../../dropbox';
import StartRecordingDialogContent from './StartRecordingDialogContent';
type Props = { type Props = {
/** /**
@ -75,7 +71,7 @@ type State = {
/** /**
* Component for the recording start dialog. * Component for the recording start dialog.
*/ */
class StartRecordingDialog extends Component<Props, State> { class AbstractStartRecordingDialog extends Component<Props, State> {
/** /**
* Initializes a new {@code StartRecordingDialog} instance. * Initializes a new {@code StartRecordingDialog} instance.
* *
@ -93,6 +89,8 @@ class StartRecordingDialog extends Component<Props, State> {
userName: undefined, userName: undefined,
spaceLeft: undefined spaceLeft: undefined
}; };
this._onSubmit = this._onSubmit.bind(this);
} }
/** /**
@ -113,7 +111,7 @@ class StartRecordingDialog extends Component<Props, State> {
* @inheritdoc * @inheritdoc
* @returns {void} * @returns {void}
*/ */
componentDidUpdate(prevProps) { componentDidUpdate(prevProps: Props) {
if (this.props._token !== prevProps._token) { if (this.props._token !== prevProps._token) {
this._onTokenUpdated(); this._onTokenUpdated();
} }
@ -158,33 +156,6 @@ class StartRecordingDialog extends Component<Props, State> {
} }
} }
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { isTokenValid, isValidating, spaceLeft, userName } = this.state;
const { _isDropboxEnabled } = this.props;
return (
<Dialog
okDisabled = { !isTokenValid && _isDropboxEnabled }
okTitleKey = 'dialog.confirm'
onSubmit = { this._onSubmit }
titleKey = 'dialog.recording'
width = 'small'>
<StartRecordingDialogContent
integrationsEnabled = { _isDropboxEnabled }
isTokenValid = { isTokenValid }
isValidating = { isValidating }
spaceLeft = { spaceLeft }
userName = { userName } />
</Dialog>
);
}
_onSubmit: () => boolean; _onSubmit: () => boolean;
/** /**
@ -240,7 +211,7 @@ class StartRecordingDialog extends Component<Props, State> {
* _token: string * _token: string
* }} * }}
*/ */
function mapStateToProps(state: Object) { export function mapStateToProps(state: Object) {
const { dropbox = {} } = state['features/base/config']; const { dropbox = {} } = state['features/base/config'];
return { return {
@ -251,4 +222,4 @@ function mapStateToProps(state: Object) {
}; };
} }
export default connect(mapStateToProps)(StartRecordingDialog); export default AbstractStartRecordingDialog;

View File

@ -1,12 +1,11 @@
// @flow // @flow
import React, { Component } from 'react'; import { Component } from 'react';
import { import {
createRecordingDialogEvent, createRecordingDialogEvent,
sendAnalytics sendAnalytics
} from '../../../analytics'; } from '../../../analytics';
import { Dialog } from '../../../base/dialog';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { getActiveSession } from '../../functions'; import { getActiveSession } from '../../functions';
@ -53,24 +52,6 @@ export default class AbstractStopRecordingDialog<P: Props>
this._onSubmit = this._onSubmit.bind(this); this._onSubmit = this._onSubmit.bind(this);
} }
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<Dialog
okTitleKey = 'dialog.confirm'
onSubmit = { this._onSubmit }
titleKey = 'dialog.recording'
width = 'small'>
{ this._renderDialogContent() }
</Dialog>
);
}
_onSubmit: () => boolean; _onSubmit: () => boolean;
/** /**
@ -90,14 +71,6 @@ export default class AbstractStopRecordingDialog<P: Props>
return true; return true;
} }
/**
* Renders the platform specific dialog content.
*
* @protected
* @returns {React$Component}
*/
_renderDialogContent: () => React$Component<*>
} }
/** /**

View File

@ -85,7 +85,7 @@ class StartRecordingDialogContent extends Component<Props> {
* @returns {React$Component} * @returns {React$Component}
*/ */
render() { render() {
if (this.props.integrationsEnabled) { if (this.props.integrationsEnabled === true) { // explicit true needed
return this._renderIntegrationsContent(); return this._renderIntegrationsContent();
} }
@ -99,7 +99,7 @@ class StartRecordingDialogContent extends Component<Props> {
*/ */
_renderNoIntegrationsContent() { _renderNoIntegrationsContent() {
return ( return (
<DialogContent> <DialogContent style = { styles.noIntegrationContent }>
{ this.props.t('recording.startRecordingBody') } { this.props.t('recording.startRecordingBody') }
</DialogContent> </DialogContent>
); );
@ -195,12 +195,12 @@ class StartRecordingDialogContent extends Component<Props> {
className = 'logged-in-panel' className = 'logged-in-panel'
style = { styles.loggedIn }> style = { styles.loggedIn }>
<Container> <Container>
<Text> <Text style = { styles.text }>
{ t('recording.loggedIn', { userName }) } { t('recording.loggedIn', { userName }) }
</Text> </Text>
</Container> </Container>
<Container> <Container>
<Text> <Text style = { styles.text }>
{ {
t('recording.availableSpace', { t('recording.availableSpace', {
spaceLeft, spaceLeft,
@ -211,7 +211,9 @@ class StartRecordingDialogContent extends Component<Props> {
</Container> </Container>
</Container> </Container>
<Container style = { styles.startRecordingText }> <Container style = { styles.startRecordingText }>
<Text>{ t('recording.startRecordingBody') }</Text> <Text style = { styles.text }>
{ t('recording.startRecordingBody') }
</Text>
</Container> </Container>
</Container> </Container>
); );

View File

@ -0,0 +1,54 @@
// @flow
import React from 'react';
import { connect } from 'react-redux';
import { translate } from '../../../../base/i18n';
import { ConfirmDialog, CustomSubmitDialog } from '../../../../base/dialog';
import AbstractStartRecordingDialog, {
mapStateToProps
} from '../AbstractStartRecordingDialog';
import StartRecordingDialogContent from '../StartRecordingDialogContent';
/**
* React Component for getting confirmation to start a file recording session in
* progress.
*
* @extends Component
*/
class StartRecordingDialog extends AbstractStartRecordingDialog {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
*/
render() {
const { isTokenValid, isValidating, spaceLeft, userName } = this.state;
const { _isDropboxEnabled } = this.props;
if (!_isDropboxEnabled) {
return (
<ConfirmDialog
contentKey = 'recording.startRecordingBody'
onSubmit = { this._onSubmit } />
);
}
return (
<CustomSubmitDialog
okDisabled = { !isTokenValid }
onSubmit = { this._onSubmit } >
<StartRecordingDialogContent
isTokenValid = { isTokenValid }
isValidating = { isValidating }
spaceLeft = { spaceLeft }
userName = { userName } />
</CustomSubmitDialog>
);
}
_onSubmit: () => boolean
}
export default translate(connect(mapStateToProps)(StartRecordingDialog));

View File

@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { DialogContent } from '../../../../base/dialog'; import { ConfirmDialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import AbstractStopRecordingDialog, { import AbstractStopRecordingDialog, {
@ -20,19 +20,19 @@ import AbstractStopRecordingDialog, {
class StopRecordingDialog extends AbstractStopRecordingDialog<Props> { class StopRecordingDialog extends AbstractStopRecordingDialog<Props> {
/** /**
* Renders the platform specific dialog content. * Implements {@code Component#render}.
* *
* @inheritdoc * @inheritdoc
*/ */
_renderDialogContent() { render() {
const { t } = this.props;
return ( return (
<DialogContent> <ConfirmDialog
{ t('dialog.stopRecordingWarning') } contentKey = 'dialog.stopRecordingWarning'
</DialogContent> onSubmit = { this._onSubmit } />
); );
} }
_onSubmit: () => boolean
} }
export default translate(connect(_mapStateToProps)(StopRecordingDialog)); export default translate(connect(_mapStateToProps)(StopRecordingDialog));

View File

@ -1,4 +1,5 @@
// @flow // @flow
export { default as RecordButton } from './RecordButton'; export { default as RecordButton } from './RecordButton';
export { default as StartRecordingDialog } from './StartRecordingDialog';
export { default as StopRecordingDialog } from './StopRecordingDialog'; export { default as StopRecordingDialog } from './StopRecordingDialog';

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { BoxModel, createStyleSheet } from '../../../base/styles'; import { BoxModel, createStyleSheet, ColorPalette } from '../../../base/styles';
// XXX The "standard" {@code BoxModel.padding} has been deemed insufficient in // XXX The "standard" {@code BoxModel.padding} has been deemed insufficient in
// the special case(s) of the recording feature bellow. // the special case(s) of the recording feature bellow.
@ -28,16 +28,26 @@ export default createStyleSheet({
paddingBottom: _PADDING paddingBottom: _PADDING
}, },
noIntegrationContent: {
color: ColorPalette.white
},
startRecordingText: { startRecordingText: {
paddingBottom: _PADDING paddingBottom: _PADDING
}, },
switch: { switch: {
color: ColorPalette.white,
paddingRight: BoxModel.padding paddingRight: BoxModel.padding
}, },
title: { title: {
color: ColorPalette.white,
fontSize: 16, fontSize: 16,
fontWeight: 'bold' fontWeight: 'bold'
},
text: {
color: ColorPalette.white
} }
}); });

View File

@ -0,0 +1,50 @@
// @flow
import React from 'react';
import { connect } from 'react-redux';
import { translate } from '../../../../base/i18n';
import { Dialog } from '../../../../base/dialog';
import AbstractStartRecordingDialog, {
mapStateToProps
} from '../AbstractStartRecordingDialog';
import StartRecordingDialogContent from '../StartRecordingDialogContent';
/**
* React Component for getting confirmation to start a file recording session in
* progress.
*
* @extends Component
*/
class StartRecordingDialog extends AbstractStartRecordingDialog {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
*/
render() {
const { isTokenValid, isValidating, spaceLeft, userName } = this.state;
const { _isDropboxEnabled } = this.props;
return (
<Dialog
okDisabled = { !isTokenValid && _isDropboxEnabled }
okTitleKey = 'dialog.confirm'
onSubmit = { this._onSubmit }
titleKey = 'dialog.recording'
width = 'small'>
<StartRecordingDialogContent
integrationsEnabled = { _isDropboxEnabled }
isTokenValid = { isTokenValid }
isValidating = { isValidating }
spaceLeft = { spaceLeft }
userName = { userName } />
</Dialog>
);
}
_onSubmit: () => boolean
}
export default translate(connect(mapStateToProps)(StartRecordingDialog));

View File

@ -1,8 +1,10 @@
// @flow // @flow
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { Dialog } from '../../../../base/dialog';
import AbstractStopRecordingDialog, { import AbstractStopRecordingDialog, {
type Props, type Props,
@ -16,20 +18,27 @@ import AbstractStopRecordingDialog, {
* @extends Component * @extends Component
*/ */
class StopRecordingDialog extends AbstractStopRecordingDialog<Props> { class StopRecordingDialog extends AbstractStopRecordingDialog<Props> {
/** /**
* Renders the platform specific dialog content. * Implements React's {@link Component#render()}.
* *
* @protected * @inheritdoc
* @returns {React$Component} * @returns {ReactElement}
*/ */
_renderDialogContent() { render() {
const { t } = this.props; const { t } = this.props;
return ( return (
t('dialog.stopRecordingWarning') <Dialog
okTitleKey = 'dialog.confirm'
onSubmit = { this._onSubmit }
titleKey = 'dialog.recording'
width = 'small'>
{ t('dialog.stopRecordingWarning') }
</Dialog>
); );
} }
_onSubmit: () => boolean
} }
export default translate(connect(_mapStateToProps)(StopRecordingDialog)); export default translate(connect(_mapStateToProps)(StopRecordingDialog));

View File

@ -1,4 +1,5 @@
// @flow // @flow
export { default as RecordButton } from './RecordButton'; export { default as RecordButton } from './RecordButton';
export { default as StartRecordingDialog } from './StartRecordingDialog';
export { default as StopRecordingDialog } from './StopRecordingDialog'; export { default as StopRecordingDialog } from './StopRecordingDialog';