<commit_before>/*---------------------------------------------------------------------------*\
 |  Player.js                                                                |
 |                                                                           |
 |  Copyright © 2017-2020, <NAME>, original author.             |
 |                                                                           |
 |      This program is free software: you can redistribute it and/or modify |
 |      it under the terms of the GNU General Public License as published by |
 |      the Free Software Foundation, either version 3 of the License, or    |
 |      (at your option) any later version.                                  |
 |                                                                           |
 |      This program is distributed in the hope that it will be useful, but  |
 |      WITHOUT ANY WARRANTY; without even the implied warranty of           |
 |      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
 |      General Public License for more details.                             |
 |                                                                           |
 |      You should have received a copy of the GNU General Public License    |
 |      along with this program.  If not, see:                               |
 |          <http://www.gnu.org/licenses/>                                   |
\*---------------------------------------------------------------------------*/

import React from 'react';
import { connect } from 'react-redux';
import '../monkey';
import { previousVideo, nextVideo, fetchQueue } from '../actions/player';
import { clearSearch } from '../actions/search';
import './Player.css';

class Player extends React.PureComponent {
  constructor(props) {
    super(props);
    this.NEXT_KEYS = [39];
    this.PREV_KEYS = [37];
  }

  componentDidMount() {
    document.addEventListener('keyup', this.onKeyUp);
    document.addEventListener('visibilitychange', this.onVisibilityChange);
  }

  onKeyUp = (eventObject) => {
    if (document.activeElement === document.body) {
      if (this.NEXT_KEYS.includes(eventObject.which)) {
        this.props.nextVideo();
      } else if (this.PREV_KEYS.includes(eventObject.which)) {
        this.props.previousVideo();
      }
    }
  }

  onVisibilityChange = () => {
    const video = document.getElementsByTagName('video')[0];
    if (video) {
      video[document.hidden ? 'pause' : 'play']();
    }
  }

  render() {
    return <ConnectedBuffer {...this.props} />;
  }
}

class Buffer extends React.Component {
  componentDidMount() {
    this.props.fetchQueue(this.props.artistId, this.props.songId);
  }

  componentDidUpdate(prevProps) {
    if (
      this.props.artistId !== prevProps.artistId
      || this.props.songId !== prevProps.songId
    ) {
      if (this.props.history.action !== 'REPLACE') {
        this.props.fetchQueue(this.props.artistId, this.props.songId);
      }
    }
  }

  render() {
    const videos = [];
    let states;

    if (
      this.props.player.index === null
      || this.props.player.index > this.props.player.queue.length - 1
    ) {
      states = [];
    } else if (
      this.props.player.index === this.props.player.queue.length - 1
      || this.props.state === 'background'
    ) {
      states = [this.props.state];
    } else {
      states = ['playing', 'buffering'];
    }

    states.forEach((state, index) => {
      const video = this.props.player.queue[this.props.player.index + index];
      const key = `/${video.artist__id}/${video.song__id}/${state}`;
      videos.push(
        <ConnectedVideo
          key={key}
          video={video}
          state={state}
          history={this.props.history}
        />
      );
    });

    return <div className="Player">{videos}</div>;
  }
}

class Video extends React.PureComponent {
  componentDidMount() {
    this.updateUrlAndTitle();
  }

  componentDidUpdate() {
    this.updateUrlAndTitle();
  }

  onMouseDown = (eventObject) => {
    if (this.props.state === 'playing') {
      if (eventObject.target.paused) {
        eventObject.target.play().catch(() => this.props.nextVideo());
      } else if (document.activeElement === document.body) {
        this.props.nextVideo();
      } else {
        this.props.clearSearch();
      }
    }
  }

  updateUrlAndTitle() {
    if (this.props.state === 'playing') {
      const { artist__id, song__id, artist, song } = this.props.video;
      this.props.history.replace(`/${artist__id}/${song__id}`);
      document.title = `Spool - ${artist} - ${song}`;
    }
  }

