[Glitch] Add hotkeys for audio/video control
Port 04a079e723 to glitch-soc
Signed-off-by: Thibaut Girka <thib@sitedethib.com>
			
			
This commit is contained in:
		
				
					committed by
					
						
						Thibaut Girka
					
				
			
			
				
	
			
			
			
						parent
						
							48f0f3ffee
						
					
				
				
					commit
					b82aa33dea
				
			@@ -392,13 +392,59 @@ class Audio extends React.PureComponent {
 | 
				
			|||||||
    return this.props.foregroundColor || '#ffffff';
 | 
					    return this.props.foregroundColor || '#ffffff';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  seekBy (time) {
 | 
				
			||||||
 | 
					    const currentTime = this.audio.currentTime + time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!isNaN(currentTime)) {
 | 
				
			||||||
 | 
					      this.setState({ currentTime }, () => {
 | 
				
			||||||
 | 
					        this.audio.currentTime = currentTime;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleAudioKeyDown = e => {
 | 
				
			||||||
 | 
					    // On the audio element or the seek bar, we can safely use the space bar
 | 
				
			||||||
 | 
					    // for playback control because there are no buttons to press
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (e.key === ' ') {
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.togglePlay();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleKeyDown = e => {
 | 
				
			||||||
 | 
					    switch(e.key) {
 | 
				
			||||||
 | 
					    case 'k':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.togglePlay();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'm':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.toggleMute();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'j':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.seekBy(-10);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'l':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.seekBy(10);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { src, intl, alt, editable, autoPlay } = this.props;
 | 
					    const { src, intl, alt, editable, autoPlay } = this.props;
 | 
				
			||||||
    const { paused, muted, volume, currentTime, duration, buffer, dragging } = this.state;
 | 
					    const { paused, muted, volume, currentTime, duration, buffer, dragging } = this.state;
 | 
				
			||||||
    const progress = Math.min((currentTime / duration) * 100, 100);
 | 
					    const progress = Math.min((currentTime / duration) * 100, 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className={classNames('audio-player', { editable })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
 | 
					      <div className={classNames('audio-player', { editable })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}>
 | 
				
			||||||
        <audio
 | 
					        <audio
 | 
				
			||||||
          src={src}
 | 
					          src={src}
 | 
				
			||||||
          ref={this.setAudioRef}
 | 
					          ref={this.setAudioRef}
 | 
				
			||||||
@@ -412,12 +458,14 @@ class Audio extends React.PureComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <canvas
 | 
					        <canvas
 | 
				
			||||||
          role='button'
 | 
					          role='button'
 | 
				
			||||||
 | 
					          tabIndex='0'
 | 
				
			||||||
          className='audio-player__canvas'
 | 
					          className='audio-player__canvas'
 | 
				
			||||||
          width={this.state.width}
 | 
					          width={this.state.width}
 | 
				
			||||||
          height={this.state.height}
 | 
					          height={this.state.height}
 | 
				
			||||||
          style={{ width: '100%', position: 'absolute', top: 0, left: 0 }}
 | 
					          style={{ width: '100%', position: 'absolute', top: 0, left: 0 }}
 | 
				
			||||||
          ref={this.setCanvasRef}
 | 
					          ref={this.setCanvasRef}
 | 
				
			||||||
          onClick={this.togglePlay}
 | 
					          onClick={this.togglePlay}
 | 
				
			||||||
 | 
					          onKeyDown={this.handleAudioKeyDown}
 | 
				
			||||||
          title={alt}
 | 
					          title={alt}
 | 
				
			||||||
          aria-label={alt}
 | 
					          aria-label={alt}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
@@ -438,6 +486,7 @@ class Audio extends React.PureComponent {
 | 
				
			|||||||
            className={classNames('video-player__seek__handle', { active: dragging })}
 | 
					            className={classNames('video-player__seek__handle', { active: dragging })}
 | 
				
			||||||
            tabIndex='0'
 | 
					            tabIndex='0'
 | 
				
			||||||
            style={{ left: `${progress}%`, backgroundColor: this._getAccentColor() }}
 | 
					            style={{ left: `${progress}%`, backgroundColor: this._getAccentColor() }}
 | 
				
			||||||
 | 
					            onKeyDown={this.handleAudioKeyDown}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -279,6 +279,81 @@ class Video extends React.PureComponent {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }, 15);
 | 
					  }, 15);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  seekBy (time) {
 | 
				
			||||||
 | 
					    const currentTime = this.video.currentTime + time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!isNaN(currentTime)) {
 | 
				
			||||||
 | 
					      this.setState({ currentTime }, () => {
 | 
				
			||||||
 | 
					        this.video.currentTime = currentTime;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleVideoKeyDown = e => {
 | 
				
			||||||
 | 
					    // On the video element or the seek bar, we can safely use the space bar
 | 
				
			||||||
 | 
					    // for playback control because there are no buttons to press
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (e.key === ' ') {
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.togglePlay();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleKeyDown = e => {
 | 
				
			||||||
 | 
					    const frameTime = 1 / 25;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch(e.key) {
 | 
				
			||||||
 | 
					    case 'k':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.togglePlay();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'm':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.toggleMute();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'f':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.toggleFullscreen();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'j':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.seekBy(-10);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'l':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.seekBy(10);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case ',':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.seekBy(-frameTime);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case '.':
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					      this.seekBy(frameTime);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If we are in fullscreen mode, we don't want any hotkeys
 | 
				
			||||||
 | 
					    // interacting with the UI that's not visible
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (this.state.fullscreen) {
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      e.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (e.key === 'Escape') {
 | 
				
			||||||
 | 
					        exitFullscreen();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  togglePlay = () => {
 | 
					  togglePlay = () => {
 | 
				
			||||||
    if (this.state.paused) {
 | 
					    if (this.state.paused) {
 | 
				
			||||||
      this.setState({ paused: false }, () => this.video.play());
 | 
					      this.setState({ paused: false }, () => this.video.play());
 | 
				
			||||||
@@ -504,6 +579,7 @@ class Video extends React.PureComponent {
 | 
				
			|||||||
        onMouseEnter={this.handleMouseEnter}
 | 
					        onMouseEnter={this.handleMouseEnter}
 | 
				
			||||||
        onMouseLeave={this.handleMouseLeave}
 | 
					        onMouseLeave={this.handleMouseLeave}
 | 
				
			||||||
        onMouseDown={this.handleMouseDownRoot}
 | 
					        onMouseDown={this.handleMouseDownRoot}
 | 
				
			||||||
 | 
					        onKeyDown={this.handleKeyDown}
 | 
				
			||||||
        tabIndex={0}
 | 
					        tabIndex={0}
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <Blurhash
 | 
					        <Blurhash
 | 
				
			||||||
@@ -528,6 +604,7 @@ class Video extends React.PureComponent {
 | 
				
			|||||||
          height={height}
 | 
					          height={height}
 | 
				
			||||||
          volume={volume}
 | 
					          volume={volume}
 | 
				
			||||||
          onClick={this.togglePlay}
 | 
					          onClick={this.togglePlay}
 | 
				
			||||||
 | 
					          onKeyDown={this.handleVideoKeyDown}
 | 
				
			||||||
          onPlay={this.handlePlay}
 | 
					          onPlay={this.handlePlay}
 | 
				
			||||||
          onPause={this.handlePause}
 | 
					          onPause={this.handlePause}
 | 
				
			||||||
          onLoadedData={this.handleLoadedData}
 | 
					          onLoadedData={this.handleLoadedData}
 | 
				
			||||||
@@ -550,6 +627,7 @@ class Video extends React.PureComponent {
 | 
				
			|||||||
              className={classNames('video-player__seek__handle', { active: dragging })}
 | 
					              className={classNames('video-player__seek__handle', { active: dragging })}
 | 
				
			||||||
              tabIndex='0'
 | 
					              tabIndex='0'
 | 
				
			||||||
              style={{ left: `${progress}%` }}
 | 
					              style={{ left: `${progress}%` }}
 | 
				
			||||||
 | 
					              onKeyDown={this.handleVideoKeyDown}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user