From 8feefa78118cdfe9a98198786a0315053dc098a1 Mon Sep 17 00:00:00 2001 From: Florrie Date: Wed, 17 Apr 2019 10:40:56 -0300 Subject: Rework input system, support number pad Also changed focus main/queue listings to [ and ], so that we can use the 2 key for the down arrow on a number pad. --- ui.js | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 28 deletions(-) (limited to 'ui.js') diff --git a/ui.js b/ui.js index e9128a3..049930b 100644 --- a/ui.js +++ b/ui.js @@ -35,18 +35,90 @@ const { promisify } = require('util') const readFile = promisify(fs.readFile) const writeFile = promisify(fs.writeFile) -// Sneaky hack :) -const addKey = (prop, key) => { - const oldFunc = telc[prop] - telc[prop] = input => input.toString().toLowerCase() === key || oldFunc(input) +const input = {} + +const keyBindings = [ + ['isUp', telc.isUp], + ['isDown', telc.isDown], + ['isLeft', telc.isLeft], + ['isRight', telc.isRight], + ['isSelect', telc.isSelect], + ['isBackspace', telc.isBackspace], + ['isMenu', 'm'], + ['isMenu', 'f'], + ['isTogglePause', telc.isSpace], + ['isToggleLoop', 'l'], + ['isStop', telc.isEscape], + ['isVolumeUp', 'v', {caseless: false}], + ['isVolumeDown', 'V', {caseless: false}], + ['isSkipBack', telc.isShiftUp], + ['isSkipAhead', telc.isShiftDown], + ['isSkipBack', 'p'], + ['isSkipAhead', 'n'], + ['isFocusTabber', '['], + ['isFocusQueue', ']'], + ['isNextTab', 't', {caseless: false}], + ['isPreviousTab', 'T', {caseless: false}], + ['isDownload', 'd'], + ['isRemove', 'x'], + ['isQueueAtEnd', 'q', {caseless: false}], + ['isQueueAtStart', 'Q', {caseless: false}], + ['isShuffleQueue', 's'], + ['isClearQueue', 'c'], + + // Number pad + ['isUp', '8'], + ['isDown', '2'], + ['isLeft', '4'], + ['isRight', '6'], + ['isSpace', '5'], + ['isTogglePause', '5'], + ['isBackspace', '.'], + ['isMenu', '+'], + ['isSkipBack', '1'], + ['isSkipAhead', '3'], + ['isVolumeDown', '/'], + ['isVolumeUp', '*'], + ['isFocusTabber', '7'], + ['isFocusQueue', '9'], + + // HJKL + ['isDown', 'j'], + ['isUp', 'k'], + // Don't use these for now... currently L is used for toggling loop. + // May want to look into changing that (so we can re-enable these). + // ['isLeft', 'h'], + // ['isRight', 'l'], +] + +const addKey = (prop, keyOrFunc, {caseless = true} = {}) => { + const oldFunc = input[prop] || (() => false) + let newFunc + if (typeof keyOrFunc === 'function') { + newFunc = keyOrFunc + } else if (typeof keyOrFunc === 'string') { + const key = keyOrFunc + if (caseless) { + newFunc = input => input.toString().toLowerCase() === key.toLowerCase() + } else { + newFunc = input => input.toString() === key + } + } + input[prop] = keyBuf => newFunc(keyBuf) || oldFunc(keyBuf) } -addKey('isDown', 'j') -addKey('isUp', 'k') -// Don't use these for now... currently L is used for toggling loop. -// May want to look into changing that (so we can re-enable these). -// addKey('isLeft', 'h') -// addKey('isRight', 'l') +for (const entry of keyBindings) { + addKey(...entry) +} + +// Some things just need to be overridden in order for the rest of tui-lib to +// recognize our new keys. +telc.isUp = input.isUp +telc.isDown = input.isDown +telc.isLeft = input.isLeft +telc.isRight = input.isRight +telc.isSelect = input.isSelect +telc.isBackspace = input.isBackspace class AppElement extends FocusElement { constructor() { @@ -434,27 +506,27 @@ class AppElement extends FocusElement { return } - if (telc.isRight(keyBuf)) { + if (input.isRight(keyBuf)) { this.seekAhead(10) - } else if (telc.isLeft(keyBuf)) { + } else if (input.isLeft(keyBuf)) { this.seekBack(10) - } else if (telc.isSpace(keyBuf)) { + } else if (input.isTogglePause(keyBuf)) { this.togglePause() - } else if (telc.isCaselessLetter(keyBuf, 'l')) { + } else if (input.isToggleLoop(keyBuf)) { this.toggleLoop() - } else if (telc.isCharacter(keyBuf, 'v')) { + } else if (input.isVolumeUp(keyBuf)) { this.volUp() - } else if (telc.isCharacter(keyBuf, 'V')) { + } else if (input.isVolumeDown(keyBuf)) { this.volDown() - } else if (telc.isEscape(keyBuf)) { + } else if (input.isStop(keyBuf)) { this.clearPlayingTrack() - } else if (telc.isShiftUp(keyBuf) || telc.isCaselessLetter(keyBuf, 'p')) { + } else if (input.isSkipBack(keyBuf)) { this.playPreviousTrack(this.playingTrack, true) - } else if (telc.isShiftDown(keyBuf) || telc.isCaselessLetter(keyBuf, 'n')) { + } else if (input.isSkipAhead(keyBuf)) { this.playNextTrack(this.playingTrack, true) - } else if (telc.isCharacter(keyBuf, '1') && this.tabber.selectable) { + } else if (input.isFocusTabber(keyBuf) && this.tabber.selectable) { this.root.select(this.tabber) - } else if (telc.isCharacter(keyBuf, '2') && this.queueListingElement.selectable) { + } else if (input.isFocusQueue(keyBuf) && this.queueListingElement.selectable) { this.root.select(this.queueListingElement) } else if (keyBuf.equals(Buffer.from([5]))) { // Ctrl-E this.editMode = !this.editMode @@ -1597,11 +1669,11 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement { } keyPressed(keyBuf) { - if (telc.isCaselessLetter(keyBuf, 'd')) { + if (input.isDownload(keyBuf)) { this.emit('download') - } else if (telc.isCharacter(keyBuf, 'q')) { + } else if (input.isQueueAtEnd(keyBuf)) { this.emit('queue', {where: 'end'}) - } else if (telc.isCharacter(keyBuf, 'Q')) { + } else if (input.isQueueAtStart(keyBuf)) { this.emit('queue', {where: 'next'}) } else if (telc.isEnter(keyBuf)) { if (isGroup(this.item)) { @@ -1609,9 +1681,9 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement { } else { this.emit('queue', {where: 'next', play: true}) } - } else if (telc.isCaselessLetter(keyBuf, 'x')) { + } else if (input.isRemove(keyBuf)) { this.emit('remove') - } else if (telc.isCaselessLetter(keyBuf, 'm') || telc.isCaselessLetter(keyBuf, 'f')) { + } else if (input.isMenu(keyBuf)) { this.emit('menu', this) } } @@ -1800,9 +1872,9 @@ class QueueListingElement extends GrouplikeListingElement { } keyPressed(keyBuf) { - if (telc.isCaselessLetter(keyBuf, 's')) { + if (input.isShuffleQueue(keyBuf)) { this.emit('shuffle') - } else if (telc.isCaselessLetter(keyBuf, 'c')) { + } else if (input.isClearQueue(keyBuf)) { this.emit('clear') } else { return super.keyPressed(keyBuf) -- cgit 1.3.0-6-gf8a5