webamp/js/hotkeys.ts
2018-10-11 07:04:01 -07:00

160 lines
3.8 KiB
TypeScript

import {
play,
pause,
stop,
adjustVolume,
toggleRepeat,
toggleShuffle,
openMediaFileDialog,
seekForward,
seekBackward,
reverseList,
nextN,
next,
previous,
toggleDoubleSizeMode,
toggleWindow
} from "./actionCreators";
import { TOGGLE_TIME_MODE, TOGGLE_LLAMA_MODE } from "./actionTypes";
import { arraysAreEqual } from "./utils";
import { Dispatch } from "./types";
const IGNORE_EVENTS_FROM_TAGS = new Set(["input", "textarea", "select"]);
export function bindHotkeys(dispatch: Dispatch): () => void {
let keylog: number[] = [];
const trigger = [
78, // N
85, // U
76, // L
76, // L
83, // S
79, // O
70, // F
84 // T
];
const listener = (e: KeyboardEvent) => {
if (
e.target instanceof Element &&
IGNORE_EVENTS_FROM_TAGS.has(e.target.tagName.toLowerCase())
) {
return;
}
if (e.ctrlKey) {
switch (e.keyCode) {
case 68: // CTRL+D
dispatch(toggleDoubleSizeMode());
e.preventDefault(); // Supress the "Bookmark" action on windows.
break;
case 76: // CTRL+L FIXME
break;
case 82: // CTRL+R
dispatch(reverseList());
break;
case 84: // CTRL+T
dispatch({ type: TOGGLE_TIME_MODE });
break;
}
} else if (e.altKey) {
switch (e.keyCode) {
case 87: // ALT+W
dispatch(toggleWindow("main"));
break;
case 69: // ALT+E
dispatch(toggleWindow("playlist"));
break;
case 71: // ALT+G
dispatch(toggleWindow("equalizer"));
break;
}
} else {
switch (e.keyCode) {
case 37: // left arrow
dispatch(seekBackward(5));
break;
case 38: // up arrow
dispatch(adjustVolume(1));
break;
case 39: // right arrow
dispatch(seekForward(5));
break;
case 40: // down arrow
dispatch(adjustVolume(-1));
break;
case 66: // B
dispatch(next());
break;
case 67: // C
dispatch(pause());
break;
case 76: // L
dispatch(openMediaFileDialog());
break;
case 82: // R
dispatch(toggleRepeat());
break;
case 83: // S
dispatch(toggleShuffle());
break;
case 86: // V
dispatch(stop());
break;
case 88: // X
dispatch(play());
break;
case 90: // Z
dispatch(previous());
break;
case 96: // numpad 0
dispatch(openMediaFileDialog());
break;
case 97: // numpad 1
dispatch(nextN(-10));
break;
case 98: // numpad 2
dispatch(adjustVolume(-1));
break;
case 99: // numpad 3
dispatch(nextN(10));
break;
case 100: // numpad 4
dispatch(previous());
break;
case 101: // numpad 5
dispatch(play());
break;
case 102: // numpad 6
dispatch(next());
break;
case 103: // numpad 7
dispatch(seekBackward(5));
break;
case 104: // numpad 8
dispatch(adjustVolume(1));
break;
case 105: // numpad 9
dispatch(seekForward(5));
break;
}
}
// Easter Egg
// Ignore escape. Usually this gets swallowed by the browser, but not always.
if (e.keyCode !== 27) {
keylog.push(e.keyCode);
keylog = keylog.slice(-8);
if (arraysAreEqual(keylog, trigger)) {
dispatch({ type: TOGGLE_LLAMA_MODE });
}
}
};
document.addEventListener("keydown", listener);
return () => {
document.removeEventListener("keydown", listener);
};
}