<commit_before>import _ from 'lodash';
import React from 'react';
import SpeechRecognizer from '../speech-recognizer';
import classNames from 'classnames';

const $ = window.$;
const S_KEY_CODE = 83;

class Javi extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      speech: {
        confidence: 0,
        final: false,
        text: ''
      },
      talking: false
    };
    this.handleSpeech = this.handleSpeech.bind(this);
    this.turnOnMic = this.turnOnMic.bind(this);
    this.turnOffMic = this.turnOffMic.bind(this);
  }

  componentWillMount() {
    $('body').keyup(this.handleKeyUp.bind(this));
    this.speechRecognition = this.initializeSpeechRecognition();
  }

  componentWillUnmount() {
    this.speechRecognition.abort();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.matchedText !== this.props.matchedText) {
      this.setState({
        speech: _.extend({}, this.state.speech, {text: nextProps.matchedText}),
        talking: false
      });
    }
  }

  handleKeyUp(event) {
    if (event.keyCode === S_KEY_CODE) {
      this.speechRecognition.start();
    }
  }

  handleSpeech(speech) {
    this.setState({speech});
    if (speech.final) {
      this.props.onSpeak(speech.text);
    }
  }

  initializeSpeechRecognition() {
    return new SpeechRecognizer({
      onEnd: this.turnOffMic,
      onError: this.turnOffMic,
      onResult: this.handleSpeech,
      onStart: this.turnOnMic,
      continuous: false
    });
  }

  turnOffMic() {
    this.setState({talking: false});
  }

  turnOnMic() {
    this.setState({talking: true});
  }

  render() {
    const microphoneClasses = classNames({
      mic: true,
      display: this.state.talking
    });

    const textClasses = classNames({final: this.state.speech.final});

    return (
      <div className='javi'>
        <div className='javi-avatar-container'>
          <img className='avatar' src='images/javi.jpg' alt='javi-avatar'/>
          <img className={microphoneClasses} src='images/mic.png' alt='mic' />
        </div>
        <p className={textClasses}>
          {this.state.speech.text}
        </p>
      </div>
    );
  }
};

Javi.propTypes = {
  matchedText: React.PropTypes.string,
  onSpeak: React.PropTypes.func
};

export default Javi;
<commit_msg>Prevent the user start recording audio if the speech recognizer is already listening<commit_after>import _ from 'lodash';
import React from 'react';
import SpeechRecognizer from '../speech-recognizer';
import classNames from 'classnames';

const $ = window.$;
const S_KEY_CODE = 83;

class Javi extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      speech: {
        confidence: 0,
        final: false,
        text: ''
      },
      talking: false
    };
    this.handleSpeech = this.handleSpeech.bind(this);
    this.turnOnMic = this.turnOnMic.bind(this);
    this.turnOffMic = this.turnOffMic.bind(this);
  }

  componentWillMount() {
    $('body').keyup(this.handleKeyUp.bind(this));
    this.speechRecognition = this.initializeSpeechRecognition();
  }

  componentWillUnmount() {
    this.speechRecognition.abort();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.matchedText !== this.props.matchedText) {
      this.setState({
        speech: _.extend({}, this.state.speech, {text: nextProps.matchedText}),
        talking: false
      });
    }
  }

  handleKeyUp(event) {
    if (event.keyCode === S_KEY_CODE && !this.state.talking) {
      this.speechRecognition.start();
    }
  }

  handleSpeech(speech) {
    this.setState({speech});
    if (speech.final) {
      this.props.onSpeak(speech.text);
    }
  }

  initializeSpeechRecognition() {
    return new SpeechRecognizer({
      onEnd: this.turnOffMic,
      onError: this.turnOffMic,
      onResult: this.handleSpeech,
      onStart: this.turnOnMic,
      continuous: false
    });
  }

  turnOffMic() {
    this.setState({talking: false});
  }

  turnOnMic() {
    this.setState({talking: true});
  }

  render() {
    const microphoneClasses = classNames({
      mic: true,
      display: this.state.talking
    });

    const textClasses = classNames({final: this.state.speech.final});

    return (
      <div className='javi'>
        <div className='javi-avatar-container'>
          <img className='avatar' src='images/javi.jpg' alt='javi-avatar'/>
          <img className={microphoneClasses} src='images/mic.png' alt='mic' />
        </div>
        <p className={textClasses}>
          {this.state.speech.text}
        </p>
      </div>
    );
  }
};

Javi.propTypes = {
  matchedText: React.PropTypes.string,
  onSpeak: React.PropTypes.func
};

export default Javi;

{'fraction_non_alphanumeric': 0.13966836734693877, 'fraction_numerical': 0.0012755102040816326, 'mean_word_length': 2.803556992724333, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1434501', 'n_tokens_mistral': 1569, 'n_tokens_neox': 1506, 'n_words': 269}