Selaa lähdekoodia

[refactor] removed UNREAD object
[add][Refs #22] Display a red bar on top of the first unread message

B Thibault 8 vuotta sitten
vanhempi
commit
5b54813bce
8 muutettua tiedostoa jossa 128 lisäystä ja 133 poistoa
  1. 25 33
      cli/data.js
  2. 9 11
      cli/dom.js
  3. 1 0
      cli/resources.js
  4. 13 12
      cli/ui.js
  5. 68 69
      srv/public/slack.min.js
  6. 1 0
      srv/public/style.css
  7. 4 1
      srv/src/slack.js
  8. 7 7
      srv/src/slackData.js

+ 25 - 33
cli/data.js

@@ -6,9 +6,9 @@ var
     SLACK
 
     /**
-     * @type {Object.<string, {hl: boolean, unread: boolean}>} number of unread per chan
+     * @type {Array.<SlackChan|SlackGroup|SlackIms>}
     **/
-    ,UNREAD_CHANS = {};
+    ,HIGHLIGHTED_CHANS = [];
 
 ;
 
@@ -32,16 +32,6 @@ SlackWrapper.prototype.update = function(data) {
         this.lastServerVersion = data["v"];
     if (data["static"]) {
         this.context.updateStatic(data["static"], Date.now());
-        UNREAD_CHANS = {};
-        this.context.forEachChans(function(i) {
-            if (i.lastMsg > i.lastRead) {
-                UNREAD_CHANS[i.id] = {
-                    hl: false
-                    ,unread: true
-                }
-            }
-            return true;
-        });
     }
     if (data["live"]) {
         for (var i in data["live"]) {
@@ -99,33 +89,33 @@ function onMsgReceived(chan, msg) {
     if (chan !== SELECTED_ROOM || !window.hasFocus) {
         var selfReg = new RegExp("<@" +SLACK.context.self.id)
             ,highligted = false
+            ,areNew = false
             ,newHighlited = false;
         msg.forEach(function(i) {
             if (parseFloat(i["ts"]) <= chan.lastRead) {
                 return;
             }
-            if (!UNREAD_CHANS[chan.id]) {
-                UNREAD_CHANS[chan.id] = {
-                    hl: false
-                    ,unread: true
-                };
-            }
-            if (chan instanceof SlackGroup || chan instanceof SlackIms || i.text.match(selfReg) || isHighlighted(i.text)) {
-                newHighlited |= !UNREAD_CHANS[chan.id].hl;
-                UNREAD_CHANS[chan.id].hl = true;
+            areNew = true;
+            if (chan instanceof SlackIms || i.text.match(selfReg) || isHighlighted(i.text)) {
+                if (HIGHLIGHTED_CHANS.indexOf(chan) === -1) {
+                    newHighlited = true;
+                    HIGHLIGHTED_CHANS.push(chan);
+                }
                 highligted = true;
             }
         });
-        updateTitle();
-        var dom = document.getElementById(chan.id);
-        if (dom) {
-            dom.classList.add(R.klass.unread);
-            if (highligted)
-                dom.classList.add(R.klass.unreadHi);
-        }
-        if (newHighlited && !window.hasFocus) {
-            // TODO setting
-            spawnNotification();
+        if (areNew) {
+            updateTitle();
+            var dom = document.getElementById(chan.id);
+            if (dom) {
+                dom.classList.add(R.klass.unread);
+                if (highligted)
+                    dom.classList.add(R.klass.unreadHi);
+            }
+            if (newHighlited && !window.hasFocus) {
+                // TODO setting
+                spawnNotification();
+            }
         }
     }
 }
@@ -134,8 +124,10 @@ function onMsgReceived(chan, msg) {
  * @param {SlackChan|SlackGroup|SlackIms} room
 **/
 function markRoomAsRead(room) {
-    if (UNREAD_CHANS[room.id]) {
-        delete UNREAD_CHANS[room.id];
+    var highlightIndex = HIGHLIGHTED_CHANS.indexOf(room);
+    room.lastRead = room.lastMsg;
+    if (highlightIndex >= 0) {
+        HIGHLIGHTED_CHANS.splice(highlightIndex, 1);
         updateTitle();
     }
     var roomLi = document.getElementById(room.id);

+ 9 - 11
cli/dom.js

@@ -42,11 +42,11 @@ function createChanListItem(chan) {
     link.textContent = chan.name;
     dom.appendChild(createTypingDisplay());
     dom.appendChild(link);
-    if (UNREAD_CHANS[chan.id]) {
-        if (UNREAD_CHANS[chan.id].hl)
-            dom.classList.add(R.klass.unreadHi);
-        if (UNREAD_CHANS[chan.id].unread)
-            dom.classList.add(R.klass.unread);
+    if (HIGHLIGHTED_CHANS.indexOf(chan) >= 0)
+        dom.classList.add(R.klass.unreadHi);
+    if (chan.lastMsg > chan.lastRead) {
+        dom.classList.add(R.klass.unread);
+        console.log("unread because ", chan);
     }
     return dom;
 }
@@ -71,12 +71,10 @@ function createImsListItem(ims) {
     if (SELECTED_ROOM === ims)
         dom.classList.add(R.klass.selected);
 
-    if (UNREAD_CHANS[ims.id]) {
-        if (UNREAD_CHANS[ims.id].hl)
-            dom.classList.add(R.klass.unreadHi);
-        if (UNREAD_CHANS[ims.id].unread)
-            dom.classList.add(R.klass.unread);
-    }
+    if (HIGHLIGHTED_CHANS.indexOf(ims) >= 0)
+        dom.classList.add(R.klass.unreadHi);
+    if (ims.lastMsg > ims.lastRead)
+        dom.classList.add(R.klass.unread);
     return dom;
 }
 

+ 1 - 0
cli/resources.js

@@ -78,6 +78,7 @@ var R = {
         }
         ,msg: {
             item: "slackmsg-item"
+            ,firstUnread: "slackmsg-first-unread"
             ,content: "slackmsg-content"
             ,meMessage: "slackmsg-me_message"
             ,ts: "slackmsg-ts"

+ 13 - 12
cli/ui.js

@@ -442,26 +442,25 @@ function setNetErrorFavicon() {
 }
 
 function updateTitle() {
-    var hasUnread = 0
-        ,hasHl = 0
+    var hasHl = HIGHLIGHTED_CHANS.length
         ,title = "";
 
     if (NEXT_RETRY) {
         title = '!' +locale.netErrorShort +' - ';
         setNetErrorFavicon();
 
+    } else if (hasHl) {
+        title = "(!" +hasHl +") - ";
+        setFavicon(hasHl, hasHl);
     } else {
-        for (var i in UNREAD_CHANS) {
-            if (UNREAD_CHANS.hasOwnProperty(i)) {
-                hasUnread += UNREAD_CHANS[i].unread;
-                hasHl += UNREAD_CHANS[i].hl;
-            }
-        }
-        if (hasHl)
-            title = "(!" +hasHl +") - ";
-        else if (hasUnread)
+        var hasUnread = 0;
+        SLACK.context.forEachChans(function(i) {
+            if (i.lastMsg > i.lastRead)
+                hasUnread++;
+        });
+        if (hasUnread)
             title = "(" +hasUnread +") - ";
-        setFavicon(hasHl, hasUnread);
+        setFavicon(0, hasUnread);
     }
     title += SLACK.context.team.name;
     document.title = title;
@@ -504,6 +503,8 @@ function onRoomUpdated() {
                         firstTsCombo = msg.ts;
                 } else
                     firstTsCombo = msg.ts;
+                if ((!prevMsg || prevMsg.ts <= SELECTED_ROOM.lastRead) && msg.ts > SELECTED_ROOM.lastRead)
+                    dom.classList.add(R.klass.msg.firstUnread);
                 prevMsg = msg;
                 prevMsgDom = dom;
                 chatFrag.appendChild(dom);

+ 68 - 69
srv/public/slack.min.js

@@ -1,72 +1,71 @@
-function aa(a){this.id=a;this.a={Y:"",$:"",ba:"",ca:"",S:"",T:"",V:"",da:""};this.version=0}function m(a){this.id=a;this.a=this.b=0;this.c={};this.version=0}function q(a){this.id=a;this.c={};this.version=this.a=this.b=this.h=0}function w(a,b){this.id=a;this.g=b;this.version=this.a=this.b=0}function ba(a){this.id=a;this.a={W:"",X:"",u:"",H:"",U:"",aa:""};this.g={};this.c=this.b=null;this.version=0}function ca(){this.b={};this.a=[]}
-function da(a,b,c){a.b=JSON.parse(b.emoji_use);b.highlight_words?a.a=(b.highlight_words||"").split(",").filter(function(a){return""!==a.trim()}):b.highlights&&(a.a=b.highlights);a.version=Math.max(a.version,c)}function ea(a){this.id=a;this.a={Z:"",u:"",H:""};this.c=this.b=null;this.version=0;this.f=!1}function fa(a,b){this.a=b.desc;this.name=b.name;this.type=b.type;this.usage=b.usage;this.B=ga(a,b)}
-function ga(a,b){if(b.service_name)return b.service_name;if(b.app){var c=b.app,d=[],f;for(f in a.f)a.f[f].l===c&&d.push(a.f[f]);if(d)for(c=0;c<d.length;c++)if(d[c].name)return d[c].name;console.log("Unknown app "+b.app);return""}return"Slack"}function z(){this.D=null;this.l={};this.A={};this.C={};this.c={};this.a=null;this.f={};this.h={version:0,data:{}};this.g={version:0,data:{}};this.b={};this.L=0}
-function ha(a,b){var c=Date.now();if(b.bots)for(var d=0,f=b.bots.length;d<f;d++){var e=a.f[b.bots[d].id];e||(e=a.f[b.bots[d].id]=new ea(b.bots[d].id));var g=b.bots[d],h=c;void 0!==g.deleted&&(e.h=g.deleted);void 0!==g.name&&(e.name=g.name);void 0!==g.app_id&&(e.l=g.app_id);g.icons&&(e.a.Z=g.icons.image_36,e.a.u=g.icons.image_48,e.a.H=g.icons.image_72);void 0!==g.presence&&(e.f="away"!==g.presence);void 0!==g.isPresent&&(e.f=g.isPresent);e.version=Math.max(e.version,h)}if(b.users)for(d=0,f=b.users.length;d<
-f;d++)(e=a.c[b.users[d].id])||(e=a.c[b.users[d].id]=new ba(b.users[d].id)),g=b.users[d],h=c,void 0!==g.name&&(e.name=g.name),void 0!==g.deleted&&(e.h=g.deleted),void 0!==g.status&&(e.status=g.status),void 0!==g.presence&&(e.f="away"!==g.presence),void 0!==g.isPresent&&(e.f=g.isPresent),g.profile&&(e.a.W=g.profile.image_24,e.a.X=g.profile.image_32,e.a.u=g.profile.image_48,e.a.H=g.profile.image_72,e.a.U=g.profile.image_192,e.a.aa=g.profile.image_512),e.version=Math.max(e.version,h);if(b.ims)for(d=0,
-f=b.ims.length;d<f;d++)if(g=B(a,b.ims[d].user)){g.b||(a.C[b.ims[d].id]=g.b=new w(b.ims[d].id,g));var e=g.b,h=b.ims[d],l=c;void 0!==h.last_read&&(e.b=parseFloat(h.last_read));void 0!==h.last_msg&&(e.a=parseFloat(h.last_msg));h.latest&&(e.a=parseFloat(h.latest.ts));e.f=g.h;e.version=Math.max(e.version,l)}if(b.channels)for(d=0,f=b.channels.length;d<f;d++){(e=a.l[b.channels[d].id])||(e=a.l[b.channels[d].id]=new m(b.channels[d].id));g=b.channels[d];h=a;l=c;void 0!==g.name&&(e.name=g.name);void 0!==g.is_archived&&
-(e.f=g.is_archived);void 0!==g.last_read&&(e.b=parseFloat(g.last_read));void 0!==g.last_msg&&(e.a=parseFloat(g.last_msg));g.latest&&(e.a=parseFloat(g.latest.ts));if(g.members&&(e.c={},g.members))for(var n=0,k=g.members.length;n<k;n++){var p=B(h,g.members[n]);e.c[p.id]=p;p.g[e.id]=e}e.version=Math.max(e.version,l)}d=0;for(f=b.groups.length;d<f;d++){(e=a.A[b.groups[d].id])||(e=a.A[b.groups[d].id]=new q(b.groups[d].id));g=a;h=b.groups[d];l=c;n=[];if(h.members){e.c={};k=e.h=0;for(p=h.members.length;k<
-p;k++){var r=B(g,h.members[k]);e.c[h.members[k]]=r;r.g[e.id]=e;n.push(r.name);e.h++}e.name=n.join(", ")}void 0!==h.is_archived&&(e.f=h.is_archived||!1===h.is_open);void 0!==h.last_read&&(e.b=parseFloat(h.last_read));void 0!==h.last_msg?e.a=parseFloat(h.last_msg):h.latest&&(e.a=parseFloat(h.latest.ts));e.version=Math.max(e.version,l)}b.emojis&&(a.h.data=b.emojis,a.h.version=c);if(void 0!==b.commands){a.g.data={};for(d in b.commands)a.g.data[d]=new fa(a,b.commands[d]);a.g.version=c}b.team&&(a.D||(a.D=
-new aa(b.team.id)),f=a.D,e=b.team,void 0!==e.name&&(f.name=e.name),e.icon&&(f.a.Y=e.icon.image_34,f.a.$=e.icon.image_44,f.a.ba=e.icon.image_68,f.a.ca=e.icon.image_88,f.a.S=e.icon.image_102,f.a.T=e.icon.image_132,f.a.V=e.icon.image_230,f.a.da=e.icon.image_default),f.version=Math.max(f.version,c));a.L=Math.max(a.L,c);b.self&&(a.a=B(a,b.self.id),a.a.c||(a.a.c=new ca),da(a.a.c,b.self.prefs,c));if(void 0!==b.typing)for(d in a.b=b.typing,a.b)for(var u in a.b[d])a.b[d][u]=c}
-function B(a,b){return a.c[b]||a.f[b]||null}function C(a,b){return a.l[b]||a.C[b]||a.A[b]||null}function ia(a,b){for(var c in a.l)if(!b(a.l[c]))return;for(c in a.C)if(!b(a.C[c]))return;for(c in a.A)if(!b(a.A[c]))break}"undefined"!==typeof module&&(module.R.ea=z);function ja(a,b){this.m=a.user||a.bot_id;this.f=a.username;this.id=a.ts;this.i=parseFloat(a.ts);this.text=a.text||"";this.c=a.attachments||[];this.o=!!a.edited;this.b=a.removed||!1;this.g="me_message"===a.subtype||a.isMeMessage;this.a={};this.version=b;var c=this;a.reactions&&a.reactions.forEach(function(a){c.a[a.name]=[];a.users.forEach(function(b){c.a[a.name].push(b)})})}
-function ka(a,b,c){b?(a.text=b.text||"",b.attachments&&(a.c=b.attachments),a.o=!!b.edited,a.b=!!b.removed,b.reactions&&(a.a={},b.reactions.forEach(function(b){a.a[b.name]=[];b.users.forEach(function(c){a.a[b.name].push(c)})}))):a.b=!0;a.version=c}function E(a,b,c,d){this.id="string"===typeof a?a:a.id;this.a=[];this.b=b;c&&F(this,c,d)}
-function la(a,b,c,d){var f=!1;a.a[b]&&(1===a.a[b].length&&a.a[b][0]===c?(delete a.a[b],f=!0):a.a[b]=a.a[b].filter(function(a){return a!==c?!1:f=!0}));f&&(a.version=d)}function F(a,b,c){var d=0;b.forEach(function(a){d=Math.max(this.push(a,c),d)}.bind(a));ma(a)}
-E.prototype.push=function(a,b){if(a.type&&"message"!==a.type)if("reaction_added"===a.type){var c=G(this,a.item.ts);if(c){var d=a.reaction,f=a.user;c.a[d]||(c.a[d]=[]);c.a[d].push(f);c.version=b}}else if("reaction_removed"===a.type)(c=G(this,a.item.ts))&&la(c,a.reaction,a.user,b);else return 0;else{c=!1;d=a.ts;f=a;"message_changed"===a.subtype&&a.previous_message?(d=a.previous_message.ts,f=a.message):"message_deleted"===a.subtype&&a.previous_message&&(d=a.previous_message.ts,f=null);for(var e=0,g=
-this.a.length;e<g;e++)if(this.a[e].id===d){ka(this.a[e],f,b);c=!0;break}c||this.a.push(new ja(a,b))}for(;this.a.length>this.b;)this.a.shift();return b};function na(a){return a.a[a.a.length-1]}function oa(a){for(var b=H.b[I.id],c=0,d=b.a.length;c<d&&a>=b.a[c].i;c++)if(b.a[c].i===a)return b.a[c];return null}function G(a,b){for(var c=0,d=a.a.length;c<d;c++)if(a.a[c].id==b)return a.a[c];return null}function ma(a){a.a.sort(function(a,c){return a.i-c.i})}"undefined"!==typeof module&&(module.R.fa=E);var J={},K;function pa(){var a;if(!a){for(var b=0,c=navigator.languages.length;b<c;b++)if(J.hasOwnProperty(navigator.languages[b])){a=navigator.languages[b];break}a||(a="en")}K=J[a];console.log("Loading language pack: "+a);if(K.j)for(b in K.j)document.getElementById(b).textContent=K.j[b]};J.fr={P:"Utilisateur inconnu",O:"Channel inconnu",K:"Nouveau message",J:"Reseau",o:"edit&eacute;",I:function(a){return 1===a.length?a[0]+" est en train d'\u00e9crire":a.join(", ")+" sont en train d'\u00e9crire"},G:function(a){"string"!==typeof a&&(a=parseFloat(a));var b=new Date,c=new Date;a=new Date(1E3*a);b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0);c.setTime(b.getTime());c.setDate(c.getDate()-1);return a.getTime()>b.getTime()?a.toLocaleTimeString():a.getTime()>c.getTime()?
-"hier, "+a.toLocaleTimeString():a.toLocaleString()},j:{fileUploadCancel:"Annuler",neterror:"Impossible de se connecter au chat !"}};J.en={P:"Unknown member",O:"Unknown channel",K:"New message",J:"Network",o:"edited",I:function(a){return 1===a.length?a[0]+" is typing":a.join(", ")+" are typing"},G:function(a){"string"!==typeof a&&(a=parseFloat(a));var b=new Date,c=new Date;a=new Date(1E3*a);b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0);c.setTime(b.getTime());c.setDate(c.getDate()-1);return a.getTime()>b.getTime()?a.toLocaleTimeString():a.getTime()>c.getTime()?"yesterday, "+a.toLocaleTimeString():a.toLocaleString()},
+function aa(a){this.id=a;this.a={W:"",Y:"",$:"",aa:"",P:"",R:"",T:"",ba:""};this.version=0}function p(a){this.id=a;this.b=this.a=0;this.c={};this.version=0}function q(a){this.id=a;this.c={};this.version=this.b=this.a=this.h=0}function z(a,b){this.id=a;this.g=b;this.version=this.b=this.a=0}function ba(a){this.id=a;this.a={U:"",V:"",s:"",F:"",S:"",Z:""};this.g={};this.c=this.b=null;this.version=0}function ca(){this.b={};this.a=[]}
+function da(a,b,c){a.b=JSON.parse(b.emoji_use);b.highlight_words?a.a=(b.highlight_words||"").split(",").filter(function(a){return""!==a.trim()}):b.highlights&&(a.a=b.highlights);a.version=Math.max(a.version,c)}function ea(a){this.id=a;this.a={X:"",s:"",F:""};this.c=this.b=null;this.version=0;this.f=!1}function fa(a,b){this.a=b.desc;this.name=b.name;this.type=b.type;this.usage=b.usage;this.A=ga(a,b)}
+function ga(a,b){if(b.service_name)return b.service_name;if(b.app){var c=b.app,d=[],f;for(f in a.f)a.f[f].l===c&&d.push(a.f[f]);if(d)for(c=0;c<d.length;c++)if(d[c].name)return d[c].name;console.log("Unknown app "+b.app);return""}return"Slack"}function B(){this.C=null;this.l={};this.w={};this.B={};this.c={};this.a=null;this.f={};this.h={version:0,data:{}};this.g={version:0,data:{}};this.b={};this.J=0}function C(a,b){return a.c[b]||a.f[b]||null}function D(a,b){return a.l[b]||a.B[b]||a.w[b]||null}
+function ha(a){var b=E.a,c;for(c in b.l)if(!1===a(b.l[c]))return;for(c in b.B)if(!1===!a(b.B[c]))return;for(c in b.w)if(!1===!a(b.w[c]))break}"undefined"!==typeof module&&(module.O.ca=B);function ia(a,b){this.m=a.user||a.bot_id;this.f=a.username;this.id=a.ts;this.i=parseFloat(a.ts);this.text=a.text||"";this.c=a.attachments||[];this.o=!!a.edited;this.b=a.removed||!1;this.g="me_message"===a.subtype||a.isMeMessage;this.a={};this.version=b;var c=this;a.reactions&&a.reactions.forEach(function(a){c.a[a.name]=[];a.users.forEach(function(b){c.a[a.name].push(b)})})}
+function ja(a,b,c){b?(a.text=b.text||"",b.attachments&&(a.c=b.attachments),a.o=!!b.edited,a.b=!!b.removed,b.reactions&&(a.a={},b.reactions.forEach(function(b){a.a[b.name]=[];b.users.forEach(function(c){a.a[b.name].push(c)})}))):a.b=!0;a.version=c}function F(a,b,c,d){this.id="string"===typeof a?a:a.id;this.a=[];this.b=b;c&&G(this,c,d)}
+function ka(a,b,c,d){var f=!1;a.a[b]&&(1===a.a[b].length&&a.a[b][0]===c?(delete a.a[b],f=!0):a.a[b]=a.a[b].filter(function(a){return a!==c?!1:f=!0}));f&&(a.version=d)}function G(a,b,c){var d=0;b.forEach(function(a){d=Math.max(this.push(a,c),d)}.bind(a));la(a)}
+F.prototype.push=function(a,b){if(a.type&&"message"!==a.type)if("reaction_added"===a.type){var c=H(this,a.item.ts);if(c){var d=a.reaction,f=a.user;c.a[d]||(c.a[d]=[]);c.a[d].push(f);c.version=b}}else if("reaction_removed"===a.type)(c=H(this,a.item.ts))&&ka(c,a.reaction,a.user,b);else return 0;else{c=!1;d=a.ts;f=a;"message_changed"===a.subtype&&a.previous_message?(d=a.previous_message.ts,f=a.message):"message_deleted"===a.subtype&&a.previous_message&&(d=a.previous_message.ts,f=null);for(var e=0,n=
+this.a.length;e<n;e++)if(this.a[e].id===d){ja(this.a[e],f,b);c=!0;break}c||this.a.push(new ia(a,b))}for(;this.a.length>this.b;)this.a.shift();return b};function ma(a){for(var b=E.b[I.id],c=0,d=b.a.length;c<d&&a>=b.a[c].i;c++)if(b.a[c].i===a)return b.a[c];return null}function H(a,b){for(var c=0,d=a.a.length;c<d;c++)if(a.a[c].id==b)return a.a[c];return null}function la(a){a.a.sort(function(a,c){return a.i-c.i})}"undefined"!==typeof module&&(module.O.da=F);var J={},K;function na(){var a;if(!a){for(var b=0,c=navigator.languages.length;b<c;b++)if(J.hasOwnProperty(navigator.languages[b])){a=navigator.languages[b];break}a||(a="en")}K=J[a];console.log("Loading language pack: "+a);if(K.j)for(b in K.j)document.getElementById(b).textContent=K.j[b]};J.fr={N:"Utilisateur inconnu",M:"Channel inconnu",I:"Nouveau message",H:"Reseau",o:"edit&eacute;",G:function(a){return 1===a.length?a[0]+" est en train d'\u00e9crire":a.join(", ")+" sont en train d'\u00e9crire"},D:function(a){"string"!==typeof a&&(a=parseFloat(a));var b=new Date,c=new Date;a=new Date(1E3*a);b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0);c.setTime(b.getTime());c.setDate(c.getDate()-1);return a.getTime()>b.getTime()?a.toLocaleTimeString():a.getTime()>c.getTime()?
+"hier, "+a.toLocaleTimeString():a.toLocaleString()},j:{fileUploadCancel:"Annuler",neterror:"Impossible de se connecter au chat !"}};J.en={N:"Unknown member",M:"Unknown channel",I:"New message",H:"Network",o:"edited",G:function(a){return 1===a.length?a[0]+" is typing":a.join(", ")+" are typing"},D:function(a){"string"!==typeof a&&(a=parseFloat(a));var b=new Date,c=new Date;a=new Date(1E3*a);b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0);c.setTime(b.getTime());c.setDate(c.getDate()-1);return a.getTime()>b.getTime()?a.toLocaleTimeString():a.getTime()>c.getTime()?"yesterday, "+a.toLocaleTimeString():a.toLocaleString()},
 j:{fileUploadCancel:"Cancel",neterror:"Cannot connect to chat !"}};var L=0;
-function qa(){var a=document.createDocumentFragment(),b=H.a.a?Object.keys(H.a.a.g):[];b.sort(function(a,b){return a[0]!==b[0]?a[0]-b[0]:C(H.a,a).name.localeCompare(C(H.a,b).name)});b.forEach(function(b){b=C(H.a,b);if(!b.f){var c=document.createElement("li"),f=document.createElement("a");c.id=b.id;f.href="#"+b.id;b instanceof q?(c.className="slack-context-room slack-group",c.dataset.count=b.h-1):b instanceof m&&(c.className="slack-context-room slack-channel");I===b&&c.classList.add("selected");f.textContent=
-b.name;c.appendChild(M());c.appendChild(f);N[b.id]&&(N[b.id].s&&c.classList.add("unreadHi"),N[b.id].F&&c.classList.add("unread"));c&&a.appendChild(c)}});b=H.a.c?Object.keys(H.a.c):[];b.sort(function(a,b){return H.a.c[a].name.localeCompare(H.a.c[b].name)});b.forEach(function(b){b=B(H.a,b);if(!b.h){b=b.b;var c=document.createElement("li"),f=document.createElement("a");c.id=b.id;f.href="#"+b.id;c.className="slack-context-room slack-ims";f.textContent=b.g.name;c.appendChild(M());c.appendChild(f);b.g.f||
-c.classList.add("away");I===b&&c.classList.add("selected");N[b.id]&&(N[b.id].s&&c.classList.add("unreadHi"),N[b.id].F&&c.classList.add("unread"));c&&a.appendChild(c)}});document.getElementById("chanList").textContent="";document.getElementById("chanList").appendChild(a);O();P();ra(function(a){document.getElementById("slackCtx").style.backgroundImage="url("+a+")"})}
-function sa(){var a=H.a.b,b;for(b in H.a.a.g)if(!H.a.a.g[b].f){var c=document.getElementById(b);a[b]?c.classList.add("slack-context-typing"):c.classList.remove("slack-context-typing")}for(var d in H.a.c)(b=H.a.c[d].b)&&!b.f&&(c=document.getElementById(b.id),a[b.id]?c.classList.add("slack-context-typing"):c.classList.remove("slack-context-typing"));ta()}
-function ta(){var a=H.a.b;if(I&&a[I.id]){var b=[],c=!1,d;for(d in a[I.id])(a=B(H.a,d))?b.push(a.name):c=!0;c&&(H.c=0);document.getElementById("whoistyping").textContent=K.I(b)}else document.getElementById("whoistyping").textContent=""}function Q(a){a?document.body.classList.remove("no-network"):document.body.classList.add("no-network");P()}
+function oa(){var a=document.createDocumentFragment(),b=E.a.a?Object.keys(E.a.a.g):[];b.sort(function(a,b){return a[0]!==b[0]?a[0]-b[0]:D(E.a,a).name.localeCompare(D(E.a,b).name)});b.forEach(function(b){b=D(E.a,b);if(!b.f){var c=document.createElement("li"),f=document.createElement("a");c.id=b.id;f.href="#"+b.id;b instanceof q?(c.className="slack-context-room slack-group",c.dataset.count=b.h-1):b instanceof p&&(c.className="slack-context-room slack-channel");I===b&&c.classList.add("selected");f.textContent=
+b.name;c.appendChild(M());c.appendChild(f);0<=N.indexOf(b)&&c.classList.add("unreadHi");b.b>b.a&&(c.classList.add("unread"),console.log("unread because ",b));c&&a.appendChild(c)}});b=E.a.c?Object.keys(E.a.c):[];b.sort(function(a,b){return E.a.c[a].name.localeCompare(E.a.c[b].name)});b.forEach(function(b){b=C(E.a,b);if(!b.h){b=b.b;var c=document.createElement("li"),f=document.createElement("a");c.id=b.id;f.href="#"+b.id;c.className="slack-context-room slack-ims";f.textContent=b.g.name;c.appendChild(M());
+c.appendChild(f);b.g.f||c.classList.add("away");I===b&&c.classList.add("selected");0<=N.indexOf(b)&&c.classList.add("unreadHi");b.b>b.a&&c.classList.add("unread");c&&a.appendChild(c)}});document.getElementById("chanList").textContent="";document.getElementById("chanList").appendChild(a);O();P();pa(function(a){document.getElementById("slackCtx").style.backgroundImage="url("+a+")"})}
+function qa(){var a=E.a.b,b;for(b in E.a.a.g)if(!E.a.a.g[b].f){var c=document.getElementById(b);a[b]?c.classList.add("slack-context-typing"):c.classList.remove("slack-context-typing")}for(var d in E.a.c)(b=E.a.c[d].b)&&!b.f&&(c=document.getElementById(b.id),a[b.id]?c.classList.add("slack-context-typing"):c.classList.remove("slack-context-typing"));ra()}
+function ra(){var a=E.a.b;if(I&&a[I.id]){var b=[],c=!1,d;for(d in a[I.id])(a=C(E.a,d))?b.push(a.name):c=!0;c&&(E.c=0);document.getElementById("whoistyping").textContent=K.G(b)}else document.getElementById("whoistyping").textContent=""}function Q(a){a?document.body.classList.remove("no-network"):document.body.classList.add("no-network");P()}
 function R(){if(S){document.body.classList.add("replyingTo");var a=document.getElementById("replyToContainer"),b=document.createElement("a");b.addEventListener("click",function(){S=null;R()});b.className="replyto-close";b.textContent="x";a.textContent="";a.appendChild(b);a.appendChild(T("reply_"+I.id,S,!0))}else document.body.classList.remove("replyingTo"),document.getElementById("replyToContainer").textContent="";U()}
 function V(){if(W){document.body.classList.add("replyingTo");var a=document.getElementById("replyToContainer"),b=document.createElement("a");b.addEventListener("click",function(){W=null;V()});b.className="replyto-close";b.textContent="x";a.textContent="";a.appendChild(b);a.appendChild(T("edit_"+I.id,W,!0));document.getElementById("msgInput").value=W.text}else document.body.classList.remove("replyingTo"),document.getElementById("replyToContainer").textContent="";U()}
-window.toggleReaction=function(a,b,c){var d=H.b[a];if(d&&(d=G(d,b))){var f=H.a.a.id;d.a[c]&&-1!==d.a[c].indexOf(f)?(d=new XMLHttpRequest,d.open("DELETE","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(c),!0),d.send(null)):ua(a,b,c)}};
-function va(a){a:{for(var b=a,c={};!c[b];){if(a=H.a.h[b])if("alias:"==a.substr(0,6))c[b]=!0,b=a.substr(6);else{b=document.createElement("span");b.className="emoji-custom emoji";b.style.backgroundImage="url('"+a+"')";a=b;break a}break}a=b}"string"===typeof a&&"makeEmoji"in window&&(a=window.makeEmoji(a));return"string"===typeof a?null:a}
-function wa(a){return a.replace(/:([^ \t:]+):/g,function(b,c){var d=va(c);if(d){var f=document.createElement("span");f.className=b===a?"emoji-medium":"emoji-small";f.appendChild(d);return f.outerHTML}return b})}
-function X(a){a=a.split(/\r?\n/g);for(var b=0,c=a.length;b<c;b++){for(var d=a[b].trim(),f="",e={},g=!1,h=0,d=d.replace(RegExp("<([@#]?)([^>]*)>","g"),function(a,b,c){c=c.split("|");if("@"===b)c[1]?"@"!==c[1][0]&&(c[1]="@"+c[1]):(a=B(H.a,c[0]),c[1]=a?"@"+a.name:K.P),c[0]="#"+c[0],c[2]="slackmsg-link slackmsg-link-user";else if("#"===b)c[1]?"#"!==c[1][0]&&(c[1]="#"+c[1]):(a=C(H.a,c[0]),c[1]=a?"#"+a.name:K.O),c[0]="#"+c[0],c[2]="slackmsg-link slackmsg-link-chan";else if(-1!==c[0].indexOf("://"))c[1]||
-(c[1]=c[0]),c[2]="slackmsg-link";else return a;return'<a href="'+c[0]+'" class="'+c[2]+'"'+(b?"":' target="_blank"')+">"+c[1]+"</a>"}),d=wa(d),l=d.length,n=function(a,b,c){for(;a[b];){var d=a[b];if(("A"<=d&&"Z">=d||"a"<=d&&"z">=d||"0"<=d&&"9">=d||-1!=="\u00e0\u00e8\u00ec\u00f2\u00f9\u00c0\u00c8\u00cc\u00d2\u00d9\u00e1\u00e9\u00ed\u00f3\u00fa\u00fd\u00c1\u00c9\u00cd\u00d3\u00da\u00dd\u00e2\u00ea\u00ee\u00f4\u00fb\u00c2\u00ca\u00ce\u00d4\u00db\u00e3\u00f1\u00f5\u00c3\u00d1\u00d5\u00e4\u00eb\u00ef\u00f6\u00fc\u00ff\u00c4\u00cb\u00cf\u00d6\u00dc\u0178\u00e7\u00c7\u00df\u00d8\u00f8\u00c5\u00e5\u00c6\u00e6\u0153".indexOf(d))&&
-a[b]!=c&&a[b+1]==c)return!0;b++}return!1},k=function(a){return Object.keys(e).length?'<span class="'+Object.keys(a).join(" ")+'">':""};h<l&&(" "===d[h]||"\t"===d[h]);)h++;"&gt;"===d.substr(h,4)&&(g=!0,h+=4);for(;h<l;h++){var p=d[h];if("<"===p){do f+=d[h++];while(">"!==d[h-1]);h--}else if(!e["slackmsg-style-bold"]&&"*"===p&&d[h+1]&&n(d,h,p))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-bold"]=!0,f+=k(e);else if(!e["slackmsg-style-strike"]&&"~"===p&&d[h+1]&&n(d,h,p))Object.keys(e).length&&
-(f+="</span>"),e["slackmsg-style-strike"]=!0,f+=k(e);else if(!e["slackmsg-style-code"]&&"`"===p&&d[h+1]&&n(d,h,p))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-code"]=!0,f+=k(e);else if(!e["slackmsg-style-italic"]&&"_"===p&&d[h+1]&&n(d,h,p))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-italic"]=!0,f+=k(e);else{var r=!1,f=f+p;do{if(e["slackmsg-style-bold"]&&"*"!==p&&"*"===d[h+1])delete e["slackmsg-style-bold"],r=!0;else if(e["slackmsg-style-strike"]&&"~"!==p&&"~"===d[h+1])delete e["slackmsg-style-strike"],
-r=!0;else if(e["slackmsg-style-code"]&&"`"!==p&&"`"===d[h+1])delete e["slackmsg-style-code"],r=!0;else if(e["slackmsg-style-italic"]&&"_"!==p&&"_"===d[h+1])delete e["slackmsg-style-italic"],r=!0;else break;p=d[++h]}while(h<l);r&&(f+="</span>"+k(e))}}e&&(f+="</span>");a[b]=g?'<span class="slackmsg-style-quote">'+f+"</span>":f}return a.join("<br/>")}function T(a,b,c){b.g?(a=xa(a,b,c),a.classList.add("slackmsg-me_message")):a=xa(a,b,c);b.o&&a.classList.add("slackmsg-edited");return a}
-function P(){var a=0,b=0,c="";if(Y)c="!"+K.J+" - ",document.getElementById("linkFavicon").href="favicon_err.png";else{for(var d in N)N.hasOwnProperty(d)&&(a+=N[d].F,b+=N[d].s);b?c="(!"+b+") - ":a&&(c="("+a+") - ");document.getElementById("linkFavicon").href=b||a?"favicon.png?h="+b+"&m="+a:"favicon_ok.png"}c+=H.a.D.name;document.title=c}
-function ya(){if("Notification"in window)if("granted"===Notification.permission){var a=Date.now();if(L+3E4<a){var b=new Notification(K.K);L=a;setTimeout(function(){b.close()},5E3)}}else"denied"!==Notification.permission&&Notification.requestPermission()}
-function za(){var a=document.createDocumentFragment(),b=I.id,c=null,d=0,f=null;H.b[b]&&H.b[b].a.forEach(function(e){if(!e.b){var h=T(b,e);c&&c.m===e.m&&e.m?(h.classList.add("slackmsg-same-author"),30>Math.abs(d-e.i)?f.classList.add("slackmsg-same-ts"):d=e.i):d=e.i;c=e;f=h;a.appendChild(h)}});var e=document.getElementById("chatWindow");e.textContent="";e.appendChild(a);e.scrollTop=e.scrollHeight-e.clientHeight}
-function Aa(a){function b(a,b){for(b=b||a.target;b!==a.currentTarget&&b;){if(b.classList.contains("slackmsg-item"))return b.id;b=b.parentElement}}for(var c=a.target;c!==a.currentTarget&&c&&!c.classList.contains("slackmsg-hover");){if(c.parentElement&&c.parentElement.classList.contains("slackmsg-hover")){if(a=b(a,c)){a=parseFloat(a.split("_")[1]);var d=oa(a);d&&c.classList.contains("slackmsg-hover-reply")?(W&&(W=null,V()),S!==d&&(S=d,R())):d&&c.classList.contains("slackmsg-hover-reaction")?Ba.N(document.body,
-function(a){a&&ua(I.id,d.id,a)}):d&&c.classList.contains("slackmsg-hover-edit")?(S&&(S=null,R()),W!==d&&(W=d,V())):d&&c.classList.contains("slackmsg-hover-remove")&&(S&&(S=null,R()),W&&(W=null,V()),Ca(d))}break}c=c.parentElement}}function U(){document.getElementById("msgInput").focus()}function O(){var a=document.location.hash.substr(1),b=C(H.a,a),a=B(H.a,a);b&&b!==I?Da(b):a&&a.b&&Da(a.b)}
-document.addEventListener("DOMContentLoaded",function(){pa();document.getElementById("chatWindow").addEventListener("click",Aa);window.addEventListener("hashchange",function(){document.location.hash&&"#"===document.location.hash[0]&&O()});document.getElementById("fileUploadCancel").addEventListener("click",function(a){a.preventDefault();document.getElementById("fileUploadError").classList.add("hidden");document.getElementById("fileUploadContainer").classList.add("hidden");document.getElementById("fileUploadInput").value=
-"";return!1});document.getElementById("fileUploadForm").addEventListener("submit",function(a){a.preventDefault();a=document.getElementById("fileUploadInput");var b=a.value;b&&(b=b.substr(b.lastIndexOf("\\")+1),Ea(b,a.files[0],function(a){var b=document.getElementById("fileUploadError");a?(b.textContent=a,b.classList.remove("hidden")):(b.classList.add("hidden"),document.getElementById("fileUploadInput").value="",document.getElementById("fileUploadContainer").classList.add("hidden"))}));return!1});
-document.getElementById("attachFile").addEventListener("click",function(a){a.preventDefault();I&&document.getElementById("fileUploadContainer").classList.remove("hidden");return!1});document.getElementById("msgForm").addEventListener("submit",function(a){a.preventDefault();a=document.getElementById("msgInput");I&&a.value&&Fa(a.value)&&(a.value="",S&&(S=null,R()),W&&(W=null,R()),document.getElementById("slashList").textContent="");U();return!1});window.addEventListener("blur",function(){window.hasFocus=
-!1});window.addEventListener("focus",function(){window.hasFocus=!0;L=0;I&&Ga();U()});var a=0;document.getElementById("msgInput").addEventListener("input",function(){if(I){var b=Date.now();!(a+3E3<b)||!H.a.a.f&&I instanceof m||(Ha(),a=b);var b=[],c=this.value;if("/"===this.value[0]){var d=c.indexOf(" "),f=-1!==d,d=-1===d?c.length:d,c=c.substr(0,d),e;for(e in H.a.g.data){var g=H.a.g.data[e];(!f&&g.name.substr(0,d)===c||f&&g.name===c)&&b.push(g)}}b.sort(function(a,b){return a.B.localeCompare(b.B)||a.name.localeCompare(b.name)});
-var d=document.getElementById("slashList"),f=document.createDocumentFragment(),h;d.textContent="";e=0;for(c=b.length;e<c;e++)g=b[e],h!==g.B&&(h=g.B,f.appendChild(Ia(g.B))),f.appendChild(Ja(g));d.appendChild(f)}});window.hasFocus=!0;(function(){var a=document.getElementById("emojiButton");if("makeEmoji"in window){var c=window.makeEmoji("smile");c?a.innerHTML="<span class='emoji-small'>"+c.outerHTML+"</span>":a.style.backgroundImage='url("smile.svg")';(c=window.makeEmoji("paperclip"))?document.getElementById("attachFile").innerHTML=
-"<span class='emoji-small'>"+c.outerHTML+"</span>":document.getElementById("attachFile").style.backgroundImage='url("public/paperclip.svg")';a.addEventListener("click",function(){Ba.N(document.body,function(a){a&&(document.getElementById("msgInput").value+=":"+a+":");U()})})}else a.classList.add("hidden")})();Z()});function M(){var a=document.createElement("span"),b=document.createElement("span"),c=document.createElement("span"),d=document.createElement("span");a.className="typing-container";b.className="typing-dot1";c.className="typing-dot2";d.className="typing-dot3";b.textContent=c.textContent=d.textContent=".";a.appendChild(b);a.appendChild(c);a.appendChild(d);return a}
-function Ka(a,b,c,d){var f=va(c);if(f){for(var e=document.createElement("li"),g=document.createElement("a"),h=document.createElement("span"),l=document.createElement("span"),n=[],k=0,p=d.length;k<p;k++){var r=B(H.a,d[k]);r&&n.push(r.name)}n.sort();l.textContent=n.join(", ");h.appendChild(f);h.className="emoji-small";g.href="javascript:toggleReaction('"+a+"', '"+b+"', '"+c+"')";g.appendChild(h);g.appendChild(l);e.className="slackmsg-reaction-item";e.appendChild(g);return e}return null}
-function xa(a,b,c){var d=document.createElement("div"),f=document.createElement("div"),e=document.createElement("div"),g=document.createElement("div"),h=document.createElement("img"),l=document.createElement("span"),n=document.createElement("ul"),k=document.createElement("li"),p=document.createElement("ul"),r=document.createElement("ul"),u=B(H.a,b.m);d.id=a+"_"+b.i;d.className="slackmsg-item";e.className="slackmsg-ts";g.className="slackmsg-msg";h.className="slackmsg-author-img";l.className="slackmsg-author-name";
-n.className="slackmsg-hover";k.className="slackmsg-hover-reply";e.innerHTML=K.G(b.i);g.innerHTML=X(b.text);l.textContent=u?u.name:b.f||"?";h.src=u?u.a.u:"";n.appendChild(k);if("makeEmoji"in window){var x=document.createElement("li"),A=window.makeEmoji("arrow_heading_down"),D=window.makeEmoji("smile"),y=window.makeEmoji("pencil2"),u=window.makeEmoji("x");x.className="slackmsg-hover-reaction";D?(x.classList.add("emoji-small"),x.appendChild(D)):x.style.backgroundImage='url("smile.svg")';A?(k.classList.add("emoji-small"),
-k.appendChild(A)):k.style.backgroundImage='url("repl.svg")';n.appendChild(x);b.m===H.a.a.id&&(k=document.createElement("li"),k.className="slackmsg-hover-edit",y?k.classList.add("emoji-small"):k.style.backgroundImage='url("edit.svg")',k.appendChild(y),n.appendChild(k),k=document.createElement("li"),k.className="slackmsg-hover-remove",u?k.classList.add("emoji-small"):k.style.backgroundImage='url("remove.svg")',k.appendChild(u),n.appendChild(k))}else k.style.backgroundImage='url("repl.svg")',b.m===H.a.a.id&&
-(k=document.createElement("li"),k.className="slackmsg-hover-edit",k.style.backgroundImage='url("edit.svg")',n.appendChild(k),k=document.createElement("li"),k.className="slackmsg-hover-remove",k.style.backgroundImage='url("remove.svg")',n.appendChild(k));d.appendChild(h);f.appendChild(l);f.appendChild(g);f.appendChild(e);f.appendChild(p);b.o&&(e=document.createElement("div"),e.textContent=K.o,e.className="slackmsg-edited",f.appendChild(e));f.appendChild(r);f.className="slackmsg-content";p.className=
-"slackmsg-attachments";r.className="slackmsg-reactions";if(!0!==c){if(b.a)for(var v in b.a)(c=Ka(a,b.id,v,b.a[v]))&&r.appendChild(c);b.c.forEach(function(a){var b=document.createElement("li"),c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("a"),f=document.createElement("div"),h=document.createElement("img"),g=document.createElement("a"),k=document.createElement("div"),t=document.createElement("div"),A=document.createElement("img"),l=document.createElement("img"),
-y=document.createElement("div"),n=document.createElement("img"),v=document.createElement("span"),D=document.createElement("span");b.className="slackmsg-attachment";var r="#e3e4e6";a.color&&("#"===a.color[0]?r=a.color[0]:"good"===a.color?r="#2fa44f":"warning"===a.color?r="#de9e31":"danger"===a.color&&(r="#d50200"));c.style.borderColor=r;c.className="slackmsg-attachment-block";d.className="slackmsg-attachment-pretext";a.pretext?d.innerHTML=X(a.pretext):d.classList.add("hidden");e.target="_blank";a.title?
-(e.innerHTML=X(a.title),a.title_link&&(e.href=a.title_link),e.className="slackmsg-attachment-title"):e.className="hidden slackmsg-attachment-title";g.target="_blank";f.className="slackmsg-author";a.author_name?(g.innerHTML=X(a.author_name),g.href=a.author_link||"",g.className="slackmsg-author-name",h.className="slackmsg-author-img",a.author_icon?h.src=a.author_icon:h.classList.add("hidden")):f.classList.add("hidden");t.innerHTML=X(a.text||"");t.a="slackmsg-attachment-text";A.className="slackmsg-attachment-thumb";
-a.thumb_url?A.src=a.thumb_url:A.classList.add("hidden");l.className="slackmsg-attachment-img";a.image_url?l.src=a.image_url:l.classList.add("hidden");y.className="slackmsg-attachment-footer";v.className="slackmsg-attachment-footer-text";n.className="slackmsg-attachment-footer-icon";a.footer?(v.innerHTML=X(a.footer),a.footer_icon?n.src=a.footer_icon:n.classList.add("hidden")):(n.classList.add("hidden"),v.classList.add("hidden"));D.className="slackmsg-ts";a.ts?D.innerHTML=K.G(a.ts):D.classList.add("hidden");
-f.appendChild(h);f.appendChild(g);k.appendChild(t);k.appendChild(A);y.appendChild(n);y.appendChild(v);y.appendChild(D);c.appendChild(e);c.appendChild(f);c.appendChild(k);c.appendChild(l);c.appendChild(y);b.appendChild(d);b.appendChild(c);b&&p.appendChild(b)})}d.appendChild(f);d.appendChild(n);return d}function Ia(a){var b=document.createElement("lh");b.textContent=a;b.className="slack-command-header";return b}
-function Ja(a){var b=document.createElement("li"),c=document.createElement("span"),d=document.createElement("span"),f=document.createElement("span");c.textContent=a.name;d.textContent=a.usage;f.textContent=a.a;b.appendChild(c);b.appendChild(d);b.appendChild(f);b.className="slack-command-item";c.className="slack-command-name";d.className="slack-command-usage";f.className="slack-command-desc";return b};var Ba=function(){function a(a,b){for(var c=a.target;c!==l&&c&&"LI"!==c.nodeName;)c=c.parentElement;c&&"LI"===c.nodeName&&c.id&&"emojibar-"===c.id.substr(0,9)?b(c.id.substr(9)):b(null)}function b(){if(!c())return!1;t&&t(null);return!0}function c(){return l.parentElement?(l.parentElement.removeChild(n),l.parentElement.removeChild(l),!0):!1}function d(a){var b=0,c;a=void 0===a?u.value:a;if(h()){var d=window.searchEmojis(a);c=f(d);for(var g in x)x[g].visible&&(x[g].visible=!1,p.removeChild(x[g].j));
-g=0;for(var k=c.length;g<k;g++){var t=c[g].name,l=x[t];if(!l){var l=x,y=t,n=t,t=window.makeEmoji(d[t]),v=document.createElement("span");v.appendChild(t);v.className="emoji-medium";t=e(n,v);l=l[y]=t}l.visible||(l.visible=!0,p.appendChild(l.j));b++}}for(g in A)A[g].visible&&(A[g].visible=!1,r.removeChild(A[g].j));c=f(H.a.h.data);g=0;for(k=c.length;g<k;g++)t=c[g].name,""!==a&&t.substr(0,a.length)!==a||"alias:"===H.a.h.data[t].substr(0,6)||(l=A[t],l||(d=A,y=l=t,t=H.a.h.data[t],n=document.createElement("span"),
-v=document.createElement("span"),n.className="emoji emoji-custom",n.style.backgroundImage='url("'+t+'")',v.appendChild(n),v.className="emoji-medium",t=e(y,v),l=d[l]=t),l.visible||(l.visible=!0,r.appendChild(l.j)),b++);return b}function f(a){var b=H.a.a.c.b,c=[],d;for(d in a){var e={name:d,M:0,count:0};a[d].names.forEach(function(a){e.count+=b[a]||0});c.push(e)}return c=c.sort(function(a,b){var c=b.count-a.count;return c?c:a.M-b.M})}function e(a,b){var c=document.createElement("li");c.appendChild(b);
-c.className="emojibar-list-item";c.id="emojibar-"+a;return{visible:!1,j:c}}function g(a){var b=document.createElement("img"),c=document.createElement("div");b.src=a;c.appendChild(b);c.className="emojibar-header";return c}function h(){return"searchEmojis"in window}var l=document.createElement("div"),n=document.createElement("div"),k=document.createElement("div"),p=document.createElement("ul"),r=document.createElement("ul"),u=document.createElement("input"),x={},A={},D=document.createElement("div"),
-y=document.createElement("span"),v=document.createElement("span"),t;n.addEventListener("click",function(a){var c=l.getBoundingClientRect();(a.screenY<c.top||a.screenY>c.bottom||a.screenX<c.left||a.screenX>c.right)&&b()});n.className="emojibar-overlay";l.className="emojibar";k.className="emojibar-emojis";D.className="emojibar-detail";y.className="emojibar-detail-img";v.className="emojibar-detail-name";p.className=r.className="emojibar-list";u.className="emojibar-search";D.appendChild(y);D.appendChild(v);
-k.appendChild(g(window.emojiProviderHeader));k.appendChild(p);k.appendChild(g("emojicustom.png"));k.appendChild(r);l.appendChild(k);l.appendChild(D);l.appendChild(u);u.addEventListener("keyup",function(){d()});l.addEventListener("mousemove",function(b){a(b,function(a){var b=a?x[a]||A[a]:null;b?(y.innerHTML=b.j.outerHTML,v.textContent=":"+a+":"):(y.textContent="",v.textContent="")})});l.addEventListener("click",function(b){a(b,function(a){a&&c()&&t&&t(a)})});return{isSupported:h,N:function(a,b){return h()?
-(t=b,a.appendChild(n),a.appendChild(l),u.value="",d(),u.focus(),!0):!1},search:d,close:b}}();var H,N={};function La(a){var b=H,c=Date.now();a.v&&(b.c=a.v);a["static"]&&(ha(b.a,a["static"]),N={},ia(b.a,function(a){a.a>a.b&&(N[a.id]={s:!1,F:!0});return!0}));if(a.live){for(var d in a.live){var f=b.b[d];f?F(f,a.live[d],c):f=b.b[d]=new E(d,250,a.live[d],c)}for(var e in a.live)(c=C(b.a,e))?(b.b[e].a.length&&(c.a=Math.max(c.a,na(b.b[e]).i)),c.f||(Ma(c,a.live[e]),I&&a.live[I.id]&&za())):H.c=0}a["static"]&&(qa(),a["static"].typing&&sa())}
-setInterval(function(){var a=H.a,b=Date.now(),c=!1,d;for(d in a.b){var f=!0,e;for(e in a.b[d])a.b[d][e]+3E3<b?(delete a.b[d][e],c=!0):f=!1;f&&(delete a.b[d],c=!0)}c&&sa()},1E3);
-function Ma(a,b){if(a!==I||!window.hasFocus){var c=new RegExp("<@"+H.a.a.id),d=!1,f=!1;b.forEach(function(b){if(!(parseFloat(b.ts)<=a.b)){N[a.id]||(N[a.id]={s:!1,F:!0});var e;if(!(e=a instanceof q||a instanceof w||b.text.match(c)))a:{e=H.a.a.c.a;for(var g=0,n=e.length;g<n;g++)if(-1!==b.text.indexOf(e[g])){e=!0;break a}e=!1}e&&(f|=!N[a.id].s,d=N[a.id].s=!0)}});P();var e=document.getElementById(a.id);e&&(e.classList.add("unread"),d&&e.classList.add("unreadHi"));f&&!window.hasFocus&&ya()}}
-function Ga(){var a=I;N[a.id]&&(delete N[a.id],P());a=document.getElementById(a.id);a.classList.remove("unread");a.classList.remove("unreadHi")}H=new function(){this.c=0;this.a=new z;this.b={}};var ra=function(){function a(a,b){b.sort(function(){return Math.random()-.5});for(var c=0,d=20;d<l-40;d+=k)for(var f=0;f+k<=n;f+=k)e(a,b[c],d,f),c++,c===b.length&&(b.sort(function(a,b){return a.w?b.w?Math.random()-.5:-1:1}),c=0)}function b(a,d){for(var e=0,f=a.length;e<f;e++)if(void 0===a[e].w){c(a[e].src,function(c){a[e].w=c;b(a,d)});return}var g=[];a.forEach(function(a){a.w&&g.push(a.w)});d(g)}function c(a,b){var c=new XMLHttpRequest;c.responseType="blob";c.onreadystatechange=function(){if(4===
-c.readyState)if(c.response){var a=new Image;a.onload=function(){var c=document.createElement("canvas");c.height=c.width=u;c=c.getContext("2d");c.drawImage(a,0,0,u,u);for(var c=c.getImageData(0,0,u,u),d=0,e=0;e<c.width*c.height*4;e+=4)c.data[e]=c.data[e+1]=c.data[e+2]=(c.data[e]+c.data[e+1]+c.data[e+2])/3,c.data[e+3]=50,d+=c.data[e];if(50>d/(c.height*c.width))for(e=0;e<c.width*c.height*4;e+=4)c.data[e]=c.data[e+1]=c.data[e+2]=255-c.data[e];b(c)};a.onerror=function(){b(null)};a.src=window.URL.createObjectURL(c.response)}else b(null)};
-c.open("GET",a,!0);c.send(null)}function d(){var a=h.createLinearGradient(0,0,0,n);a.addColorStop(0,"#4D394B");a.addColorStop(1,"#201820");h.fillStyle=a;h.fillRect(0,0,l,n);return h.getImageData(0,0,l,n)}function f(a,b){for(var c=(a.height-b.height)/2,d=0;d<b.height;d++)for(var e=0;e<b.width;e++){var f=b.data[4*(d*b.width+e)]/255,g=4*((d+c)*a.width+e+c);a.data[g]*=f;a.data[g+1]*=f;a.data[g+2]*=f}return a}function e(a,b,c,d){var e=Math.floor(d);a=[a.data[e*l*4+0],a.data[e*l*4+1],a.data[e*l*4+2]];h.fillStyle=
-"#"+(1.1*a[0]<<16|1.1*a[1]<<8|1.1*a[2]).toString(16);h.beginPath();h.moveTo(c+k/2,d+p);h.lineTo(c-p+k,d+k/2);h.lineTo(c+k/2,d-p+k);h.lineTo(c+p,d+k/2);h.closePath();h.fill();h.putImageData(f(h.getImageData(c+p,d+p,r,r),b),c+p,d+p)}var g=document.createElement("canvas"),h=g.getContext("2d"),l=g.width=250,n=g.height=290,k=(l-40)/3,p=.1*k,r=Math.floor(k-2*p),u=.5*r,x;return function(c){if(x)c(x);else{var e=d(),f=[],h;for(h in H.a.c)H.a.c[h].h||f.push({src:"api/avatar?user="+h});b(f,function(b){a(e,b);
-x=g.toDataURL();c(x)})}}}();var Y=0,I=null,S=null,W=null;function Na(a){var b=new XMLHttpRequest;b.timeout=6E4;b.onreadystatechange=function(){if(4===b.readyState)if(b.status){var c=null,d=2===Math.floor(b.status/100);if(d){Y&&(Y=0,Q(!0));c=b.response;try{c=JSON.parse(c)}catch(f){c=null}}else Y?(Y+=Math.floor((Y||5)/2),Y=Math.min(60,Y)):(Y=5,Q(!1));a(d,c)}else Y&&(Y=0,Q(!0)),Na(a)};b.open("GET","api?v="+H.c,!0);b.send(null)}function Ha(){var a=new XMLHttpRequest;a.open("POST","api/typing?room="+I.id,!0);a.send(null)}
-function Oa(a,b){a?(b&&La(b),Z()):setTimeout(Z,1E3*Y)}function Z(){Na(Oa)}
-function Da(a){I&&document.getElementById(I.id).classList.remove("selected");document.getElementById(a.id).classList.add("selected");document.body.classList.remove("no-room-selected");I=a;a=I.name||(I.g?I.g.name:void 0);if(!a){a=[];for(var b in I.c)a.push(I.c[b].name);a=a.join(", ")}document.getElementById("currentRoomTitle").textContent=a;za();U();document.getElementById("fileUploadContainer").classList.add("hidden");Ga();S&&(S=null,R());W&&(W=null,R());ta();I.b&&!H.b[I.id]&&(b=new XMLHttpRequest,
-b.open("GET","api/hist?room="+I.id,!0),b.send(null))}function Ea(a,b,c){var d=I;new FileReader;var f=new FormData,e=new XMLHttpRequest;f.append("file",b);f.append("filename",a);e.onreadystatechange=function(){4===e.readyState&&(204===e.status?c(null):c(e.statusText))};e.open("POST","api/file?room="+d.id);e.send(f)}
-function Fa(a){if(W){var b=new XMLHttpRequest;b.open("PUT","api/msg?room="+I.id+"&ts="+W.id+"&text="+encodeURIComponent(a),!0);b.send(null);return!0}if("/"===a[0]){var c=a.indexOf(" "),b=-1===c?"":a.substr(c);return(a=H.a.g.data[a.substr(0,-1===c?void 0:c)])?(c=new XMLHttpRequest,c.open("POST","api/cmd?room="+I.id+"&cmd="+encodeURIComponent(a.name.substr(1))+"&args="+encodeURIComponent(b.trim()),!0),c.send(null),!0):!1}var b=I,c=S,d=new XMLHttpRequest;a="api/msg?room="+b.id+"&text="+encodeURIComponent(a);
-if(c){var f=B(H.a,c.m),e="Message";"C"===b.id[0]?e="Channel message":"D"===b.id[0]?e="Direct message":"G"===b.id[0]&&(e="Group message");a+="&attachments="+encodeURIComponent(JSON.stringify([{fallback:c.text,author_name:"<@"+f.id+"|"+f.name+">",author_icon:f.a.u,text:c.text,footer:e,ts:c.i}]))}d.open("POST",a,!0);d.send(null);return!0}function Ca(a){var b=new XMLHttpRequest;b.open("DELETE","api/msg?room="+I.id+"&ts="+a.id,!0);b.send(null)}
-function ua(a,b,c){var d=new XMLHttpRequest;d.open("POST","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(c),!0);d.send(null)};
+window.toggleReaction=function(a,b,c){var d=E.b[a];if(d&&(d=H(d,b))){var f=E.a.a.id;d.a[c]&&-1!==d.a[c].indexOf(f)?(d=new XMLHttpRequest,d.open("DELETE","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(c),!0),d.send(null)):sa(a,b,c)}};
+function ta(a){a:{for(var b=a,c={};!c[b];){if(a=E.a.h[b])if("alias:"==a.substr(0,6))c[b]=!0,b=a.substr(6);else{b=document.createElement("span");b.className="emoji-custom emoji";b.style.backgroundImage="url('"+a+"')";a=b;break a}break}a=b}"string"===typeof a&&"makeEmoji"in window&&(a=window.makeEmoji(a));return"string"===typeof a?null:a}
+function ua(a){return a.replace(/:([^ \t:]+):/g,function(b,c){var d=ta(c);if(d){var f=document.createElement("span");f.className=b===a?"emoji-medium":"emoji-small";f.appendChild(d);return f.outerHTML}return b})}
+function X(a){a=a.split(/\r?\n/g);for(var b=0,c=a.length;b<c;b++){for(var d=a[b].trim(),f="",e={},n=!1,k=0,d=d.replace(RegExp("<([@#]?)([^>]*)>","g"),function(a,b,c){c=c.split("|");if("@"===b)c[1]?"@"!==c[1][0]&&(c[1]="@"+c[1]):(a=C(E.a,c[0]),c[1]=a?"@"+a.name:K.N),c[0]="#"+c[0],c[2]="slackmsg-link slackmsg-link-user";else if("#"===b)c[1]?"#"!==c[1][0]&&(c[1]="#"+c[1]):(a=D(E.a,c[0]),c[1]=a?"#"+a.name:K.M),c[0]="#"+c[0],c[2]="slackmsg-link slackmsg-link-chan";else if(-1!==c[0].indexOf("://"))c[1]||
+(c[1]=c[0]),c[2]="slackmsg-link";else return a;return'<a href="'+c[0]+'" class="'+c[2]+'"'+(b?"":' target="_blank"')+">"+c[1]+"</a>"}),d=ua(d),l=d.length,h=function(a,b,c){for(;a[b];){var d=a[b];if(("A"<=d&&"Z">=d||"a"<=d&&"z">=d||"0"<=d&&"9">=d||-1!=="\u00e0\u00e8\u00ec\u00f2\u00f9\u00c0\u00c8\u00cc\u00d2\u00d9\u00e1\u00e9\u00ed\u00f3\u00fa\u00fd\u00c1\u00c9\u00cd\u00d3\u00da\u00dd\u00e2\u00ea\u00ee\u00f4\u00fb\u00c2\u00ca\u00ce\u00d4\u00db\u00e3\u00f1\u00f5\u00c3\u00d1\u00d5\u00e4\u00eb\u00ef\u00f6\u00fc\u00ff\u00c4\u00cb\u00cf\u00d6\u00dc\u0178\u00e7\u00c7\u00df\u00d8\u00f8\u00c5\u00e5\u00c6\u00e6\u0153".indexOf(d))&&
+a[b]!=c&&a[b+1]==c)return!0;b++}return!1},g=function(a){return Object.keys(e).length?'<span class="'+Object.keys(a).join(" ")+'">':""};k<l&&(" "===d[k]||"\t"===d[k]);)k++;"&gt;"===d.substr(k,4)&&(n=!0,k+=4);for(;k<l;k++){var m=d[k];if("<"===m){do f+=d[k++];while(">"!==d[k-1]);k--}else if(!e["slackmsg-style-bold"]&&"*"===m&&d[k+1]&&h(d,k,m))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-bold"]=!0,f+=g(e);else if(!e["slackmsg-style-strike"]&&"~"===m&&d[k+1]&&h(d,k,m))Object.keys(e).length&&
+(f+="</span>"),e["slackmsg-style-strike"]=!0,f+=g(e);else if(!e["slackmsg-style-code"]&&"`"===m&&d[k+1]&&h(d,k,m))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-code"]=!0,f+=g(e);else if(!e["slackmsg-style-italic"]&&"_"===m&&d[k+1]&&h(d,k,m))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-italic"]=!0,f+=g(e);else{var v=!1,f=f+m;do{if(e["slackmsg-style-bold"]&&"*"!==m&&"*"===d[k+1])delete e["slackmsg-style-bold"],v=!0;else if(e["slackmsg-style-strike"]&&"~"!==m&&"~"===d[k+1])delete e["slackmsg-style-strike"],
+v=!0;else if(e["slackmsg-style-code"]&&"`"!==m&&"`"===d[k+1])delete e["slackmsg-style-code"],v=!0;else if(e["slackmsg-style-italic"]&&"_"!==m&&"_"===d[k+1])delete e["slackmsg-style-italic"],v=!0;else break;m=d[++k]}while(k<l);v&&(f+="</span>"+g(e))}}e&&(f+="</span>");a[b]=n?'<span class="slackmsg-style-quote">'+f+"</span>":f}return a.join("<br/>")}function T(a,b,c){b.g?(a=va(a,b,c),a.classList.add("slackmsg-me_message")):a=va(a,b,c);b.o&&a.classList.add("slackmsg-edited");return a}
+function wa(a,b){document.getElementById("linkFavicon").href=a||b?"favicon.png?h="+a+"&m="+b:"favicon_ok.png"}function P(){var a=N.length,b="";if(Y)b="!"+K.H+" - ",document.getElementById("linkFavicon").href="favicon_err.png";else if(a)b="(!"+a+") - ",wa(a,a);else{var c=0;ha(function(a){a.b>a.a&&c++});c&&(b="("+c+") - ");wa(0,c)}b+=E.a.C.name;document.title=b}
+function xa(){if("Notification"in window)if("granted"===Notification.permission){var a=Date.now();if(L+3E4<a){var b=new Notification(K.I);L=a;setTimeout(function(){b.close()},5E3)}}else"denied"!==Notification.permission&&Notification.requestPermission()}
+function ya(){var a=document.createDocumentFragment(),b=I.id,c=null,d=0,f=null;E.b[b]&&E.b[b].a.forEach(function(e){if(!e.b){var k=T(b,e);c&&c.m===e.m&&e.m?(k.classList.add("slackmsg-same-author"),30>Math.abs(d-e.i)?f.classList.add("slackmsg-same-ts"):d=e.i):d=e.i;(!c||c.i<=I.a)&&e.i>I.a&&k.classList.add("slackmsg-first-unread");c=e;f=k;a.appendChild(k)}});var e=document.getElementById("chatWindow");e.textContent="";e.appendChild(a);e.scrollTop=e.scrollHeight-e.clientHeight}
+function za(a){function b(a,b){for(b=b||a.target;b!==a.currentTarget&&b;){if(b.classList.contains("slackmsg-item"))return b.id;b=b.parentElement}}for(var c=a.target;c!==a.currentTarget&&c&&!c.classList.contains("slackmsg-hover");){if(c.parentElement&&c.parentElement.classList.contains("slackmsg-hover")){if(a=b(a,c)){a=parseFloat(a.split("_")[1]);var d=ma(a);d&&c.classList.contains("slackmsg-hover-reply")?(W&&(W=null,V()),S!==d&&(S=d,R())):d&&c.classList.contains("slackmsg-hover-reaction")?Aa.L(document.body,
+function(a){a&&sa(I.id,d.id,a)}):d&&c.classList.contains("slackmsg-hover-edit")?(S&&(S=null,R()),W!==d&&(W=d,V())):d&&c.classList.contains("slackmsg-hover-remove")&&(S&&(S=null,R()),W&&(W=null,V()),Ba(d))}break}c=c.parentElement}}function U(){document.getElementById("msgInput").focus()}function O(){var a=document.location.hash.substr(1),b=D(E.a,a),a=C(E.a,a);b&&b!==I?Ca(b):a&&a.b&&Ca(a.b)}
+document.addEventListener("DOMContentLoaded",function(){na();document.getElementById("chatWindow").addEventListener("click",za);window.addEventListener("hashchange",function(){document.location.hash&&"#"===document.location.hash[0]&&O()});document.getElementById("fileUploadCancel").addEventListener("click",function(a){a.preventDefault();document.getElementById("fileUploadError").classList.add("hidden");document.getElementById("fileUploadContainer").classList.add("hidden");document.getElementById("fileUploadInput").value=
+"";return!1});document.getElementById("fileUploadForm").addEventListener("submit",function(a){a.preventDefault();a=document.getElementById("fileUploadInput");var b=a.value;b&&(b=b.substr(b.lastIndexOf("\\")+1),Da(b,a.files[0],function(a){var b=document.getElementById("fileUploadError");a?(b.textContent=a,b.classList.remove("hidden")):(b.classList.add("hidden"),document.getElementById("fileUploadInput").value="",document.getElementById("fileUploadContainer").classList.add("hidden"))}));return!1});
+document.getElementById("attachFile").addEventListener("click",function(a){a.preventDefault();I&&document.getElementById("fileUploadContainer").classList.remove("hidden");return!1});document.getElementById("msgForm").addEventListener("submit",function(a){a.preventDefault();a=document.getElementById("msgInput");I&&a.value&&Ea(a.value)&&(a.value="",S&&(S=null,R()),W&&(W=null,R()),document.getElementById("slashList").textContent="");U();return!1});window.addEventListener("blur",function(){window.hasFocus=
+!1});window.addEventListener("focus",function(){window.hasFocus=!0;L=0;I&&Fa();U()});var a=0;document.getElementById("msgInput").addEventListener("input",function(){if(I){var b=Date.now();!(a+3E3<b)||!E.a.a.f&&I instanceof p||(Ga(),a=b);var b=[],c=this.value;if("/"===this.value[0]){var d=c.indexOf(" "),f=-1!==d,d=-1===d?c.length:d,c=c.substr(0,d),e;for(e in E.a.g.data){var n=E.a.g.data[e];(!f&&n.name.substr(0,d)===c||f&&n.name===c)&&b.push(n)}}b.sort(function(a,b){return a.A.localeCompare(b.A)||a.name.localeCompare(b.name)});
+var d=document.getElementById("slashList"),f=document.createDocumentFragment(),k;d.textContent="";e=0;for(c=b.length;e<c;e++)n=b[e],k!==n.A&&(k=n.A,f.appendChild(Ha(n.A))),f.appendChild(Ia(n));d.appendChild(f)}});window.hasFocus=!0;(function(){var a=document.getElementById("emojiButton");if("makeEmoji"in window){var c=window.makeEmoji("smile");c?a.innerHTML="<span class='emoji-small'>"+c.outerHTML+"</span>":a.style.backgroundImage='url("smile.svg")';(c=window.makeEmoji("paperclip"))?document.getElementById("attachFile").innerHTML=
+"<span class='emoji-small'>"+c.outerHTML+"</span>":document.getElementById("attachFile").style.backgroundImage='url("public/paperclip.svg")';a.addEventListener("click",function(){Aa.L(document.body,function(a){a&&(document.getElementById("msgInput").value+=":"+a+":");U()})})}else a.classList.add("hidden")})();Z()});function M(){var a=document.createElement("span"),b=document.createElement("span"),c=document.createElement("span"),d=document.createElement("span");a.className="typing-container";b.className="typing-dot1";c.className="typing-dot2";d.className="typing-dot3";b.textContent=c.textContent=d.textContent=".";a.appendChild(b);a.appendChild(c);a.appendChild(d);return a}
+function Ja(a,b,c,d){var f=ta(c);if(f){for(var e=document.createElement("li"),n=document.createElement("a"),k=document.createElement("span"),l=document.createElement("span"),h=[],g=0,m=d.length;g<m;g++){var v=C(E.a,d[g]);v&&h.push(v.name)}h.sort();l.textContent=h.join(", ");k.appendChild(f);k.className="emoji-small";n.href="javascript:toggleReaction('"+a+"', '"+b+"', '"+c+"')";n.appendChild(k);n.appendChild(l);e.className="slackmsg-reaction-item";e.appendChild(n);return e}return null}
+function va(a,b,c){var d=document.createElement("div"),f=document.createElement("div"),e=document.createElement("div"),n=document.createElement("div"),k=document.createElement("img"),l=document.createElement("span"),h=document.createElement("ul"),g=document.createElement("li"),m=document.createElement("ul"),v=document.createElement("ul"),r=C(E.a,b.m);d.id=a+"_"+b.i;d.className="slackmsg-item";e.className="slackmsg-ts";n.className="slackmsg-msg";k.className="slackmsg-author-img";l.className="slackmsg-author-name";
+h.className="slackmsg-hover";g.className="slackmsg-hover-reply";e.innerHTML=K.D(b.i);n.innerHTML=X(b.text);l.textContent=r?r.name:b.f||"?";k.src=r?r.a.s:"";h.appendChild(g);if("makeEmoji"in window){var w=document.createElement("li"),y=window.makeEmoji("arrow_heading_down"),A=window.makeEmoji("smile"),x=window.makeEmoji("pencil2"),r=window.makeEmoji("x");w.className="slackmsg-hover-reaction";A?(w.classList.add("emoji-small"),w.appendChild(A)):w.style.backgroundImage='url("smile.svg")';y?(g.classList.add("emoji-small"),
+g.appendChild(y)):g.style.backgroundImage='url("repl.svg")';h.appendChild(w);b.m===E.a.a.id&&(g=document.createElement("li"),g.className="slackmsg-hover-edit",x?g.classList.add("emoji-small"):g.style.backgroundImage='url("edit.svg")',g.appendChild(x),h.appendChild(g),g=document.createElement("li"),g.className="slackmsg-hover-remove",r?g.classList.add("emoji-small"):g.style.backgroundImage='url("remove.svg")',g.appendChild(r),h.appendChild(g))}else g.style.backgroundImage='url("repl.svg")',b.m===E.a.a.id&&
+(g=document.createElement("li"),g.className="slackmsg-hover-edit",g.style.backgroundImage='url("edit.svg")',h.appendChild(g),g=document.createElement("li"),g.className="slackmsg-hover-remove",g.style.backgroundImage='url("remove.svg")',h.appendChild(g));d.appendChild(k);f.appendChild(l);f.appendChild(n);f.appendChild(e);f.appendChild(m);b.o&&(e=document.createElement("div"),e.textContent=K.o,e.className="slackmsg-edited",f.appendChild(e));f.appendChild(v);f.className="slackmsg-content";m.className=
+"slackmsg-attachments";v.className="slackmsg-reactions";if(!0!==c){if(b.a)for(var u in b.a)(c=Ja(a,b.id,u,b.a[u]))&&v.appendChild(c);b.c.forEach(function(a){var b=document.createElement("li"),c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("a"),f=document.createElement("div"),g=document.createElement("img"),h=document.createElement("a"),k=document.createElement("div"),l=document.createElement("div"),t=document.createElement("img"),y=document.createElement("img"),
+n=document.createElement("div"),u=document.createElement("img"),x=document.createElement("span"),A=document.createElement("span");b.className="slackmsg-attachment";var r="#e3e4e6";a.color&&("#"===a.color[0]?r=a.color[0]:"good"===a.color?r="#2fa44f":"warning"===a.color?r="#de9e31":"danger"===a.color&&(r="#d50200"));c.style.borderColor=r;c.className="slackmsg-attachment-block";d.className="slackmsg-attachment-pretext";a.pretext?d.innerHTML=X(a.pretext):d.classList.add("hidden");e.target="_blank";a.title?
+(e.innerHTML=X(a.title),a.title_link&&(e.href=a.title_link),e.className="slackmsg-attachment-title"):e.className="hidden slackmsg-attachment-title";h.target="_blank";f.className="slackmsg-author";a.author_name?(h.innerHTML=X(a.author_name),h.href=a.author_link||"",h.className="slackmsg-author-name",g.className="slackmsg-author-img",a.author_icon?g.src=a.author_icon:g.classList.add("hidden")):f.classList.add("hidden");l.innerHTML=X(a.text||"");l.a="slackmsg-attachment-text";t.className="slackmsg-attachment-thumb";
+a.thumb_url?t.src=a.thumb_url:t.classList.add("hidden");y.className="slackmsg-attachment-img";a.image_url?y.src=a.image_url:y.classList.add("hidden");n.className="slackmsg-attachment-footer";x.className="slackmsg-attachment-footer-text";u.className="slackmsg-attachment-footer-icon";a.footer?(x.innerHTML=X(a.footer),a.footer_icon?u.src=a.footer_icon:u.classList.add("hidden")):(u.classList.add("hidden"),x.classList.add("hidden"));A.className="slackmsg-ts";a.ts?A.innerHTML=K.D(a.ts):A.classList.add("hidden");
+f.appendChild(g);f.appendChild(h);k.appendChild(l);k.appendChild(t);n.appendChild(u);n.appendChild(x);n.appendChild(A);c.appendChild(e);c.appendChild(f);c.appendChild(k);c.appendChild(y);c.appendChild(n);b.appendChild(d);b.appendChild(c);b&&m.appendChild(b)})}d.appendChild(f);d.appendChild(h);return d}function Ha(a){var b=document.createElement("lh");b.textContent=a;b.className="slack-command-header";return b}
+function Ia(a){var b=document.createElement("li"),c=document.createElement("span"),d=document.createElement("span"),f=document.createElement("span");c.textContent=a.name;d.textContent=a.usage;f.textContent=a.a;b.appendChild(c);b.appendChild(d);b.appendChild(f);b.className="slack-command-item";c.className="slack-command-name";d.className="slack-command-usage";f.className="slack-command-desc";return b};var Aa=function(){function a(a,b){for(var c=a.target;c!==l&&c&&"LI"!==c.nodeName;)c=c.parentElement;c&&"LI"===c.nodeName&&c.id&&"emojibar-"===c.id.substr(0,9)?b(c.id.substr(9)):b(null)}function b(){if(!c())return!1;t&&t(null);return!0}function c(){return l.parentElement?(l.parentElement.removeChild(h),l.parentElement.removeChild(l),!0):!1}function d(a){var b=0,c;a=void 0===a?r.value:a;if(k()){var d=window.searchEmojis(a);c=f(d);for(var g in w)w[g].visible&&(w[g].visible=!1,m.removeChild(w[g].j));
+g=0;for(var h=c.length;g<h;g++){var l=c[g].name,t=w[l];if(!t){var t=w,n=l,u=l,l=window.makeEmoji(d[l]),x=document.createElement("span");x.appendChild(l);x.className="emoji-medium";l=e(u,x);t=t[n]=l}t.visible||(t.visible=!0,m.appendChild(t.j));b++}}for(g in y)y[g].visible&&(y[g].visible=!1,v.removeChild(y[g].j));c=f(E.a.h.data);g=0;for(h=c.length;g<h;g++)l=c[g].name,""!==a&&l.substr(0,a.length)!==a||"alias:"===E.a.h.data[l].substr(0,6)||(t=y[l],t||(d=y,n=t=l,l=E.a.h.data[l],u=document.createElement("span"),
+x=document.createElement("span"),u.className="emoji emoji-custom",u.style.backgroundImage='url("'+l+'")',x.appendChild(u),x.className="emoji-medium",l=e(n,x),t=d[t]=l),t.visible||(t.visible=!0,v.appendChild(t.j)),b++);return b}function f(a){var b=E.a.a.c.b,c=[],d;for(d in a){var e={name:d,K:0,count:0};a[d].names.forEach(function(a){e.count+=b[a]||0});c.push(e)}return c=c.sort(function(a,b){var c=b.count-a.count;return c?c:a.K-b.K})}function e(a,b){var c=document.createElement("li");c.appendChild(b);
+c.className="emojibar-list-item";c.id="emojibar-"+a;return{visible:!1,j:c}}function n(a){var b=document.createElement("img"),c=document.createElement("div");b.src=a;c.appendChild(b);c.className="emojibar-header";return c}function k(){return"searchEmojis"in window}var l=document.createElement("div"),h=document.createElement("div"),g=document.createElement("div"),m=document.createElement("ul"),v=document.createElement("ul"),r=document.createElement("input"),w={},y={},A=document.createElement("div"),
+x=document.createElement("span"),u=document.createElement("span"),t;h.addEventListener("click",function(a){var c=l.getBoundingClientRect();(a.screenY<c.top||a.screenY>c.bottom||a.screenX<c.left||a.screenX>c.right)&&b()});h.className="emojibar-overlay";l.className="emojibar";g.className="emojibar-emojis";A.className="emojibar-detail";x.className="emojibar-detail-img";u.className="emojibar-detail-name";m.className=v.className="emojibar-list";r.className="emojibar-search";A.appendChild(x);A.appendChild(u);
+g.appendChild(n(window.emojiProviderHeader));g.appendChild(m);g.appendChild(n("emojicustom.png"));g.appendChild(v);l.appendChild(g);l.appendChild(A);l.appendChild(r);r.addEventListener("keyup",function(){d()});l.addEventListener("mousemove",function(b){a(b,function(a){var b=a?w[a]||y[a]:null;b?(x.innerHTML=b.j.outerHTML,u.textContent=":"+a+":"):(x.textContent="",u.textContent="")})});l.addEventListener("click",function(b){a(b,function(a){a&&c()&&t&&t(a)})});return{isSupported:k,L:function(a,b){return k()?
+(t=b,a.appendChild(h),a.appendChild(l),r.value="",d(),r.focus(),!0):!1},search:d,close:b}}();var E,N=[];setInterval(function(){var a=E.a,b=Date.now(),c=!1,d;for(d in a.b){var f=!0,e;for(e in a.b[d])a.b[d][e]+3E3<b?(delete a.b[d][e],c=!0):f=!1;f&&(delete a.b[d],c=!0)}c&&qa()},1E3);
+function Ka(a,b){if(a!==I||!window.hasFocus){var c=new RegExp("<@"+E.a.a.id),d=!1,f=!1,e=!1;b.forEach(function(b){if(!(parseFloat(b.ts)<=a.a)){f=!0;var k;if(!(k=a instanceof z||b.text.match(c)))a:{k=E.a.a.c.a;for(var h=0,g=k.length;h<g;h++)if(-1!==b.text.indexOf(k[h])){k=!0;break a}k=!1}k&&(-1===N.indexOf(a)&&(e=!0,N.push(a)),d=!0)}});if(f){P();var n=document.getElementById(a.id);n&&(n.classList.add("unread"),d&&n.classList.add("unreadHi"));e&&!window.hasFocus&&xa()}}}
+function Fa(){var a=I,b=N.indexOf(a);a.a=a.b;0<=b&&(N.splice(b,1),P());a=document.getElementById(a.id);a.classList.remove("unread");a.classList.remove("unreadHi")}E=new function(){this.c=0;this.a=new B;this.b={}};var pa=function(){function a(a,b){b.sort(function(){return Math.random()-.5});for(var c=0,d=20;d<l-40;d+=g)for(var f=0;f+g<=h;f+=g)e(a,b[c],d,f),c++,c===b.length&&(b.sort(function(a,b){return a.u?b.u?Math.random()-.5:-1:1}),c=0)}function b(a,d){for(var e=0,f=a.length;e<f;e++)if(void 0===a[e].u){c(a[e].src,function(c){a[e].u=c;b(a,d)});return}var g=[];a.forEach(function(a){a.u&&g.push(a.u)});d(g)}function c(a,b){var c=new XMLHttpRequest;c.responseType="blob";c.onreadystatechange=function(){if(4===
+c.readyState)if(c.response){var a=new Image;a.onload=function(){var c=document.createElement("canvas");c.height=c.width=r;c=c.getContext("2d");c.drawImage(a,0,0,r,r);for(var c=c.getImageData(0,0,r,r),d=0,e=0;e<c.width*c.height*4;e+=4)c.data[e]=c.data[e+1]=c.data[e+2]=(c.data[e]+c.data[e+1]+c.data[e+2])/3,c.data[e+3]=50,d+=c.data[e];if(50>d/(c.height*c.width))for(e=0;e<c.width*c.height*4;e+=4)c.data[e]=c.data[e+1]=c.data[e+2]=255-c.data[e];b(c)};a.onerror=function(){b(null)};a.src=window.URL.createObjectURL(c.response)}else b(null)};
+c.open("GET",a,!0);c.send(null)}function d(){var a=k.createLinearGradient(0,0,0,h);a.addColorStop(0,"#4D394B");a.addColorStop(1,"#201820");k.fillStyle=a;k.fillRect(0,0,l,h);return k.getImageData(0,0,l,h)}function f(a,b){for(var c=(a.height-b.height)/2,d=0;d<b.height;d++)for(var e=0;e<b.width;e++){var g=b.data[4*(d*b.width+e)]/255,f=4*((d+c)*a.width+e+c);a.data[f]*=g;a.data[f+1]*=g;a.data[f+2]*=g}return a}function e(a,b,c,d){var e=Math.floor(d);a=[a.data[e*l*4+0],a.data[e*l*4+1],a.data[e*l*4+2]];k.fillStyle=
+"#"+(1.1*a[0]<<16|1.1*a[1]<<8|1.1*a[2]).toString(16);k.beginPath();k.moveTo(c+g/2,d+m);k.lineTo(c-m+g,d+g/2);k.lineTo(c+g/2,d-m+g);k.lineTo(c+m,d+g/2);k.closePath();k.fill();k.putImageData(f(k.getImageData(c+m,d+m,v,v),b),c+m,d+m)}var n=document.createElement("canvas"),k=n.getContext("2d"),l=n.width=250,h=n.height=290,g=(l-40)/3,m=.1*g,v=Math.floor(g-2*m),r=.5*v,w;return function(c){if(w)c(w);else{var e=d(),f=[],g;for(g in E.a.c)E.a.c[g].h||f.push({src:"api/avatar?user="+g});b(f,function(b){a(e,b);
+w=n.toDataURL();c(w)})}}}();var Y=0,I=null,S=null,W=null;function La(a){var b=new XMLHttpRequest;b.timeout=6E4;b.onreadystatechange=function(){if(4===b.readyState)if(b.status){var c=null,d=2===Math.floor(b.status/100);if(d){Y&&(Y=0,Q(!0));c=b.response;try{c=JSON.parse(c)}catch(f){c=null}}else Y?(Y+=Math.floor((Y||5)/2),Y=Math.min(60,Y)):(Y=5,Q(!1));a(d,c)}else Y&&(Y=0,Q(!0)),La(a)};b.open("GET","api?v="+E.c,!0);b.send(null)}function Ga(){var a=new XMLHttpRequest;a.open("POST","api/typing?room="+I.id,!0);a.send(null)}
+function Ma(a,b){if(a){if(b){var c=E,d=Date.now();b.v&&(c.c=b.v);if(b["static"]){var f=c.a,e=b["static"],n=Date.now();if(e.bots)for(var k=0,l=e.bots.length;k<l;k++){var h=f.f[e.bots[k].id];h||(h=f.f[e.bots[k].id]=new ea(e.bots[k].id));var g=e.bots[k],m=n;void 0!==g.deleted&&(h.h=g.deleted);void 0!==g.name&&(h.name=g.name);void 0!==g.app_id&&(h.l=g.app_id);g.icons&&(h.a.X=g.icons.image_36,h.a.s=g.icons.image_48,h.a.F=g.icons.image_72);void 0!==g.presence&&(h.f="away"!==g.presence);void 0!==g.isPresent&&
+(h.f=g.isPresent);h.version=Math.max(h.version,m)}if(e.users)for(k=0,l=e.users.length;k<l;k++)(h=f.c[e.users[k].id])||(h=f.c[e.users[k].id]=new ba(e.users[k].id)),g=e.users[k],m=n,void 0!==g.name&&(h.name=g.name),void 0!==g.deleted&&(h.h=g.deleted),void 0!==g.status&&(h.status=g.status),void 0!==g.presence&&(h.f="away"!==g.presence),void 0!==g.isPresent&&(h.f=g.isPresent),g.profile&&(h.a.U=g.profile.image_24,h.a.V=g.profile.image_32,h.a.s=g.profile.image_48,h.a.F=g.profile.image_72,h.a.S=g.profile.image_192,
+h.a.Z=g.profile.image_512),h.version=Math.max(h.version,m);if(e.ims)for(k=0,l=e.ims.length;k<l;k++)if(g=C(f,e.ims[k].user)){g.b||(f.B[e.ims[k].id]=g.b=new z(e.ims[k].id,g));var h=g.b,m=e.ims[k],v=n;void 0!==m.last_read&&(h.a=Math.max(parseFloat(m.last_read),h.a));void 0!==m.last_msg&&(h.b=parseFloat(m.last_msg));m.latest&&(h.b=parseFloat(m.latest.ts));h.f=g.h;h.version=Math.max(h.version,v)}if(e.channels)for(k=0,l=e.channels.length;k<l;k++){(h=f.l[e.channels[k].id])||(h=f.l[e.channels[k].id]=new p(e.channels[k].id));
+g=e.channels[k];m=f;v=n;void 0!==g.name&&(h.name=g.name);void 0!==g.is_archived&&(h.f=g.is_archived);void 0!==g.last_read&&(h.a=Math.max(parseFloat(g.last_read),h.a));void 0!==g.last_msg&&(h.b=parseFloat(g.last_msg));g.latest&&(h.b=parseFloat(g.latest.ts));if(g.members&&(h.c={},g.members))for(var r=0,w=g.members.length;r<w;r++){var y=C(m,g.members[r]);h.c[y.id]=y;y.g[h.id]=h}h.version=Math.max(h.version,v)}k=0;for(l=e.groups.length;k<l;k++){(h=f.w[e.groups[k].id])||(h=f.w[e.groups[k].id]=new q(e.groups[k].id));
+g=f;m=e.groups[k];v=n;r=[];if(m.members){h.c={};w=h.h=0;for(y=m.members.length;w<y;w++){var A=C(g,m.members[w]);h.c[m.members[w]]=A;A.g[h.id]=h;r.push(A.name);h.h++}h.name=r.join(", ")}void 0!==m.is_archived&&(h.f=m.is_archived||!1===m.is_open);void 0!==m.last_read&&(h.a=Math.max(parseFloat(m.last_read),h.a));void 0!==m.last_msg?h.b=parseFloat(m.last_msg):m.latest&&(h.b=parseFloat(m.latest.ts));h.version=Math.max(h.version,v)}e.emojis&&(f.h.data=e.emojis,f.h.version=n);if(void 0!==e.commands){f.g.data=
+{};for(k in e.commands)f.g.data[k]=new fa(f,e.commands[k]);f.g.version=n}e.team&&(f.C||(f.C=new aa(e.team.id)),l=f.C,h=e.team,void 0!==h.name&&(l.name=h.name),h.icon&&(l.a.W=h.icon.image_34,l.a.Y=h.icon.image_44,l.a.$=h.icon.image_68,l.a.aa=h.icon.image_88,l.a.P=h.icon.image_102,l.a.R=h.icon.image_132,l.a.T=h.icon.image_230,l.a.ba=h.icon.image_default),l.version=Math.max(l.version,n));f.J=Math.max(f.J,n);e.self&&(f.a=C(f,e.self.id),f.a.c||(f.a.c=new ca),da(f.a.c,e.self.prefs,n));if(void 0!==e.typing)for(k in f.b=
+e.typing,f.b)for(var x in f.b[k])f.b[k][x]=n}if(b.live){for(var u in b.live)(f=c.b[u])?G(f,b.live[u],d):c.b[u]=new F(u,250,b.live[u],d);for(var t in b.live)(d=D(c.a,t))?(c.b[t].a.length&&(u=c.b[t],d.b=Math.max(d.b,u.a[u.a.length-1].i)),d.f||(Ka(d,b.live[t]),I&&b.live[I.id]&&ya())):E.c=0}b["static"]&&(oa(),b["static"].typing&&qa())}Z()}else setTimeout(Z,1E3*Y)}function Z(){La(Ma)}
+function Ca(a){I&&document.getElementById(I.id).classList.remove("selected");document.getElementById(a.id).classList.add("selected");document.body.classList.remove("no-room-selected");I=a;a=I.name||(I.g?I.g.name:void 0);if(!a){a=[];for(var b in I.c)a.push(I.c[b].name);a=a.join(", ")}document.getElementById("currentRoomTitle").textContent=a;ya();U();document.getElementById("fileUploadContainer").classList.add("hidden");Fa();S&&(S=null,R());W&&(W=null,R());ra();I.a&&!E.b[I.id]&&(b=new XMLHttpRequest,
+b.open("GET","api/hist?room="+I.id,!0),b.send(null))}function Da(a,b,c){var d=I;new FileReader;var f=new FormData,e=new XMLHttpRequest;f.append("file",b);f.append("filename",a);e.onreadystatechange=function(){4===e.readyState&&(204===e.status?c(null):c(e.statusText))};e.open("POST","api/file?room="+d.id);e.send(f)}
+function Ea(a){if(W){var b=new XMLHttpRequest;b.open("PUT","api/msg?room="+I.id+"&ts="+W.id+"&text="+encodeURIComponent(a),!0);b.send(null);return!0}if("/"===a[0]){var c=a.indexOf(" "),b=-1===c?"":a.substr(c);return(a=E.a.g.data[a.substr(0,-1===c?void 0:c)])?(c=new XMLHttpRequest,c.open("POST","api/cmd?room="+I.id+"&cmd="+encodeURIComponent(a.name.substr(1))+"&args="+encodeURIComponent(b.trim()),!0),c.send(null),!0):!1}var b=I,c=S,d=new XMLHttpRequest;a="api/msg?room="+b.id+"&text="+encodeURIComponent(a);
+if(c){var f=C(E.a,c.m),e="Message";"C"===b.id[0]?e="Channel message":"D"===b.id[0]?e="Direct message":"G"===b.id[0]&&(e="Group message");a+="&attachments="+encodeURIComponent(JSON.stringify([{fallback:c.text,author_name:"<@"+f.id+"|"+f.name+">",author_icon:f.a.s,text:c.text,footer:e,ts:c.i}]))}d.open("POST",a,!0);d.send(null);return!0}function Ba(a){var b=new XMLHttpRequest;b.open("DELETE","api/msg?room="+I.id+"&ts="+a.id,!0);b.send(null)}
+function sa(a,b,c){var d=new XMLHttpRequest;d.open("POST","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(c),!0);d.send(null)};

+ 1 - 0
srv/public/style.css

@@ -39,6 +39,7 @@ body { display: flex; margin: 0; padding: 0; font-family: Lato, sans-serif; }
 .slack-context-room.slack-channel + .slack-context-room:not(.slack-channel), .slack-context-room.slack-group + .slack-context-room:not(.slack-group) { margin-top: 1em; }
 .slackmsg-item { display: flex; position: relative; padding: 10px; }
 .slackmsg-item:hover { background: #F9F9F9; }
+.slackmsg-item.slackmsg-first-unread { border-top: 1px solid red; }
 .slackmsg-content { display: inline-block; }
 .slackmsg-author { display: inline-block; }
 .slackmsg-author-img { max-height: 36px; max-width: 36px; margin-right: 10px; border-radius: 3px; }

+ 4 - 1
srv/src/slack.js

@@ -230,11 +230,14 @@ Slack.prototype.onMessage = function(msg, t) {
     this.data.onMessage(msg, t);
     if ((msg["channel"] || msg["channel_id"] || (msg["item"] && msg["item"]["channel"])) && msg["type"] && UPDATE_LIVE.indexOf(msg["type"]) !== -1) {
         var channelId = msg["channel"] || msg["channel_id"] || msg["item"]["channel"]
+            ,channel = this.data.getChannel(msg["channel"])
             ,histo = this.history[channelId];
         if (histo) {
             this.data.liveV = Math.max(this.data.liveV, histo.push(msg, t));
             histo.resort();
-        } else if (this.data.getChannel(msg["channel"])) {
+            if (channel)
+                channel.lastMsg = Math.max(this.data.liveV, channel.lastMsg);
+        } else if (channel) {
             this.fetchHistory(msg["channel"]);
         }
     }

+ 7 - 7
srv/src/slackData.js

@@ -105,7 +105,7 @@ SlackChan.prototype.update = function(chanData, slackData, t) {
     if (chanData["creator"] !== undefined) this.creator = slackData.getMember(chanData["creator"]);
     if (chanData["is_archived"] !== undefined) this.archived = chanData["is_archived"];
     if (chanData["is_member"] !== undefined) this.isMember = chanData["is_member"];
-    if (chanData["last_read"] !== undefined) this.lastRead = parseFloat(chanData["last_read"]);
+    if (chanData["last_read"] !== undefined) this.lastRead = Math.max(parseFloat(chanData["last_read"]), this.lastRead);
     if (chanData["last_msg"] !== undefined) this.lastMsg = parseFloat(chanData["last_msg"]);
     if (chanData["latest"]) this.lastMsg = parseFloat(chanData["latest"]["ts"]);
     if (chanData["members"]) {
@@ -190,7 +190,7 @@ SlackGroup.prototype.update = function(slack, groupData, t) {
     if (groupData["created"] !== undefined) this.created = groupData["created"];
     if (groupData["creator"] !== undefined) this.creator = slack.getMember(groupData["creator"]);
     if (groupData["is_archived"] !== undefined) this.archived = groupData["is_archived"] || groupData["is_open"] === false;
-    if (groupData["last_read"] !== undefined) this.lastRead = parseFloat(groupData["last_read"]);
+    if (groupData["last_read"] !== undefined) this.lastRead = Math.max(parseFloat(groupData["last_read"]), this.lastRead);
     if (groupData["last_msg"] !== undefined) this.lastMsg = parseFloat(groupData["last_msg"]);
     else if (groupData["latest"]) this.lastMsg = parseFloat(groupData["latest"]["ts"]);
     if (groupData["topic"]) {
@@ -234,7 +234,7 @@ function SlackIms(id, user) {
 **/
 SlackIms.prototype.update = function(user, imsData, t) {
     if (imsData["created"] !== undefined) this.created = imsData["created"];
-    if (imsData["last_read"] !== undefined) this.lastRead = parseFloat(imsData["last_read"]);
+    if (imsData["last_read"] !== undefined) this.lastRead = Math.max(parseFloat(imsData["last_read"]), this.lastRead);
     if (imsData["last_msg"] !== undefined) this.lastMsg = parseFloat(imsData["last_msg"]);
     if (imsData["latest"]) this.lastMsg = parseFloat(imsData["latest"]["ts"]);
     this.archived = user.deleted;
@@ -719,18 +719,18 @@ SlackData.prototype.getChannel = function(chanId) {
 };
 
 /**
- * @param {function((SlackGroup|SlackIms|SlackChan)):boolean} cb should return false to stop iterating
+ * @param {function((SlackGroup|SlackIms|SlackChan)):(boolean|undefined)} cb should return false to stop iterating
  * @return {boolean} true if iterated through all entities
 **/
 SlackData.prototype.forEachChans = function(cb) {
     for (var i in this.channels) {
-        if (!cb(this.channels[i])) return false;
+        if (cb(this.channels[i]) === false) return false;
     }
     for (var i in this.ims) {
-        if (!cb(this.ims[i])) return false;
+        if (!cb(this.ims[i]) === false) return false;
     }
     for (var i in this.groups) {
-        if (!cb(this.groups[i])) return false;
+        if (!cb(this.groups[i]) === false) return false;
     }
     return true;
 }