405 lines
18 KiB
CoffeeScript
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);
|
|
}`
|
|
|
|
}) |