« get me outta code hell

mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--todo.txt7
-rw-r--r--ui.js63
2 files changed, 38 insertions, 32 deletions
diff --git a/todo.txt b/todo.txt
index 1993e64..680f5e9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -99,3 +99,10 @@ TODO: Only show scrollbars if the form is actually scrollable. (This would make
 
 TODO: "Play" (now), in the context menu, should act like a queue-up-next, not a
       queue-at-end. (Done!)
+
+TODO: Make the queue code more sane.
+      (Done!)
+
+TODO: Figure out when the "queue" context menu options should immediately play
+      the track. Currently, they don't ever initiate playing (besides the
+      "Play now" option).
diff --git a/ui.js b/ui.js
index a7df2b3..98efd96 100644
--- a/ui.js
+++ b/ui.js
@@ -25,13 +25,6 @@ const fs = require('fs')
 const { promisify } = require('util')
 const writeFile = promisify(fs.writeFile)
 
-// TODO: Come up with a better name for this
-const Flags = {
-  playNow: Symbol(),
-  playIfNothingElse: Symbol(),
-  shuffleGroup: Symbol()
-}
-
 class AppElement extends FocusElement {
   constructor() {
     super()
@@ -127,13 +120,27 @@ class AppElement extends FocusElement {
     grouplikeListing.on('select (enter)', item => handleSelectFromMain(item))
     grouplikeListing.on('select (space)', item => this.handleSpacePressed(
       () => handleSelectFromMain(item)))
-    grouplikeListing.on('play', item => this.playGrouplikeItem(item))
-    grouplikeListing.on('queue (at end)', item => this.queueGrouplikeItem(item))
-    grouplikeListing.on('queue (at end, shuffled)', item => this.shuffleQueueGrouplikeItem(item))
-    grouplikeListing.on('queue (play next)', item => this.queueGrouplikeItem(item, Flags.playIfNothingElse, this.playingTrack))
-    grouplikeListing.on('queue (play next, shuffled)', item => this.shuffleQueueGrouplikeItem(item, Flags.playIfNothingElse, this.playingTrack))
     grouplikeListing.on('menu', (item, opts) => this.menu.show(opts))
 
+    grouplikeListing.on('queue', (item, {where = 'end', shuffle = false, play = false}) => {
+      if (isGroup(item) && shuffle) {
+        item = {items: shuffleArray(flattenGrouplike(item).items)}
+      }
+
+      let afterItem
+      if (where === 'end') {
+        afterItem = null
+      } else {
+        afterItem = this.playingTrack
+      }
+
+      this.queueGrouplikeItem(item, afterItem)
+
+      if (play) {
+        this.playGrouplikeItem(item)
+      }
+    })
+
     const updateListingsFor = item => {
       for (const grouplikeListing of this.tabber.tabberElements) {
         if (grouplikeListing.grouplike === item) {
@@ -450,7 +457,7 @@ class AppElement extends FocusElement {
     this.player.kill()
   }
 
-  async queueGrouplikeItem(topItem, play = Flags.playIfNothingElse, afterItem = null) {
+  async queueGrouplikeItem(topItem, afterItem = null) {
     const newTrackIndex = this.queueGrouplike.items.length
 
     const recursivelyAddTracks = item => {
@@ -489,12 +496,8 @@ class AppElement extends FocusElement {
 
     // This is the first new track, if a group was queued.
     const newTrack = this.queueGrouplike.items[newTrackIndex]
-    if (
-      play === Flags.playNow ||
-      (play === Flags.playIfNothingElse && !this.playingTrack && newTrack)
-    ) {
-      this.playGrouplikeItem(newTrack, false)
-    }
+
+    return newTrack
   }
 
   unqueueGrouplikeItem(topItem) {
@@ -554,7 +557,7 @@ class AppElement extends FocusElement {
     }
   }
 
-  async playGrouplikeItem(item, shouldQueue = true) {
+  async playGrouplikeItem(item) {
     if (this.player === null) {
       throw new Error('Attempted to play before a player was loaded')
     }
@@ -565,10 +568,6 @@ class AppElement extends FocusElement {
       playingThisTrack = false
     })
 
-    if (shouldQueue) {
-      this.queueGrouplikeItem(item, false, this.playingTrack)
-    }
-
     // If it's a group, play the first track.
     if (isGroup(item)) {
       item = flattenGrouplike(item).items[0]
@@ -788,7 +787,7 @@ class GrouplikeListingElement extends FocusElement {
     if (this.grouplike.items.length) {
       for (const item of this.grouplike.items) {
         const itemElement = new GrouplikeItemElement(item, this.recordStore)
-        for (const evtName of ['download', 'remove (backspace)', 'remove (x)', 'mark', 'select (space)', 'select (enter)', 'play', 'queue (at end)', 'queue (at end, shuffled)', 'queue (play next)', 'queue (play next, shuffled)', 'menu']) {
+        for (const evtName of ['download', 'remove (backspace)', 'remove (x)', 'mark', 'select (space)', 'select (enter)', 'queue', 'menu']) {
           itemElement.on(evtName, (...data) => this.emit(evtName, item, ...data))
         }
         form.addInput(itemElement)
@@ -955,9 +954,9 @@ class GrouplikeItemElement extends Button {
     if (telc.isCaselessLetter(keyBuf, 'd')) {
       this.emit('download')
     } else if (telc.isCharacter(keyBuf, 'q')) {
-      this.emit('queue (at end)')
+      this.emit('queue', {where: 'end'})
     } else if (telc.isCharacter(keyBuf, 'Q')) {
-      this.emit('queue (play next)')
+      this.emit('queue', {where: 'next'})
     } else if (telc.isSpace(keyBuf)) {
       this.emit('select (space)')
     } else if (telc.isEnter(keyBuf)) {
@@ -975,11 +974,11 @@ class GrouplikeItemElement extends Button {
         x: this.absLeft,
         y: this.absTop + 1,
         items: [
-          {label: 'Play', action: () => this.emit('play')},
-          {label: 'Play next', action: () => this.emit('queue (play next)')},
-          {label: 'Play at end', action: () => this.emit('queue (at end)')},
-          isGroup(this.item) && {label: 'Play next, shuffled', action: () => this.emit('queue (play next, shuffled)')},
-          isGroup(this.item) && {label: 'Play at end, shuffled', action: () => this.emit('queue (at end, shuffled)')}
+          {label: 'Play', action: () => this.emit('queue', {where: 'next', play: true})},
+          {label: 'Play next', action: () => this.emit('queue', {where: 'next'})},
+          {label: 'Play at end', action: () => this.emit('queue', {where: 'end'})},
+          isGroup(this.item) && {label: 'Play next, shuffled', action: () => this.emit('queue', {where: 'next', shuffle: true})},
+          isGroup(this.item) && {label: 'Play at end, shuffled', action: () => this.emit('queue', {where: 'end', shuffle: true})}
         ]
       })
     }