« 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--ui.js86
1 files changed, 81 insertions, 5 deletions
diff --git a/ui.js b/ui.js
index 076974f..f04b922 100644
--- a/ui.js
+++ b/ui.js
@@ -78,6 +78,7 @@ const keyBindings = [
   ['isShuffleQueue', 's'],
   ['isClearQueue', 'c'],
   ['isFocusMenubar', ';'],
+  ['isFocusLabels', 'l'],
 
   // Number pad
   ['isUp', '8'],
@@ -1183,8 +1184,12 @@ class GrouplikeListingElement extends Form {
       this.form.scrollToBeginning()
     } else if (telc.isCharacter(keyBuf, 'G')) {
       this.form.selectAndShow(this.grouplike.items[this.grouplike.items.length - 1])
-    } else if (keyBuf[0] === 12 && this.grouplike.isTheQueue) { // ctrl-L
-      this.form.selectAndShow(this.app.backend.playingTrack)
+    } else if (keyBuf[0] === 12) { // ctrl-L
+      if (this.grouplike.isTheQueue) {
+        this.form.selectAndShow(this.app.backend.playingTrack)
+      } else {
+        this.toggleExpandLabels()
+      }
     } else if (keyBuf[0] === 1) { // ctrl-A
       this.toggleSelectAll()
     } else {
@@ -1213,6 +1218,18 @@ class GrouplikeListingElement extends Form {
     }
   }
 
+  toggleExpandLabels() {
+    this.expandLabels = !this.expandLabels
+    for (const input of this.form.inputs) {
+      if (!(input instanceof InteractiveGrouplikeItemElement)) {
+        continue
+      }
+      if (!input.labelsSelected) {
+        input.expandLabels = this.expandLabels
+        input.computeText()
+      }
+    }
+  }
 
   buildItems(resetIndex = false) {
     if (!this.grouplike) {
@@ -1288,6 +1305,13 @@ class GrouplikeListingElement extends Form {
     for (const evtName of ['download', 'remove', 'mark', 'paste', 'browse', 'queue', 'unqueue', 'menu']) {
       itemElement.on(evtName, (...data) => this.emit(evtName, itemElement.item, ...data))
     }
+
+    itemElement.on('unselected labels', () => {
+      if (!this.expandLabels) {
+        itemElement.expandLabels = false
+        itemElement.computeText()
+      }
+    })
   }
 
   loadParentGrouplike() {
@@ -1555,6 +1579,10 @@ class BasicGrouplikeItemElement extends Button {
     return 2
   }
 
+  getSelfSelected() {
+    return this.isSelected
+  }
+
   computeText() {
     let w = this.w - this.x - this.getLeftPadding()
 
@@ -1587,7 +1615,7 @@ class BasicGrouplikeItemElement extends Button {
     // dimmed) even if you don't have the listing selected. To change that,
     // uncomment this and add it to the isCurrentInput line.
     // const isListingSelected = this.parent.parent.isSelected
-    const isSelfSelected = this.isSelected
+    const isSelfSelected = this.getSelfSelected()
 
     if (isSelfSelected) {
       writable.write(ansi.invert())
@@ -1950,6 +1978,7 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
     this.hideMetadata = false
     this.expandLabels = false
     this.labelsSelected = false
+    this.selectedLabelIndex = 0
   }
 
   drawTo(writable) {
@@ -1969,6 +1998,10 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
     this.computeText()
   }
 
+  unselected() {
+    this.unselectLabels()
+  }
+
   getLabelTexts() {
     const separator = this.isSelected ? '' : ''
     let labels = []
@@ -1979,7 +2012,11 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
     return labels.map((label, i) => {
       return [
         label,
-        separator + (this.expandLabels ? ' ' + label + ' ' : label[0])
+        separator + (this.expandLabels
+          ? (this.labelsSelected && i === this.selectedLabelIndex
+            ? `<${label}>`
+            : ` ${label} `)
+          : label[0])
       ]
     })
   }
@@ -2046,8 +2083,21 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
     return 3
   }
 
+  getSelfSelected() {
+    return !this.labelsSelected && super.getSelfSelected()
+  }
+
   keyPressed(keyBuf) {
-    if (input.isDownload(keyBuf)) {
+    if (this.labelsSelected) {
+      if (input.isRight(keyBuf)) {
+        this.selectNextLabel()
+      } else if (input.isLeft(keyBuf)) {
+        this.selectPreviousLabel()
+      } else if (telc.isEscape(keyBuf) || input.isFocusLabels(keyBuf)) {
+        this.unselectLabels()
+        return false
+      }
+    } else if (input.isDownload(keyBuf)) {
       this.emit('download')
     } else if (input.isQueueAtEnd(keyBuf)) {
       this.emit('queue', {where: 'end'})
@@ -2063,9 +2113,35 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
       this.emit('remove')
     } else if (input.isMenu(keyBuf)) {
       this.emit('menu', this)
+    } else if (input.isFocusLabels(keyBuf)) {
+      this.labelsSelected = true
+      this.expandLabels = true
+      this.selectedLabelIndex = 0
     }
   }
 
+  unselectLabels() {
+    this.labelsSelected = false
+    this.emit('unselected labels')
+    this.computeText()
+  }
+
+  selectNextLabel() {
+    this.selectedLabelIndex++
+    if (this.selectedLabelIndex >= this.getLabelTexts().length) {
+      this.selectedLabelIndex = 0
+    }
+    this.computeText()
+  }
+
+  selectPreviousLabel() {
+    this.selectedLabelIndex--
+    if (this.selectedLabelIndex < 0) {
+      this.selectedLabelIndex = this.getLabelTexts().length - 1
+    }
+    this.computeText()
+  }
+
   clicked(button, {ctrl}) {
     if (button === 'left') {
       if (this.isSelected) {