  render() {
    const className = this.props.state.capitalize();
    return (
      <video
        className={className}
        src={this.props.video.mp4_url}
        preload="auto"
        loop
        autoPlay={this.props.state === 'buffering' ? null : 'autoplay'}
        muted={this.props.state !== 'playing'}
        playsInline
        onMouseDown={this.onMouseDown}
      /><commit_msg>Mute videos by default on iOS<commit_after>/*---------------------------------------------------------------------------*\
 |  Player.js                                                                |
 |                                                                           |
 |  Copyright © 2017-2020, <NAME>, original author.             |
 |                                                                           |
 |      This program is free software: you can redistribute it and/or modify |
 |      it under the terms of the GNU General Public License as published by |
 |      the Free Software Foundation, either version 3 of the License, or    |
 |      (at your option) any later version.                                  |
 |                                                                           |
 |      This program is distributed in the hope that it will be useful, but  |
 |      WITHOUT ANY WARRANTY; without even the implied warranty of           |
 |      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
 |      General Public License for more details.                             |
 |                                                                           |
 |      You should have received a copy of the GNU General Public License    |
 |      along with this program.  If not, see:                               |
 |          <http://www.gnu.org/licenses/>                                   |
\*---------------------------------------------------------------------------*/

import React from 'react';
import { connect } from 'react-redux';
import '../monkey';
import { previousVideo, nextVideo, fetchQueue } from '../actions/player';
import { clearSearch } from '../actions/search';
import './Player.css';

class Player extends React.PureComponent {
  constructor(props) {
    super(props);
    this.NEXT_KEYS = [39];
    this.PREV_KEYS = [37];
  }

  componentDidMount() {
    document.addEventListener('keyup', this.onKeyUp);
    document.addEventListener('visibilitychange', this.onVisibilityChange);
  }

  onKeyUp = (eventObject) => {
    if (document.activeElement === document.body) {
      if (this.NEXT_KEYS.includes(eventObject.which)) {
        this.props.nextVideo();
      } else if (this.PREV_KEYS.includes(eventObject.which)) {
        this.props.previousVideo();
      }
    }
  }

  onVisibilityChange = () => {
    const video = document.getElementsByTagName('video')[0];
    if (video) {
      video[document.hidden ? 'pause' : 'play']();
    }
  }

  render() {
    return <ConnectedBuffer {...this.props} />;
  }
}

class Buffer extends React.Component {
  componentDidMount() {
    this.props.fetchQueue(this.props.artistId, this.props.songId);
  }

  componentDidUpdate(prevProps) {
    if (
      this.props.artistId !== prevProps.artistId
      || this.props.songId !== prevProps.songId
    ) {
      if (this.props.history.action !== 'REPLACE') {
        this.props.fetchQueue(this.props.artistId, this.props.songId);
      }
    }
  }

  render() {
    const videos = [];
    let states;

    if (
      this.props.player.index === null
      || this.props.player.index > this.props.player.queue.length - 1
    ) {
      states = [];
    } else if (
      this.props.player.index === this.props.player.queue.length - 1
      || this.props.state === 'background'
    ) {
      states = [this.props.state];
    } else {
      states = ['playing', 'buffering'];
    }

    states.forEach((state, index) => {
      const video = this.props.player.queue[this.props.player.index + index];
      const key = `/${video.artist__id}/${video.song__id}/${state}`;
      videos.push(
        <ConnectedVideo
          key={key}
          video={video}
          state={state}
          history={this.props.history}
        />
      );
    });

    return <div className="Player">{videos}</div>;
  }
}

class Video extends React.PureComponent {
  componentDidMount() {
    this.updateUrlAndTitle();
  }

  componentDidUpdate() {
    this.updateUrlAndTitle();
  }

  onMouseDown = (eventObject) => {
    if (this.props.state === 'playing') {
      if (eventObject.target.paused) {
        eventObject.target.play().catch(() => this.props.nextVideo());
      } else if (document.activeElement === document.body) {
        this.props.nextVideo();
      } else {
        this.props.clearSearch();
      }
    }
  }

  updateUrlAndTitle() {
    if (this.props.state === 'playing') {
      const { artist__id, song__id, artist, song } = this.props.video;
      this.props.history.replace(`/${artist__id}/${song__id}`);
      document.title = `Spool - ${artist} - ${song}`;
    }
  }

  render() {
    const className = this.props.state.capitalize();
    const iOS = !!navigator.userAgent.match(/iPhone|iPad|iPod/i);
    const muted = iOS || this.props.state !== 'playing';
    return (
      <video
        className={className}
        src={this.props.video.mp4_url}
        preload="auto"
        loop
        autoPlay={this.props.state === 'buffering' ? null : 'autoplay'}
        muted={muted}
        playsInline
        onMouseDown={this.onMouseDown}
      />
{'fraction_non_alphanumeric': 0.1574384236453202, 'fraction_numerical': 0.003349753694581281, 'mean_word_length': 1.6573298429319372, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '629242', 'n_tokens_mistral': 2791, 'n_tokens_neox': 2725, 'n_words': 586}