nukeop/nuclear

View on GitHub
packages/app/app/containers/ShortcutsContainer/index.js

Summary

Maintainability
C
1 day
Test Coverage
import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Mousetrap from 'mousetrap';
import Sound from 'react-hifi';
import _ from 'lodash';
import { compose } from 'recompose';

import * as PlayerActions from '../../actions/player';
import * as QueueActions from '../../actions/queue';
import * as WindowActions from '../../actions/window';

const VOLUME_ITERATION = 1;
const SEEK_ITERATION = 10;
const COEF_ITERATION = 0.1;
const BASE_COEF = 1;

class Shortcuts extends React.Component {
  coef = BASE_COEF;
  timeout = null;

  getSeekIteration() {
    const { settings } = this.props;
    return _.defaultTo(settings.seekIteration, SEEK_ITERATION);
  }

  incrementCoef() {
    clearTimeout(this.timeout);
    this.coef = this.coef + COEF_ITERATION;
    this.timeout = setTimeout(() => {
      this.coef = BASE_COEF;
    }, 100);
  }

  handleSpaceBar = () => {
    const { queue, player, actions } = this.props;

    if (queue.queueItems.length > 0) {
      if (player.playbackStatus === Sound.status.PLAYING) {
        actions.pausePlayback(false);
      } else {
        actions.startPlayback(false);
      }
    }
    return false;
  }

  playCurrentSong = () => {
    const { queue, player, actions } = this.props;

    if (
      queue.queueItems.length > 0 &&
      player.playbackStatus !== Sound.status.PLAYING
    ) {
      actions.startPlayback(false);
    }
    return false;
  }

  increaseVolume = () => {
    const { player, actions } = this.props;

    if (player.volume < 100) {
      actions.updateVolume(player.volume + VOLUME_ITERATION * this.coef, false);
      this.incrementCoef();
    }
    return false;
  }

  decreaseVolume = () => {
    const { player, actions } = this.props;

    if (player.volume > 0) {
      actions.updateVolume(player.volume - VOLUME_ITERATION * this.coef, false);
      this.incrementCoef();
    }
    return false;
  }

  increaseSeek = () => {
    const { player, actions } = this.props;

    if (player.playbackProgress < 100) {
      actions.updateSeek(player.seek + this.getSeekIteration() * this.coef);
      this.incrementCoef();
    }
    return false;
  }

  decreaseSeek = () => {
    const { player, actions } = this.props;

    if (player.playbackProgress > 0) {
      actions.updateSeek(player.seek - this.getSeekIteration() * this.coef);
      this.incrementCoef();
    }
    return false;
  }

  goToPreviousPage = () => {
    const { history } = this.props;
    if (history.index > 1) {
      history.goBack();
    }
  }

  goToNextPage = () => {
    const { history } = this.props;
    if (history.index < history.length - 1) {
      history.goForward();
    }
  }


  componentDidMount() {
    Mousetrap.addKeycodes({
      179: 'MediaPlayPause',
      177: 'MediaTrackPrevious',
      176: 'MediaTrackNext'


    });

    Mousetrap.bind('space', this.handleSpaceBar);
    Mousetrap.bind('enter', this.playCurrentSong);
    Mousetrap.bind('up', this.increaseVolume);
    Mousetrap.bind('down', this.decreaseVolume);
    Mousetrap.bind('left', this.decreaseSeek);
    Mousetrap.bind('right', this.increaseSeek);
    Mousetrap.bind('alt+left', this.goToPreviousPage);
    Mousetrap.bind('alt+right', this.goToNextPage);
    Mousetrap.bind(['ctrl+right', 'command+right'], this.props.actions.nextSong);
    Mousetrap.bind(['ctrl+left', 'command+left'], this.props.actions.previousSong);
    Mousetrap.bind(['ctrl+top', 'command+top'], this.props.actions.unmute);
    Mousetrap.bind(['ctrl+down', 'command+down'], this.props.actions.mute);
    Mousetrap.bind('MediaPlayPause',  this.handleSpaceBar);
    Mousetrap.bind('MediaTrackPrevious',  this.props.actions.previousSong);
    Mousetrap.bind('MediaTrackNext',  this.props.actions.nextSong);
  }

  componentWillUnmount() {
    Mousetrap.unbind([
      'space',
      'enter',
      'left',
      'right',
      'up',
      'down',
      'alt+left',
      'alt+right',
      'ctrl+right',
      'command+right',
      'ctrl+left',
      'command+left',
      'ctrl+top',
      'command+top',
      'ctrl+down',
      'command+down',
      'f12',
      'command+i',
      'MediaPlayPause',
      'MediaTrackPrevious',
      'MediaTrackNext'


    ]);
  }

  componentDidUpdate() {
    if (this.props.settings.devtools) {
      Mousetrap.bind(['f12', 'command+i'], this.props.actions.openDevtools);
    } else {
      Mousetrap.unbind(['f12', 'command+i']);
    }
  }

  shouldComponentUpdate(nextProps) {
    return nextProps.settings.devtools !== this.props.settings.devtools;
  }

  render() {
    return null;
  }
}

function mapStateToProps({ player, queue, settings }) {
  return {
    player,
    queue,
    settings
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(Object.assign({}, PlayerActions, QueueActions, WindowActions), dispatch)
  };
}

export default compose(
  withRouter,
  connect(mapStateToProps, mapDispatchToProps)
)(Shortcuts);