« 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.js68
1 files changed, 45 insertions, 23 deletions
diff --git a/ui.js b/ui.js
index de01ace..43fd2b3 100644
--- a/ui.js
+++ b/ui.js
@@ -361,14 +361,16 @@ class AppElement extends FocusElement {
       {text: 'Multi', menuFn: () => {
         const { queuePlayers } = this.backend
         return [
-          {label: `(Multi-players - ${queuePlayers.length})`},
+          {key: 'heading', label: `(Multi-players - ${queuePlayers.length})`},
           {divider: true},
           ...queuePlayers.map((queuePlayer, index) => {
             const PIE = new PlaybackInfoElement(queuePlayer, this)
             PIE.displayMode = 'collapsed'
             PIE.updateTrack()
-            return {element: PIE}
-          })
+            return {key: 'qp' + index, element: PIE}
+          }),
+          {divider: true},
+          {key: 'add-new-player', label: `Add new player`, action: () => this.addQueuePlayer().then(() => 'reload')}
         ]
       }}
     ])
@@ -505,6 +507,9 @@ class AppElement extends FocusElement {
 
   handleRemovedQueuePlayer(queuePlayer) {
     this.removeQueuePlayerListenersAndUI(queuePlayer)
+    if (this.menubar.contextMenu) {
+      setTimeout(() => this.menubar.contextMenu.reload(), 0)
+    }
   }
 
   async handlePlaying(track, oldTrack, queuePlayer) {
@@ -3227,15 +3232,6 @@ class PlaybackInfoElement extends FocusElement {
           action: () => {
             const { parent } = this
             this.app.removeQueuePlayer(this.queuePlayer)
-            if (parent) {
-              parent.removeInput(this)
-              parent.fixLayout()
-              // uhhh for some reason this selects the app instead of the form
-              // for all the PIEs? not sure why but it probably has to do with
-              // context menu shenanigans. it's currently 29:50 and i am really
-              // definitely not going to try to figure that out right now!
-              parent.root.select(parent)
-            }
           }
         }
       ]
@@ -3695,7 +3691,16 @@ class ContextMenu extends FocusElement {
     this.submenu = null
   }
 
-  show({x = 0, y = 0, items}) {
+  show({x = 0, y = 0, items: itemsArg, focusKey = null}) {
+    this.reload = () => {
+      const els = [this.root.selectedElement, ...this.root.selectedElement.directAncestors]
+      const focusKey = Object.keys(keyElementMap).find(key => els.includes(keyElementMap[key]))
+      this.close(false)
+      this.show({x, y, items: itemsArg, focusKey})
+    }
+
+    let items = (typeof itemsArg === 'function') ? itemsArg() : itemsArg
+
     items = items.filter(Boolean)
     if (!items.length) {
       return
@@ -3722,9 +3727,13 @@ class ContextMenu extends FocusElement {
       }
     }
 
+    const keyElementMap = {}
+
     for (const item of items.filter(Boolean)) {
+      let focusEl
       if (item.element) {
         addDividerIfWanted()
+        focusEl = item.element
         this.form.addInput(item.element)
         item.element.showContextMenu = this.showSubmenu
         if (item.isDefault) {
@@ -3737,21 +3746,30 @@ class ContextMenu extends FocusElement {
         const button = new Button(item.label)
         button.keyboardIdentifier = item.keyboardIdentifier || item.label
         if (item.action) {
-          button.on('pressed', () => {
-            this.close()
-            item.action()
+          button.on('pressed', async () => {
+            if (await item.action() === 'reload') {
+              this.reload()
+            } else {
+              this.close()
+            }
           })
         }
+        focusEl = button
         this.form.addInput(button)
         if (item.isDefault) {
           this.root.select(button)
         }
       }
+      if (item.key) {
+        keyElementMap[item.key] = focusEl
+      }
     }
 
     this.fixLayout()
 
-    if (!items.some(item => item.isDefault)) {
+    if (focusKey && keyElementMap[focusKey]) {
+      this.root.select(keyElementMap[focusKey])
+    } else if (!items.some(item => item.isDefault)) {
       this.form.firstInput()
     }
 
@@ -3799,16 +3817,20 @@ class ContextMenu extends FocusElement {
     if (this.visible) {
       const newlySelected = this.root.selectedElement
       this.close()
-      this.selectedBefore.root.select(newlySelected)
+      newlySelected.root.select(newlySelected)
     }
   }
 
-  close() {
+  close(remove = true) {
     this.clearItems()
     this.visible = false
-    this.selectedBefore.root.select(this.selectedBefore)
-    this.parent.removeChild(this)
-    this.emit('closed')
+    if (this.selectedBefore.root.select) {
+      this.selectedBefore.root.select(this.selectedBefore)
+    }
+    if (remove && this.parent) {
+      this.parent.removeChild(this)
+      this.emit('closed')
+    }
   }
 
   clearItems() {
@@ -4039,7 +4061,7 @@ class Menubar extends ListScrollForm {
       button.on('pressed', () => {
         this.contextMenu = this.showContextMenu({
           x: container.absLeft, y: container.absY + 1,
-          items: menuFn ? menuFn() : menuItems
+          items: menuFn
         })
         this.contextMenu.on('closed', () => {
           this.contextMenu = null