« 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.txt1
-rw-r--r--ui.js138
2 files changed, 106 insertions, 33 deletions
diff --git a/todo.txt b/todo.txt
index ad1ebac..dadbca7 100644
--- a/todo.txt
+++ b/todo.txt
@@ -589,6 +589,7 @@ TODO: Show the current chunk of a track you're on according to its timestamps,
 
       Possibly tricky, but try to make this tie in with the "time since/until"
       indicator thingies at the bottom of the queue listing element too!
+      (Done - both parts!)
 
 TODO: Some kind of timestamp indicator in the progress bar area??? E.g, name
       of the current timestamp, and MAYBE some kind of visual breakup of the
diff --git a/ui.js b/ui.js
index 0383807..c62f93a 100644
--- a/ui.js
+++ b/ui.js
@@ -1819,7 +1819,12 @@ class AppElement extends FocusElement {
 
     const { playingTrack, timeData } = this.SQP
     const { items } = this.SQP.queueGrouplike
-    const { currentItem: selectedTrack } = this.queueListingElement
+    const {
+      currentInput: selectedInput,
+      currentItem: selectedTrack
+    } = this.queueListingElement
+
+    const isTimestamp = (selectedInput instanceof TimestampGrouplikeItemElement)
 
     let trackRemainSec = 0
     let trackPassedSec = 0
@@ -1832,6 +1837,7 @@ class AppElement extends FocusElement {
 
     const playingIndex = items.indexOf(playingTrack)
     const selectedIndex = items.indexOf(selectedTrack)
+    const timestampData = playingTrack && this.getTimestampData(playingTrack)
 
     // 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
@@ -1854,7 +1860,10 @@ class AppElement extends FocusElement {
       durationRange = items
       durationAdd = 0
       durationSymbol = ''
-    } else if (selectedIndex === playingIndex) {
+    } else if (
+      selectedIndex === playingIndex &&
+      (!isTimestamp || selectedInput.isCurrentTimestamp)
+    ) {
       // Remaining length of the queue.
       if (timeData) {
         durationRange = items.slice(playingIndex + 1)
@@ -1864,20 +1873,40 @@ class AppElement extends FocusElement {
         durationAdd = 0
       }
       durationSymbol = ''
-    } else if (selectedIndex < playingIndex) {
+    } else if (
+      selectedIndex < playingIndex ||
+      (isTimestamp && selectedInput.data.timestamp <= trackPassedSec)
+    ) {
       // 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) {
+      if (isTimestamp) {
+        if (selectedIndex < playingIndex) {
+          durationRange.unshift(items[selectedIndex])
+        }
+        durationAdd -= selectedInput.data.timestampEnd
+      }
+    } else if (
+      selectedIndex > playingIndex ||
+      (isTimestamp && selectedInput.data.timestamp > trackPassedSec)
+    ) {
       // Time until the selected track begins.
       if (timeData) {
-        durationRange = items.slice(playingIndex + 1, selectedIndex)
-        durationAdd = trackRemainSec
+        if (selectedIndex === playingIndex) {
+          durationRange = []
+          durationAdd = -trackPassedSec
+        } else {
+          durationRange = items.slice(playingIndex + 1, selectedIndex)
+          durationAdd = trackRemainSec
+        }
       } else {
         durationRange = items.slice(playingIndex, selectedIndex)
         durationAdd = 0
       }
+      if (isTimestamp) {
+        durationAdd += selectedInput.data.timestamp
+      }
       durationSymbol = '+'
     }
 
@@ -1890,18 +1919,53 @@ class AppElement extends FocusElement {
 
     let collapseExtraInfo = false
     if (playingTrack) {
-      let insertString
-      const distance = Math.abs(selectedIndex - playingIndex)
-      if (selectedIndex < playingIndex) {
-        insertString = ` (-${distance})`
-        collapseExtraInfo = true
-      } else if (selectedIndex > playingIndex) {
-        insertString = ` (+${distance})`
-        collapseExtraInfo = true
+      let trackPart
+
+      {
+        const distance = Math.abs(selectedIndex - playingIndex)
+
+        let insertString
+        if (selectedIndex < playingIndex) {
+          insertString = ` (-${distance})`
+          collapseExtraInfo = true
+        } else if (selectedIndex > playingIndex) {
+          insertString = ` (+${distance})`
+          collapseExtraInfo = true
+        } else {
+          insertString = ''
+        }
+
+        trackPart = `${playingIndex + 1 + insertString} / ${items.length}`
+      }
+
+      let timestampPart
+
+      if (isTimestamp && selectedIndex === playingIndex) {
+        const selectedTimestampIndex = timestampData.indexOf(selectedInput.data)
+
+        const found = timestampData.findIndex(ts => ts.timestamp > timeData.curSecTotal)
+        const playingTimestampIndex = (found >= 0 ? found - 1 : 0)
+        const distance = Math.abs(selectedTimestampIndex - playingTimestampIndex)
+
+        let insertString
+        if (selectedTimestampIndex < playingTimestampIndex) {
+          insertString = ` (-${distance})`
+          collapseExtraInfo = true
+        } else if (selectedTimestampIndex > playingTimestampIndex) {
+          insertString = ` (+${distance})`
+          collapseExtraInfo = true
+        } else {
+          insertString = ''
+        }
+
+        timestampPart = `${playingTimestampIndex + 1 + insertString} / ${timestampData.length}`
+      }
+
+      if (timestampPart) {
+        this.queueLengthLabel.text = `(${this.SQP.playSymbol} ${trackPart} : ${timestampPart})`
       } else {
-        insertString = ''
+        this.queueLengthLabel.text = `(${this.SQP.playSymbol} ${trackPart})`
       }
-      this.queueLengthLabel.text = `(${this.SQP.playSymbol} ${playingIndex + 1 + insertString} / ${items.length})`
     } else {
       this.queueLengthLabel.text = `(${items.length})`
     }
@@ -2240,7 +2304,7 @@ class GrouplikeListingElement extends Form {
       // Generate some items! Just go over the data list and generate one for
       // each timestamp.
       const tsElements = timestampData.map(ts => {
-        const el = new TimestampGrouplikeItemElement(item, ts.timestamp, ts.timestampEnd, ts.comment, this.app)
+        const el = new TimestampGrouplikeItemElement(item, ts, this.app)
         el.on('pressed', () => this.emit('timestamp', item, ts.timestamp))
         return el
       })
@@ -2471,9 +2535,13 @@ class GrouplikeListingElement extends Form {
   }
 
   get currentItem() {
-    const element = this.form.inputs[this.form.curIndex] || null
+    const element = this.currentInput
     return element && element.item
   }
+
+  get currentInput() {
+    return this.form.inputs[this.form.curIndex] || null
+  }
 }
 
 class GrouplikeListingForm extends ListScrollForm {
@@ -3426,21 +3494,21 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
 }
 
 class TimestampGrouplikeItemElement extends BasicGrouplikeItemElement {
-  constructor(item, timestamp, timestampEnd, comment, app) {
+  constructor(item, timestampData, app) {
     super('')
 
     this.app = app
-    this.timestamp = timestamp
-    this.timestampEnd = timestampEnd
-    this.comment = comment
+    this.data = timestampData
     this.item = item
   }
 
   drawTo(writable) {
+    const { data } = this
+
     const metadata = this.app.backend.getMetadataFor(this.item)
     const duration = (metadata && metadata.duration) || 0
-    const strings = getTimeStringsFromSec(this.timestamp, duration)
-    const stringsEnd = getTimeStringsFromSec(this.timestampEnd, duration)
+    const strings = getTimeStringsFromSec(data.timestamp, duration)
+    const stringsEnd = getTimeStringsFromSec(data.timestampEnd, duration)
 
     this.text = (
       /*
@@ -3449,8 +3517,8 @@ class TimestampGrouplikeItemElement extends BasicGrouplikeItemElement {
         : `(${strings.timeDone})`) +
         */
       `(${strings.timeDone})` +
-      (this.comment
-        ? ` ${this.comment}`
+      (data.comment
+        ? ` ${data.comment}`
         : '')
     )
 
@@ -3463,13 +3531,7 @@ class TimestampGrouplikeItemElement extends BasicGrouplikeItemElement {
     const color = ansi.setAttributes([ansi.A_BRIGHT, ansi.C_CYAN])
     const reset = ansi.setAttributes([ansi.C_RESET])
 
-    const { SQP } = this.app
-    if (
-      SQP.playingTrack === this.item &&
-      SQP.timeData &&
-      SQP.timeData.curSecTotal >= this.timestamp &&
-      SQP.timeData.curSecTotal < this.timestampEnd
-    ) {
+    if (this.isCurrentTimestamp) {
       parts = [
         color,
         ' ',
@@ -3496,6 +3558,16 @@ class TimestampGrouplikeItemElement extends BasicGrouplikeItemElement {
     this.drawX += 4
   }
 
+  get isCurrentTimestamp() {
+    const { SQP } = this.app
+    return (
+      SQP.playingTrack === this.item &&
+      SQP.timeData &&
+      SQP.timeData.curSecTotal >= this.data.timestamp &&
+      SQP.timeData.curSecTotal < this.data.timestampEnd
+    )
+  }
+
   getLeftPadding() {
     return 4
   }