mirror of https://github.com/jitsi/jitsi-meet
parent
4ac367d403
commit
7164cd49e4
@ -0,0 +1,103 @@ |
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react'; |
||||
|
||||
import { |
||||
createRecordingDialogEvent, |
||||
sendAnalytics |
||||
} from '../../../analytics'; |
||||
import { Dialog } from '../../../base/dialog'; |
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; |
||||
|
||||
export type Props = { |
||||
|
||||
/** |
||||
* The {@code JitsiConference} for the current conference. |
||||
*/ |
||||
_conference: Object, |
||||
|
||||
/** |
||||
* Invoked to obtain translated strings. |
||||
*/ |
||||
t: Function |
||||
} |
||||
|
||||
/** |
||||
* Abstract class for {@code StartRecordingDialog} components. |
||||
*/ |
||||
export default class AbstractStartRecordingDialog<P: Props> |
||||
extends Component<P> { |
||||
/** |
||||
* Initializes a new {@code StartRecordingDialog} instance. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
constructor(props: P) { |
||||
super(props); |
||||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
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; |
||||
|
||||
/** |
||||
* Starts a file recording session. |
||||
* |
||||
* @private |
||||
* @returns {boolean} - True (to note that the modal should be closed). |
||||
*/ |
||||
_onSubmit() { |
||||
sendAnalytics( |
||||
createRecordingDialogEvent('start', 'confirm.button') |
||||
); |
||||
|
||||
this.props._conference.startRecording({ |
||||
mode: JitsiRecordingConstants.mode.FILE |
||||
}); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Renders the platform specific dialog content. |
||||
* |
||||
* @protected |
||||
* @returns {React$Component} |
||||
*/ |
||||
_renderDialogContent: () => React$Component<*> |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the Redux state to the associated props for the |
||||
* {@code StartRecordingDialog} component. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _conference: JitsiConference |
||||
* }} |
||||
*/ |
||||
export function _mapStateToProps(state: Object) { |
||||
return { |
||||
_conference: state['features/base/conference'].conference |
||||
}; |
||||
} |
@ -0,0 +1,120 @@ |
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react'; |
||||
|
||||
import { |
||||
createRecordingDialogEvent, |
||||
sendAnalytics |
||||
} from '../../../analytics'; |
||||
import { Dialog } from '../../../base/dialog'; |
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; |
||||
|
||||
import { getActiveSession } from '../../functions'; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} props of |
||||
* {@link AbstractStopRecordingDialog}. |
||||
*/ |
||||
export type Props = { |
||||
|
||||
/** |
||||
* The {@code JitsiConference} for the current conference. |
||||
*/ |
||||
_conference: Object, |
||||
|
||||
/** |
||||
* The redux representation of the recording session to be stopped. |
||||
*/ |
||||
_fileRecordingSession: Object, |
||||
|
||||
/** |
||||
* Invoked to obtain translated strings. |
||||
*/ |
||||
t: Function |
||||
}; |
||||
|
||||
/** |
||||
* Abstract React Component for getting confirmation to stop a file recording |
||||
* session in progress. |
||||
* |
||||
* @extends Component |
||||
*/ |
||||
export default class AbstractStopRecordingDialog<P: Props> |
||||
extends Component<P> { |
||||
/** |
||||
* Initializes a new {@code AbstrStopRecordingDialog} instance. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
constructor(props: P) { |
||||
super(props); |
||||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
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; |
||||
|
||||
/** |
||||
* Stops the recording session. |
||||
* |
||||
* @private |
||||
* @returns {boolean} - True (to note that the modal should be closed). |
||||
*/ |
||||
_onSubmit() { |
||||
sendAnalytics(createRecordingDialogEvent('stop', 'confirm.button')); |
||||
|
||||
const { _fileRecordingSession } = this.props; |
||||
|
||||
if (_fileRecordingSession) { |
||||
this.props._conference.stopRecording(_fileRecordingSession.id); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Renders the platform specific dialog content. |
||||
* |
||||
* @protected |
||||
* @returns {React$Component} |
||||
*/ |
||||
_renderDialogContent: () => React$Component<*> |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the Redux state to the associated props for the |
||||
* {@code StopRecordingDialog} component. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _conference: JitsiConference, |
||||
* _fileRecordingSession: Object |
||||
* }} |
||||
*/ |
||||
export function _mapStateToProps(state: Object) { |
||||
return { |
||||
_conference: state['features/base/conference'].conference, |
||||
_fileRecordingSession: |
||||
getActiveSession(state, JitsiRecordingConstants.mode.FILE) |
||||
}; |
||||
} |
@ -0,0 +1,108 @@ |
||||
// @flow
|
||||
|
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { openDialog } from '../../../base/dialog'; |
||||
import { translate } from '../../../base/i18n'; |
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; |
||||
import { |
||||
isLocalParticipantModerator |
||||
} from '../../../base/participants'; |
||||
import { |
||||
AbstractButton, |
||||
type AbstractButtonProps |
||||
} from '../../../base/toolbox'; |
||||
|
||||
import { getActiveSession } from '../../functions'; |
||||
|
||||
import StartRecordingDialog from './StartRecordingDialog'; |
||||
import StopRecordingDialog from './StopRecordingDialog'; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} props of {@link RecordButton}. |
||||
*/ |
||||
type Props = AbstractButtonProps & { |
||||
|
||||
/** |
||||
* The current conference object. |
||||
*/ |
||||
_conference: Object, |
||||
|
||||
/** |
||||
* True if there is a running active recording, false otherwise. |
||||
*/ |
||||
_isRecordingRunning: boolean, |
||||
|
||||
/** |
||||
* The redux {@code dispatch} function. |
||||
*/ |
||||
dispatch: Function, |
||||
|
||||
/** |
||||
* The i18n translate function. |
||||
*/ |
||||
t: Function |
||||
}; |
||||
|
||||
/** |
||||
* An implementation of a button for starting and stopping recording. |
||||
*/ |
||||
class RecordButton extends AbstractButton<Props, *> { |
||||
accessibilityLabel = 'Recording'; |
||||
iconName = 'recEnable'; |
||||
label = 'dialog.startRecording'; |
||||
toggledIconName = 'recDisable'; |
||||
toggledLabel = 'dialog.stopRecording'; |
||||
|
||||
/** |
||||
* Handles clicking / pressing the button. |
||||
* |
||||
* @override |
||||
* @protected |
||||
* @returns {void} |
||||
*/ |
||||
_handleClick() { |
||||
const { _isRecordingRunning, dispatch } = this.props; |
||||
|
||||
dispatch(openDialog( |
||||
_isRecordingRunning ? StopRecordingDialog : StartRecordingDialog |
||||
)); |
||||
} |
||||
|
||||
/** |
||||
* Indicates whether this button is in toggled state or not. |
||||
* |
||||
* @override |
||||
* @protected |
||||
* @returns {boolean} |
||||
*/ |
||||
_isToggled() { |
||||
return this.props._isRecordingRunning; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the redux state to the associated props for the |
||||
* {@code RecordButton} component. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _conference: Object, |
||||
* _isRecordingRunning: boolean, |
||||
* visible: boolean |
||||
* }} |
||||
*/ |
||||
function _mapStateToProps(state): Object { |
||||
const isModerator = isLocalParticipantModerator(state); |
||||
const { fileRecordingsEnabled } = state['features/base/config']; |
||||
|
||||
return { |
||||
_conference: state['features/base/conference'].conference, |
||||
_isRecordingRunning: |
||||
Boolean(getActiveSession(state, JitsiRecordingConstants.mode.FILE)), |
||||
visible: isModerator && fileRecordingsEnabled |
||||
}; |
||||
} |
||||
|
||||
export default translate(connect(_mapStateToProps)(RecordButton)); |
@ -0,0 +1,40 @@ |
||||
// @flow
|
||||
|
||||
import React from 'react'; |
||||
import { Text, View } from 'react-native'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { translate } from '../../../base/i18n'; |
||||
|
||||
import styles from '../styles'; |
||||
|
||||
import AbstractStartRecordingDialog, { |
||||
type Props, |
||||
_mapStateToProps |
||||
} from './AbstractStartRecordingDialog'; |
||||
|
||||
/** |
||||
* React Component for getting confirmation to start a file recording session. |
||||
* |
||||
* @extends Component |
||||
*/ |
||||
class StartRecordingDialog extends AbstractStartRecordingDialog<Props> { |
||||
/** |
||||
* Renders the platform specific dialog content. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
_renderDialogContent() { |
||||
const { t } = this.props; |
||||
|
||||
return ( |
||||
<View style = { styles.messageContainer }> |
||||
<Text> |
||||
{ t('recording.startRecordingBody') } |
||||
</Text> |
||||
</View> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default translate(connect(_mapStateToProps)(StartRecordingDialog)); |
@ -1,103 +1,33 @@ |
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { |
||||
createRecordingDialogEvent, |
||||
sendAnalytics |
||||
} from '../../../analytics'; |
||||
import { Dialog } from '../../../base/dialog'; |
||||
import { translate } from '../../../base/i18n'; |
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} props of |
||||
* {@link StartRecordingDialog}. |
||||
*/ |
||||
type Props = { |
||||
|
||||
/** |
||||
* The {@code JitsiConference} for the current conference. |
||||
*/ |
||||
_conference: Object, |
||||
|
||||
/** |
||||
* Invoked to obtain translated strings. |
||||
*/ |
||||
t: Function |
||||
}; |
||||
import AbstractStartRecordingDialog, { |
||||
type Props, |
||||
_mapStateToProps |
||||
} from './AbstractStartRecordingDialog'; |
||||
|
||||
/** |
||||
* React Component for getting confirmation to start a file recording session. |
||||
* |
||||
* @extends Component |
||||
*/ |
||||
class StartRecordingDialog extends Component<Props> { |
||||
class StartRecordingDialog extends AbstractStartRecordingDialog<Props> { |
||||
/** |
||||
* Initializes a new {@code StartRecordingDialog} instance. |
||||
* Renders the platform specific dialog content. |
||||
* |
||||
* @param {Props} props - The read-only properties with which the new |
||||
* instance is to be initialized. |
||||
* @protected |
||||
* @returns {React$Component} |
||||
*/ |
||||
constructor(props: Props) { |
||||
super(props); |
||||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
this._onSubmit = this._onSubmit.bind(this); |
||||
} |
||||
_renderDialogContent() { |
||||
const { t } = this.props; |
||||
|
||||
/** |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
return ( |
||||
<Dialog |
||||
okTitleKey = 'dialog.confirm' |
||||
onSubmit = { this._onSubmit } |
||||
titleKey = 'dialog.recording' |
||||
width = 'small'> |
||||
{ this.props.t('recording.startRecordingBody') } |
||||
</Dialog> |
||||
t('recording.startRecordingBody') |
||||
); |
||||
} |
||||
|
||||
_onSubmit: () => boolean; |
||||
|
||||
/** |
||||
* Starts a file recording session. |
||||
* |
||||
* @private |
||||
* @returns {boolean} - True (to note that the modal should be closed). |
||||
*/ |
||||
_onSubmit() { |
||||
sendAnalytics(createRecordingDialogEvent('start', 'confirm.button')); |
||||
|
||||
this.props._conference.startRecording({ |
||||
mode: JitsiRecordingConstants.mode.FILE |
||||
}); |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the Redux state to the associated props for the |
||||
* {@code StartRecordingDialog} component. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _conference: JitsiConference |
||||
* }} |
||||
*/ |
||||
function _mapStateToProps(state) { |
||||
return { |
||||
_conference: state['features/base/conference'].conference |
||||
}; |
||||
} |
||||
|
||||
export default translate(connect(_mapStateToProps)(StartRecordingDialog)); |
||||
|
@ -0,0 +1,42 @@ |
||||
// @flow
|
||||
|
||||
import React from 'react'; |
||||
import { Text, View } from 'react-native'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { translate } from '../../../base/i18n'; |
||||
|
||||
import styles from '../styles'; |
||||
|
||||
import AbstractStopRecordingDialog, { |
||||
type Props, |
||||
_mapStateToProps |
||||
} from './AbstractStopRecordingDialog'; |
||||
|
||||
/** |
||||
* React Component for getting confirmation to stop a file recording session in |
||||
* progress. |
||||
* |
||||
* @extends Component |
||||
*/ |
||||
class StopRecordingDialog extends AbstractStopRecordingDialog<Props> { |
||||
|
||||
/** |
||||
* Renders the platform specific dialog content. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
_renderDialogContent() { |
||||
const { t } = this.props; |
||||
|
||||
return ( |
||||
<View style = { styles.messageContainer }> |
||||
<Text> |
||||
{ t('dialog.stopRecordingWarning') } |
||||
</Text> |
||||
</View> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default translate(connect(_mapStateToProps)(StopRecordingDialog)); |
@ -1,2 +1,3 @@ |
||||
export { default as RecordButton } from './RecordButton'; |
||||
export { default as StartRecordingDialog } from './StartRecordingDialog'; |
||||
export { default as StopRecordingDialog } from './StopRecordingDialog'; |
||||
|
@ -1,3 +1,7 @@ |
||||
export { StartLiveStreamDialog, StopLiveStreamDialog } from './LiveStream'; |
||||
export { StartRecordingDialog, StopRecordingDialog } from './Recording'; |
||||
export { |
||||
RecordButton, |
||||
StartRecordingDialog, |
||||
StopRecordingDialog |
||||
} from './Recording'; |
||||
export { default as RecordingLabel } from './RecordingLabel'; |
||||
|
Loading…
Reference in new issue