« 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--backend.js4
-rw-r--r--socket.js19
-rw-r--r--ui.js32
3 files changed, 47 insertions, 8 deletions
diff --git a/backend.js b/backend.js
index 205aad3..4c84b04 100644
--- a/backend.js
+++ b/backend.js
@@ -853,8 +853,8 @@ class Backend extends EventEmitter {
     return download(item, this.getRecordFor(item))
   }
 
-  showLogMessage(text, isVerbose = false) {
-    this.emit('log message', text, isVerbose)
+  showLogMessage(messageInfo) {
+    this.emit('log message', messageInfo)
   }
 }
 
diff --git a/socket.js b/socket.js
index efe3d07..c7fb023 100644
--- a/socket.js
+++ b/socket.js
@@ -419,9 +419,19 @@ function attachBackendToSocketClient(backend, client, {
   function logCommand(command) {
     const nickToMessage = nickname => `\x1b[32;1m${nickname}\x1b[0m`
     const itemToMessage = item => `\x1b[32m"${item.name}"\x1b[0m`
+
     let senderNickname = command.sender === 'server' ? 'the server' : command.senderNickname
+    // TODO: This should use a unique sender ID, provided by the server and
+    // corresponding to the socket. This could be implemented into the UI!
+    // But also, right now users can totally pretend to be the server by...
+    // setting their nickname to "the server", which is silly.
+    const sender = senderNickname
+
     let actionmsg = `sent ${command.code} (no action message specified)`
+    let code = command.code
+    let mayCombine = false
     let isVerbose = false
+
     switch (command.code) {
       case 'clear-queue':
         actionmsg = 'cleared the queue'
@@ -459,6 +469,7 @@ function attachBackendToSocketClient(backend, client, {
         // TODO: the second value here should be the duration of the track
         // (this will make values like 0:0x:yy / 1:xx:yy appear correctly)
         actionmsg = `seeked to ${getTimeStringsFromSec(command.time, command.time).timeDone}`
+        mayCombine = true
         break
       case 'set-nickname':
         actionmsg = `updated their nickname (from ${nickToMessage(command.oldNickname)})`
@@ -496,7 +507,13 @@ function attachBackendToSocketClient(backend, client, {
         break
     }
     const text = `${nickToMessage(senderNickname)} ${actionmsg}`
-    backend.showLogMessage(text, isVerbose)
+    backend.showLogMessage({
+      text,
+      code,
+      sender,
+      mayCombine,
+      isVerbose
+    })
   }
 
   client.on('sent-command', command => {
diff --git a/ui.js b/ui.js
index 3952c38..c948080 100644
--- a/ui.js
+++ b/ui.js
@@ -547,8 +547,8 @@ class AppElement extends FocusElement {
     }
   }
 
-  handleLogMessage(text, isVerbose) {
-    this.log.newLogMessage(text, isVerbose)
+  handleLogMessage(messageInfo) {
+    this.log.newLogMessage(messageInfo)
   }
 
   async handlePlayingDetails(track, oldTrack, queuePlayer) {
@@ -4591,12 +4591,27 @@ class Log extends ListScrollForm {
     super('vertical')
   }
 
-  newLogMessage(text, isVerbose = false) {
+  newLogMessage(messageInfo) {
     if (this.inputs.length === 10) {
       this.removeInput(this.inputs[0])
     }
 
-    const logMessage = new LogMessage(text, isVerbose)
+    if (messageInfo.mayCombine) {
+      // If a message is specified to "combine", it'll replace an immediately
+      // previous message of the same code and sender.
+      const previous = this.inputs[this.inputs.length - 1]
+      if (
+        previous &&
+        previous.info.code === messageInfo.code &&
+        previous.info.sender === messageInfo.sender
+      ) {
+        // If the code and sender match, just remove the previous message.
+        // It'll be replaced by the one we're about to add!
+        this.removeInput(previous)
+      }
+    }
+
+    const logMessage = new LogMessage(messageInfo)
     this.addInput(logMessage)
     this.fixLayout()
     this.scrollToEnd()
@@ -4606,9 +4621,16 @@ class Log extends ListScrollForm {
 }
 
 class LogMessage extends FocusElement {
-  constructor(text, isVerbose = false) {
+  constructor(info) {
     super()
 
+    this.info = info
+
+    const {
+      text,
+      isVerbose = false
+    } = info
+
     this.label = new LogMessageLabel(text, isVerbose)
     this.addChild(this.label)
   }