« get me outta code hell

S to shuffle queue - mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-06-04 23:25:36 -0300
committerFlorrie <towerofnix@gmail.com>2018-06-04 23:26:09 -0300
commit37aac405d924bd017a4d504c5a222eed3dae8884 (patch)
treeb7a95f82728b49ae112b32cbc3ca0ad128affbf9
parent6055638558a345904b41467839191a7143862d25 (diff)
S to shuffle queue
-rw-r--r--README.md1
-rw-r--r--general-util.js24
-rw-r--r--todo.txt2
-rw-r--r--ui.js13
4 files changed, 40 insertions, 0 deletions
diff --git a/README.md b/README.md
index aff943a..e0de494 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,7 @@
 * <kbd>Space</kbd>, <kbd>p</kbd>, or <kbd>k</kbd> - toggle pause
 * <kbd>Right</kbd> or <kbd>l</kbd> - seek ahead
 * <kbd>Left</kbd> or <kbd>j</kbd> - seek back
+* <kbd>s</kbd> - shuffle the queue
 * **In the main listing:**
   * <kbd>Enter</kbd> - if the selected item is a group, enter it; otherwise play it
   * <kbd>Backspace</kbd> - leave the current group (if in one)
diff --git a/general-util.js b/general-util.js
index 879219d..2ce7ed4 100644
--- a/general-util.js
+++ b/general-util.js
@@ -63,3 +63,27 @@ module.exports.downloadPlaylistFromOptionValue = function(arg) {
     return downloadPlaylistFromLocalPath(arg)
   }
 }
+
+module.exports.shuffleArray = function(array) {
+  // Shuffles the items in an array. Returns a new array (does not modify the
+  // passed array). Super-interesting post on how this algorithm works:
+  // https://bost.ocks.org/mike/shuffle/
+
+  const workingArray = array.slice(0)
+
+  let m = array.length
+
+  while (m) {
+    let i = Math.floor(Math.random() * m)
+    m--
+
+    // Stupid lol; avoids the need of a temporary variable!
+    Object.assign(workingArray, {
+      [m]: workingArray[i],
+      [i]: workingArray[m]
+    })
+  }
+
+  return workingArray
+}
+
diff --git a/todo.txt b/todo.txt
index 044a508..e190b31 100644
--- a/todo.txt
+++ b/todo.txt
@@ -4,6 +4,8 @@ TODO: A way to see the path of the currently selected item in any grouplike
       (Done!)
 
 TODO: A "shuffle queue" button!
+      (Half-way done -- the functionality is there, press "S", but there's no
+      button for it yet.)
 
 TODO: A "clear queue" button.
 
diff --git a/ui.js b/ui.js
index 47270bd..47c50a8 100644
--- a/ui.js
+++ b/ui.js
@@ -1,6 +1,7 @@
 const { getDownloaderFor } = require('./downloaders')
 const { getPlayer } = require('./players')
 const { parentSymbol, isGroup, isTrack, getItemPath } = require('./playlist-utils')
+const { shuffleArray } = require('./general-util')
 const ansi = require('./tui-lib/util/ansi')
 const Button = require('./tui-lib/ui/form/Button')
 const DisplayElement = require('./tui-lib/ui/DisplayElement')
@@ -143,11 +144,23 @@ class AppElement extends FocusElement {
     } else if (telc.isCharacter(keyBuf, '2') && this.queueListingElement.selectable) {
       this.form.curIndex = this.form.inputs.indexOf(this.queueListingElement)
       this.form.updateSelectedElement()
+    } else if (telc.isCaselessLetter(keyBuf, 's')) {
+      this.shuffleQueue()
     } else {
       super.keyPressed(keyBuf)
     }
   }
 
+  shuffleQueue() {
+    const queue = this.queueGrouplike
+    const index = queue.items.indexOf(this.playingTrack) + 1 // This is 0 if no track is playing
+    const initialItems = queue.items.slice(0, index)
+    const remainingItems = queue.items.slice(index)
+    const newItems = initialItems.concat(shuffleArray(remainingItems))
+    queue.items = newItems
+    this.queueListingElement.buildItems()
+  }
+
   handleSpacePressed(callback) {
     // Pauses/resumes if a track is currently playing; otherwise, calls the
     // callback function.