« 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--playlist-utils.js42
-rw-r--r--todo.txt1
-rw-r--r--ui.js7
3 files changed, 22 insertions, 28 deletions
diff --git a/playlist-utils.js b/playlist-utils.js
index e6d8947..d2a0bad 100644
--- a/playlist-utils.js
+++ b/playlist-utils.js
@@ -197,35 +197,20 @@ function shuffleOrderOfGroups(grouplike) {
   // *if* you also did --collapse-groups first. That was how shuffle-groups was
   // usually used (by me) anyway, so I figure bringing it over (with simpler
   // code) is reasonable. The only potentially confusing part is the behavior
-  // when a group contains both tracks and groups (the tracks are all
-  // considered "leftover" and randomly shuffled between the flat groups in the
-  // end result)... but I couldn't think of any better way to incorporate such
-  // "leftover" items into the result.)
-
-  // First filter the given grouplike into a list of "flat" groups, which are
-  // groups that only contain tracks - no groups. When a group contains both
-  // groups and tracks, add these "leftover" tracks to the list too.
-  const flatItems = []
-  const recursive = group => {
-    for (const item of group.items) {
-      if (isGroup(item) && item.items.every(isTrack)) {
-        flatItems.push(item)
-      } else if (isGroup(item)) {
-        recursive(item)
-      } else {
-        flatItems.push(item)
-      }
-    }
-  }
-  recursive(grouplike)
-
-  // Now shuffle this list of groups (and potentially tracks). This won't
-  // shuffle the *contents* of the groups; only the order in which the whole
-  // list of groups (and tracks) plays.
-  const shuffled = shuffleArray(flatItems)
+  // when a group contains both tracks and groups (the extra tracks in each
+  // group are collected together and considered "leftover", and are treated as
+  // their own ordered flat groups).
+
+  // Shuffle the list of groups (and potentially tracks). This won't shuffle
+  // the *contents* of the groups; only the order in which the whole list of
+  // groups (and tracks) plays.
+  const { items } = collapseGrouplike(grouplike)
+  return {items: shuffleArray(items)}
+}
 
-  // And we're done! Return the shuffled list as a grouplike.
-  return {items: shuffled}
+function reverseOrderOfGroups(grouplike) {
+  const { items } = collapseGrouplike(grouplike)
+  return {items: items.reverse()}
 }
 
 function collectGrouplikeChildren(grouplike, filter = null) {
@@ -621,6 +606,7 @@ module.exports = {
   filterTracks,
   flattenGrouplike, countTotalItems,
   shuffleOrderOfGroups,
+  reverseOrderOfGroups,
   partiallyFlattenGrouplike, collapseGrouplike,
   filterGrouplikeByProperty,
   filterPlaylistByPathString, filterGrouplikeByPath,
diff --git a/todo.txt b/todo.txt
index f4b93f4..0a3d5e6 100644
--- a/todo.txt
+++ b/todo.txt
@@ -264,6 +264,7 @@ TODO: An "interweaved" option in the "order" picker - works like putting every
 
 TODO: A "reverse" option in the order picker! Also a "reverse order of groups"
       or something, cuz why not yo.
+      (Done!)
 
 TODO: The context menu crashes when the input spans across the screen! Need to
       figure out some kind of "fix layout according to max dimensions" code in
diff --git a/ui.js b/ui.js
index 2b88b3a..e73d8f5 100644
--- a/ui.js
+++ b/ui.js
@@ -20,6 +20,7 @@ const {
   isGroup,
   isTrack,
   parentSymbol,
+  reverseOrderOfGroups,
   searchForItem,
   shuffleOrderOfGroups
 } = require('./playlist-utils')
@@ -255,6 +256,8 @@ class AppElement extends FocusElement {
     this.orderControl = new InlineListPickerElement('Order?', [
       {value: 'shuffle', label: 'Shuffle all'},
       {value: 'shuffle-groups', label: 'Shuffle order of groups'},
+      {value: 'reverse', label: 'Reverse all'},
+      {value: 'reverse-groups', label: 'Reverse order of groups'},
       {value: 'normal', label: 'In order'}
     ])
 
@@ -934,6 +937,10 @@ class AppElement extends FocusElement {
         item = {items: shuffleArray(flattenGrouplike(item).items)}
       } else if (order === 'shuffle-groups') {
         item = shuffleOrderOfGroups(item)
+      } else if (order === 'reverse') {
+        item = {items: flattenGrouplike(item).items.reverse()}
+      } else if (order === 'reverse-groups') {
+        item = reverseOrderOfGroups(item)
       }
     } else {
       // Make it into a grouplike that just contains itself.