<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import WaveSurfer from 'wavesurfer.js';
import { defineMessages, injectIntl } from 'react-intl';
import { formatTime } from 'flavours/glitch/features/video';
import Icon from 'flavours/glitch/components/icon';
import classNames from 'classnames';
import { throttle } from 'lodash';

const messages = defineMessages({
  play: { id: 'video.play', defaultMessage: 'Play' },
  pause: { id: 'video.pause', defaultMessage: 'Pause' },
  mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
  unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
});

const arrayOf = (length, fill) => (new Array(length)).fill(fill);

export default @injectIntl
class Audio extends React.PureComponent {

  static propTypes = {
    src: PropTypes.string.isRequired,
    alt: PropTypes.string,
    duration: PropTypes.number,
    height: PropTypes.number,
    preload: PropTypes.bool,
    editable: PropTypes.bool,
    intl: PropTypes.object.isRequired,
  };

  state = {
    currentTime: 0,
    duration: null,
    paused: true,
    muted: false,
    volume: 0.5,
  };

  // hard coded in components.scss
  // any way to get ::before values programatically?

  volWidth = 50;

  volOffset = 70;

  volHandleOffset = v => {
    const offset = v * this.volWidth + this.volOffset;
    return (offset > 110) ? 110 : offset;
  }

  setVolumeRef = c => {
    this.volume = c;
  }

  setWaveformRef = c => {
    this.waveform = c;
  }

  componentDidMount () {
    if (this.waveform) {
      this._updateWaveform();
    }
  }

  componentDidUpdate (prevProps) {
    if (this.waveform && prevProps.src !== this.props.src) {
      this._updateWaveform();
    }
  }

  componentWillUnmount () {
    if (this.wavesurfer) {
      this.wavesurfer.destroy();
      this.wavesurfer = null;
    }
  }

  _updateWaveform () {
    const { src, height, duration, preload } = this.props;

    const progressColor = window.getComputedStyle(document.querySelector('.audio-player__progress-placeholder')).getPropertyValue('background-color');
    const waveColor     = window.getComputedStyle(document.querySelector('.audio-player__wave-placeholder')).getPropertyValue('background-color');

    if (this.wavesurfer) {
      this.wavesurfer.destroy();
    }

    const wavesurfer = WaveSurfer.create({
      container: this.waveform,
      height,
      barWidth: 3,
      cursorWidth: 0,
      progressColor,
      waveColor,
      forceDecode: true,
    });

    wavesurfer.setVolume(this.state.volume);

    if (preload) {
      wavesurfer.load(src);
    } else {
      wavesurfer.load(src, arrayOf(1, 0.5), null, duration);
    }

    wavesurfer.on('ready', () => this.setState({ duration: Math.floor(wavesurfer.getDuration()) }));
    wavesurfer.on('audioprocess', () => this.setState({ currentTime: Math.floor(wavesurfer.getCurrentTime()) }));
    wavesurfer.on('pause', () => this.setState({ paused: true }));
    wavesurfer.on('play', () => this.setState({ paused: false }));
    wavesurfer.on('volume', volume => this.setState({ volume }));
    wavesurfer.on('mute', muted => this.setState({ muted }));

    this.wavesurfer = wavesurfer;
  }

  togglePlay = () => {
    if (this.state.paused) {
      if (!this.props.preload) {
        this.wavesurfer.createBackend();
        this.wavesurfer.createPeakCache();
        this.wavesurfer.load(this.props.src);
      }

      this.wavesurfer.play();
    } else {
      this.wavesurfer.pause();
    }
  }

  toggleMute = () => {
    this.wavesurfer.setMute(!this.state.muted);
  }

  handleVolumeMouseDown = e => {
    document.addEventListener('mousemove', this.handleMouseVolSlide, true);
    document.addEventListener('mouseup', this.handleVolumeMouseUp, true);
    document.addEventListener('touchmove', this.handleMouseVolSlide, true);
    document.addEventListener('touchend', this.handleVolumeMouseUp, true);

    this.handleMouseVolSlide(e);

    e.preventDefault();
    e.stopPropagation();
  }

