« 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.txt11
-rw-r--r--ui.js98
2 files changed, 85 insertions, 24 deletions
diff --git a/todo.txt b/todo.txt
index 148bd17..8bfc682 100644
--- a/todo.txt
+++ b/todo.txt
@@ -510,3 +510,14 @@ TODO: Revisit labels and notes features! They're commented out for now :P
 TODO: Pressing "Reveal" should focus the main listing. This is prrrrobably a
       case of context menu selection-restoring being a pain.
       (Done!)
+
+TODO: When a track besides the currently playing one is selected in the queue
+      listing, display the time either *until the track starts* or *since the
+      track ended* appropriately, ala "+03:45" or "-1:32:17", in the queue
+      time label (which is positioned at the bottom of the queue listing).
+      (Done!)
+
+TODO: In that regard, also change the queue length label (just above the time
+      label) to indicate which track is selected --- RELATIVE to the current
+      track, ala "40 (+5) / 1032" or "5 (-1) / 10".
+      (Done!)
diff --git a/ui.js b/ui.js
index d223f18..81df56e 100644
--- a/ui.js
+++ b/ui.js
@@ -258,6 +258,7 @@ class AppElement extends FocusElement {
     this.queueTimeLabel = new Label('')
     this.queuePane.addChild(this.queueTimeLabel)
 
+    this.queueListingElement.on('select', item => this.updateQueueLengthLabel())
     this.queueListingElement.on('open', item => this.openSpecialOrThroughSystem(item))
     this.queueListingElement.on('queue', item => this.play(item))
     this.queueListingElement.on('remove', item => this.unqueue(item))
@@ -1213,7 +1214,7 @@ class AppElement extends FocusElement {
       this.alignPartyLabel()
     }
 
-    const leftWidth = Math.max(Math.floor(0.8 * this.contentW), this.contentW - 80)
+    const leftWidth = Math.max(Math.floor(0.7 * this.contentW), this.contentW - 80)
 
     /*
     if (this.textInfoPane.visible) {
@@ -1537,42 +1538,91 @@ class AppElement extends FocusElement {
 
     const { playingTrack, timeData } = this.SQP
     const { items } = this.SQP.queueGrouplike
+    const { currentItem: selectedTrack } = this.queueListingElement
 
     let trackRemainSec = 0
+    let trackPassedSec = 0
 
     if (timeData) {
       const { curSecTotal = 0, lenSecTotal = 0 } = timeData
       trackRemainSec = lenSecTotal - curSecTotal
+      trackPassedSec = curSecTotal
+    }
+
+    const playingIndex = items.indexOf(playingTrack)
+    const selectedIndex = items.indexOf(selectedTrack)
+
+    // This will be set to a list of tracks, which will later be used to
+    // calculate a particular duration (as described below) to be shown in
+    // the time label.
+    let durationRange
+
+    // This will be added to the calculated duration before it is displayed.
+    // It's used to account for the time of the current track, if that is
+    // relevant to the particular duration being calculated.
+    let durationAdd
+
+    // This will be stuck behind the final duration when it is displayed. It's
+    // used to indicate the "direction" of the calculated duration to the user.
+    let durationSymbol
+
+    // Depending on which track is selected relative to which track is playing
+    // (and on whether any track is playing at all), display...
+    if (!playingTrack) {
+      // Full length of the queue.
+      durationRange = items
+      durationAdd = 0
+      durationSymbol = ''
+    } else if (selectedIndex === playingIndex) {
+      // Remaining length of the queue.
+      if (timeData) {
+        durationRange = items.slice(playingIndex + 1)
+        durationAdd = trackRemainSec
+      } else {
+        durationRange = items.slice(playingIndex)
+        durationAdd = 0
+      }
+      durationSymbol = ''
+    } else if (selectedIndex < playingIndex) {
+      // Time since the selected track ended.
+      durationRange = items.slice(selectedIndex + 1, playingIndex)
+      durationAdd = trackPassedSec // defaults to 0: no need to check timeData
+      durationSymbol = '-'
+    } else if (selectedIndex > playingIndex) {
+      // Time until the selected track begins.
+      if (timeData) {
+        durationRange = items.slice(playingIndex + 1, selectedIndex)
+        durationAdd = trackRemainSec
+      } else {
+        durationRange = items.slice(playingIndex, selectedIndex)
+        durationAdd = 0
+      }
+      durationSymbol = '+'
     }
 
-    // Index of tracks "ahead" of the current track. All tracks before this
-    // index are accounted for by either being behind the current track (and
-    // thus ignorable) or being the current track (and thus having its
-    // remaining duration be counted by the time data stored on the playback
-    // info element).
-    let index = 0
+    // Use the duration* variables to calculate and display the specified
+    // duration.
+    const { seconds: durationCalculated, approxSymbol } = this.backend.getDuration({items: durationRange})
+    const durationTotal = durationCalculated + durationAdd
+    const { duration: durationString } = getTimeStringsFromSec(0, durationTotal)
+    this.queueTimeLabel.text = `(${durationSymbol + durationString + approxSymbol})`
 
     if (playingTrack) {
-      index = items.indexOf(playingTrack)
-      // If it's NOT counted by the playback info element's time data yet,
-      // we skip this - the current track is counted as "ahead" and its
-      // duration will be tallied like the rest of the "ahead" tracks.
-      if (timeData) {
-        index++
+      let insertString
+      const distance = Math.abs(selectedIndex - playingIndex)
+      if (selectedIndex < playingIndex) {
+        insertString = ` (-${distance})`
+      } else if (selectedIndex > playingIndex) {
+        insertString = ` (+${distance})`
+      } else {
+        insertString = ''
       }
+      this.queueLengthLabel.text = `(${this.SQP.playSymbol} ${playingIndex + insertString} / ${items.length})`
+    } else {
+      this.queueLengthLabel.text = `(${items.length})`
     }
 
-    const { seconds: aheadRemainSec, approxSymbol } = this.backend.getDuration({items: items.slice(index)})
-    const totalRemainSec = trackRemainSec + aheadRemainSec
-
-    const { duration } = getTimeStringsFromSec(0, totalRemainSec)
-
-    this.queueLengthLabel.text = (playingTrack && items.includes(playingTrack)
-      ? `(${this.SQP.playSymbol} ${index} / ${items.length})`
-      : `(${items.length})`)
-
-    this.queueTimeLabel.text = `(${duration + approxSymbol})`
-
+    // Layout stuff to position the length and time labels correctly.
     this.queueLengthLabel.centerInParent()
     this.queueTimeLabel.centerInParent()
     this.queueLengthLabel.y = this.queuePane.contentH - 2