Pārlūkot izejas kodu

Merge branch 'lazyDom' of isundil/mimouchat into devel

isundil 6 gadi atpakaļ
vecāks
revīzija
9caec3f820
6 mainītis faili ar 210 papildinājumiem un 218 dzēšanām
  1. 10 1
      cli/dom.js
  2. 1 1
      cli/osmTile.js
  3. 149 64
      cli/ui.js
  4. 39 148
      srv/public/mimouchat.min.js
  5. 4 1
      srv/public/style.css
  6. 7 3
      srv/src/slackManager.js

+ 10 - 1
cli/dom.js

@@ -312,9 +312,11 @@ function makeUserColor(username) {
 /**
  * @param {Chatter} user
  * @param {string} userName
+ * @param {boolean} isMeMessage
+ * @param {number} firstTs
  * @return {Element}
 **/
-function createMessageGroupDom(user, userName) {
+function createMessageGroupDom(user, userName, isMeMessage, firstTs) {
     var dom = document.createElement("div")
         ,authorBlock = document.createElement("div")
         ,authorName = document.createElement("a")
@@ -338,10 +340,17 @@ function createMessageGroupDom(user, userName) {
     authorBlock.appendChild(authorName);
     authorBlock.className = R.klass.msg.author;
     dom.className = R.klass.msg.authorGroup;
+    if (isMeMessage)
+        dom.classList.add(R.klass.msg.meMessage);
     dom.appendChild(authorBlock);
     dom.content = document.createElement("div");
     dom.content.className = R.klass.msg.authorMessages;
+    dom.messages = [];
     dom.appendChild(dom.content);
+
+    dom.ts = firstTs;
+    dom.meMessage = isMeMessage;
+    dom.userId = user.id;
     return dom;
 }
 

+ 1 - 1
cli/osmTile.js

@@ -85,7 +85,7 @@ function makeOSMTiles(geo) {
                             mapCtx.drawImage(img.img, tileSize *img.i, tileSize *img.j, tileSize, tileSize);
                             drawPlot(px -absoluteX, py -absoluteY, accRadiusPx);
                         }
-                    });
+                    }).catch(function() {});
         },
         currentZoom,
         setZoom = function(val) {

+ 149 - 64
cli/ui.js

@@ -167,6 +167,8 @@ function onRoomSelected() {
     }
     var roomLi = document.getElementById("room_" +SELECTED_ROOM.id);
     document.getElementById(R.id.currentRoom.title).textContent = name;
+    document.getElementById(R.id.currentRoom.content).textContent = '';
+    MSG_GROUPS = [];
     onRoomUpdated();
     focusInput();
 
@@ -307,90 +309,171 @@ function spawnNotification() {
         Notification.requestPermission();
 }
 
+function isSameGroup(group, msg) {
+    return group &&
+        isSameDay(msg.ts, group.ts) &&
+        !(msg instanceof MeMessage) &&
+        !group.meMessage &&
+        msg.userId === group.userId;
+}
+
 function onRoomUpdated() {
-    var chatFrag = document.createDocumentFragment(),
-        currentRoomId = SELECTED_ROOM.id,
+    var chatFrag = document.getElementById(R.id.currentRoom.content),
         prevMsg = null,
         firstTsCombo = 0,
-        prevMsgDom = null,
-        prevTs = 0,
-        currentMsgGroupDom;
+        currentGroup = 0,
+        currentMsgInGroup = 0;
 
     if (SELECTED_ROOM.starred)
         document.getElementById(R.id.mainSection).classList.add(R.klass.starred);
     else
         document.getElementById(R.id.mainSection).classList.remove(R.klass.starred);
-    MSG_GROUPS = [];
-    if (DATA.history[currentRoomId])
-        DATA.history[currentRoomId].messages.forEach(function(msg) {
-            if (!msg.removed) {
-                var dom = msg.getDom(),
-                    newGroupDom = false,
-                    sameDayThanPrevious = isSameDay(msg.ts, prevTs);
-
-                if (prevMsg && prevMsg.userId === msg.userId && msg.userId && sameDayThanPrevious) {
-                    if (Math.abs(firstTsCombo -msg.ts) < 30 && !(msg instanceof MeMessage))
-                        prevMsgDom.classList.add(R.klass.msg.sameTs);
-                    else
+    DATA.history[SELECTED_ROOM.id] && DATA.history[SELECTED_ROOM.id].messages.forEach(function(msg) {
+        var groupDomCreated = false;
+        if (MSG_GROUPS[currentGroup]) {
+            if (currentMsgInGroup >= MSG_GROUPS[currentGroup].messages.length) {
+                if (!msg.removed) {
+                    if (isSameGroup(MSG_GROUPS[currentGroup], msg)) {
+                        // New message belonging in this group
+                        var dom = msg.getDom();
+                        if (Math.abs(firstTsCombo -msg.ts) < 30 && prevMsg)
+                            prevMsg.getDom().classList.add(R.klass.msg.sameTs);
                         firstTsCombo = msg.ts;
-                } else {
+                        if ((!prevMsg || prevMsg.ts <= SELECTED_ROOM.lastRead) && msg.ts > SELECTED_ROOM.lastRead)
+                            dom.classList.add(R.klass.msg.firstUnread);
+                        else
+                            dom.classList.remove(R.klass.msg.firstUnread);
+                        MSG_GROUPS[currentGroup].content.appendChild(dom);
+                        MSG_GROUPS[currentGroup].messages.push(msg.id);
+                        ++currentMsgInGroup;
+                        prevMsg = msg;
+                        return;
+                    }
+                    if (msg.ts < MSG_GROUPS[currentGroup].ts) {
+                        while (currentGroup > 0 && msg.ts < MSG_GROUPS[currentGroup].ts) {
+                            // New message in previous group, move group cursor before the group to be inserted
+                            --currentGroup;
+                        }
+                        while (MSG_GROUPS[currentGroup]) {
+                            MSG_GROUPS[currentGroup].remove();
+                            MSG_GROUPS.splice(currentGroup, 1);
+                        }
+                    } else {
+                        // New message in next group
+                        while (MSG_GROUPS[currentGroup].content.children[currentMsgInGroup])
+                            MSG_GROUPS[currentGroup].content.children[currentMsgInGroup].remove();
+                        MSG_GROUPS[currentGroup].messages.splice(currentMsgInGroup);
+                        if (!MSG_GROUPS[currentGroup].messages.length) {
+                            MSG_GROUPS[currentGroup].remove();
+                            MSG_GROUPS[currentGroup] = null;
+                        } else {
+                            currentGroup++;
+                        }
+                    }
+                    currentMsgInGroup = 0;
                     firstTsCombo = msg.ts;
-                    newGroupDom = true;
-                }
-                if (SELECTED_ROOM_UNREAD > -1 &&
-                        (!prevMsg || prevMsg.ts <= SELECTED_ROOM_UNREAD) &&
-                        msg.ts > SELECTED_ROOM_UNREAD) {
-                    dom.classList.add(R.klass.msg.firstUnread);
-                    dom.insertBefore(UNREAD_INDICATOR_DOM, dom.firstChild);
-                } else {
-                    dom.classList.remove(R.klass.msg.firstUnread);
                 }
-                if (msg instanceof MeMessage) {
-                    prevMsg = null;
-                    prevMsgDom = null;
-                    firstTsCombo = 0;
-                    newGroupDom = true;
-                    chatFrag.appendChild(dom);
-                    currentMsgGroupDom = null;
-                } else {
-                    if (newGroupDom || !currentMsgGroupDom) {
-                        currentMsgGroupDom = createMessageGroupDom(DATA.context.getUser(msg.userId), msg.username);
-                        MSG_GROUPS.push(currentMsgGroupDom);
-                        chatFrag.appendChild(currentMsgGroupDom);
+                // else message got removed
+            }
+            if (isSameGroup(MSG_GROUPS[currentGroup], msg)) {
+                if (MSG_GROUPS[currentGroup].messages[currentMsgInGroup] === msg.id) {
+                    // same message
+                    var dom = MSG_GROUPS[currentGroup].content.children[currentMsgInGroup];
+                    if (msg.removed) {
+                        // Check removed
+                        dom.remove();
+                        MSG_GROUPS[currentGroup].messages.splice(currentMsgInGroup, 1);
+                    } else if (msg.uiNeedRefresh) {
+                        // Check invalidated
+                        var newDom = msg.getDom();
+                        MSG_GROUPS[currentGroup].content.replaceChild(dom, newDom);
+                        dom = newDom;
                     }
+                    if ((!prevMsg || prevMsg.ts <= SELECTED_ROOM.lastRead) && msg.ts > SELECTED_ROOM.lastRead)
+                        dom.classList.add(R.klass.msg.firstUnread);
+                    else
+                        dom.classList.remove(R.klass.msg.firstUnread);
+                    currentMsgInGroup++;
+                    prevMsg = msg;
+                } else if (!msg.removed) {
+                    // Another message, insert it before
+                    var dom = msg.getDom();
+                    MSG_GROUPS[currentGroup].content.insertBefore(dom, MSG_GROUPS[currentGroup].content.children[currentMsgInGroup]);
+                    MSG_GROUPS[currentGroup].messages.splice(currentMsgInGroup, 0, msg.id);
+                    if ((!prevMsg || prevMsg.ts <= SELECTED_ROOM.lastRead) && msg.ts > SELECTED_ROOM.lastRead)
+                        dom.classList.add(R.klass.msg.firstUnread);
+                    else
+                        dom.classList.remove(R.klass.msg.firstUnread);
+                    // Check invalidated
+                    currentMsgInGroup++;
                     prevMsg = msg;
-                    prevMsgDom = dom;
-                    currentMsgGroupDom.content.appendChild(dom);
-                }
-                if (!currentMsgGroupDom || currentMsgGroupDom.content.firstChild === dom) {
-                    if (sameDayThanPrevious) {
-                        (currentMsgGroupDom || dom).classList.remove(R.klass.msg.firstOfDay);
-                    } else {
-                        (currentMsgGroupDom || dom).classList.add(R.klass.msg.firstOfDay);
-                        (currentMsgGroupDom || dom).dataset["date"] = locale.formatDay(msg.ts);
-                    }
                 }
-                prevTs = msg.ts;
-            } else {
-                msg.removeDom();
+                return;
             }
-        });
-    var isFirstPending = true;
+        }
+        if (msg.removed)
+            return;
+        if (MSG_GROUPS[currentGroup] && !isSameGroup(MSG_GROUPS[currentGroup], msg)) { // Next group is not the good one, insert a new group
+            MSG_GROUPS.splice(currentGroup, 0, null);
+        }
+        if (!MSG_GROUPS[currentGroup]) {
+            MSG_GROUPS[currentGroup] = createMessageGroupDom(DATA.context.getUser(msg.userId), msg.username, msg instanceof MeMessage, msg.ts);
+            groupDomCreated = true;
+        }
+        /** @type {Element} */
+        var dom = msg.getDom();
+        firstTsCombo = msg.ts;
+        if ((!prevMsg || prevMsg.ts <= SELECTED_ROOM.lastRead) && msg.ts > SELECTED_ROOM.lastRead) {
+            dom.classList.add(R.klass.msg.firstUnread);
+            dom.insertBefore(UNREAD_INDICATOR_DOM, dom.firstChild);
+        } else {
+            dom.classList.remove(R.klass.msg.firstUnread);
+        }
+        MSG_GROUPS[currentGroup].content.appendChild(dom);
+        MSG_GROUPS[currentGroup].messages.push(msg.id);
+        prevMsg = msg;
+
+        if (groupDomCreated) {
+            if (MSG_GROUPS[currentGroup +1])
+                chatFrag.insertBefore(MSG_GROUPS[currentGroup], MSG_GROUPS[currentGroup +1]);
+            else
+                chatFrag.appendChild(MSG_GROUPS[currentGroup]);
+            currentMsgInGroup = 1;
+        }
+        return;
+    });
+    if (MSG_GROUPS[currentGroup]) {
+        while (MSG_GROUPS[currentGroup].content.children[currentMsgInGroup])
+            MSG_GROUPS[currentGroup].content.children[currentMsgInGroup].remove();
+        MSG_GROUPS[currentGroup].messages.splice(currentMsgInGroup);
+        if (!MSG_GROUPS[currentGroup].messages.length)
+            --currentGroup;
+        for (var i = currentGroup +1;MSG_GROUPS[i]; i++) {
+            MSG_GROUPS[i].remove();
+        }
+    }
+    for (var i =0, len =MSG_GROUPS.length; i < len; ++i) {
+        if (MSG_GROUPS[i -1] && isSameDay(MSG_GROUPS[i -1].ts, MSG_GROUPS[i].ts)) {
+            MSG_GROUPS[i].classList.remove(R.klass.msg.firstOfDay);
+        } else {
+            MSG_GROUPS[i].classList.add(R.klass.msg.firstOfDay);
+            MSG_GROUPS[i].dataset["date"] = MSG_GROUPS[i].dataset["date"] || locale.formatDay(MSG_GROUPS[i].ts);
+        }
+    }
+    currentGroup = MSG_GROUPS.length;
     PENDING_MESSAGES.forEach(function(msg) {
         if (msg.channel === SELECTED_ROOM.id) {
-            if (isFirstPending) {
-                currentMsgGroupDom = createMessageGroupDom(SELECTED_CONTEXT.self, "");
-                chatFrag.appendChild(currentMsgGroupDom);
-                isFirstPending = false;
+            if (!MSG_GROUPS[currentGroup]) {
+                MSG_GROUPS[currentGroup] = createMessageGroupDom(SELECTED_CONTEXT.self, SELECTED_CONTEXT.self.getName(), msg instanceof MeMessage, msg.ts);
+                chatFrag.appendChild(MSG_GROUPS[currentGroup]);
             }
-            currentMsgGroupDom.content.appendChild(msg.dom);
+            MSG_GROUPS[currentGroup].classList.add("pending");
+            MSG_GROUPS[currentGroup].content.appendChild(msg.dom);
+            MSG_GROUPS[currentGroup].messages.push(msg.id);
         }
     });
-    var content = document.getElementById(R.id.currentRoom.content);
-    //TODO lazy add dom if needed
-    content.textContent = "";
-    content.appendChild(chatFrag);
     //TODO scroll lock
+    var content = document.getElementById(R.id.currentRoom.content);
     content.scrollTop = content.scrollHeight -content.clientHeight;
     updateTitle();
     if (window.hasFocus)
@@ -457,7 +540,9 @@ function displayTmpMessage(channel, input, isMeMessage) {
         channel: channel.id,
         text: input.trim(),
         isMe: isMeMessage,
-        dom: createTmpMsgDom(input, isMeMessage)
+        dom: createTmpMsgDom(input, isMeMessage),
+        ts: Date.now(),
+        id: "pending" +channel.id +Date.now()
     };
     PENDING_MESSAGES.push(obj);
     if (channel === SELECTED_ROOM)

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 39 - 148
srv/public/mimouchat.min.js


+ 4 - 1
srv/public/style.css

@@ -91,11 +91,14 @@ button, .button { border: 1px solid black; border-radius: 3px; background: rgb(2
 .chat-context-room:not(.selected).unreadHi, .chat-context-room:not(.selected).unreadHi > a { font-weight: bold; color: #4c9689; }
 .chatmsg-authorGroup { position: relative; }
 .chatmsg-authorGroup .chatmsg-item .chatmsg-author-name { display: none; }
+.chatmsg-authorGroup.chatmsg-me_message { padding: 0; }
+.chatmsg-authorGroup.chatmsg-me_message .chatmsg-author { display: none; }
+.chatmsg-authorGroup.chatmsg-me_message > .chatmsg-author-messages { padding: 0; }
 .chatmsg-authorGroup > .chatmsg-author { position: absolute; }
 .chatmsg-authorGroup > .chatmsg-author * { vertical-align: top; }
 .chatmsg-authorGroup > .chatmsg-author .chatmsg-author-img-wrapper { position: relative; display: inline-block; top: 0; }
 .chatmsg-authorGroup > .chatmsg-author-messages { padding: 18px 0 0 36px; }
-.chatmsg-authorGroup, .chatmsg-me_message { padding: 10px; }
+.chatmsg-authorGroup, .chatmsg-authorGroup .chatmsg-me_message { padding: 10px; }
 .chatmsg-authorGroup .chatmsg-item { padding: 4px 10px; }
 .chatmsg-authorGroup.chatmsg-first-daily,.chatmsg-me_message.chatmsg-first-daily { margin-top: 1em; }
 .chatmsg-authorGroup.chatmsg-first-daily::before,.chatmsg-me_message.chatmsg-first-daily::before { position: absolute; top: -1em; width: calc(100% - 20px); content: attr(data-date); border-bottom: 1px solid rgb(156, 156, 156); }

+ 7 - 3
srv/src/slackManager.js

@@ -15,7 +15,10 @@ var instance = new SlackManager();
 setInterval(function() {
     var keys = instance.cache.keys();
     keys.forEach(function(instKey) {
-        instance.cache.get(instKey).ping();
+        if (!instance.cache.get(instKey))
+            instance.cache.del(instKey);
+        else
+            instance.cache.get(instKey).ping();
     });
 }, PING_DELAY);
 
@@ -24,7 +27,7 @@ setInterval(function() {
         now = Date.now();
     keys.forEach(function(instKey) {
         var inst = instance.cache.get(instKey);
-        if (inst.data.cleanTyping(now))
+        if (inst && inst.data.cleanTyping(now))
             MultiChatManager.onCtxUpdated(inst);
     });
 }, 1000);
@@ -38,7 +41,8 @@ SlackManager.prototype.getAuthScope = function() {
 setInterval(function() {
     var keys = instance.cache.keys();
     keys.forEach(function(instKey) {
-        instance.cache.get(instKey).rtmPing();
+        let instVal = instance.cache.get(instKey);
+        instVal && instVal.rtmPing();
     });
 }, RTM_PING_DELAY);
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels