<commit_before>const React = require('react')
const BitField = require('bitfield').default
const prettyBytes = require('prettier-bytes')

const TorrentSummary = require('../lib/torrent-summary')
const Playlist = require('../lib/playlist')
const { dispatch, dispatcher } = require('../lib/dispatcher')
const config = require('../../config')

// Shows a streaming video player. Standard features + Chromecast + Airplay
module.exports = class Player extends React.Component {
  render () {
    // Show the video as large as will fit in the window, play immediately
    // If the video is on Chromecast or Airplay, show a title screen instead
    const state = this.props.state
    const showVideo = state.playing.location === 'local'
    const showControls = state.playing.location !== 'external'
    return (
      <div
        className='player'
        onWheel={handleVolumeWheel}
        onMouseMove={dispatcher('mediaMouseMoved')}
      >
        {showVideo ? renderMedia(state) : renderCastScreen(state)}
        {showControls ? renderPlayerControls(state) : null}
      </div>
    )
  }

  onComponentWillUnmount () {
    // Unload the media element so that Chromium stops trying to fetch data
    const tag = document.querySelector('audio,video')
    if (!tag) return
    tag.pause()
    tag.src = ''
    tag.load()
  }
}

// Handles volume change by wheel
function handleVolumeWheel (e) {
  dispatch('changeVolume', (-e.deltaY | e.deltaX) / 500)
}

function renderMedia (state) {
  if (!state.server) return

  // Unfortunately, play/pause can't be done just by modifying HTML.
  // Instead, grab the DOM node and play/pause it if necessary
  // Get the <video> or <audio> tag
  const mediaElement = document.querySelector(state.playing.type)
  if (mediaElement !== null) {
    if (state.playing.isPaused && !mediaElement.paused) {
      mediaElement.pause()
    } else if (!state.playing.isPaused && mediaElement.paused) {
      mediaElement.play()
    }
    // When the user clicks or drags on the progress bar, jump to that position
    if (state.playing.jumpToTime != null) {
      mediaElement.currentTime = state.playing.jumpToTime
      state.playing.jumpToTime = null
    }
    if (state.playing.playbackRate !== mediaElement.playbackRate) {
      mediaElement.playbackRate = state.playing.playbackRate
    }
    // Recover previous volume
    if (state.previousVolume !== null && isFinite(state.previousVolume)) {
      mediaElement.volume = state.previousVolume
      state.previousVolume = null
    }

    // Set volume
    if (state.playing.setVolume !== null && isFinite(state.playing.setVolume)) {
      mediaElement.volume = state.playing.setVolume
      state.playing.setVolume = null
    }

    // Switch to the newly added subtitle track, if available
    const tracks = mediaElement.textTracks || []
    for (let j = 0; j < tracks.length; j++) {
      const isSelectedTrack = j === state.playing.subtitles.selectedIndex
      tracks[j].mode = isSelectedTrack ? 'showing' : 'hidden'
    }

    // Save video position
    const file = state.getPlayingFileSummary()
    file.currentTime = state.playing.currentTime = mediaElement.currentTime
    file.duration = state.playing.duration = mediaElement.duration

    // Save selected subtitle
    if (state.playing.subtitles.selectedIndex !== -1) {
      const index = state.playing.subtitles.selectedIndex
      file.selectedSubtitle = state.playing.subtitles.tracks[index].filePath
    } else if (file.selectedSubtitle != null) {
      delete file.selectedSubtitle
    }

    // Switch to selected audio track
    const audioTracks = mediaElement.audioTracks || []
    for (let j = 0; j < audioTracks.length; j++) {
      const isSelectedTrack = j === state.playing.audioTracks.selectedIndex
      audioTracks[j].enabled = isSelectedTrack
    }

    state.playing.volume = mediaElement.volume
  }

  // Add subtitles to the <video> tag
  const trackTags = []
  if (state.playing.subtitles.selectedIndex >= 0) {
    for (let i = 0; i < state.playing.subtitles.tracks.length; i++) {
      const track = state.playing.subtitles.tracks[i]
      const isSelected = state.playing.subtitles.selectedIndex === i
      trackTags.push(
        <track
          key={i}
          default={isSelected}
          label={track.label}
          kind='subtitles'
          src={track.buffer}
        />
      )
    }
  }

  // Create the <audio> or <video> tag
  const MediaTagName = state.playing.type
  const mediaTag = (
    <MediaTagName
      src={Playlist.getCurrentLocalURL(state)}
      onDoubleClick={dispatcher('toggleFullScreen')}
      onLoadedMetadata={onLoadedMetadata}
      onEnded={onEnded}
      onStalled={dispatcher('mediaStalled')}
      onError={dispatcher('mediaError')}
      onTimeUpdate={dispatcher('mediaTimeUpdate')}
      onEncrypted={dispatcher('mediaEncrypted')}
    >
      {trackTags}
    </MediaTagName>
  )

  // Show the media.
  return (
    <div
      key='letterbox'
      className='letterbox'
      onMouseMove={dispatcher('mediaMouseMoved')}
    >
      {mediaTag}
      {renderOverlay(state)}
    </div>
  )

  function onLoadedMetadata (e) {
    const mediaElement = e.target
<commit_msg>Play/Pause video on click (#1878)<commit_after>const React = require('react')
const BitField = require('bitfield').default
const prettyBytes = require('prettier-bytes')

const TorrentSummary = require('../lib/torrent-summary')
const Playlist = require('../lib/playlist')
const { dispatch, dispatcher } = require('../lib/dispatcher')
const config = require('../../config')

// Shows a streaming video player. Standard features + Chromecast + Airplay
module.exports = class Player extends React.Component {
  render () {
    // Show the video as large as will fit in the window, play immediately
    // If the video is on Chromecast or Airplay, show a title screen instead
    const state = this.props.state
    const showVideo = state.playing.location === 'local'
    const showControls = state.playing.location !== 'external'
    return (
      <div
        className='player'
        onWheel={handleVolumeWheel}
        onMouseMove={dispatcher('mediaMouseMoved')}
      >
        {showVideo ? renderMedia(state) : renderCastScreen(state)}
        {showControls ? renderPlayerControls(state) : null}
      </div>
    )
  }

  onComponentWillUnmount () {
    // Unload the media element so that Chromium stops trying to fetch data
    const tag = document.querySelector('audio,video')
    if (!tag) return
    tag.pause()
    tag.src = ''
    tag.load()
  }
}

// Handles volume change by wheel
function handleVolumeWheel (e) {
  dispatch('changeVolume', (-e.deltaY | e.deltaX) / 500)
}

function renderMedia (state) {
  if (!state.server) return

  // Unfortunately, play/pause can't be done just by modifying HTML.
  // Instead, grab the DOM node and play/pause it if necessary
  // Get the <video> or <audio> tag
  const mediaElement = document.querySelector(state.playing.type)
  if (mediaElement !== null) {
    if (state.playing.isPaused && !mediaElement.paused) {
      mediaElement.pause()
    } else if (!state.playing.isPaused && mediaElement.paused) {
      mediaElement.play()
    }
    // When the user clicks or drags on the progress bar, jump to that position
    if (state.playing.jumpToTime != null) {
      mediaElement.currentTime = state.playing.jumpToTime
      state.playing.jumpToTime = null
    }
    if (state.playing.playbackRate !== mediaElement.playbackRate) {
      mediaElement.playbackRate = state.playing.playbackRate
    }
    // Recover previous volume
    if (state.previousVolume !== null && isFinite(state.previousVolume)) {
      mediaElement.volume = state.previousVolume
      state.previousVolume = null
    }

    // Set volume
    if (state.playing.setVolume !== null && isFinite(state.playing.setVolume)) {
      mediaElement.volume = state.playing.setVolume
      state.playing.setVolume = null
    }

    // Switch to the newly added subtitle track, if available
    const tracks = mediaElement.textTracks || []
    for (let j = 0; j < tracks.length; j++) {
      const isSelectedTrack = j === state.playing.subtitles.selectedIndex
      tracks[j].mode = isSelectedTrack ? 'showing' : 'hidden'
    }

    // Save video position
    const file = state.getPlayingFileSummary()
    file.currentTime = state.playing.currentTime = mediaElement.currentTime
    file.duration = state.playing.duration = mediaElement.duration

    // Save selected subtitle
    if (state.playing.subtitles.selectedIndex !== -1) {
      const index = state.playing.subtitles.selectedIndex
      file.selectedSubtitle = state.playing.subtitles.tracks[index].filePath
    } else if (file.selectedSubtitle != null) {
      delete file.selectedSubtitle
    }

    // Switch to selected audio track
    const audioTracks = mediaElement.audioTracks || []
    for (let j = 0; j < audioTracks.length; j++) {
      const isSelectedTrack = j === state.playing.audioTracks.selectedIndex
      audioTracks[j].enabled = isSelectedTrack
    }

    state.playing.volume = mediaElement.volume
  }

  // Add subtitles to the <video> tag
  const trackTags = []
  if (state.playing.subtitles.selectedIndex >= 0) {
    for (let i = 0; i < state.playing.subtitles.tracks.length; i++) {
      const track = state.playing.subtitles.tracks[i]
      const isSelected = state.playing.subtitles.selectedIndex === i
      trackTags.push(
        <track
          key={i}
          default={isSelected}
          label={track.label}
          kind='subtitles'
          src={track.buffer}
        />
      )
    }
  }

  // Create the <audio> or <video> tag
  const MediaTagName = state.playing.type
  const mediaTag = (
    <MediaTagName
      src={Playlist.getCurrentLocalURL(state)}
      onDoubleClick={dispatcher('toggleFullScreen')}
      onClick={dispatcher('playPause')}
      onLoadedMetadata={onLoadedMetadata}
      onEnded={onEnded}
      onStalled={dispatcher('mediaStalled')}
      onError={dispatcher('mediaError')}
      onTimeUpdate={dispatcher('mediaTimeUpdate')}
      onEncrypted={dispatcher('mediaEncrypted')}
    >
      {trackTags}
    </MediaTagName>
  )

  // Show the media.
  return (
    <div
      key='letterbox'
      className='letterbox'
      onMouseMove={dispatcher('mediaMouseMoved')}
    >
      {mediaTag}
      {renderOverlay(state)}
    </div>
  )

  function onLoadedMetadata (e) {
    const mediaElement = e.target

{'fraction_non_alphanumeric': 0.11702127659574468, 'fraction_numerical': 0.0019168104274487254, 'mean_word_length': 3.008835958509412, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 29, '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': '2211421', 'n_tokens_mistral': 3134, 'n_tokens_neox': 3010, 'n_words': 731}