From b7198ba4b312dfb6ef0e51b28c2cf48d78f6b77f Mon Sep 17 00:00:00 2001 From: Bettenbuk Zoltan Date: Tue, 23 Apr 2019 14:30:46 +0200 Subject: [PATCH] Add recording file sharing switch --- images/icon-users.png | Bin 0 -> 4717 bytes lang/main.json | 1 + .../base/dialog/components/native/styles.js | 5 ++ .../Recording/AbstractStartRecordingDialog.js | 36 ++++++++ .../Recording/StartRecordingDialogContent.js | 80 +++++++++++++++++- .../Recording/native/StartRecordingDialog.js | 14 ++- .../components/Recording/styles.native.js | 18 ++-- .../components/Recording/styles.web.js | 2 + .../Recording/web/StartRecordingDialog.js | 10 ++- 9 files changed, 150 insertions(+), 16 deletions(-) create mode 100644 images/icon-users.png diff --git a/images/icon-users.png b/images/icon-users.png new file mode 100644 index 0000000000000000000000000000000000000000..0944953438fd71ece3bdb8cf3c35341deff9bba7 GIT binary patch literal 4717 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 { this._onSubmit = this._onSubmit.bind(this); this._onSelectedRecordingServiceChanged = this._onSelectedRecordingServiceChanged.bind(this); + this._onSharingSettingChanged = this._onSharingSettingChanged.bind(this); let selectedRecordingService; @@ -112,6 +124,7 @@ class AbstractStartRecordingDialog extends Component { isTokenValid: false, isValidating: false, userName: undefined, + sharingEnabled: true, spaceLeft: undefined, selectedRecordingService }; @@ -154,6 +167,19 @@ class AbstractStartRecordingDialog extends Component { return this.props._isDropboxEnabled; } + _onSharingSettingChanged: () => void; + + /** + * Callback to handle sharing setting change from the dialog. + * + * @returns {void} + */ + _onSharingSettingChanged() { + this.setState({ + sharingEnabled: !this.state.sharingEnabled + }); + } + _onSelectedRecordingServiceChanged: (string) => void; /** @@ -233,6 +259,11 @@ class AbstractStartRecordingDialog extends Component { }); attributes.type = RECORDING_TYPES.DROPBOX; } else { + appData = JSON.stringify({ + 'file_recording_metadata': { + 'share': this.state.sharingEnabled + } + }); attributes.type = RECORDING_TYPES.JITSI_REC_SERVICE; } @@ -266,12 +297,16 @@ class AbstractStartRecordingDialog extends Component { * @returns {{ * _appKey: string, * _conference: JitsiConference, + * _fileRecordingsServiceEnabled: boolean, + * _fileRecordingsServiceSharingEnabled: boolean, + * _isDropboxEnabled: boolean, * _token: string * }} */ export function mapStateToProps(state: Object) { const { fileRecordingsServiceEnabled = false, + fileRecordingsServiceSharingEnabled = false, dropbox = {} } = state['features/base/config']; @@ -279,6 +314,7 @@ export function mapStateToProps(state: Object) { _appKey: dropbox.appKey, _conference: state['features/base/conference'].conference, _fileRecordingsServiceEnabled: fileRecordingsServiceEnabled, + _fileRecordingsServiceSharingEnabled: fileRecordingsServiceSharingEnabled, _isDropboxEnabled: isDropboxEnabled(state), _token: state['features/dropbox'].token }; diff --git a/react/features/recording/components/Recording/StartRecordingDialogContent.js b/react/features/recording/components/Recording/StartRecordingDialogContent.js index 5c1e42091..ac555a5a4 100644 --- a/react/features/recording/components/Recording/StartRecordingDialogContent.js +++ b/react/features/recording/components/Recording/StartRecordingDialogContent.js @@ -25,6 +25,7 @@ import { authorizeDropbox, updateDropboxToken } from '../../../dropbox'; import { default as styles, DROPBOX_LOGO, + ICON_SHARE, JITSI_LOGO } from './styles'; @@ -49,6 +50,12 @@ type Props = { */ 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. */ @@ -70,11 +77,21 @@ type Props = { */ onChange: 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. */ @@ -131,6 +148,60 @@ class StartRecordingDialogContent extends Component { ); } + /** + * Renders the file recording service sharing options, if enabled. + * + * @returns {React$Component} + */ + _renderFileSharingContent() { + if (!this.props.fileRecordingsServiceSharingEnabled) { + return null; + } + + const { + _dialogStyles, + isValidating, + onSharingSettingChanged, + selectedRecordingService, + sharingSetting, t } = this.props; + + const controlDisabled = selectedRecordingService !== RECORDING_TYPES.JITSI_REC_SERVICE; + + return ( + + + + + + { t('recording.fileSharingdescription') } + + + + ); + } + /** * Renders the content in case no integrations were enabled. * @@ -162,9 +233,10 @@ class StartRecordingDialogContent extends Component { === RECORDING_TYPES.JITSI_REC_SERVICE } /> ) : null; - return ( + return [ { { t('recording.serviceDescription') } { switchContent } - - ); + , + this._renderFileSharingContent() + ]; } /** @@ -267,6 +340,7 @@ class StartRecordingDialogContent extends Component { className = 'authorization-panel'> { content } + { this._renderFileSharingContent() } ); } diff --git a/react/features/recording/components/Recording/native/StartRecordingDialog.js b/react/features/recording/components/Recording/native/StartRecordingDialog.js index 54593d142..fb79e3efd 100644 --- a/react/features/recording/components/Recording/native/StartRecordingDialog.js +++ b/react/features/recording/components/Recording/native/StartRecordingDialog.js @@ -28,10 +28,15 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { isTokenValid, isValidating, selectedRecordingService, + sharingEnabled, spaceLeft, userName } = this.state; - const { _fileRecordingsServiceEnabled, _isDropboxEnabled } = this.props; + const { + _fileRecordingsServiceEnabled, + _fileRecordingsServiceSharingEnabled, + _isDropboxEnabled + } = this.props; // disable ok button id recording service is shown only, when // validating dropbox token, if that is not enabled we either always @@ -46,13 +51,15 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { okDisabled = { isOkDisabled } onSubmit = { this._onSubmit } > @@ -62,6 +69,7 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { _areIntegrationsEnabled: () => boolean; _onSubmit: () => boolean _onSelectedRecordingServiceChanged: (string) => void; + _onSharingSettingChanged: () => void; } export default translate(connect(mapStateToProps)(StartRecordingDialog)); diff --git a/react/features/recording/components/Recording/styles.native.js b/react/features/recording/components/Recording/styles.native.js index 9c0d0bc30..c4fe92a1c 100644 --- a/react/features/recording/components/Recording/styles.native.js +++ b/react/features/recording/components/Recording/styles.native.js @@ -1,26 +1,30 @@ // @flow -import { BoxModel, createStyleSheet, ColorPalette } from '../../../base/styles'; +import { BoxModel, ColorPalette } from '../../../base/styles'; // XXX The "standard" {@code BoxModel.padding} has been deemed insufficient in // the special case(s) of the recording feature bellow. const _PADDING = BoxModel.padding * 1.5; -export const DROPBOX_LOGO - = require('../../../../../images/dropboxLogo_square.png'); +export const DROPBOX_LOGO = require('../../../../../images/dropboxLogo_square.png'); -export const JITSI_LOGO - = require('../../../../../images/jitsiLogo_square.png'); +export const ICON_SHARE = require('../../../../../images/icon-users.png'); + +export const JITSI_LOGO = require('../../../../../images/jitsiLogo_square.png'); /** * The styles of the React {@code Components} of the feature recording. */ -export default createStyleSheet({ +export default { container: { flex: 0, flexDirection: 'column' }, + controlDisabled: { + opacity: 0.5 + }, + header: { alignItems: 'center', flex: 0, @@ -62,4 +66,4 @@ export default createStyleSheet({ text: { color: ColorPalette.white } -}); +}; diff --git a/react/features/recording/components/Recording/styles.web.js b/react/features/recording/components/Recording/styles.web.js index 26854766b..1b8318589 100644 --- a/react/features/recording/components/Recording/styles.web.js +++ b/react/features/recording/components/Recording/styles.web.js @@ -4,4 +4,6 @@ export default {}; export const DROPBOX_LOGO = 'images/dropboxLogo_square.png'; +export const ICON_SHARE = 'images/icon-users.png'; + export const JITSI_LOGO = 'images/jitsiLogo_square.png'; diff --git a/react/features/recording/components/Recording/web/StartRecordingDialog.js b/react/features/recording/components/Recording/web/StartRecordingDialog.js index 8f63fa8e9..b8453572b 100644 --- a/react/features/recording/components/Recording/web/StartRecordingDialog.js +++ b/react/features/recording/components/Recording/web/StartRecordingDialog.js @@ -28,10 +28,11 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { isTokenValid, isValidating, selectedRecordingService, + sharingEnabled, spaceLeft, userName } = this.state; - const { _fileRecordingsServiceEnabled, _isDropboxEnabled } = this.props; + const { _fileRecordingsServiceEnabled, _fileRecordingsServiceSharingEnabled, _isDropboxEnabled } = this.props; // disable ok button id recording service is shown only, when // validating dropbox token, if that is not enabled we either always @@ -49,13 +50,15 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { titleKey = 'dialog.startRecording' width = 'small'> @@ -65,6 +68,7 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { _areIntegrationsEnabled: () => boolean; _onSubmit: () => boolean; _onSelectedRecordingServiceChanged: (string) => void; + _onSharingSettingChanged: () => void; } export default translate(connect(mapStateToProps)(StartRecordingDialog));