  handleVolumeMouseUp = () => {
    document.removeEventListener('mousemove', this.handleMouseVolSlide, true);<commit_msg>[Glitch] Fix public page crash due to audio player, fix unpause in audio player<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import WaveSurfer from 'wavesurfer.js';
import { defineMessages, injectIntl } from 'react-intl';
import { formatTime } from 'flavours/glitch/features/video';
import Icon from 'flavours/glitch/components/icon';
import classNames from 'classnames';
import { throttle } from 'lodash';

const messages = defineMessages({
  play: { id: 'video.play', defaultMessage: 'Play' },
  pause: { id: 'video.pause', defaultMessage: 'Pause' },
  mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
  unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
});

const arrayOf = (length, fill) => (new Array(length)).fill(fill);

export default @injectIntl
class Audio extends React.PureComponent {

  static propTypes = {
    src: PropTypes.string.isRequired,
    alt: PropTypes.string,
    duration: PropTypes.number,
    height: PropTypes.number,
    preload: PropTypes.bool,
    editable: PropTypes.bool,
    intl: PropTypes.object.isRequired,
  };

  state = {
    currentTime: 0,
    duration: null,
    paused: true,
    muted: false,
    volume: 0.5,
  };

  // hard coded in components.scss
  // any way to get ::before values programatically?

  volWidth = 50;

  volOffset = 70;

  volHandleOffset = v => {
    const offset = v * this.volWidth + this.volOffset;
    return (offset > 110) ? 110 : offset;
  }

  setVolumeRef = c => {
    this.volume = c;
  }

  setWaveformRef = c => {
    this.waveform = c;
  }

  componentDidMount () {
    if (this.waveform) {
      this._updateWaveform();
    }
  }

  componentDidUpdate (prevProps) {
    if (this.waveform && prevProps.src !== this.props.src) {
      this._updateWaveform();
    }
  }

  componentWillUnmount () {
    if (this.wavesurfer) {
      this.wavesurfer.destroy();
      this.wavesurfer = null;
    }
  }

  _updateWaveform () {
    const { src, height, duration, preload } = this.props;

    const progressColor = window.getComputedStyle(document.querySelector('.audio-player__progress-placeholder')).getPropertyValue('background-color');
    const waveColor     = window.getComputedStyle(document.querySelector('.audio-player__wave-placeholder')).getPropertyValue('background-color');

    if (this.wavesurfer) {
      this.wavesurfer.destroy();
      this.loaded = false;
    }

    const wavesurfer = WaveSurfer.create({
      container: this.waveform,
      height,
      barWidth: 3,
      cursorWidth: 0,
      progressColor,
      waveColor,
      forceDecode: true,
    });

    wavesurfer.setVolume(this.state.volume);

    if (preload) {
      wavesurfer.load(src);
      this.loaded = true;
    } else {
      wavesurfer.load(src, arrayOf(1, 0.5), null, duration);
      this.loaded = false;
    }

    wavesurfer.on('ready', () => this.setState({ duration: Math.floor(wavesurfer.getDuration()) }));
    wavesurfer.on('audioprocess', () => this.setState({ currentTime: Math.floor(wavesurfer.getCurrentTime()) }));
    wavesurfer.on('pause', () => this.setState({ paused: true }));
    wavesurfer.on('play', () => this.setState({ paused: false }));
    wavesurfer.on('volume', volume => this.setState({ volume }));
    wavesurfer.on('mute', muted => this.setState({ muted }));

    this.wavesurfer = wavesurfer;
  }

  togglePlay = () => {
    if (this.state.paused) {
      if (!this.props.preload && !this.loaded) {
        this.wavesurfer.createBackend();
        this.wavesurfer.createPeakCache();
        this.wavesurfer.load(this.props.src);
        this.loaded = true;
      }

      this.wavesurfer.play();
      this.setState({ paused: false });
    } else {
      this.wavesurfer.pause();
      this.setState({ paused: true });
    }
  }

  toggleMute = () => {
    this.wavesurfer.setMute(!this.state.muted);
  }

  handleVolumeMouseDown = e => {
    document.addEventListener('mousemove', this.handleMouseVolSlide, true);
    document.addEventListener('mouseup', this.handleVolumeMouseUp, true);
    document.addEventListener('touchmove', this.handleMouseVolSlide, true);
    document.addEventListener('touchend', this.handleVolumeMouseUp, true);

    this.handleMouseVolSlide(e);

    e.preventDefault();
    e.stopPropagation();
  }

  handleVolumeMouseUp = () => {
    document.removeEventListener('mousemove', this.handleMouseVolSlide, true);
{'fraction_non_alphanumeric': 0.14490202980171302, 'fraction_numerical': 0.004223864836325237, 'mean_word_length': 3.3825192802056554, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, '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': '3628103', 'n_tokens_mistral': 2774, 'n_tokens_neox': 2702, 'n_words': 527}