You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
/* global $, Whisper, moment, WebAudioRecorder */
 | 
						|
 | 
						|
/* eslint-disable more/no-then */
 | 
						|
 | 
						|
// eslint-disable-next-line func-names
 | 
						|
(function() {
 | 
						|
  'use strict';
 | 
						|
 | 
						|
  window.Whisper = window.Whisper || {};
 | 
						|
 | 
						|
  Whisper.RecorderView = Whisper.View.extend({
 | 
						|
    className: 'recorder clearfix',
 | 
						|
    templateName: 'recorder',
 | 
						|
    initialize() {
 | 
						|
      this.startTime = Date.now();
 | 
						|
      this.interval = setInterval(this.updateTime.bind(this), 1000);
 | 
						|
 | 
						|
      this.onSwitchAwayBound = this.onSwitchAway.bind(this);
 | 
						|
      $(window).on('blur', this.onSwitchAwayBound);
 | 
						|
 | 
						|
      this.start();
 | 
						|
    },
 | 
						|
    events: {
 | 
						|
      'click .close': 'close',
 | 
						|
      'click .finish': 'finish',
 | 
						|
      close: 'close',
 | 
						|
    },
 | 
						|
    onSwitchAway() {
 | 
						|
      this.close();
 | 
						|
    },
 | 
						|
    updateTime() {
 | 
						|
      const duration = moment.duration(Date.now() - this.startTime, 'ms');
 | 
						|
      const minutes = `${Math.trunc(duration.asMinutes())}`;
 | 
						|
      let seconds = `${duration.seconds()}`;
 | 
						|
      if (seconds.length < 2) {
 | 
						|
        seconds = `0${seconds}`;
 | 
						|
      }
 | 
						|
      this.$('.time').text(`${minutes}:${seconds}`);
 | 
						|
    },
 | 
						|
    close() {
 | 
						|
      // Note: the 'close' event can be triggered by InboxView, when the user clicks
 | 
						|
      //   anywhere outside the recording pane.
 | 
						|
 | 
						|
      if (this.recorder.isRecording()) {
 | 
						|
        this.recorder.cancelRecording();
 | 
						|
      }
 | 
						|
      this.recorder = null;
 | 
						|
 | 
						|
      if (this.interval) {
 | 
						|
        clearInterval(this.interval);
 | 
						|
      }
 | 
						|
      this.interval = null;
 | 
						|
 | 
						|
      if (this.source) {
 | 
						|
        this.source.disconnect();
 | 
						|
      }
 | 
						|
      this.source = null;
 | 
						|
 | 
						|
      if (this.context) {
 | 
						|
        this.context.close().then(() => {
 | 
						|
          window.log.info('audio context closed');
 | 
						|
        });
 | 
						|
      }
 | 
						|
      this.context = null;
 | 
						|
 | 
						|
      this.remove();
 | 
						|
      this.trigger('closed');
 | 
						|
 | 
						|
      $(window).off('blur', this.onSwitchAwayBound);
 | 
						|
    },
 | 
						|
    finish() {
 | 
						|
      this.clickedFinish = true;
 | 
						|
      this.recorder.finishRecording();
 | 
						|
      this.close();
 | 
						|
    },
 | 
						|
    handleBlob(recorder, blob) {
 | 
						|
      if (blob && this.clickedFinish) {
 | 
						|
        this.trigger('send', blob);
 | 
						|
      } else {
 | 
						|
        this.close();
 | 
						|
      }
 | 
						|
    },
 | 
						|
    start() {
 | 
						|
      this.clickedFinish = false;
 | 
						|
      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.bind(this);
 | 
						|
      navigator.webkitGetUserMedia(
 | 
						|
        { audio: true },
 | 
						|
        stream => {
 | 
						|
          this.source = this.context.createMediaStreamSource(stream);
 | 
						|
          this.source.connect(this.input);
 | 
						|
        },
 | 
						|
        this.onError.bind(this)
 | 
						|
      );
 | 
						|
      this.recorder.startRecording();
 | 
						|
    },
 | 
						|
    onError(error) {
 | 
						|
      // Protect against out-of-band errors, which can happen if the user revokes media
 | 
						|
      //   permissions after successfully accessing the microphone.
 | 
						|
      if (!this.recorder) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      this.close();
 | 
						|
 | 
						|
      if (error && error.name === 'PermissionDeniedError') {
 | 
						|
        window.log.warn(
 | 
						|
          'RecorderView.onError: Microphone access is not allowed!'
 | 
						|
        );
 | 
						|
        window.showPermissionsPopup();
 | 
						|
      } else {
 | 
						|
        window.log.error(
 | 
						|
          'RecorderView.onError:',
 | 
						|
          error && error.stack ? error.stack : error
 | 
						|
        );
 | 
						|
      }
 | 
						|
    },
 | 
						|
  });
 | 
						|
})();
 |