jam-cloud/web/app/assets/javascripts/react-components/SessionRecordingSettings.js...

405 lines
18 KiB
CoffeeScript

context = window
mixins = []
ExternalVideoStore = context.ExternalVideoStore
mixins.push(Reflux.listenTo(ExternalVideoStore, "onExternalVideoStateChanged"))
mixins.push(Reflux.listenTo(RecordingStore, "onRecordingStateChanged"))
@SessionRecordingSettings = React.createClass({
mixins: mixins
onExternalVideoStateChanged: (videoState) ->
console.log('_REC_ onExternalVideoStateChanged', videoState);
$root = $(this.getDOMNode())
if videoState.videoEnabled
$root.find('#recording-input-both').attr('disabled', false).iCheck('update').iCheck('uncheck')
else
$root.find('#recording-input-both').prop('disabled',true).iCheck('update').iCheck('uncheck');
$root.find('#recording-input-audio').attr('checked', true).iCheck('update').iCheck('check')
# onRecordingStateChanged: (recordingState) ->
# if recordingState.audioRecordingFormat
# @setState({audioFormat: recordingState.audioRecordingFormat})
onRecordingStateChanged: `function (recordingState) {
console.log('_REC_ onRecordingStateChanged', recordingState);
if (recordingState.audioRecordingFormat) {
this.setState({audioFormat: recordingState.audioRecordingFormat});
}
// This checks to see if we can clear out the grayed out state on the submit button
if(this.state.startRequested && (recordingState.cause == 'started' || (recordingState.reason == 'rest' && recordingState.isRecording == false))) {
this.setState({startRequested: false})
}
}`
getInitialState: () ->
try
settings = localStorage.getItem('recordSettings')
rs = JSON.parse(settings)
{
recordingType: rs.recordingType,
audioFormat: rs.audioFormat,
audioStoreType: rs.audioStoreType,
videoFormat: rs.videoFormat,
audioDelay: rs.audioDelay,
includeChat: rs.includeChat,
startRequested: false,
}
catch e
console.error('error loading recording settings from local storage', e.message)
logger.log(e.stack)
{
recordingType: context.JK.RECORD_TYPE_AUDIO,
recordingName: '',
audioFormat: 'mp3',
audioStoreType: context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['key'],
videoFormat: 'mp4',
audioDelay: 100,
includeChat: false,
startRequested: false
}
setRecordingNameChange: (e) ->
@setState(recordingName: e.target.value)
# setRecordingTypeChange: (e) ->
# recordType = e.target.value
# $root = $(@getDOMNode())
# $recordTypeAudio = $root.find('#recording-input-audio')
# $recordTypeBoth = $root.find('#recording-input-both')
# if recordType == context.JK.RECORD_TYPE_BOTH
# if not $recordTypeBoth.attr('disabled')
# $recordTypeBoth.iCheck('check').attr('checked', true)
# @toggleDisableVideoContrls(false)
# else
# $recordTypeAudio.iCheck('check').attr('checked', true)
# @toggleDisableVideoContrls(true)
# obsReady = true #hardcoded for now
# if !$recordTypeBoth.prop('disabled') && recordType == context.JK.RECORD_TYPE_BOTH && !obsReady
# context.JK.Banner.showAlert("To make a video recording in JamKazam, you must first install and configure OBS software. Click the link below for a help article that explains how to do this. <a href=''>View Help Article</a>")
# setTimeout (->
# $recordTypeAudio.prop('checked', true).iCheck('update').iCheck('check')
# $recordTypeBoth.prop('checked', false).iCheck('update').iCheck('uncheck')
# ), 1000
# return
# @setState(recordingType: recordType)
setRecordingTypeChange: `async function(e) {
const recordType = e.target.value;
const $root = $(this.getDOMNode());
const $recordTypeAudio = $root.find('#recording-input-audio');
const $recordTypeBoth = $root.find('#recording-input-both');
if (recordType === context.JK.RECORD_TYPE_BOTH) {
if (!$recordTypeBoth.attr('disabled')) {
$recordTypeBoth.iCheck('check').attr('checked', true);
this.toggleDisableVideoContrls(false);
}
} else {
$recordTypeAudio.iCheck('check').attr('checked', true);
this.toggleDisableVideoContrls(true);
}
const obsAvailable = await context.jamClient.IsOBSAvailable();
if (!$recordTypeBoth.prop('disabled') && (recordType === context.JK.RECORD_TYPE_BOTH) && !obsAvailable) {
context.JK.Banner.showAlert(context.JK.ALERT_MESSAGES.OBS_UNAVAILABLE);
setTimeout((function() {
$recordTypeAudio.prop('checked', true).iCheck('update').iCheck('check');
$recordTypeBoth.prop('checked', false).iCheck('update').iCheck('uncheck');
}), 1000);
return;
}
this.setState({recordingType: recordType});
}`
setAudioFormatChange: (e) ->
$root = $(@getDOMNode())
audioFormat = $root.find("#audio-format").val()
@setState(audioFormat: audioFormat)
setVideoFormatChange: (e) ->
$root = $(@getDOMNode())
videoFormat = $root.find("#video-format").val()
@setState(videoFormat: videoFormat)
setAudioStoreTypeChange: (e) ->
$root = $(@getDOMNode())
audioStoreType = e.target.value;
$audioStoreTypeMixAndStems = $root.find('#audio-store-type-mix-and-stems')
$audioStoreTypeMix = $root.find('#audio-store-type-mix')
if audioStoreType == context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['key']
$audioStoreTypeMixAndStems.iCheck('check').attr('checked', true)
$audioStoreTypeMix.iCheck('uncheck').attr('checked', false)
context.jamClient.SetAudioRecordingPreference(context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['backendValues'][0])
else
$audioStoreTypeMixAndStems.iCheck('uncheck').attr('checked', false)
$audioStoreTypeMix.iCheck('check').attr('checked', true)
context.jamClient.SetAudioRecordingPreference(context.JK.AUDIO_STORE_TYPE_MIX_ONLY['backendValues'][0])
@setState(audioStoreType: audioStoreType)
toggleDisableVideoContrls: (isDisable) ->
$root = $(@getDOMNode())
$videoFormat = $root.find("#video-format")
$audioDelay = $root.find("#audio-delay")
$videoFormat.attr('disabled', isDisable)
$audioDelay.attr('disabled', isDisable)
setAudioDelay: (e) ->
@setState(audioDelay: e.target.value)
setIncludeChat: (e) ->
@setState(includeChat: e.target.checked)
cancel: (e) ->
e.preventDefault()
@props.handleCancel()
startRecording: (e) ->
e.preventDefault()
if @state.startRequested == true
console.log("recording already attempted; ignoring")
return;
if @isFormValid()
@setState(startRequested: true)
@props.handleSubmit(@state)
else
context.JK.Banner.showAlert("Name can not be blank.")
isFormValid: (e) ->
$root = $(@getDOMNode())
$recName = $root.find('#recording-name')
$recName.val().trim().length > 0
render: () ->
audioFormatOptions = []
videoFormatOptions = []
for format, i in context.JK.AUDIO_FORMATS
if format == @state.audioFormat
audioFormatOptions.push `<option key={format} value={format}>{format}</option>`
else
audioFormatOptions.push `<option key={format} value={format}>{format}</option>`
for format, i in context.JK.VIDEO_FORMATS
videoFormatOptions.push `<option key={format} value={format}>{format}</option>`
startRecordingClasses = classNames({"button-orange": true, disabled: this.state.startRequested})
`<form>
<div className="form-item">
<label>Record:</label>
<div className="recording-type-container">
<div className="recording-type recording-type-audio">
<input type="radio" name="recording-input-type" id="recording-input-audio" value={context.JK.RECORD_TYPE_AUDIO} checked={context.JK.RECORD_TYPE_AUDIO == this.state.recordingType} defaultChecked="checked" />
<label htmlFor="recording-input-audio">Audio only</label>
</div>
<div className="recording-type recording-type-both">
<input type="radio" name="recording-input-type" id="recording-input-both" value={context.JK.RECORD_TYPE_BOTH} checked={context.JK.RECORD_TYPE_BOTH == this.state.recordingType} />
<label htmlFor="recording-input-both">Audio and Video</label>
</div>
</div>
</div>
<div className="form-item">
<label htmlFor="recording-name">Name:</label>
<div>
<input type="text" name="name" id="recording-name" value={this.state.recordingName} onChange={this.setRecordingNameChange} />
</div>
</div>
<div className="form-item">
<label htmlFor="audio-format">Audio Format:</label>
<div>
<select id="audio-format" value={this.state.audioFormat} onChange={this.setAudioFormatChange} defaultValue={this.state.audioFormat}>
{audioFormatOptions}
</select>
</div>
</div>
<div className="form-item">
<label htmlFor="audio-store-types">Audio Files:</label>
<div className="audio-store-type-container">
<div className="audio-store-type audio-store-type-mix-and-stems">
<input type="radio" name="audio-store-type" id="audio-store-type-mix-and-stems" value={context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['key']} checked={context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['key'] == this.state.audioStoreType} defaultChecked="checked" />
<label htmlFor="audio-store-type-mix-and-stems">{context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['value']}</label>
<span className="audio-store-type-mix-and-stems-help">?</span>
</div>
<div className="audio-store-type audio-store-type-mix">
<input type="radio" name="audio-store-type" id="audio-store-type-mix" value={context.JK.AUDIO_STORE_TYPE_MIX_ONLY['key']} checked={context.JK.AUDIO_STORE_TYPE_MIX_ONLY['key'] == this.state.audioStoreType} />
<label htmlFor="recording-input-both">{context.JK.AUDIO_STORE_TYPE_MIX_ONLY['value']}</label>
</div>
</div>
</div>
<div className="form-item">
<label htmlFor="audio-delay">Audio Delay (ms):</label>
<div>
<input type="number" min="0" width="3" name="name" id="audio-delay" onChange={this.setAudioDelay} value={this.state.audioDelay} />
</div>
<span className="audio-delay-help">?</span>
</div>
<div className="form-item include-chat-check">
<label>Voice Chat:</label>
<input type="checkbox" name="include-chat" id="include-chat" checked={this.state.includeChat} />
<label className="include-chat-label" htmlFor="include-chat">Include voice chat in recorded audio</label>
<span className="include-chat-help">?</span>
</div>
<div className="form-item">
<label htmlFor="video-format">Video Format:</label>
<div>
<select id="video-format" value={this.state.videoFormat} onChange={this.setVideoFormatChange}>
{videoFormatOptions}
</select>
</div>
</div>
<div className="form-actions">
<a className="button-grey btnCancel" onClick={this.cancel}>CANCEL</a>
<a className={startRecordingClasses} onClick={this.startRecording}>START RECORDING</a>
</div>
</form>`
# componentDidMount: () ->
# $root = jQuery(this.getDOMNode())
# context.JK.dropdown($root.find('select'))
# $inputAudioRadioBtn = $root.find('#recording-input-audio')
# $inputBothRadioBtn = $root.find('#recording-input-both')
# $inputBothRadioBtn.on('ifClicked', this.setRecordingTypeChange)
# $inputAudioRadioBtn.on('ifClicked', this.setRecordingTypeChange)
# $inputRecordStoreTypeMixAndStems = $root.find('#audio-store-type-mix-and-stems')
# $inputRecordStoreTypeMix = $root.find('#audio-store-type-mix')
# $inputRecordStoreTypeMixAndStems.on('ifClicked', this.setAudioStoreTypeChange)
# $inputRecordStoreTypeMix.on('ifClicked', this.setAudioStoreTypeChange)
# context.JK.checkbox($inputRecordStoreTypeMixAndStems)
# context.JK.checkbox($inputRecordStoreTypeMix)
# #only enable audio & video radio button if a video is ongoing
# if !context.JK.videoIsOngoing
# @setState({recordingType: context.JK.RECORD_TYPE_AUDIO})
# $inputAudioRadioBtn.attr('checked', true).iCheck('update').iCheck('check')
# $inputBothRadioBtn.attr('disabled',true).iCheck('update').iCheck('uncheck')
# @toggleDisableVideoContrls(true)
# else
# $inputBothRadioBtn.attr('disabled', false).iCheck('update')
# if @state.recordingType == context.JK.RECORD_TYPE_BOTH
# $inputBothRadioBtn.attr('checked', true).iCheck('update').iCheck('check')
# @toggleDisableVideoContrls(false)
# context.JK.checkbox($inputAudioRadioBtn)
# context.JK.checkbox($inputBothRadioBtn)
# $includeChatCheckbox = $root.find('#include-chat')
# $includeChatCheckbox.iCheck('check').attr('checked', @state.includeChat)
# $includeChatCheckbox.on 'ifToggled', (e) =>
# @setState(includeChat: e.target.checked)
# context.JK.checkbox($includeChatCheckbox)
# context.JK.helpBubble($root.find(".audio-store-type-mix-and-stems-help"), "audio-store-type-mix-and-stems", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450})
# context.JK.helpBubble($root.find(".include-chat-help"), "include-chat-in-recording", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450})
# context.JK.helpBubble($root.find(".audio-delay-help"), "audio-delay-in-recording", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450})
updateAudioStoreState: `function (audioStoreType) {
const $root = $(this.getDOMNode());
const $audioStoreTypeMixAndStems = $root.find('#audio-store-type-mix-and-stems');
const $audioStoreTypeMix = $root.find('#audio-store-type-mix');
if (context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS['backendValues'].indexOf(audioStoreType) > -1) {
$audioStoreTypeMixAndStems.iCheck('check').attr('checked', true);
$audioStoreTypeMix.iCheck('uncheck').attr('checked', false);
} else {
$audioStoreTypeMixAndStems.iCheck('uncheck').attr('checked', false);
$audioStoreTypeMix.iCheck('check').attr('checked', true);
}
}`
componentDidMount: `function(){
const $root = jQuery(this.getDOMNode());
context.JK.dropdown($root.find('select'));
const $inputAudioRadioBtn = $root.find('#recording-input-audio');
const $inputBothRadioBtn = $root.find('#recording-input-both');
$inputBothRadioBtn.on('ifClicked', this.setRecordingTypeChange);
$inputAudioRadioBtn.on('ifClicked', this.setRecordingTypeChange);
const $inputRecordStoreTypeMixAndStems = $root.find('#audio-store-type-mix-and-stems');
const $inputRecordStoreTypeMix = $root.find('#audio-store-type-mix');
//get the audio store type from backend and set the radio button accordingly using jamClient.GetAudioRecordingPreference()
context.jamClient.GetAudioRecordingPreference().then((audioStoreType) => {
this.updateAudioStoreState(audioStoreType);
});
$inputRecordStoreTypeMixAndStems.on('ifClicked', this.setAudioStoreTypeChange);
$inputRecordStoreTypeMix.on('ifClicked', this.setAudioStoreTypeChange);
context.JK.checkbox($inputRecordStoreTypeMixAndStems);
context.JK.checkbox($inputRecordStoreTypeMix);
//only enable audio & video radio button if a video is ongoing
if (!context.JK.videoIsOngoing) {
this.setState({recordingType: context.JK.RECORD_TYPE_AUDIO});
$inputAudioRadioBtn.attr('checked', true).iCheck('update').iCheck('check');
$inputBothRadioBtn.attr('disabled',true).iCheck('update').iCheck('uncheck');
this.toggleDisableVideoContrls(true);
} else {
$inputBothRadioBtn.attr('disabled', false).iCheck('update');
if (this.state.recordingType === context.JK.RECORD_TYPE_BOTH) {
$inputBothRadioBtn.attr('checked', true).iCheck('update').iCheck('check');
this.toggleDisableVideoContrls(false);
}
}
context.JK.checkbox($inputAudioRadioBtn);
context.JK.checkbox($inputBothRadioBtn);
const $includeChatCheckbox = $root.find('#include-chat');
$includeChatCheckbox.iCheck('check').attr('checked', this.state.includeChat);
$includeChatCheckbox.on('ifToggled', e => {
return this.setState({includeChat: e.target.checked});
});
context.JK.checkbox($includeChatCheckbox);
context.JK.helpBubble($root.find(".audio-store-type-mix-and-stems-help"), "audio-store-type-mix-and-stems", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450});
context.JK.helpBubble($root.find(".include-chat-help"), "include-chat-in-recording", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450});
return context.JK.helpBubble($root.find(".audio-delay-help"), "audio-delay-in-recording", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450});
}`
# componentDidUpdate: () ->
# console.log('componentDidUpdate')
# $root = $(this.getDOMNode())
# context.JK.dropdown($root.find('select'))
# $root.find('#audio-format').unbind('change').change(this.setAudioFormatChange)
# $root.find('#video-format').unbind('change').change(this.setVideoFormatChange)
# #$root.find('#audio-store-types').unbind('change').change(this.setAudioStoreTypeChange)
componentDidUpdate: `function () {
context.jamClient.GetAudioRecordingPreference().then((audioStoreType) => {
//console.log('_REC_ componentDidUpdate audioStoreType', audioStoreType);
this.updateAudioStoreState(audioStoreType);
});
const $root = $(this.getDOMNode());
context.JK.dropdown($root.find('select'));
$root.find('#audio-format').unbind('change').change(this.setAudioFormatChange);
$root.find('#video-format').unbind('change').change(this.setVideoFormatChange);
}`
})