<commit_before>import React from 'react';
import bem, {makeBem} from 'js/bem';
import KoboRange from 'js/components/common/koboRange';
import LoadingSpinner from 'js/components/common/loadingSpinner';
import InlineMessage from 'js/components/common/inlineMessage';
import Button from 'js/components/common/button';
import 'js/components/common/audioPlayer.scss';

bem.AudioPlayer = makeBem(null, 'audio-player');
bem.AudioPlayer__controls = makeBem(bem.AudioPlayer, 'controls', 'div');
bem.AudioPlayer__progress = makeBem(bem.AudioPlayer, 'progress', 'div');
bem.AudioPlayer__time = makeBem(bem.AudioPlayer, 'time', 'div');
bem.AudioPlayer__timeCurrent = makeBem(bem.AudioPlayer, 'time-current', 'span');
bem.AudioPlayer__timeTotal = makeBem(bem.AudioPlayer, 'time-total', 'span');
bem.AudioPlayer__seek = makeBem(bem.AudioPlayer, 'seek', 'div');

interface AudioPlayerProps {
  mediaURL: string;
}

interface AudioPlayerState {
  isLoading: boolean;
  isPlaying: boolean;
  isBroken?: boolean;
  currentTime: number;
  totalTime: number;
}

/** Custom audio player for viewing audio submissions in data table */
class AudioPlayer extends React.Component<AudioPlayerProps, AudioPlayerState> {
  audioInterface: HTMLAudioElement = new Audio();

  constructor(props: AudioPlayerProps) {
    super(props);

    this.state = {
      isLoading: true,
      isPlaying: false,
      currentTime: 0,
      totalTime: 0,
    };
  }

  componentDidMount() {
    this.prepareAudio();
  }

  componentWillUnmount() {
    this.audioInterface.pause();
  }

  prepareAudio() {
    this.audioInterface = new Audio(this.props.mediaURL);

    // Set up listeners for audio component
    this.audioInterface.onloadedmetadata = this.onAudioLoaded.bind(this);
    this.audioInterface.onerror = this.onAudioError.bind(this);
    this.audioInterface.ontimeupdate = this.onAudioTimeUpdated.bind(this);
  }

  onAudioError() {<commit_msg>fix memory leak in audioPlayer component<commit_after>import React from 'react';
import bem, {makeBem} from 'js/bem';
import KoboRange from 'js/components/common/koboRange';
import LoadingSpinner from 'js/components/common/loadingSpinner';
import InlineMessage from 'js/components/common/inlineMessage';
import Button from 'js/components/common/button';
import 'js/components/common/audioPlayer.scss';

bem.AudioPlayer = makeBem(null, 'audio-player');
bem.AudioPlayer__controls = makeBem(bem.AudioPlayer, 'controls', 'div');
bem.AudioPlayer__progress = makeBem(bem.AudioPlayer, 'progress', 'div');
bem.AudioPlayer__time = makeBem(bem.AudioPlayer, 'time', 'div');
bem.AudioPlayer__timeCurrent = makeBem(bem.AudioPlayer, 'time-current', 'span');
bem.AudioPlayer__timeTotal = makeBem(bem.AudioPlayer, 'time-total', 'span');
bem.AudioPlayer__seek = makeBem(bem.AudioPlayer, 'seek', 'div');

interface AudioPlayerProps {
  mediaURL: string;
}

interface AudioPlayerState {
  isLoading: boolean;
  isPlaying: boolean;
  isBroken?: boolean;
  currentTime: number;
  totalTime: number;
}

/** Custom audio player for viewing audio submissions in data table */
class AudioPlayer extends React.Component<AudioPlayerProps, AudioPlayerState> {
  audioInterface: HTMLAudioElement = new Audio();

  private onAudioLoadedBound = this.onAudioLoaded.bind(this);
  private onAudioErrorBound = this.onAudioError.bind(this);
  private onAudioTimeUpdatedBound = this.onAudioTimeUpdated.bind(this);

  constructor(props: AudioPlayerProps) {
    super(props);

    this.state = {
      isLoading: true,
      isPlaying: false,
      currentTime: 0,
      totalTime: 0,
    };
  }

  componentDidMount() {
    // Prepare audio.
    this.audioInterface = new Audio(this.props.mediaURL);

    // Set up listeners for audio component.
    this.audioInterface.addEventListener('loadedmetadata', this.onAudioLoadedBound);
    this.audioInterface.addEventListener('error', this.onAudioErrorBound);
    this.audioInterface.addEventListener('timeupdate', this.onAudioTimeUpdatedBound);
  }

  componentWillUnmount() {
    // Pausing makes it subject to garbage collection.
    this.audioInterface.pause();

    this.audioInterface.removeEventListener('loadedmetadata', this.onAudioLoadedBound);
    this.audioInterface.removeEventListener('error', this.onAudioErrorBound);
    this.audioInterface.removeEventListener('timeupdate', this.onAudioTimeUpdatedBound);
  }

  onAudioError() {
{'fraction_non_alphanumeric': 0.11933119560238205, 'fraction_numerical': 0.0009161704076958314, 'mean_word_length': 5.247496423462088, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '1072562', 'n_tokens_mistral': 1329, 'n_tokens_neox': 1296, 'n_words': 271}