[polari: 8/8] chatView: Improve handling of initial pending messages



commit 13499792ce5f924a9744ab30a93415ab9b4e5b14
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Jul 15 22:04:06 2016 +0200

    chatView: Improve handling of initial pending messages
    
    When a room has pending messages when we join, we currently
    simply insert them into the log. While simple, there are
    two issues with that approach:
    
     - we will always display the nick for the first pending
       message, so grouping will be wrong if the last message
       from the logs was from the same nick
     - if the message was already seen by the logger, we will
       duplicate it in the chat log (e.g. when mission-control
       restarts us after a crash)
    
    Address those issues by caching pending messages and only
    inserting them with the first batch of (de-duplicated) logs
    instead of immediately.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=768907

 src/chatView.js |   38 ++++++++++++++++++++++++++++++++------
 1 files changed, 32 insertions(+), 6 deletions(-)
---
diff --git a/src/chatView.js b/src/chatView.js
index 7805a87..1f8bf4a 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -298,6 +298,7 @@ const ChatView = new Lang.Class({
         this._needsIndicator = true;
         this._pending = new Map();
         this._pendingLogs = [];
+        this._initialPending = [];
         this._statusCount = { left: 0, joined: 0, total: 0 };
 
         this._room.account.connect('notify::nickname', Lang.bind(this,
@@ -504,13 +505,31 @@ const ChatView = new Lang.Class({
 
         let nick = this._pendingLogs[0].nick;
         let type = this._pendingLogs[0].messageType;
-        for (let i = 0; i < this._pendingLogs.length; i++)
+        let maxNum = this._pendingLogs.length - this._initialPending.length;
+        for (let i = 0; i < maxNum; i++)
             if (this._pendingLogs[i].nick != nick ||
                 this._pendingLogs[i].messageType != type)
                 return this._pendingLogs.splice(i);
         return [];
     },
 
+    _appendInitialPending: function(logs) {
+        let pending = this._initialPending.splice(0);
+        let firstPending = pending[0];
+
+        let numLogs = logs.length;
+        let pos;
+        for (pos = numLogs - pending.length; pos < numLogs; pos++)
+            if (logs[pos].nick == firstPending.nick &&
+                logs[pos].text == firstPending.text &&
+                logs[pos].timestamp == firstPending.timestamp &&
+                logs[pos].messageType == firstPending.messageType)
+                break;
+        // Remove entries that are also in pending (if any), then
+        // add the entries from pending
+        logs.splice.apply(logs, [pos, numLogs, ...pending]);
+    },
+
     _insertPendingLogs: function() {
         let pending = this._getReadyLogs();
 
@@ -519,11 +538,21 @@ const ChatView = new Lang.Class({
             return;
         }
 
+        let numInitialPending = this._initialPending.length;
+        if (numInitialPending)
+            this._appendInitialPending(pending);
+
+        let indicatorIndex = pending.length - numInitialPending;
+
         let state = { lastNick: null, lastTimestamp: 0 };
         let iter = this._view.buffer.get_start_iter();
+
         for (let i = 0; i < pending.length; i++) {
             this._insertMessage(iter, pending[i], state);
 
+            if (i == indicatorIndex)
+                this._setIndicatorMark(iter);
+
             if (!iter.is_end() || i < pending.length - 1)
                 this._view.buffer.insert(iter, '\n', -1);
         }
@@ -906,11 +935,8 @@ const ChatView = new Lang.Class({
             this._channelSignals.push(this._channel.connect(signal.name, signal.handler));
         }));
 
-        this._channel.dup_pending_messages().forEach(Lang.bind(this,
-            function(message) {
-                this._insertTpMessage(message);
-            }));
-        this._checkMessages();
+        let pending = this._channel.dup_pending_messages();
+        this._initialPending = pending.map(p => this._createMessage(p));
     },
 
     _onMemberRenamed: function(room, oldMember, newMember) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]