2018-07-07 00:48:14 +00:00
|
|
|
/* global Whisper, moment, WebAudioRecorder */
|
|
|
|
|
|
|
|
/* eslint-disable more/no-then */
|
|
|
|
|
|
|
|
// eslint-disable-next-line func-names
|
2018-04-27 21:25:04 +00:00
|
|
|
(function() {
|
|
|
|
'use strict';
|
2018-07-07 00:48:14 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
window.Whisper = window.Whisper || {};
|
2016-08-15 22:36:29 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
Whisper.RecorderView = Whisper.View.extend({
|
|
|
|
className: 'recorder clearfix',
|
|
|
|
templateName: 'recorder',
|
2018-07-07 00:48:14 +00:00
|
|
|
initialize() {
|
2018-04-27 21:25:04 +00:00
|
|
|
this.startTime = Date.now();
|
|
|
|
this.interval = setInterval(this.updateTime.bind(this), 1000);
|
|
|
|
this.start();
|
|
|
|
},
|
|
|
|
events: {
|
|
|
|
'click .close': 'close',
|
|
|
|
'click .finish': 'finish',
|
|
|
|
close: 'close',
|
|
|
|
},
|
2018-07-07 00:48:14 +00:00
|
|
|
updateTime() {
|
|
|
|
const duration = moment.duration(Date.now() - this.startTime, 'ms');
|
|
|
|
const minutes = `${Math.trunc(duration.asMinutes())}`;
|
|
|
|
let seconds = `${duration.seconds()}`;
|
2018-04-27 21:25:04 +00:00
|
|
|
if (seconds.length < 2) {
|
2018-07-07 00:48:14 +00:00
|
|
|
seconds = `0${seconds}`;
|
2018-04-27 21:25:04 +00:00
|
|
|
}
|
2018-07-07 00:48:14 +00:00
|
|
|
this.$('.time').text(`${minutes}:${seconds}`);
|
2018-04-27 21:25:04 +00:00
|
|
|
},
|
2018-07-07 00:48:14 +00:00
|
|
|
close() {
|
2018-04-27 21:25:04 +00:00
|
|
|
// Note: the 'close' event can be triggered by InboxView, when the user clicks
|
|
|
|
// anywhere outside the recording pane.
|
2018-01-05 00:51:00 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
if (this.recorder.isRecording()) {
|
|
|
|
this.recorder.cancelRecording();
|
|
|
|
}
|
2018-07-03 22:33:50 +00:00
|
|
|
this.recorder = null;
|
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
if (this.interval) {
|
|
|
|
clearInterval(this.interval);
|
|
|
|
}
|
2018-07-03 22:33:50 +00:00
|
|
|
this.interval = null;
|
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
if (this.source) {
|
|
|
|
this.source.disconnect();
|
|
|
|
}
|
2018-07-03 22:33:50 +00:00
|
|
|
this.source = null;
|
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
if (this.context) {
|
2018-07-07 00:48:14 +00:00
|
|
|
this.context.close().then(() => {
|
2018-04-27 21:25:04 +00:00
|
|
|
console.log('audio context closed');
|
|
|
|
});
|
|
|
|
}
|
2018-07-03 22:33:50 +00:00
|
|
|
this.context = null;
|
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
this.remove();
|
|
|
|
this.trigger('closed');
|
|
|
|
},
|
2018-07-07 00:48:14 +00:00
|
|
|
finish() {
|
2018-04-27 21:25:04 +00:00
|
|
|
this.recorder.finishRecording();
|
|
|
|
this.close();
|
|
|
|
},
|
2018-07-07 00:48:14 +00:00
|
|
|
handleBlob(recorder, blob) {
|
2018-04-27 21:25:04 +00:00
|
|
|
if (blob) {
|
|
|
|
this.trigger('send', blob);
|
|
|
|
}
|
|
|
|
},
|
2018-07-07 00:48:14 +00:00
|
|
|
start() {
|
2018-04-27 21:25:04 +00:00
|
|
|
this.context = new AudioContext();
|
|
|
|
this.input = this.context.createGain();
|
|
|
|
this.recorder = new WebAudioRecorder(this.input, {
|
|
|
|
encoding: 'mp3',
|
|
|
|
workerDir: 'js/', // must end with slash
|
|
|
|
});
|
|
|
|
this.recorder.onComplete = this.handleBlob.bind(this);
|
|
|
|
this.recorder.onError = this.onError;
|
|
|
|
navigator.webkitGetUserMedia(
|
|
|
|
{ audio: true },
|
2018-07-07 00:48:14 +00:00
|
|
|
stream => {
|
2018-04-27 21:25:04 +00:00
|
|
|
this.source = this.context.createMediaStreamSource(stream);
|
|
|
|
this.source.connect(this.input);
|
2018-07-07 00:48:14 +00:00
|
|
|
},
|
2018-04-27 21:25:04 +00:00
|
|
|
this.onError.bind(this)
|
|
|
|
);
|
|
|
|
this.recorder.startRecording();
|
|
|
|
},
|
2018-07-07 00:48:14 +00:00
|
|
|
onError(error) {
|
2018-07-03 22:33:50 +00:00
|
|
|
// Protect against out-of-band errors, which can happen if the user revokes media
|
|
|
|
// permissions after successfully accessing the microphone.
|
|
|
|
if (!this.recorder) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
this.close();
|
2018-07-03 22:33:50 +00:00
|
|
|
|
|
|
|
if (error && error.name === 'PermissionDeniedError') {
|
|
|
|
console.log('RecorderView.onError: Microphone access is not allowed!');
|
|
|
|
window.showPermissionsPopup();
|
|
|
|
} else {
|
|
|
|
console.log(
|
|
|
|
'RecorderView.onError:',
|
|
|
|
error && error.stack ? error.stack : error
|
|
|
|
);
|
|
|
|
}
|
2018-04-27 21:25:04 +00:00
|
|
|
},
|
|
|
|
});
|
2016-08-15 22:36:29 +00:00
|
|
|
})();
|