feat(recording): StartRecordingDialogContent web and native (#12009)
* feat(recording): StartRecordingDialogContent web and native
This commit is contained in:
parent
f07bd4a0d6
commit
e458eed931
|
@ -7,7 +7,7 @@ export interface ButtonProps {
|
||||||
/**
|
/**
|
||||||
* Label used for accessibility.
|
* Label used for accessibility.
|
||||||
*/
|
*/
|
||||||
accessibilityLabel: string;
|
accessibilityLabel?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the button is disabled.
|
* Whether or not the button is disabled.
|
||||||
|
|
|
@ -0,0 +1,360 @@
|
||||||
|
/* eslint-disable lines-around-comment */
|
||||||
|
import { Component } from 'react';
|
||||||
|
// @ts-ignore
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createRecordingDialogEvent,
|
||||||
|
sendAnalytics
|
||||||
|
// @ts-ignore
|
||||||
|
} from '../../../analytics';
|
||||||
|
// @ts-ignore
|
||||||
|
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
||||||
|
// @ts-ignore
|
||||||
|
import {
|
||||||
|
_abstractMapStateToProps
|
||||||
|
// @ts-ignore
|
||||||
|
} from '../../../base/dialog';
|
||||||
|
// @ts-ignore
|
||||||
|
import { StyleType } from '../../../base/styles';
|
||||||
|
// @ts-ignore
|
||||||
|
import { authorizeDropbox, updateDropboxToken } from '../../../dropbox';
|
||||||
|
// @ts-ignore
|
||||||
|
import { isVpaasMeeting } from '../../../jaas/functions';
|
||||||
|
// @ts-ignore
|
||||||
|
import { RECORDING_TYPES } from '../../constants';
|
||||||
|
// @ts-ignore
|
||||||
|
import { supportsLocalRecording } from '../../functions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the React {@code Component} props of
|
||||||
|
* {@link AbstractStartRecordingDialogContent}.
|
||||||
|
*/
|
||||||
|
export interface Props extends WithTranslation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style of the dialogs feature.
|
||||||
|
*/
|
||||||
|
_dialogStyles: StyleType,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to hide the storage warning or not.
|
||||||
|
*/
|
||||||
|
_hideStorageWarning: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether local recording is available or not.
|
||||||
|
*/
|
||||||
|
_localRecordingAvailable: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether local recording is enabled or not.
|
||||||
|
*/
|
||||||
|
_localRecordingEnabled: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we won't notify the other participants about the recording.
|
||||||
|
*/
|
||||||
|
_localRecordingNoNotification: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether self local recording is enabled or not.
|
||||||
|
*/
|
||||||
|
_localRecordingSelfEnabled: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color-schemed stylesheet of this component.
|
||||||
|
*/
|
||||||
|
_styles: StyleType,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The redux dispatch function.
|
||||||
|
*/
|
||||||
|
dispatch: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show file recordings service, even if integrations
|
||||||
|
* are enabled.
|
||||||
|
*/
|
||||||
|
fileRecordingsServiceEnabled: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show the possibility to share file recording with other people (e.g. Meeting participants), based on
|
||||||
|
* the actual implementation on the backend.
|
||||||
|
*/
|
||||||
|
fileRecordingsServiceSharingEnabled: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true the content related to the integrations will be shown.
|
||||||
|
*/
|
||||||
|
integrationsEnabled: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <tt>true</tt> if we have valid oauth token.
|
||||||
|
*/
|
||||||
|
isTokenValid: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <tt>true</tt> if we are in process of validating the oauth token.
|
||||||
|
*/
|
||||||
|
isValidating: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the current meeting is a vpaas one.
|
||||||
|
*/
|
||||||
|
isVpaas: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not we should only record the local streams.
|
||||||
|
*/
|
||||||
|
localRecordingOnlySelf: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function will be called when there are changes related to the
|
||||||
|
* switches.
|
||||||
|
*/
|
||||||
|
onChange: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to change the local recording only self setting.
|
||||||
|
*/
|
||||||
|
onLocalRecordingSelfChange: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to be invoked on sharing setting change.
|
||||||
|
*/
|
||||||
|
onSharingSettingChanged: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently selected recording service of type: RECORDING_TYPES.
|
||||||
|
*/
|
||||||
|
selectedRecordingService: string | null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean to set file recording sharing on or off.
|
||||||
|
*/
|
||||||
|
sharingSetting: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of MiB of available space in user's Dropbox account.
|
||||||
|
*/
|
||||||
|
spaceLeft: number | null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display name of the user's Dropbox account.
|
||||||
|
*/
|
||||||
|
userName: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React Component for getting confirmation to start a file recording session.
|
||||||
|
*
|
||||||
|
* @augments Component
|
||||||
|
*/
|
||||||
|
class AbstractStartRecordingDialogContent<P extends Props> extends Component<P> {
|
||||||
|
/**
|
||||||
|
* Initializes a new {@code AbstractStartRecordingDialogContent} instance.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
constructor(props: P) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
// Bind event handler; it bounds once for every instance.
|
||||||
|
this._onSignIn = this._onSignIn.bind(this);
|
||||||
|
this._onSignOut = this._onSignOut.bind(this);
|
||||||
|
this._onDropboxSwitchChange = this._onDropboxSwitchChange.bind(this);
|
||||||
|
this._onRecordingServiceSwitchChange = this._onRecordingServiceSwitchChange.bind(this);
|
||||||
|
this._onLocalRecordingSwitchChange = this._onLocalRecordingSwitchChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the Component's componentDidMount method.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
componentDidMount() {
|
||||||
|
if (!this._shouldRenderNoIntegrationsContent()
|
||||||
|
&& !this._shouldRenderIntegrationsContent()
|
||||||
|
&& !this._shouldRenderFileSharingContent()) {
|
||||||
|
this._onLocalRecordingSwitchChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements {@code Component#componentDidUpdate}.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
componentDidUpdate(prevProps: P) {
|
||||||
|
// Auto sign-out when the use chooses another recording service.
|
||||||
|
if (prevProps.selectedRecordingService === RECORDING_TYPES.DROPBOX
|
||||||
|
&& this.props.selectedRecordingService !== RECORDING_TYPES.DROPBOX && this.props.isTokenValid) {
|
||||||
|
this._onSignOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the file sharing content should be rendered or not.
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_shouldRenderFileSharingContent() {
|
||||||
|
const {
|
||||||
|
fileRecordingsServiceEnabled,
|
||||||
|
fileRecordingsServiceSharingEnabled,
|
||||||
|
isVpaas,
|
||||||
|
selectedRecordingService
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!fileRecordingsServiceEnabled
|
||||||
|
|| !fileRecordingsServiceSharingEnabled
|
||||||
|
|| isVpaas
|
||||||
|
|| selectedRecordingService !== RECORDING_TYPES.JITSI_REC_SERVICE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the no integrations content should be rendered or not.
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_shouldRenderNoIntegrationsContent() {
|
||||||
|
// show the non integrations part only if fileRecordingsServiceEnabled
|
||||||
|
// is enabled
|
||||||
|
if (!this.props.fileRecordingsServiceEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the integrations content should be rendered or not.
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_shouldRenderIntegrationsContent() {
|
||||||
|
if (!this.props.integrationsEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for onValueChange events from the Switch component.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onRecordingServiceSwitchChange() {
|
||||||
|
const {
|
||||||
|
onChange,
|
||||||
|
selectedRecordingService
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
// act like group, cannot toggle off
|
||||||
|
if (selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(RECORDING_TYPES.JITSI_REC_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for onValueChange events from the Switch component.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onDropboxSwitchChange() {
|
||||||
|
const {
|
||||||
|
isTokenValid,
|
||||||
|
onChange,
|
||||||
|
selectedRecordingService
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
// act like group, cannot toggle off
|
||||||
|
if (selectedRecordingService === RECORDING_TYPES.DROPBOX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(RECORDING_TYPES.DROPBOX);
|
||||||
|
|
||||||
|
if (!isTokenValid) {
|
||||||
|
this._onSignIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for onValueChange events from the Switch component.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onLocalRecordingSwitchChange() {
|
||||||
|
const {
|
||||||
|
_localRecordingAvailable,
|
||||||
|
onChange,
|
||||||
|
selectedRecordingService
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!_localRecordingAvailable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// act like group, cannot toggle off
|
||||||
|
if (selectedRecordingService
|
||||||
|
=== RECORDING_TYPES.LOCAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(RECORDING_TYPES.LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sings in a user.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onSignIn() {
|
||||||
|
sendAnalytics(createRecordingDialogEvent('start', 'signIn.button'));
|
||||||
|
this.props.dispatch(authorizeDropbox());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sings out an user from dropbox.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onSignOut() {
|
||||||
|
sendAnalytics(createRecordingDialogEvent('start', 'signOut.button'));
|
||||||
|
this.props.dispatch(updateDropboxToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps part of the redux state to the props of this component.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @returns {Props}
|
||||||
|
*/
|
||||||
|
export function mapStateToProps(state: any) {
|
||||||
|
const { localRecording, recordingService } = state['features/base/config'];
|
||||||
|
const _localRecordingAvailable
|
||||||
|
= !localRecording?.disable && supportsLocalRecording();
|
||||||
|
|
||||||
|
return {
|
||||||
|
..._abstractMapStateToProps(state),
|
||||||
|
isVpaas: isVpaasMeeting(state),
|
||||||
|
_hideStorageWarning: recordingService?.hideStorageWarning,
|
||||||
|
_localRecordingAvailable,
|
||||||
|
_localRecordingEnabled: !localRecording?.disable,
|
||||||
|
_localRecordingSelfEnabled: !localRecording?.disableSelfRecording,
|
||||||
|
_localRecordingNoNotification: !localRecording?.notifyAllParticipants,
|
||||||
|
_styles: ColorSchemeRegistry.get(state, 'StartRecordingDialogContent')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AbstractStartRecordingDialogContent;
|
|
@ -1,781 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
createRecordingDialogEvent,
|
|
||||||
sendAnalytics
|
|
||||||
} from '../../../analytics';
|
|
||||||
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
|
||||||
import {
|
|
||||||
_abstractMapStateToProps
|
|
||||||
} from '../../../base/dialog';
|
|
||||||
import { translate } from '../../../base/i18n';
|
|
||||||
import {
|
|
||||||
Container,
|
|
||||||
Image,
|
|
||||||
LoadingIndicator,
|
|
||||||
Switch,
|
|
||||||
Text
|
|
||||||
} from '../../../base/react';
|
|
||||||
import { connect } from '../../../base/redux';
|
|
||||||
import { StyleType } from '../../../base/styles';
|
|
||||||
import { Button } from '../../../base/ui';
|
|
||||||
import { BUTTON_TYPES } from '../../../base/ui/constants';
|
|
||||||
import { authorizeDropbox, updateDropboxToken } from '../../../dropbox';
|
|
||||||
import { isVpaasMeeting } from '../../../jaas/functions';
|
|
||||||
import { RECORDING_TYPES } from '../../constants';
|
|
||||||
import { getRecordingDurationEstimation, supportsLocalRecording } from '../../functions';
|
|
||||||
|
|
||||||
import {
|
|
||||||
DROPBOX_LOGO,
|
|
||||||
ICON_CLOUD,
|
|
||||||
ICON_INFO,
|
|
||||||
ICON_USERS,
|
|
||||||
LOCAL_RECORDING,
|
|
||||||
TRACK_COLOR
|
|
||||||
} from './styles';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Style of the dialogs feature.
|
|
||||||
*/
|
|
||||||
_dialogStyles: StyleType,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to hide the storage warning or not.
|
|
||||||
*/
|
|
||||||
_hideStorageWarning: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether local recording is enabled or not.
|
|
||||||
*/
|
|
||||||
_localRecordingEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether we won't notify the other participants about the recording.
|
|
||||||
*/
|
|
||||||
_localRecordingNoNotification: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether self local recording is enabled or not.
|
|
||||||
*/
|
|
||||||
_localRecordingSelfEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The color-schemed stylesheet of this component.
|
|
||||||
*/
|
|
||||||
_styles: StyleType,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The redux dispatch function.
|
|
||||||
*/
|
|
||||||
dispatch: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to show file recordings service, even if integrations
|
|
||||||
* are enabled.
|
|
||||||
*/
|
|
||||||
fileRecordingsServiceEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to show the possibility to share file recording with other people (e.g. Meeting participants), based on
|
|
||||||
* the actual implementation on the backend.
|
|
||||||
*/
|
|
||||||
fileRecordingsServiceSharingEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true the content related to the integrations will be shown.
|
|
||||||
*/
|
|
||||||
integrationsEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <tt>true</tt> if we have valid oauth token.
|
|
||||||
*/
|
|
||||||
isTokenValid: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <tt>true</tt> if we are in process of validating the oauth token.
|
|
||||||
*/
|
|
||||||
isValidating: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the current meeting is a vpaas one.
|
|
||||||
*/
|
|
||||||
isVpaas: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not we should only record the local streams.
|
|
||||||
*/
|
|
||||||
localRecordingOnlySelf: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function will be called when there are changes related to the
|
|
||||||
* switches.
|
|
||||||
*/
|
|
||||||
onChange: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to change the local recording only self setting.
|
|
||||||
*/
|
|
||||||
onLocalRecordingSelfChange: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to be invoked on sharing setting change.
|
|
||||||
*/
|
|
||||||
onSharingSettingChanged: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The currently selected recording service of type: RECORDING_TYPES.
|
|
||||||
*/
|
|
||||||
selectedRecordingService: ?string,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Boolean to set file recording sharing on or off.
|
|
||||||
*/
|
|
||||||
sharingSetting: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of MiB of available space in user's Dropbox account.
|
|
||||||
*/
|
|
||||||
spaceLeft: ?number,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The translate function.
|
|
||||||
*/
|
|
||||||
t: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The display name of the user's Dropbox account.
|
|
||||||
*/
|
|
||||||
userName: ?string
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* React Component for getting confirmation to start a file recording session.
|
|
||||||
*
|
|
||||||
* @augments Component
|
|
||||||
*/
|
|
||||||
class StartRecordingDialogContent extends Component<Props> {
|
|
||||||
_localRecordingAvailable: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a new {@code StartRecordingDialogContent} instance.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this._localRecordingAvailable = props._localRecordingEnabled && supportsLocalRecording();
|
|
||||||
|
|
||||||
// Bind event handler so it is only bound once for every instance.
|
|
||||||
this._onSignIn = this._onSignIn.bind(this);
|
|
||||||
this._onSignOut = this._onSignOut.bind(this);
|
|
||||||
this._onDropboxSwitchChange = this._onDropboxSwitchChange.bind(this);
|
|
||||||
this._onRecordingServiceSwitchChange = this._onRecordingServiceSwitchChange.bind(this);
|
|
||||||
this._onLocalRecordingSwitchChange = this._onLocalRecordingSwitchChange.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the Component's componentDidMount method.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
componentDidMount() {
|
|
||||||
if (!this._shouldRenderNoIntegrationsContent()
|
|
||||||
&& !this._shouldRenderIntegrationsContent()
|
|
||||||
&& !this._shouldRenderFileSharingContent()) {
|
|
||||||
this._onLocalRecordingSwitchChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements {@code Component#componentDidUpdate}.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
// Auto sign-out when the use chooses another recording service.
|
|
||||||
if (prevProps.selectedRecordingService === RECORDING_TYPES.DROPBOX
|
|
||||||
&& this.props.selectedRecordingService !== RECORDING_TYPES.DROPBOX && this.props.isTokenValid) {
|
|
||||||
this._onSignOut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the component.
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
render() {
|
|
||||||
const { _styles: styles } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container
|
|
||||||
className = 'recording-dialog'
|
|
||||||
style = { styles.container }>
|
|
||||||
{ this._renderNoIntegrationsContent() }
|
|
||||||
{ this._renderFileSharingContent() }
|
|
||||||
{ this._renderUploadToTheCloudInfo() }
|
|
||||||
{ this._renderIntegrationsContent() }
|
|
||||||
{ this._renderLocalRecordingContent() }
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the file sharing content should be rendered or not.
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
_shouldRenderFileSharingContent() {
|
|
||||||
const {
|
|
||||||
fileRecordingsServiceEnabled,
|
|
||||||
fileRecordingsServiceSharingEnabled,
|
|
||||||
isVpaas,
|
|
||||||
selectedRecordingService
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (!fileRecordingsServiceEnabled
|
|
||||||
|| !fileRecordingsServiceSharingEnabled
|
|
||||||
|| isVpaas
|
|
||||||
|| selectedRecordingService !== RECORDING_TYPES.JITSI_REC_SERVICE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the file recording service sharing options, if enabled.
|
|
||||||
*
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderFileSharingContent() {
|
|
||||||
if (!this._shouldRenderFileSharingContent()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
_dialogStyles,
|
|
||||||
_styles: styles,
|
|
||||||
isValidating,
|
|
||||||
onSharingSettingChanged,
|
|
||||||
sharingSetting,
|
|
||||||
t
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container
|
|
||||||
className = 'recording-header'
|
|
||||||
key = 'fileSharingSetting'
|
|
||||||
style = { styles.header }>
|
|
||||||
<Container className = 'recording-icon-container file-sharing-icon-container'>
|
|
||||||
<Image
|
|
||||||
className = 'recording-file-sharing-icon'
|
|
||||||
src = { ICON_USERS }
|
|
||||||
style = { styles.recordingIcon } />
|
|
||||||
</Container>
|
|
||||||
<Text
|
|
||||||
className = 'recording-title'
|
|
||||||
style = {{
|
|
||||||
..._dialogStyles.text,
|
|
||||||
...styles.title
|
|
||||||
}}>
|
|
||||||
{ t('recording.fileSharingdescription') }
|
|
||||||
</Text>
|
|
||||||
<Switch
|
|
||||||
className = 'recording-switch'
|
|
||||||
disabled = { isValidating }
|
|
||||||
onValueChange
|
|
||||||
= { onSharingSettingChanged }
|
|
||||||
style = { styles.switch }
|
|
||||||
trackColor = {{ false: TRACK_COLOR }}
|
|
||||||
value = { sharingSetting } />
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the info in case recording is uploaded to the cloud.
|
|
||||||
*
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderUploadToTheCloudInfo() {
|
|
||||||
const {
|
|
||||||
_dialogStyles,
|
|
||||||
_hideStorageWarning,
|
|
||||||
_styles: styles,
|
|
||||||
isVpaas,
|
|
||||||
selectedRecordingService,
|
|
||||||
t
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (!(isVpaas && selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE) || _hideStorageWarning) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container
|
|
||||||
className = 'recording-info'
|
|
||||||
key = 'cloudUploadInfo'
|
|
||||||
style = { styles.headerInfo }>
|
|
||||||
<Image
|
|
||||||
className = 'recording-info-icon'
|
|
||||||
src = { ICON_INFO }
|
|
||||||
style = { styles.recordingInfoIcon } />
|
|
||||||
<Text
|
|
||||||
className = 'recording-info-title'
|
|
||||||
style = {{
|
|
||||||
..._dialogStyles.text,
|
|
||||||
...styles.titleInfo
|
|
||||||
}}>
|
|
||||||
{ t('recording.serviceDescriptionCloudInfo') }
|
|
||||||
</Text>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the no integrations content should be rendered or not.
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
_shouldRenderNoIntegrationsContent() {
|
|
||||||
// show the non integrations part only if fileRecordingsServiceEnabled
|
|
||||||
// is enabled
|
|
||||||
if (!this.props.fileRecordingsServiceEnabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the content in case no integrations were enabled.
|
|
||||||
*
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderNoIntegrationsContent() {
|
|
||||||
if (!this._shouldRenderNoIntegrationsContent()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { _dialogStyles, _styles: styles, isValidating, isVpaas, t } = this.props;
|
|
||||||
|
|
||||||
const switchContent
|
|
||||||
= this.props.integrationsEnabled || this.props._localRecordingEnabled
|
|
||||||
? (
|
|
||||||
<Switch
|
|
||||||
className = 'recording-switch'
|
|
||||||
disabled = { isValidating }
|
|
||||||
onValueChange = { this._onRecordingServiceSwitchChange }
|
|
||||||
style = { styles.switch }
|
|
||||||
trackColor = {{ false: TRACK_COLOR }}
|
|
||||||
value = { this.props.selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE } />
|
|
||||||
) : null;
|
|
||||||
|
|
||||||
const label = isVpaas ? t('recording.serviceDescriptionCloud') : t('recording.serviceDescription');
|
|
||||||
const jitsiContentRecordingIconContainer
|
|
||||||
= this.props.integrationsEnabled || this.props._localRecordingEnabled
|
|
||||||
? 'jitsi-content-recording-icon-container-with-switch'
|
|
||||||
: 'jitsi-content-recording-icon-container-without-switch';
|
|
||||||
const contentRecordingClass = isVpaas
|
|
||||||
? 'cloud-content-recording-icon-container'
|
|
||||||
: jitsiContentRecordingIconContainer;
|
|
||||||
const jitsiRecordingHeaderClass = !isVpaas && 'jitsi-recording-header';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container
|
|
||||||
className = { `recording-header ${jitsiRecordingHeaderClass}` }
|
|
||||||
key = 'noIntegrationSetting'
|
|
||||||
style = { styles.header }>
|
|
||||||
<Container className = { contentRecordingClass }>
|
|
||||||
<Image
|
|
||||||
className = 'content-recording-icon'
|
|
||||||
src = { ICON_CLOUD }
|
|
||||||
style = { styles.recordingIcon } />
|
|
||||||
</Container>
|
|
||||||
<Text
|
|
||||||
className = 'recording-title'
|
|
||||||
style = {{
|
|
||||||
..._dialogStyles.text,
|
|
||||||
...styles.title
|
|
||||||
}}>
|
|
||||||
{ label }
|
|
||||||
</Text>
|
|
||||||
{ switchContent }
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the integrations content should be rendered or not.
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
_shouldRenderIntegrationsContent() {
|
|
||||||
if (!this.props.integrationsEnabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the content in case integrations were enabled.
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderIntegrationsContent() {
|
|
||||||
if (!this._shouldRenderIntegrationsContent()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { _dialogStyles, _styles: styles, isTokenValid, isValidating, t } = this.props;
|
|
||||||
|
|
||||||
let content = null;
|
|
||||||
let switchContent = null;
|
|
||||||
|
|
||||||
if (isValidating) {
|
|
||||||
content = this._renderSpinner();
|
|
||||||
switchContent = <Container className = 'recording-switch' />;
|
|
||||||
} else if (isTokenValid) {
|
|
||||||
content = this._renderSignOut();
|
|
||||||
switchContent = (
|
|
||||||
<Container className = 'recording-switch'>
|
|
||||||
<Button
|
|
||||||
label = { t('recording.signOut') }
|
|
||||||
onClick = { this._onSignOut }
|
|
||||||
onPress = { this._onSignOut }
|
|
||||||
type = { BUTTON_TYPES.SECONDARY } />
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
switchContent = (
|
|
||||||
<Container className = 'recording-switch'>
|
|
||||||
<Button
|
|
||||||
label = { t('recording.signIn') }
|
|
||||||
onClick = { this._onSignIn }
|
|
||||||
onPress = { this._onSignIn }
|
|
||||||
type = { BUTTON_TYPES.PRIMARY } />
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.fileRecordingsServiceEnabled || this._localRecordingAvailable) {
|
|
||||||
switchContent = (
|
|
||||||
<Switch
|
|
||||||
className = 'recording-switch'
|
|
||||||
disabled = { isValidating }
|
|
||||||
onValueChange = { this._onDropboxSwitchChange }
|
|
||||||
style = { styles.switch }
|
|
||||||
trackColor = {{ false: TRACK_COLOR }}
|
|
||||||
value = { this.props.selectedRecordingService
|
|
||||||
=== RECORDING_TYPES.DROPBOX } />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<Container
|
|
||||||
className = { `recording-header ${this._shouldRenderNoIntegrationsContent()
|
|
||||||
? 'recording-header-line' : ''}` }
|
|
||||||
style = { styles.headerIntegrations }>
|
|
||||||
<Container
|
|
||||||
className = 'recording-icon-container'>
|
|
||||||
<Image
|
|
||||||
className = 'recording-icon'
|
|
||||||
src = { DROPBOX_LOGO }
|
|
||||||
style = { styles.recordingIcon } />
|
|
||||||
</Container>
|
|
||||||
<Text
|
|
||||||
className = 'recording-title'
|
|
||||||
style = {{
|
|
||||||
..._dialogStyles.text,
|
|
||||||
...styles.title
|
|
||||||
}}>
|
|
||||||
{ t('recording.authDropboxText') }
|
|
||||||
</Text>
|
|
||||||
{ switchContent }
|
|
||||||
</Container>
|
|
||||||
<Container
|
|
||||||
className = 'authorization-panel'>
|
|
||||||
{ content }
|
|
||||||
</Container>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDropboxSwitchChange: () => void;
|
|
||||||
_onRecordingServiceSwitchChange: () => void;
|
|
||||||
_onLocalRecordingSwitchChange: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for onValueChange events from the Switch component.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onRecordingServiceSwitchChange() {
|
|
||||||
const {
|
|
||||||
onChange,
|
|
||||||
selectedRecordingService
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
// act like group, cannot toggle off
|
|
||||||
if (selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(RECORDING_TYPES.JITSI_REC_SERVICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for onValueChange events from the Switch component.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onDropboxSwitchChange() {
|
|
||||||
const {
|
|
||||||
isTokenValid,
|
|
||||||
onChange,
|
|
||||||
selectedRecordingService
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
// act like group, cannot toggle off
|
|
||||||
if (selectedRecordingService === RECORDING_TYPES.DROPBOX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(RECORDING_TYPES.DROPBOX);
|
|
||||||
|
|
||||||
if (!isTokenValid) {
|
|
||||||
this._onSignIn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for onValueChange events from the Switch component.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onLocalRecordingSwitchChange() {
|
|
||||||
const {
|
|
||||||
onChange,
|
|
||||||
selectedRecordingService
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (!this._localRecordingAvailable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// act like group, cannot toggle off
|
|
||||||
if (selectedRecordingService
|
|
||||||
=== RECORDING_TYPES.LOCAL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(RECORDING_TYPES.LOCAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a spinner component.
|
|
||||||
*
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderSpinner() {
|
|
||||||
return (
|
|
||||||
<LoadingIndicator
|
|
||||||
isCompleting = { false }
|
|
||||||
size = 'small' />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the screen with the account information of a logged in user.
|
|
||||||
*
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderSignOut() {
|
|
||||||
const { _styles: styles, spaceLeft, t, userName } = this.props;
|
|
||||||
const duration = getRecordingDurationEstimation(spaceLeft);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<Container
|
|
||||||
className = 'logged-in-panel'
|
|
||||||
style = { styles.loggedIn }>
|
|
||||||
<Container>
|
|
||||||
<Text
|
|
||||||
style = { [
|
|
||||||
styles.text,
|
|
||||||
styles.recordingText
|
|
||||||
] }>
|
|
||||||
{ t('recording.loggedIn', { userName }) }
|
|
||||||
</Text>
|
|
||||||
</Container>
|
|
||||||
<Container>
|
|
||||||
<Text
|
|
||||||
style = { [
|
|
||||||
styles.text,
|
|
||||||
styles.recordingText
|
|
||||||
] }>
|
|
||||||
{
|
|
||||||
t('recording.availableSpace', {
|
|
||||||
spaceLeft,
|
|
||||||
duration
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Text>
|
|
||||||
</Container>
|
|
||||||
</Container>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderLocalRecordingContent: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the content for local recordings.
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @returns {React$Component}
|
|
||||||
*/
|
|
||||||
_renderLocalRecordingContent() {
|
|
||||||
const {
|
|
||||||
_styles: styles,
|
|
||||||
isValidating,
|
|
||||||
t,
|
|
||||||
_dialogStyles,
|
|
||||||
selectedRecordingService,
|
|
||||||
_localRecordingNoNotification
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (!this._localRecordingAvailable) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Container>
|
|
||||||
<Container
|
|
||||||
className = 'recording-header recording-header-line'
|
|
||||||
style = { styles.header }>
|
|
||||||
<Container
|
|
||||||
className = 'recording-icon-container'>
|
|
||||||
<Image
|
|
||||||
className = 'recording-icon'
|
|
||||||
src = { LOCAL_RECORDING }
|
|
||||||
style = { styles.recordingIcon } />
|
|
||||||
</Container>
|
|
||||||
<Text
|
|
||||||
className = 'recording-title'
|
|
||||||
style = {{
|
|
||||||
..._dialogStyles.text,
|
|
||||||
...styles.title
|
|
||||||
}}>
|
|
||||||
{ t('recording.saveLocalRecording') }
|
|
||||||
</Text>
|
|
||||||
<Switch
|
|
||||||
className = 'recording-switch'
|
|
||||||
disabled = { isValidating }
|
|
||||||
onValueChange = { this._onLocalRecordingSwitchChange }
|
|
||||||
style = { styles.switch }
|
|
||||||
trackColor = {{ false: TRACK_COLOR }}
|
|
||||||
value = { this.props.selectedRecordingService
|
|
||||||
=== RECORDING_TYPES.LOCAL } />
|
|
||||||
</Container>
|
|
||||||
</Container>
|
|
||||||
{selectedRecordingService === RECORDING_TYPES.LOCAL && (
|
|
||||||
<>
|
|
||||||
{this.props._localRecordingSelfEnabled && (
|
|
||||||
<Container>
|
|
||||||
<Container
|
|
||||||
className = 'recording-header space-top'
|
|
||||||
style = { styles.header }>
|
|
||||||
<Container className = 'recording-icon-container file-sharing-icon-container'>
|
|
||||||
<Image
|
|
||||||
className = 'recording-file-sharing-icon'
|
|
||||||
src = { ICON_USERS }
|
|
||||||
style = { styles.recordingIcon } />
|
|
||||||
</Container>
|
|
||||||
<Text
|
|
||||||
className = 'recording-title'
|
|
||||||
style = {{
|
|
||||||
..._dialogStyles.text,
|
|
||||||
...styles.title
|
|
||||||
}}>
|
|
||||||
{t('recording.onlyRecordSelf')}
|
|
||||||
</Text>
|
|
||||||
<Switch
|
|
||||||
className = 'recording-switch'
|
|
||||||
disabled = { isValidating }
|
|
||||||
onValueChange = { this.props.onLocalRecordingSelfChange }
|
|
||||||
style = { styles.switch }
|
|
||||||
trackColor = {{ false: TRACK_COLOR }}
|
|
||||||
value = { this.props.localRecordingOnlySelf } />
|
|
||||||
</Container>
|
|
||||||
</Container>
|
|
||||||
)}
|
|
||||||
<Text className = 'local-recording-warning text'>
|
|
||||||
{t('recording.localRecordingWarning')}
|
|
||||||
</Text>
|
|
||||||
{_localRecordingNoNotification && !this.props.localRecordingOnlySelf
|
|
||||||
&& <Text className = 'local-recording-warning notification'>
|
|
||||||
{t('recording.localRecordingNoNotificationWarning')}
|
|
||||||
</Text>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSignIn: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sings in a user.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onSignIn() {
|
|
||||||
sendAnalytics(createRecordingDialogEvent('start', 'signIn.button'));
|
|
||||||
this.props.dispatch(authorizeDropbox());
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSignOut: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sings out an user from dropbox.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onSignOut() {
|
|
||||||
sendAnalytics(createRecordingDialogEvent('start', 'signOut.button'));
|
|
||||||
this.props.dispatch(updateDropboxToken());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps part of the redux state to the props of this component.
|
|
||||||
*
|
|
||||||
* @param {Object} state - The Redux state.
|
|
||||||
* @returns {Props}
|
|
||||||
*/
|
|
||||||
function _mapStateToProps(state) {
|
|
||||||
return {
|
|
||||||
..._abstractMapStateToProps(state),
|
|
||||||
isVpaas: isVpaasMeeting(state),
|
|
||||||
_hideStorageWarning: state['features/base/config'].recordingService?.hideStorageWarning,
|
|
||||||
_localRecordingEnabled: !state['features/base/config'].localRecording?.disable,
|
|
||||||
_localRecordingSelfEnabled: !state['features/base/config'].localRecording?.disableSelfRecording,
|
|
||||||
_localRecordingNoNotification: !state['features/base/config'].localRecording?.notifyAllParticipants,
|
|
||||||
_styles: ColorSchemeRegistry.get(state, 'StartRecordingDialogContent')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default translate(connect(_mapStateToProps)(StartRecordingDialogContent));
|
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { translate } from '../../../../base/i18n';
|
import { translate } from '../../../../base/i18n';
|
||||||
|
@ -14,9 +12,11 @@ import AbstractStartRecordingDialog, {
|
||||||
type Props,
|
type Props,
|
||||||
mapStateToProps
|
mapStateToProps
|
||||||
} from '../AbstractStartRecordingDialog';
|
} from '../AbstractStartRecordingDialog';
|
||||||
import StartRecordingDialogContent from '../StartRecordingDialogContent';
|
|
||||||
import styles from '../styles.native';
|
import styles from '../styles.native';
|
||||||
|
|
||||||
|
import StartRecordingDialogContent from './StartRecordingDialogContent';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React Component for getting confirmation to start a file recording session in
|
* React Component for getting confirmation to start a file recording session in
|
||||||
* progress.
|
* progress.
|
||||||
|
|
|
@ -0,0 +1,314 @@
|
||||||
|
/* eslint-disable lines-around-comment */
|
||||||
|
import React from 'react';
|
||||||
|
import { Image, View } from 'react-native';
|
||||||
|
import { Switch, Text } from 'react-native-paper';
|
||||||
|
|
||||||
|
import { translate } from '../../../../base/i18n/functions';
|
||||||
|
// @ts-ignore
|
||||||
|
import { LoadingIndicator } from '../../../../base/react';
|
||||||
|
import { connect } from '../../../../base/redux/functions';
|
||||||
|
import Button from '../../../../base/ui/components/native/Button';
|
||||||
|
import { BUTTON_TYPES } from '../../../../base/ui/constants';
|
||||||
|
// @ts-ignore
|
||||||
|
import { RECORDING_TYPES } from '../../../constants';
|
||||||
|
// @ts-ignore
|
||||||
|
import { getRecordingDurationEstimation } from '../../../functions';
|
||||||
|
import AbstractStartRecordingDialogContent, {
|
||||||
|
Props,
|
||||||
|
mapStateToProps
|
||||||
|
} from '../AbstractStartRecordingDialogContent';
|
||||||
|
import {
|
||||||
|
DROPBOX_LOGO,
|
||||||
|
ICON_CLOUD,
|
||||||
|
ICON_INFO,
|
||||||
|
ICON_USERS,
|
||||||
|
TRACK_COLOR
|
||||||
|
// @ts-ignore
|
||||||
|
} from '../styles.native';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start recording dialog content for the mobile application.
|
||||||
|
*/
|
||||||
|
class StartRecordingDialogContent extends AbstractStartRecordingDialogContent<Props> {
|
||||||
|
/**
|
||||||
|
* Renders the component.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const { _styles: styles } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style = { styles.container }>
|
||||||
|
{ this._renderNoIntegrationsContent() }
|
||||||
|
{ this._renderFileSharingContent() }
|
||||||
|
{ this._renderUploadToTheCloudInfo() }
|
||||||
|
{ this._renderIntegrationsContent() }
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the content in case no integrations were enabled.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderNoIntegrationsContent() {
|
||||||
|
const {
|
||||||
|
_dialogStyles,
|
||||||
|
_styles: styles,
|
||||||
|
integrationsEnabled,
|
||||||
|
isValidating,
|
||||||
|
selectedRecordingService,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!this._shouldRenderNoIntegrationsContent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchContent
|
||||||
|
= integrationsEnabled
|
||||||
|
? (
|
||||||
|
<Switch
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { this._onRecordingServiceSwitchChange }
|
||||||
|
style = { styles.switch }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE } />
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key = 'noIntegrationSetting'
|
||||||
|
style = { styles.header }>
|
||||||
|
<Image
|
||||||
|
source = { ICON_CLOUD }
|
||||||
|
style = { styles.recordingIcon } />
|
||||||
|
<Text
|
||||||
|
style = {{
|
||||||
|
..._dialogStyles.text,
|
||||||
|
...styles.title
|
||||||
|
}}>
|
||||||
|
{ t('recording.serviceDescription') }
|
||||||
|
</Text>
|
||||||
|
{ switchContent }
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the file recording service sharing options, if enabled.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderFileSharingContent() {
|
||||||
|
if (!this._shouldRenderFileSharingContent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
_dialogStyles,
|
||||||
|
_styles: styles,
|
||||||
|
isValidating,
|
||||||
|
onSharingSettingChanged,
|
||||||
|
sharingSetting,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key = 'fileSharingSetting'
|
||||||
|
style = { styles.header }>
|
||||||
|
<Image
|
||||||
|
source = { ICON_USERS }
|
||||||
|
style = { styles.recordingIcon } />
|
||||||
|
<Text
|
||||||
|
style = {{
|
||||||
|
..._dialogStyles.text,
|
||||||
|
...styles.title
|
||||||
|
}}>
|
||||||
|
{ t('recording.fileSharingdescription') }
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
disabled = { isValidating }
|
||||||
|
// @ts-ignore
|
||||||
|
onValueChange = { onSharingSettingChanged }
|
||||||
|
style = { styles.switch }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { sharingSetting } />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the info in case recording is uploaded to the cloud.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderUploadToTheCloudInfo() {
|
||||||
|
const {
|
||||||
|
_dialogStyles,
|
||||||
|
_hideStorageWarning,
|
||||||
|
_styles: styles,
|
||||||
|
isVpaas,
|
||||||
|
selectedRecordingService,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!(isVpaas && selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE) || _hideStorageWarning) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key = 'cloudUploadInfo'
|
||||||
|
style = { styles.headerInfo }>
|
||||||
|
<Image
|
||||||
|
source = { ICON_INFO }
|
||||||
|
style = { styles.recordingInfoIcon } />
|
||||||
|
<Text
|
||||||
|
style = {{
|
||||||
|
..._dialogStyles.text,
|
||||||
|
...styles.titleInfo
|
||||||
|
}}>
|
||||||
|
{ t('recording.serviceDescriptionCloudInfo') }
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a spinner component.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderSpinner() {
|
||||||
|
return (
|
||||||
|
<LoadingIndicator
|
||||||
|
isCompleting = { false }
|
||||||
|
size = 'small' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the screen with the account information of a logged in user.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderSignOut() {
|
||||||
|
const { _styles: styles, spaceLeft, t, userName } = this.props;
|
||||||
|
const duration = getRecordingDurationEstimation(spaceLeft);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style = { styles.loggedIn }>
|
||||||
|
<Text
|
||||||
|
style = { [
|
||||||
|
styles.text,
|
||||||
|
styles.recordingText
|
||||||
|
] }>
|
||||||
|
{ t('recording.loggedIn', { userName }) }
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style = { [
|
||||||
|
styles.text,
|
||||||
|
styles.recordingText
|
||||||
|
] }>
|
||||||
|
{
|
||||||
|
t('recording.availableSpace', {
|
||||||
|
spaceLeft,
|
||||||
|
duration
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the content in case integrations were enabled.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderIntegrationsContent() {
|
||||||
|
if (!this._shouldRenderIntegrationsContent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
_dialogStyles,
|
||||||
|
_styles: styles,
|
||||||
|
fileRecordingsServiceEnabled,
|
||||||
|
isTokenValid,
|
||||||
|
isValidating,
|
||||||
|
selectedRecordingService,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
let content = null;
|
||||||
|
let switchContent = null;
|
||||||
|
|
||||||
|
if (isValidating) {
|
||||||
|
content = this._renderSpinner();
|
||||||
|
switchContent = <View />;
|
||||||
|
} else if (isTokenValid) {
|
||||||
|
content = this._renderSignOut();
|
||||||
|
switchContent = (
|
||||||
|
<Button
|
||||||
|
accessibilityLabel = 'recording.signOut'
|
||||||
|
labelKey = 'recording.signOut'
|
||||||
|
onClick = { this._onSignOut }
|
||||||
|
type = { BUTTON_TYPES.SECONDARY } />
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
switchContent = (
|
||||||
|
<Button
|
||||||
|
accessibilityLabel = 'recording.signIn'
|
||||||
|
labelKey = 'recording.signIn'
|
||||||
|
onClick = { this._onSignIn }
|
||||||
|
type = { BUTTON_TYPES.PRIMARY } />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileRecordingsServiceEnabled) {
|
||||||
|
switchContent = (
|
||||||
|
<Switch
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { this._onDropboxSwitchChange }
|
||||||
|
style = { styles.switch }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { selectedRecordingService
|
||||||
|
=== RECORDING_TYPES.DROPBOX } />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<View
|
||||||
|
style = { styles.headerIntegrations }>
|
||||||
|
<Image
|
||||||
|
source = { DROPBOX_LOGO }
|
||||||
|
style = { styles.recordingIcon } />
|
||||||
|
<Text
|
||||||
|
style = {{
|
||||||
|
..._dialogStyles.text,
|
||||||
|
...styles.title
|
||||||
|
}}>
|
||||||
|
{ t('recording.authDropboxText') }
|
||||||
|
</Text>
|
||||||
|
{ switchContent }
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
{ content }
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(mapStateToProps)(StartRecordingDialogContent));
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Dialog } from '../../../../base/dialog';
|
import { Dialog } from '../../../../base/dialog';
|
||||||
|
@ -11,7 +9,9 @@ import { RECORDING_TYPES } from '../../../constants';
|
||||||
import AbstractStartRecordingDialog, {
|
import AbstractStartRecordingDialog, {
|
||||||
mapStateToProps as abstractMapStateToProps
|
mapStateToProps as abstractMapStateToProps
|
||||||
} from '../AbstractStartRecordingDialog';
|
} from '../AbstractStartRecordingDialog';
|
||||||
import StartRecordingDialogContent from '../StartRecordingDialogContent';
|
|
||||||
|
import StartRecordingDialogContent from './StartRecordingDialogContent';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React Component for getting confirmation to start a file recording session in
|
* React Component for getting confirmation to start a file recording session in
|
||||||
|
|
|
@ -0,0 +1,401 @@
|
||||||
|
/* eslint-disable lines-around-comment */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { translate } from '../../../../base/i18n/functions';
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Image,
|
||||||
|
LoadingIndicator,
|
||||||
|
Switch,
|
||||||
|
Text
|
||||||
|
// @ts-ignore
|
||||||
|
} from '../../../../base/react';
|
||||||
|
import { connect } from '../../../../base/redux/functions';
|
||||||
|
import Button from '../../../../base/ui/components/web/Button';
|
||||||
|
import { BUTTON_TYPES } from '../../../../base/ui/constants';
|
||||||
|
// @ts-ignore
|
||||||
|
import { RECORDING_TYPES } from '../../../constants';
|
||||||
|
// @ts-ignore
|
||||||
|
import { getRecordingDurationEstimation } from '../../../functions';
|
||||||
|
import AbstractStartRecordingDialogContent, {
|
||||||
|
Props,
|
||||||
|
mapStateToProps
|
||||||
|
} from '../AbstractStartRecordingDialogContent';
|
||||||
|
import {
|
||||||
|
DROPBOX_LOGO,
|
||||||
|
ICON_CLOUD,
|
||||||
|
ICON_INFO,
|
||||||
|
ICON_USERS,
|
||||||
|
LOCAL_RECORDING,
|
||||||
|
TRACK_COLOR
|
||||||
|
// @ts-ignore
|
||||||
|
} from '../styles.web';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start recording dialog content for the mobile application.
|
||||||
|
*/
|
||||||
|
class StartRecordingDialogContent extends AbstractStartRecordingDialogContent<Props> {
|
||||||
|
/**
|
||||||
|
* Renders the component.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container className = 'recording-dialog'>
|
||||||
|
{ this._renderNoIntegrationsContent() }
|
||||||
|
{ this._renderFileSharingContent() }
|
||||||
|
{ this._renderUploadToTheCloudInfo() }
|
||||||
|
{ this._renderIntegrationsContent() }
|
||||||
|
{ this._renderLocalRecordingContent() }
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the content in case no integrations were enabled.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderNoIntegrationsContent() {
|
||||||
|
if (!this._shouldRenderNoIntegrationsContent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
_localRecordingAvailable,
|
||||||
|
integrationsEnabled,
|
||||||
|
isValidating,
|
||||||
|
isVpaas,
|
||||||
|
selectedRecordingService,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const switchContent
|
||||||
|
= integrationsEnabled || _localRecordingAvailable
|
||||||
|
? (
|
||||||
|
<Switch
|
||||||
|
className = 'recording-switch'
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { this._onRecordingServiceSwitchChange }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE } />
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
const label = isVpaas ? t('recording.serviceDescriptionCloud') : t('recording.serviceDescription');
|
||||||
|
const jitsiContentRecordingIconContainer
|
||||||
|
= integrationsEnabled || _localRecordingAvailable
|
||||||
|
? 'jitsi-content-recording-icon-container-with-switch'
|
||||||
|
: 'jitsi-content-recording-icon-container-without-switch';
|
||||||
|
const contentRecordingClass = isVpaas
|
||||||
|
? 'cloud-content-recording-icon-container'
|
||||||
|
: jitsiContentRecordingIconContainer;
|
||||||
|
const jitsiRecordingHeaderClass = !isVpaas && 'jitsi-recording-header';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
className = { `recording-header ${jitsiRecordingHeaderClass}` }
|
||||||
|
key = 'noIntegrationSetting'>
|
||||||
|
<Container className = { contentRecordingClass }>
|
||||||
|
<Image
|
||||||
|
className = 'content-recording-icon'
|
||||||
|
src = { ICON_CLOUD } />
|
||||||
|
</Container>
|
||||||
|
<Text className = 'recording-title'>
|
||||||
|
{ label }
|
||||||
|
</Text>
|
||||||
|
{ switchContent }
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the file recording service sharing options, if enabled.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderFileSharingContent() {
|
||||||
|
if (!this._shouldRenderFileSharingContent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
isValidating,
|
||||||
|
onSharingSettingChanged,
|
||||||
|
sharingSetting,
|
||||||
|
t
|
||||||
|
// @ts-ignore
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
className = 'recording-header'
|
||||||
|
key = 'fileSharingSetting'>
|
||||||
|
<Container className = 'recording-icon-container file-sharing-icon-container'>
|
||||||
|
<Image
|
||||||
|
className = 'recording-file-sharing-icon'
|
||||||
|
src = { ICON_USERS } />
|
||||||
|
</Container>
|
||||||
|
<Text className = 'recording-title'>
|
||||||
|
{ t('recording.fileSharingdescription') }
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
className = 'recording-switch'
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { onSharingSettingChanged }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { sharingSetting } />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the info in case recording is uploaded to the cloud.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderUploadToTheCloudInfo() {
|
||||||
|
const {
|
||||||
|
_hideStorageWarning,
|
||||||
|
isVpaas,
|
||||||
|
selectedRecordingService,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!(isVpaas && selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE) || _hideStorageWarning) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
className = 'recording-info'
|
||||||
|
key = 'cloudUploadInfo'>
|
||||||
|
<Image
|
||||||
|
className = 'recording-info-icon'
|
||||||
|
src = { ICON_INFO } />
|
||||||
|
<Text className = 'recording-info-title'>
|
||||||
|
{ t('recording.serviceDescriptionCloudInfo') }
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a spinner component.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderSpinner() {
|
||||||
|
return (
|
||||||
|
<LoadingIndicator
|
||||||
|
isCompleting = { false }
|
||||||
|
size = 'small' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the screen with the account information of a logged in user.
|
||||||
|
*
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderSignOut() {
|
||||||
|
const {
|
||||||
|
spaceLeft,
|
||||||
|
t,
|
||||||
|
userName
|
||||||
|
} = this.props;
|
||||||
|
const duration = getRecordingDurationEstimation(spaceLeft);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Container className = 'logged-in-panel'>
|
||||||
|
<Container>
|
||||||
|
<Text>
|
||||||
|
{ t('recording.loggedIn', { userName }) }
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
<Container>
|
||||||
|
<Text>
|
||||||
|
{
|
||||||
|
t('recording.availableSpace', {
|
||||||
|
spaceLeft,
|
||||||
|
duration
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the content in case integrations were enabled.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderIntegrationsContent() {
|
||||||
|
if (!this._shouldRenderIntegrationsContent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
_localRecordingAvailable,
|
||||||
|
fileRecordingsServiceEnabled,
|
||||||
|
isTokenValid,
|
||||||
|
isValidating,
|
||||||
|
selectedRecordingService,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
let content = null;
|
||||||
|
let switchContent = null;
|
||||||
|
|
||||||
|
if (isValidating) {
|
||||||
|
content = this._renderSpinner();
|
||||||
|
switchContent = <Container className = 'recording-switch' />;
|
||||||
|
} else if (isTokenValid) {
|
||||||
|
content = this._renderSignOut();
|
||||||
|
switchContent = (
|
||||||
|
<Container className = 'recording-switch'>
|
||||||
|
<Button
|
||||||
|
accessibilityLabel = { t('recording.signOut') }
|
||||||
|
labelKey = 'recording.signOut'
|
||||||
|
onClick = { this._onSignOut }
|
||||||
|
type = { BUTTON_TYPES.SECONDARY } />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
switchContent = (
|
||||||
|
<Container className = 'recording-switch'>
|
||||||
|
<Button
|
||||||
|
accessibilityLabel = { t('recording.signIn') }
|
||||||
|
labelKey = 'recording.signIn'
|
||||||
|
onClick = { this._onSignIn }
|
||||||
|
type = { BUTTON_TYPES.PRIMARY } />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileRecordingsServiceEnabled || _localRecordingAvailable) {
|
||||||
|
switchContent = (
|
||||||
|
<Switch
|
||||||
|
className = 'recording-switch'
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { this._onDropboxSwitchChange }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { selectedRecordingService
|
||||||
|
=== RECORDING_TYPES.DROPBOX } />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Container
|
||||||
|
className = { `recording-header ${this._shouldRenderNoIntegrationsContent()
|
||||||
|
? 'recording-header-line' : ''}` }>
|
||||||
|
<Container
|
||||||
|
className = 'recording-icon-container'>
|
||||||
|
<Image
|
||||||
|
className = 'recording-icon'
|
||||||
|
src = { DROPBOX_LOGO } />
|
||||||
|
</Container>
|
||||||
|
<Text className = 'recording-title'>
|
||||||
|
{ t('recording.authDropboxText') }
|
||||||
|
</Text>
|
||||||
|
{ switchContent }
|
||||||
|
</Container>
|
||||||
|
<Container className = 'authorization-panel'>
|
||||||
|
{ content }
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the content for local recordings.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {React$Component}
|
||||||
|
*/
|
||||||
|
_renderLocalRecordingContent() {
|
||||||
|
const {
|
||||||
|
_localRecordingAvailable,
|
||||||
|
_localRecordingNoNotification,
|
||||||
|
_localRecordingSelfEnabled,
|
||||||
|
isValidating,
|
||||||
|
localRecordingOnlySelf,
|
||||||
|
onLocalRecordingSelfChange,
|
||||||
|
t,
|
||||||
|
selectedRecordingService
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!_localRecordingAvailable) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Container>
|
||||||
|
<Container
|
||||||
|
className = 'recording-header recording-header-line'>
|
||||||
|
<Container
|
||||||
|
className = 'recording-icon-container'>
|
||||||
|
<Image
|
||||||
|
className = 'recording-icon'
|
||||||
|
src = { LOCAL_RECORDING } />
|
||||||
|
</Container>
|
||||||
|
<Text className = 'recording-title'>
|
||||||
|
{ t('recording.saveLocalRecording') }
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
className = 'recording-switch'
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { this._onLocalRecordingSwitchChange }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { selectedRecordingService
|
||||||
|
=== RECORDING_TYPES.LOCAL } />
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
{selectedRecordingService === RECORDING_TYPES.LOCAL && (
|
||||||
|
<>
|
||||||
|
{_localRecordingSelfEnabled && (
|
||||||
|
<Container>
|
||||||
|
<Container className = 'recording-header space-top'>
|
||||||
|
<Container className = 'recording-icon-container file-sharing-icon-container'>
|
||||||
|
<Image
|
||||||
|
className = 'recording-file-sharing-icon'
|
||||||
|
src = { ICON_USERS } />
|
||||||
|
</Container>
|
||||||
|
<Text className = 'recording-title'>
|
||||||
|
{t('recording.onlyRecordSelf')}
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
className = 'recording-switch'
|
||||||
|
disabled = { isValidating }
|
||||||
|
onValueChange = { onLocalRecordingSelfChange }
|
||||||
|
trackColor = {{ false: TRACK_COLOR }}
|
||||||
|
value = { localRecordingOnlySelf } />
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
<Text className = 'local-recording-warning text'>
|
||||||
|
{t('recording.localRecordingWarning')}
|
||||||
|
</Text>
|
||||||
|
{_localRecordingNoNotification && !localRecordingOnlySelf
|
||||||
|
&& <Text className = 'local-recording-warning notification'>
|
||||||
|
{t('recording.localRecordingNoNotificationWarning')}
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(mapStateToProps)(StartRecordingDialogContent));
|
Loading…
Reference in New Issue