« get me outta code hell

Only render when stuff on-screen actually changes! - mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/ui.js
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2019-09-15 17:17:31 -0300
committerFlorrie <towerofnix@gmail.com>2019-09-15 17:17:31 -0300
commit8053f12b63e272cc9119a30f9ddc480b5ea75641 (patch)
treee52eee3680eef45032cbc5acc3e49838b9fc6378 /ui.js
parent6be85bb511f9e3e55ab503c9b8b44afb31b84f2d (diff)
Only render when stuff on-screen actually changes!
This means we can basically guarantee 0% CPU usage when nothing on the
screen is changing! There may still be some kinks to work out, but I've
tested most features and fixed any apparent bugs (including an unrelated
bug in the suspend feature which made it crash when resuming the process).
Diffstat (limited to 'ui.js')
-rw-r--r--ui.js36
1 files changed, 31 insertions, 5 deletions
diff --git a/ui.js b/ui.js
index c6bb448..f425048 100644
--- a/ui.js
+++ b/ui.js
@@ -1471,12 +1471,13 @@ class GrouplikeListingForm extends ListScrollForm {
   }
 
   set curIndex(newIndex) {
-    this._curIndex = newIndex
+    this.setDep('curIndex', newIndex)
     this.emit('selected input', this.inputs[this.curIndex])
+    return newIndex
   }
 
   get curIndex() {
-    return this._curIndex
+    return this.getDep('curIndex')
   }
 
   get firstItemIndex() {
@@ -1889,6 +1890,14 @@ class InlineListPickerElement extends FocusElement {
   }
 }
 
+// Quite hacky, but ATM I can't think of any way to neatly tie getDep/setDep
+// into the slider and toggle elements.
+const drawAfter = (fn, thisObj) => (...args) => {
+  const ret = fn(...args)
+  thisObj.scheduleDrawWithoutPropertyChange()
+  return ret
+}
+
 class SliderElement extends FocusElement {
   // Same general principle and usage as InlineListPickerElement, but for
   // changing a numeric value.
@@ -1896,7 +1905,7 @@ class SliderElement extends FocusElement {
   constructor(labelText, {setValue, getValue, maxValue = 100, percent = true, getEnabled = () => true}) {
     super()
     this.labelText = labelText
-    this.setValue = setValue
+    this.setValue = drawAfter(setValue, this)
     this.getValue = getValue
     this.getEnabled = getEnabled
     this.maxValue = maxValue
@@ -2036,7 +2045,7 @@ class ToggleControl extends FocusElement {
   constructor(labelText, {setValue, getValue, getEnabled = () => true}) {
     super()
     this.labelText = labelText
-    this.setValue = setValue
+    this.setValue = drawAfter(setValue, this)
     this.getValue = getValue
     this.getEnabled = getEnabled
     this.keyboardIdentifier = this.labelText
@@ -2549,8 +2558,12 @@ class PlaybackInfoElement extends DisplayElement {
   }
 
   updateProgress(timeData, player) {
-    this.timeData = timeData
     const {timeDone, duration, lenSecTotal, curSecTotal} = timeData
+    this.timeData = timeData
+    this.curSecTotal = curSecTotal
+    this.lenSecTotal = lenSecTotal
+    this.volume = player.volume
+    this.isLooping = player.isLooping
 
     this.progressBarLabel.text = '-'.repeat(Math.floor(this.w / lenSecTotal * curSecTotal))
     this.progressTextLabel.text = timeDone + ' / ' + duration
@@ -2585,6 +2598,15 @@ class PlaybackInfoElement extends DisplayElement {
     this.timeData = {}
     this.fixLayout()
   }
+
+  get curSecTotal() { return this.getDep('curSecTotal') }
+  set curSecTotal(v) { return this.setDep('curSecTotal', v) }
+  get lenSecTotal() { return this.getDep('lenSecTotal') }
+  set lenSecTotal(v) { return this.setDep('lenSecTotal', v) }
+  get volume() { return this.getDep('volume') }
+  set volume(v) { return this.setDep('volume', v) }
+  get isLooping() { return this.getDep('isLooping') }
+  set isLooping(v) { return this.setDep('isLooping', v) }
 }
 
 class OpenPlaylistDialog extends Dialog {
@@ -3310,6 +3332,10 @@ class PartyBanner extends DisplayElement {
   drawTo(writable) {
     writable.write(ansi.moveCursor(this.absTop, this.absLeft))
 
+    // TODO: Figure out how to connect this to the draw dependency system.
+    // Currently the party banner doesn't schedule any renders itself (meaning
+    // if you have nothing playing or otherwise rendering, it'll just stay
+    // still).
     const timerNum = Date.now() / 2000 * this.direction
     let lastAttribute = ''
     const updateAttribute = offsetNum => {