소스 검색

[add][Refs #1][Refs #3] emoji picker
[add] Search in emoji list
[add][Refs #3] Add a reaction button
[quickfix][Refs #1] emojis match [^ \t] instead of \w because of :+1: bug
[quickfix][Refs #1] If the message only contains an emoji, make it bigger
[add][Refs #1] Add a "add an emoji" button

B Thibault 8 년 전
부모
커밋
5eb11cc8a3
8개의 변경된 파일208개의 추가작업 그리고 67개의 파일을 삭제
  1. 78 15
      cli/emojiBar.js
  2. 12 0
      cli/resources.js
  3. 33 12
      cli/ui.js
  4. 32 0
      srv/public/emojione.logo.svg
  5. 0 0
      srv/public/emojione.sprites.js
  6. 3 2
      srv/public/index.html
  7. 41 38
      srv/public/slack.min.js
  8. 9 0
      srv/public/style.css

+ 78 - 15
cli/emojiBar.js

@@ -1,39 +1,56 @@
 
 var EMOJI_BAR = (function() {
     var dom = document.createElement("div")
+        ,overlay = document.createElement("div")
+        ,emojisDom = document.createElement("div")
         ,unicodeEmojis = document.createElement("ul")
         ,customEmojis = document.createElement("ul")
+        ,searchBar = document.createElement("input")
         ,emojiCache = { unicode: {}, custom: {}}
+        /** @type {function((string|null))|undefined} */
+        ,emojiSelectedHandler
 
     /** @type {function():boolean} */
     ,isSupported = function() {
         return ("searchEmojis" in window);
     }
 
-    /** @type {function(Element):{dom:Element,visible:boolean}} */
-    ,wrapEmojiLi = function(emojiDom) {
+    ,makeHeader = function(imgSrc) {
+        var img = document.createElement("img")
+            ,dom = document.createElement("div");
+        img.src = imgSrc;
+        dom.appendChild(img);
+        dom.className = R.klass.emojibar.header;
+        return dom;
+    }
+
+    /** @type {function(string, Element):{dom:Element,visible:boolean}} */
+    ,wrapEmojiLi = function(emojiName, emojiDom) {
         var dom = document.createElement("li");
         dom.appendChild(emojiDom);
+        dom.className = R.klass.emojibar.item;
+        dom.id = "emojibar-" +emojiName;
         return {
             visible: false
             ,dom: dom
         };
     }
 
-    /** @type {function(*):{dom:Element,visible:boolean}} */
-    ,makeUnicodeEmojiLi = function(emoji) {
+    /** @type {function(string, *):{dom:Element,visible:boolean}} */
+    ,makeUnicodeEmojiLi = function(emojiName, emoji) {
         var domEmoji = window['makeEmoji'](emoji)
             ,domParent = document.createElement("span");
         domParent.appendChild(domEmoji);
         domParent.className = R.klass.emoji.medium;
-        return wrapEmojiLi(domParent);
+        return wrapEmojiLi(emojiName, domParent);
     }
 
-    /** @type function(string):number */
+    /** @type function(string=):number */
     ,search = function(queryString) {
         var emojiCount = 0
             ,toRemove = [];
 
+        queryString = queryString === undefined ? searchBar.value : queryString;
         if (isSupported()) {
             /** @type {Object.<string, *>} */
             var emojis = window['searchEmojis'](queryString);
@@ -47,7 +64,7 @@ var EMOJI_BAR = (function() {
                 var e = emojiCache.unicode[i];
 
                 if (!e)
-                    e = emojiCache.unicode[i] = makeUnicodeEmojiLi(emojis[i]);
+                    e = emojiCache.unicode[i] = makeUnicodeEmojiLi(i, emojis[i]);
                 if (!e.visible) {
                     e.visible = true;
                     unicodeEmojis.appendChild(e.dom);
@@ -59,29 +76,77 @@ var EMOJI_BAR = (function() {
         return emojiCount;
     }
 
-    /** @type function(Element):boolean */
-    ,spawn = function(domParent) {
+    /** @type function(Element, function((string|null))=):boolean */
+    ,spawn = function(domParent, handler) {
         if (isSupported()) {
+            emojiSelectedHandler = handler;
+            domParent.appendChild(overlay);
             domParent.appendChild(dom);
-            search("");
+            searchBar.value = "";
+            search();
+            searchBar.focus();
             return true;
         }
         return false;
     }
 
     /** @type {function():boolean} */
-    ,close = function() {
+    ,doClose = function() {
         if (dom.parentElement) {
+            dom.parentElement.removeChild(overlay);
             dom.parentElement.removeChild(dom);
             return true;
         }
         return false;
     }
+    /** @type {function():boolean} */
+    ,close = function() {
+        var closed = doClose();
+        if (!closed)
+            return false;
+        if (emojiSelectedHandler)
+            emojiSelectedHandler(null);
+        return true;
+    }
+    ,onEmojiSelected = function(emojiName) {
+        if (doClose() && emojiSelectedHandler)
+            emojiSelectedHandler(emojiName);
+    }
 
     ;
 
-    dom.appendChild(unicodeEmojis);
-    dom.appendChild(customEmojis);
+    overlay.addEventListener("click", function(e) {
+        var bounds = dom.getBoundingClientRect();
+        if (e.screenY < bounds.top || e.screenY > bounds.bottom ||
+            e.screenX < bounds.left || e.screenX > bounds.right)
+            close();
+    });
+
+    overlay.className = R.klass.emojibar.overlay;
+    dom.className = R.klass.emojibar.container;
+    emojisDom.className = R.klass.emojibar.emojis;
+    unicodeEmojis.className = customEmojis.className = R.klass.emojibar.list;
+    searchBar.className = R.klass.emojibar.search;
+    emojisDom.appendChild(makeHeader(window['emojiProviderHeader']));
+    emojisDom.appendChild(unicodeEmojis);
+    emojisDom.appendChild(makeHeader("emojicustom.png"));
+    emojisDom.appendChild(customEmojis);
+    dom.appendChild(emojisDom);
+    dom.appendChild(searchBar);
+
+    searchBar.addEventListener("keyup", function() {
+        search();
+    });
+
+    dom.addEventListener("click", function(e) {
+        var target = e.target;
+        while (target !== dom && target && target.nodeName !== "LI")
+            target = target.parentElement;
+        if (target && target.nodeName === "LI" && target.id && target.id.substr(0, "emojibar-".length) === "emojibar-") {
+            var emojiId = target.id.substr("emojibar-".length);
+            onEmojiSelected(emojiId);
+        }
+    });
 
     return {
         isSupported: isSupported
@@ -91,5 +156,3 @@ var EMOJI_BAR = (function() {
     };
 })();
 
-//EMOJI_BAR.spawn(document.body);
-

+ 12 - 0
cli/resources.js

@@ -18,6 +18,7 @@ var R = {
                 ,error: "fileUploadError"
                 ,cancel: "fileUploadCancel"
             }
+            ,emoji: "emojiButton"
 
         }
         ,favicon: "linkFavicon"
@@ -36,6 +37,16 @@ var R = {
             ,medium: "emoji-medium"
             ,custom: "emoji-custom"
         }
+        ,emojibar: {
+            container: "emojibar"
+            ,emojis: "emojibar-emojis"
+            ,close: "emojibar-close"
+            ,header: "emojibar-header"
+            ,list: "emojibar-list"
+            ,item: "emojibar-list-item"
+            ,search: "emojibar-search"
+            ,overlay: "emojibar-overlay"
+        }
         ,chatList: {
             entry: "slack-context-room"
             ,typeChannel: "slack-channel"
@@ -54,6 +65,7 @@ var R = {
             ,hover: {
                 container: "slackmsg-hover"
                 ,reply: "slackmsg-hover-reply"
+                ,reaction: "slackmsg-hover-reaction"
             }
 
             ,replyTo: {

+ 33 - 12
cli/ui.js

@@ -208,6 +208,7 @@ function doCreateMessageDom(channelId, msg, skipAttachment) {
         ,authorName = document.createElement("span")
         ,hover = document.createElement("ul")
         ,hoverReply = document.createElement("li")
+        ,hoverReaction = document.createElement("li")
         ,attachments = document.createElement("ul")
         ,reactions = document.createElement("ul")
         ,sender = msg.raw["user"] ?
@@ -223,6 +224,7 @@ function doCreateMessageDom(channelId, msg, skipAttachment) {
     authorName.className = R.klass.msg.authorname;
     hover.className = R.klass.msg.hover.container;
     hoverReply.className = R.klass.msg.hover.reply;
+    hoverReaction.className = R.klass.msg.hover.reaction;
     ts.innerHTML = formatDate(msg.ts);
     text.innerHTML = formatSlackText(msg.raw["text"] || "");
     authorName.textContent = sender ? sender.name : (msg.raw["username"] || "?");
@@ -232,6 +234,7 @@ function doCreateMessageDom(channelId, msg, skipAttachment) {
     author.appendChild(authorImg);
     author.appendChild(authorName);
     hover.appendChild(hoverReply);
+    hover.appendChild(hoverReaction);
     dom.appendChild(author);
     dom.appendChild(text);
     dom.appendChild(ts);
@@ -306,11 +309,11 @@ function makeEmojiDom(emojiCode) {
  * @return {string}
 **/
 function formatEmojis(inputString) {
-    return inputString.replace(/:(\w+):/g, function(returnFailed, emoji) {
+    return inputString.replace(/:([^ \t]+):/g, function(returnFailed, emoji) {
         var emojiDom = makeEmojiDom(emoji);
         if (emojiDom) {
             var domParent = document.createElement("span");
-            domParent.className = R.klass.emoji.small;
+            domParent.className = returnFailed === inputString ? R.klass.emoji.medium : R.klass.emoji.small;
             domParent.appendChild(emojiDom);
             return domParent.outerHTML;
         }
@@ -711,20 +714,22 @@ function chatClickDelegate(e) {
     while (target !== e.currentTarget && target) {
         if (target.classList.contains(R.klass.msg.hover.container)) {
             return;
-        } else if (target.classList.contains(R.klass.msg.hover.reply)) {
+        } else if (target.parentElement && target.parentElement.classList.contains(R.klass.msg.hover.container)) {
             var messageId = getMessageId(e, target);
             if (messageId) {
                 messageId = parseFloat(messageId.split("_")[1]);
-                var history = SLACK.history[SELECTED_ROOM.id].messages;
-
-                for (var i =0, histLen =history.length; i < histLen && history[i].ts <= messageId; i++) {
-                    if (history[i].ts === messageId) {
-                        if (REPLYING_TO !== history[i]) {
-                            REPLYING_TO = history[i];
-                            onReplyingToUpdated();
-                        }
-                        return;
+                var msg = SLACK.history[SELECTED_ROOM.id].getMessage(messageId);
+
+                if (msg && target.classList.contains(R.klass.msg.hover.reply)) {
+                    if (REPLYING_TO !== msg) {
+                        REPLYING_TO = msg;
+                        onReplyingToUpdated();
                     }
+                } else if (msg && target.classList.contains(R.klass.msg.hover.reaction)) {
+                    EMOJI_BAR.spawn(document.body, function(emoji) {
+                        if (emoji)
+                            addReaction(SELECTED_ROOM.id, msg.id, emoji);
+                    });
                 }
             }
             return;
@@ -817,6 +822,22 @@ document.addEventListener('DOMContentLoaded', function() {
     });
     window.hasFocus = true;
 
+    //Emoji closure
+    (function() {
+        var emojiButton = document.getElementById(R.id.message.emoji);
+        if ('makeEmoji' in window) {
+            emojiButton.innerHTML = "<span class='" +R.klass.emoji.small +"'>" +window['makeEmoji']('smile').outerHTML +"</span>";
+            document.getElementById(R.id.message.file.bt).innerHTML = "<span class='" +R.klass.emoji.small +"'>" +window['makeEmoji']('paperclip').outerHTML +"</span>";
+            emojiButton.addEventListener("click", function() {
+                EMOJI_BAR.spawn(document.body, function(e) {
+                    if (e) document.getElementById(R.id.message.input).value += ":"+e+":";
+                });
+            });
+        } else {
+            emojiButton.classList.add(R.klass.hidden);
+        }
+    })();
+
     startPolling();
 });
 

+ 32 - 0
srv/public/emojione.logo.svg

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 529.1 74.8" style="enable-background:new 0 0 529.1 74.8;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#F5A300;}
+	.st1{fill:#24BAC5;}
+	.st2{fill:#8CC63E;}
+	.st3{fill:#FFFFFF;}
+</style>
+<title>logo-typeface</title>
+<path class="st0" d="M526.8,54.8h-12.7c-8.8,0-5.4,8.4-22.3,8.4c-20.6,0-19-22.9-19-22.9h56.3c0-22.1-9.2-39.8-37.2-39.8
+	c-22.5,0-37,12-37,36.7c0,21.8,11.3,37.5,37,37.5C519.1,74.7,525.9,57.2,526.8,54.8 M472.9,28.9c0,0-0.4-16.7,19-16.7
+	s19,16.7,19,16.7L472.9,28.9L472.9,28.9z"/>
+<path class="st1" d="M334.3,0.4c-22.9,0-37.1,11.8-37.1,37.1s14.2,37.1,37.1,37.1s37.1-11.7,37.1-37.1S357.2,0.4,334.3,0.4z
+	 M334.3,63.3c-15.8,0-20-13.9-20-25.7s4.2-25.7,20-25.7s20,13.9,20,25.7S350.2,63.3,334.3,63.3z"/>
+<path class="st2" d="M440.5,10.2c-6-6.2-15.3-9.7-27.3-9.7l0,0c-12,0-21.4,3.5-27.3,9.7c-4.9,5.1-7,10.6-7,21.6v42.9h17.7V29.5
+	c0-11,8.7-16,16.7-16s16.7,4.9,16.7,16v45.2h17.6V31.7C447.5,20.8,445.5,15.3,440.5,10.2z"/>
+<path class="st3" d="M48.7,68.9v4.7H0V0.5h47.8v4.7H5.2V34h37.2v4.5H5.2v30.4L48.7,68.9L48.7,68.9z"/>
+<path class="st3" d="M129.5,73.7V10.4l-28.8,49.3h-3.3L68.5,10.4v63.2h-5.2V0.5h5.2L99,52.8l30.5-52.3h5.2v73.1L129.5,73.7
+	L129.5,73.7z"/>
+<path class="st3" d="M183.6,74.2c-4.8,0.1-9.6-1-13.9-3.2c-4.1-2.1-7.8-4.9-10.8-8.3c-3-3.5-5.4-7.5-7-11.8c-1.6-4.4-2.5-9-2.5-13.7
+	c0-4.8,0.9-9.5,2.6-14c1.7-4.3,4.1-8.4,7.2-11.8c3-3.4,6.7-6.2,10.9-8.2c4.2-2,8.9-3.1,13.6-3c4.8-0.1,9.6,1.1,13.9,3.2
+	c4.1,2.1,7.8,5,10.8,8.5c3,3.5,5.4,7.6,7,11.9c5,13.5,2.2,28.6-7.4,39.3c-3.1,3.4-6.8,6.1-10.9,8C193,73.1,188.3,74.2,183.6,74.2z
+	 M154.7,37.1c0,4.1,0.7,8.2,2.1,12.1c1.4,3.8,3.4,7.3,6,10.3c2.6,3,5.7,5.4,9.2,7.2c3.6,1.8,7.6,2.7,11.7,2.7
+	c4.1,0.1,8.2-0.9,11.9-2.8c3.5-1.8,6.6-4.3,9.1-7.4c2.6-3.1,4.5-6.6,5.9-10.4c2.8-7.7,2.7-16.2-0.1-23.8c-1.4-3.8-3.4-7.3-6-10.3
+	c-2.6-3-5.7-5.4-9.2-7.2c-7.4-3.6-16.1-3.6-23.5,0.1c-3.5,1.8-6.6,4.3-9.1,7.4C157.5,21.2,154.7,29,154.7,37.1z"/>
+<path class="st3" d="M222.5,66c1.9,1.3,4,2.2,6.2,2.8c2.6,0.7,5.3,1.1,8,1.1c4,0,7.2-0.7,9.5-2.2c2.4-1.5,4.3-3.7,5.4-6.3
+	c1.4-3.2,2.2-6.7,2.4-10.1c0.4-4,0.6-8.6,0.6-13.6V0.6h5.2v37.1c0,5.1-0.2,10.1-0.7,15.2c-0.3,4.1-1.4,8-3.1,11.7
+	c-1.5,3.1-4,5.8-7,7.5c-3,1.8-7.1,2.7-12.3,2.7c-5.6,0.2-11.2-1.4-15.9-4.5L222.5,66z"/>
+<path class="st3" d="M278.4,73.7v-73h5.2v73H278.4z"/>
+</svg>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
srv/public/emojione.sprites.js


+ 3 - 2
srv/public/index.html

@@ -21,8 +21,9 @@
                     </div>
                     <input type="text" id="msgInput" class="msgform-input" autocomplete="off" />
                     <div class="msgform-action">
-                        <input type="submit" class="button" value=">" />
+                        <a id="emojiButton" class="button"/></a>
                         <a id="attachFile" href="#!" class="button"><img src="paperclip.svg" alt="Send file" class="attach-file-icon" /></a>
+                        <input type="submit" class="button" value=">" />
                     </div>
                 </form>
             </div>
@@ -30,8 +31,8 @@
         <div class="hidden file-upload-container" id="fileUploadContainer"><form id="fileUploadForm" enctype="multipart/form-data">
             <input type="file" id="fileUploadInput" />
             <div id="fileUploadError" class="file-upload-error hidden"></div>
-            <input type="submit" class="button"/>
             <a id="fileUploadCancel" class="button"/></a>
+            <input type="submit" class="button"/>
         </form></div>
         <div class="error" id="neterror"></div>
         <script src="emojione.sprites.js"></script>

+ 41 - 38
srv/public/slack.min.js

@@ -1,38 +1,41 @@
-function k(a){this.id=a.id;this.name=a.name}function aa(a,b){this.id=a.id;this.name=a.name;this.b=parseFloat(a.last_read);this.a={};if(a.members)for(var d=0,c=a.members.length;d<c;d++){var f=m(b,a.members[d]);this.a[f.id]=f;f.f[this.id]=this}}function ba(a,b){var d=[];this.id=b.id;this.a={};for(var c=0,f=b.members.length;c<f;c++){var e=m(a,b.members[c]);this.a[b.members[c]]=e;e.f[this.id]=this;d.push(e.name)}this.name=d.join(", ");this.b=parseFloat(b.last_read)}
-function ca(a,b){this.id=b.id;this.c=a;this.b=parseFloat(b.last_read)}function da(a){this.id=a.id;this.name=a.name;this.status=a.status;this.b={I:a.profile.image_24,J:a.profile.image_32,l:a.profile.image_48,D:a.profile.image_72,H:a.profile.image_192,L:a.profile.image_512};this.f={};this.a=null}function ea(a){this.id=a.id;this.name=a.name;this.b={K:a.icons.image_36,l:a.icons.image_48,D:a.icons.image_72};this.f={};this.a=null}
-function t(){this.s=null;this.f={};this.c={};this.i={};this.a={};this.b=null;this.h={};this.o={}}function m(a,b){return a.a[b]||a.h[b]||null}function u(a,b){return a.f[b]||a.i[b]||a.c[b]||null}"undefined"!==typeof module&&(module.C.F=t);function fa(a,b){this.i=a.user;this.id=a.ts;this.c=b||parseFloat(a.ts);this.type=a.type;this.h=a.subtype;this.b=a;this.a={};var d=this;a.reactions&&a.reactions.forEach(function(a){d.a[a.name]=[];a.users.forEach(function(b){d.a[a.name].push(b)})})}function v(a,b,d){this.id="string"===typeof a?a:a.id;this.a=[];this.b=b;d&&x(this,d)}function ga(a,b,d){a.a[b]&&(1===a.a[b].length?delete a.a[b]:a.a[b]=a.a[b].filter(function(a){return a!==d}))}
-function x(a,b){var d=0;b.forEach(function(a){d=Math.max(this.push(a),d)}.bind(a));ha(a)}v.prototype.push=function(a){for(var b=parseFloat(a.ts),d=0,c=this.a.length;d<c;d++)if(this.a[d].c===b)return b;for(this.a.push(new fa(a,b));this.a.length>this.b;)this.a.shift();if("reaction_added"===a.type){if(d=y(this,parseFloat(a.item.ts)))c=a.reaction,a=a.user,d.a[c]||(d.a[c]=[]),d.a[c].push(a)}else"reaction_removed"===a.type&&(d=y(this,parseFloat(a.item.ts)))&&ga(d,a.reaction,a.user);return b};
-function y(a,b){for(var d=0,c=a.a.length;d<c&&b>=a.a[d].c;d++)if(a.a[d].c===b)return a.a[d];return null}function ha(a){a.a.sort(function(a,d){return a.c-d.c})}"undefined"!==typeof module&&(module.C.G=v);var A={},C;function ia(){var a;if(!a){for(var b=0,d=navigator.languages.length;b<d;b++)if(A.hasOwnProperty(navigator.languages[b])){a=navigator.languages[b];break}a||(a="en")}C=A[a];console.log("Loading language pack: "+a);if(C.g)for(b in C.g)document.getElementById(b).textContent=C.g[b]};A.fr={B:"Utilisateur inconnu",A:"Channel inconnu",w:"Nouveau message",u:"Reseau",g:{fileUploadCancel:"Annuler",neterror:"Impossible de se connecter au chat !"}};A.en={B:"Unknown member",A:"Unknown channel",w:"New message",u:"Network",g:{fileUploadCancel:"Cancel",neterror:"Cannot connect to chat !"}};var D=null,E=0;
-function ja(){var a=document.createDocumentFragment(),b=G.a.b?Object.keys(G.a.b.f):[];b.sort(function(a,b){return a[0]!==b[0]?a[0]-b[0]:(G.a.f[a]||G.a.c[a]).name.localeCompare((G.a.f[b]||G.a.c[b]).name)});b.forEach(function(b){b=G.a.f[b]||G.a.c[b];var c=document.createElement("li"),d=document.createElement("a");c.id=b.id;d.href="#"+b.id;"D"===b.id[0]?c.className="slack-context-room slack-ims":"G"===b.id[0]?c.className="slack-context-room slack-group":"C"===b.id[0]&&(c.className="slack-context-room slack-channel");d.textContent=
-b.name;c.appendChild(d);c&&a.appendChild(c)});b=G.a.a?Object.keys(G.a.a):[];b.sort(function(a,b){return G.a.a[a].name.localeCompare(G.a.a[b].name)});b.forEach(function(b){b=G.a.a[b].a;var c=document.createElement("li"),d=document.createElement("a");c.id=b.id;d.href="#"+b.id;c.className="slack-context-room";d.textContent=b.c.name;c.appendChild(d);c&&a.appendChild(c)});document.getElementById("chanList").textContent="";document.getElementById("chanList").appendChild(a);H();I()}
-function J(a){a?document.body.classList.remove("no-network"):document.body.classList.add("no-network");I()}function L(){if(D){document.body.classList.add("replyingTo");var a=document.getElementById("replyToContainer"),b=document.createElement("a");b.addEventListener("click",function(){D=null;L()});b.className="replyto-close";b.textContent="x";a.textContent="";a.appendChild(b);a.appendChild(M("reply_"+N.id,D,!0))}else document.body.classList.remove("replyingTo")}
-function ka(a,b,d,c){var f=O(d);if(f){for(var e=document.createElement("li"),h=document.createElement("a"),g=document.createElement("span"),p=document.createElement("span"),q=[],r=0,l=c.length;r<l;r++){var n=m(G.a,c[r]);n&&q.push(n.name)}q.sort();p.textContent=q.join(", ");g.appendChild(f);g.className="emoji-small";h.href="javascript:toggleReaction('"+a+"', '"+b+"', '"+d+"')";h.appendChild(g);h.appendChild(p);e.className="slackmsg-reaction-item";e.appendChild(h);return e}return null}
-window.toggleReaction=function(a,b,d){var c=G.b[a];if(c){a:{for(var f=0,e=c.a.length;f<e;f++)if(c.a[f].id==b){c=c.a[f];break a}c=null}c&&(f=G.a.b.id,c.a[d]&&-1!==c.a[d].indexOf(f)?(c=new XMLHttpRequest,c.open("DELETE","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(d),!0)):(c=new XMLHttpRequest,c.open("POST","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(d),!0)),c.send(null))}};
-function P(a,b,d){var c=document.createElement("div"),f=document.createElement("div"),e=document.createElement("div"),h=document.createElement("div"),g=document.createElement("img"),p=document.createElement("span"),q=document.createElement("ul"),r=document.createElement("li"),l=document.createElement("ul"),n=document.createElement("ul"),w=b.b.user?G.a.a[b.b.user]:G.a.h[b.b.bot_id];c.id=a+"_"+b.c;c.className="slackmsg-item";f.className="slackmsg-ts";e.className="slackmsg-msg";h.className="slackmsg-author";
-g.className="slackmsg-author-img";p.className="slackmsg-author-name";q.className="slackmsg-hover";r.className="slackmsg-hover-reply";f.innerHTML=Q(b.c);e.innerHTML=R(b.b.text||"");p.textContent=w?w.name:b.b.username||"?";w||b.b.username||(e.textContent=b.b.subtype||JSON.stringify(b.b));g.src=w?w.b.l:"";h.appendChild(g);h.appendChild(p);q.appendChild(r);c.appendChild(h);c.appendChild(e);c.appendChild(f);c.appendChild(l);c.appendChild(n);l.className="slackmsg-attachments";n.className="slackmsg-reactions";
-if(!0!==d){if(b.a)for(var z in b.a)(d=ka(a,b.id,z,b.a[z]))&&n.appendChild(d);b.b.attachments&&b.b.attachments.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"),p=document.createElement("div"),q=document.createElement("img"),w=document.createElement("img"),n=document.createElement("div"),
-r=document.createElement("img"),z=document.createElement("span"),F=document.createElement("span");b.className="slackmsg-attachment";var B="#e3e4e6";a.color&&("#"===a.color[0]?B=a.color[0]:"good"===a.color?B="#2fa44f":"warning"===a.color?B="#de9e31":"danger"===a.color&&(B="#d50200"));c.style.borderColor=B;d.className="slackmsg-attachment-pretext";a.pretext?d.innerHTML=R(a.pretext):d.classList.add("hidden");e.target="_blank";a.title?(e.innerHTML=R(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=R(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");p.innerHTML=R(a.text||"");p.a="slackmsg-attachment-text";q.className="slackmsg-attachment-thumb";a.thumb_url?q.src=a.thumb_url:q.classList.add("hidden");
-w.className="slackmsg-attachment-img";a.image_url?w.src=a.image_url:w.classList.add("hidden");n.className="slackmsg-attachment-footer";z.className="slackmsg-attachment-footer-text";r.className="slackmsg-attachment-footer-icon";a.footer?(z.innerHTML=R(a.footer),a.footer_icon?r.src=a.footer_icon:r.classList.add("hidden")):(r.classList.add("hidden"),z.classList.add("hidden"));F.className="slackmsg-ts";a.ts?F.innerHTML=Q(a.ts):F.classList.add("hidden");f.appendChild(g);f.appendChild(h);K.appendChild(p);
-K.appendChild(q);n.appendChild(r);n.appendChild(z);n.appendChild(F);c.appendChild(e);c.appendChild(f);c.appendChild(K);c.appendChild(w);c.appendChild(n);b.appendChild(d);b.appendChild(c);b&&l.appendChild(b)})}c.appendChild(q);return c}function Q(a){"string"!==typeof a&&(a=parseFloat(a));return(new Date(1E3*a)).toLocaleTimeString()}
-function O(a){a:{for(var b=a,d={};!d[b];){if(a=G.a.o[b])if("alias:"==a.substr(0,6))d[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 la(a){return a.replace(/:(\w+):/g,function(a,d){var b=O(d);if(b){var f=document.createElement("span");f.className="emoji-small";f.appendChild(b);return f.outerHTML}return a})}
-function R(a){a=a.split(/\r?\n/g);for(var b=0,d=a.length;b<d;b++){for(var c=a[b],f="",e={},h=!1,g=0,c=c.replace(RegExp("<([@#]?)([^>]*)>","g"),function(a,b,c){c=c.split("|");if("@"===b)c[1]?"@"!==c[1][0]&&(c[1]="@"+c[1]):(a=m(G.a,c[0]),c[1]=a?"@"+a.name:C.B),c[0]="#"+c[0],c[2]="slackmsg-link slackmsg-link-user";else if("#"===b)c[1]?"#"!==c[1][0]&&(c[1]="#"+c[1]):(a=u(G.a,c[0]),c[1]=a?"#"+a.name:C.A),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>"}),c=la(c),p=c.length,q=function(a,b,c){for(;a[b];){if(" "!=a[b]&&a[b]!=c&&a[b+1]==c)return!0;b++}return!1},r=function(a){return Object.keys(e).length?'<span class="'+Object.keys(a).join(" ")+'">':""};g<p&&(" "===c[g]||"\t"===c[g]);)g++;"&gt;"===c.substr(g,4)&&(h=!0,g+=4);for(;g<p;g++){var l=c[g];if("<"===l){do f+=c[g++];while(">"!==c[g-1]);g--}else if(!e["slackmsg-style-bold"]&&
-"*"===l&&c[g+1]&&q(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-bold"]=!0,f+=r(e);else if(!e["slackmsg-style-strike"]&&"~"===l&&c[g+1]&&q(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-strike"]=!0,f+=r(e);else if(!e["slackmsg-style-code"]&&"`"===l&&c[g+1]&&q(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-code"]=!0,f+=r(e);else if(!e["slackmsg-style-italic"]&&"_"===l&&c[g+1]&&q(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-italic"]=
-!0,f+=r(e);else{var n=!1,f=f+l;do{if(e["slackmsg-style-bold"]&&"*"!==l&&"*"===c[g+1])delete e["slackmsg-style-bold"],n=!0;else if(e["slackmsg-style-strike"]&&"~"!==l&&"~"===c[g+1])delete e["slackmsg-style-strike"],n=!0;else if(e["slackmsg-style-code"]&&"`"!==l&&"`"===c[g+1])delete e["slackmsg-style-code"],n=!0;else if(e["slackmsg-style-italic"]&&"_"!==l&&"_"===c[g+1])delete e["slackmsg-style-italic"],n=!0;else break;l=c[++g]}while(g<p);n&&(f+="</span>"+r(e))}}e&&(f+="</span>");a[b]=h?'<span class="slackmsg-style-quote">'+
-f+"</span>":f}return a.join("<br/>")}function M(a,b,d){"me_message"===b.h?(a=P(a,b,d),a.classList.add("slackmsg-me_message")):a=P(a,b,d);return a}function I(){var a=0,b=0,d="";if(S)d="!"+C.u+" - ",document.getElementById("linkFavicon").href="favicon_err.png";else{for(var c in T)T.hasOwnProperty(c)&&(a+=T[c].m,b+=T[c].j);b?d="(!"+b+") - ":a&&(d="("+a+") - ");document.getElementById("linkFavicon").href=b||a?"favicon.png?h="+b+"&m="+a:"favicon_ok.png"}d+=G.a.s.name;document.title=d}
-function ma(){if("Notification"in window)if("granted"===Notification.permission){var a=Date.now();if(E+3E4<a){var b=new Notification(C.w);E=a;setTimeout(function(){b.close()},5E3)}}else"denied"!==Notification.permission&&Notification.requestPermission()}
-function U(){var a=document.createDocumentFragment(),b=N.id;document.getElementById("chatWindow").textContent="";G.b[b]&&G.b[b].a.forEach(function(c){"message"===c.type&&(c=M(b,c),a.appendChild(c))});var d=document.getElementById("chatWindow");d.appendChild(a);d.scrollTop=d.scrollHeight-d.clientHeight}
-function na(a){for(var b=a.target;b!==a.currentTarget&&b&&!b.classList.contains("slackmsg-hover");){if(b.classList.contains("slackmsg-hover-reply")){a:{for(b=b||a.target;b!==a.currentTarget&&b;){if(b.classList.contains("slackmsg-item")){a=b.id;break a}b=b.parentElement}a=void 0}if(a){a=parseFloat(a.split("_")[1]);for(var b=G.b[N.id].a,d=0,c=b.length;d<c&&b[d].c<=a;d++)if(b[d].c===a){D!==b[d]&&(D=b[d],L());break}}break}b=b.parentElement}}function V(){document.getElementById("msgInput").focus()}
-function H(){var a=document.location.hash.substr(1),b=u(G.a,a),a=m(G.a,a);b&&b!==N?W(b):a&&a.a&&W(a.a)}
-document.addEventListener("DOMContentLoaded",function(){ia();document.getElementById("chatWindow").addEventListener("click",na);window.addEventListener("hashchange",function(){document.location.hash&&"#"===document.location.hash[0]&&H()});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),oa(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();N&&document.getElementById("fileUploadContainer").classList.remove("hidden");return!1});document.getElementById("msgForm").addEventListener("submit",function(a){a.preventDefault();a=document.getElementById("msgInput");if(N&&a.value){var b=N,d=D,c=new XMLHttpRequest,f="api/msg?room="+b.id+"&text="+encodeURIComponent(a.value);if(d){var e=m(G.a,d.i),h="Message";"C"===b.id[0]?h="Channel message":"D"===b.id[0]?
-h="Direct message":"G"===b.id[0]&&(h="Group message");f+="&attachments="+encodeURIComponent(JSON.stringify([{fallback:d.b.text||"",author_name:"<@"+e.id+"|"+e.name+">",author_icon:e.b.l,text:d.b.text||"",footer:h,ts:d.c}]))}c.open("POST",f,!0);c.send(null);a.value="";D&&(D=null,L())}V();return!1});window.addEventListener("blur",function(){window.hasFocus=!1});window.addEventListener("focus",function(){window.hasFocus=!0;E=0;N&&X();V()});window.hasFocus=!0;Y()});(function(){function a(a){var d=0;if(b()){a=window.searchEmojis(a);for(var f in e)e[f].visible&&!a[f]&&(e[f].visible=!1,c.removeChild(e[f].g));for(f in a){var h=e[f];if(!h){var h=e,r=f,l=window.makeEmoji(a[f]),n=document.createElement("span");n.appendChild(l);n.className="emoji-medium";l=document.createElement("li");l.appendChild(n);h=h[r]={visible:!1,g:l}}h.visible||(h.visible=!0,c.appendChild(h.g));d++}}return d}function b(){return"searchEmojis"in window}var d=document.createElement("div"),c=document.createElement("ul"),
-f=document.createElement("ul"),e={};d.appendChild(c);d.appendChild(f);return{isSupported:b,M:function(c){return b()?(c.appendChild(d),a(""),!0):!1},search:a,close:function(){return d.parentElement?(d.parentElement.removeChild(d),!0):!1}}})();var G,T={};function pa(a,b){if(a&&(a!==N||!window.hasFocus)){var d=new RegExp("<@"+G.a.b.id),c=!1,f=!1;T[a.id]||(T[a.id]={j:0,m:0});b.forEach(function(b){"message"===b.type&&b.text&&("D"===a.id[0]||b.text.match(d)?(f|=!T[a.id].j,T[a.id].j++,c=!0):T[a.id].m++)});I();document.getElementById(a.id).classList.add("unread");c&&document.getElementById(a.id).classList.add("unreadHi");f&&!window.hasFocus&&ma()}}
-function X(){var a=N;T[a.id]&&(T[a.id]={j:0,m:0},I());a=document.getElementById(a.id);a.classList.remove("unread");a.classList.remove("unreadHi")}G=new function(){this.c=0;this.a=new t;this.b={}};var S=0,N=null;function Z(a){var b=new XMLHttpRequest;b.timeout=6E4;b.onreadystatechange=function(){if(4===b.readyState)if(b.status){var d=null,c=2===Math.floor(b.status/100);if(c){S&&(S=0,J(!0));d=b.response;try{d=JSON.parse(d)}catch(f){d=null}}else S?(S+=Math.floor((S||5)/2),S=Math.min(60,S)):(S=5,J(!1));a(c,d)}else S&&(S=0,J(!0)),Z(a)};b.open("GET","api?v="+G.c,!0);b.send(null)}
-function qa(a,b){if(a){if(b){var d=G;b.v&&(d.c=b.v);if(b["static"]){for(var c=d.a,f=b["static"],e=0,h=f.bots.length;e<h;e++)c.h[f.bots[e].id]=new ea(f.bots[e]);e=0;for(h=f.users.length;e<h;e++)c.a[f.users[e].id]=new da(f.users[e]);e=0;for(h=f.ims.length;e<h;e++){var g=m(c,f.ims[e].user);g&&(g.a=new ca(g,f.ims[e]),c.i[g.a.id]=g.a)}e=0;for(h=f.channels.length;e<h;e++)c.f[f.channels[e].id]=new aa(f.channels[e],c);e=0;for(h=f.groups.length;e<h;e++)c.c[f.groups[e].id]=new ba(c,f.groups[e]);c.o=f.emojis;
-c.s=new k(f.team);c.b=m(c,f.self.id);ja()}if(b.live){for(var p in b.live)(c=d.b[p])?x(c,b.live[p]):d.b[p]=new v(p,250,b.live[p]);for(var q in b.live)pa(u(d.a,q),b.live[q]),N&&b.live[N.id]&&U()}}Y()}else setTimeout(Y,1E3*S)}function Y(){Z(qa)}
-function W(a){N&&document.getElementById(N.id).classList.remove("selected");document.getElementById(a.id).classList.add("selected");document.body.classList.remove("no-room-selected");N=a;a=N.name||(N.c?N.c.name:void 0);if(!a){a=[];for(var b in N.a)a.push(N.a[b].name);a=a.join(", ")}document.getElementById("currentRoomTitle").textContent=a;U();V();document.getElementById("fileUploadContainer").classList.add("hidden");X();D&&(D=null,L());N.b&&!G.b[N.id]&&(b=new XMLHttpRequest,b.open("GET","api/hist?room="+
-N.id,!0),b.send(null))}function oa(a,b,d){var c=N;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?d(null):d(e.statusText))};e.open("POST","api/file?room="+c.id);e.send(f)};
+function aa(a){this.id=a.id;this.name=a.name}function ba(a,b){this.id=a.id;this.name=a.name;this.b=parseFloat(a.last_read);this.a={};if(a.members)for(var d=0,c=a.members.length;d<c;d++){var f=k(b,a.members[d]);this.a[f.id]=f;f.f[this.id]=this}}function ca(a,b){var d=[];this.id=b.id;this.a={};for(var c=0,f=b.members.length;c<f;c++){var e=k(a,b.members[c]);this.a[b.members[c]]=e;e.f[this.id]=this;d.push(e.name)}this.name=d.join(", ");this.b=parseFloat(b.last_read)}
+function da(a,b){this.id=b.id;this.c=a;this.b=parseFloat(b.last_read)}function ea(a){this.id=a.id;this.name=a.name;this.status=a.status;this.b={J:a.profile.image_24,K:a.profile.image_32,l:a.profile.image_48,F:a.profile.image_72,I:a.profile.image_192,M:a.profile.image_512};this.f={};this.a=null}function fa(a){this.id=a.id;this.name=a.name;this.b={L:a.icons.image_36,l:a.icons.image_48,F:a.icons.image_72};this.f={};this.a=null}
+function n(){this.s=null;this.f={};this.c={};this.i={};this.a={};this.b=null;this.h={};this.o={}}function k(a,b){return a.a[b]||a.h[b]||null}function u(a,b){return a.f[b]||a.i[b]||a.c[b]||null}"undefined"!==typeof module&&(module.D.G=n);function ga(a,b){this.i=a.user;this.id=a.ts;this.c=b||parseFloat(a.ts);this.type=a.type;this.h=a.subtype;this.b=a;this.a={};var d=this;a.reactions&&a.reactions.forEach(function(a){d.a[a.name]=[];a.users.forEach(function(b){d.a[a.name].push(b)})})}function v(a,b,d){this.id="string"===typeof a?a:a.id;this.a=[];this.b=b;d&&w(this,d)}function ha(a,b,d){a.a[b]&&(1===a.a[b].length?delete a.a[b]:a.a[b]=a.a[b].filter(function(a){return a!==d}))}
+function w(a,b){var d=0;b.forEach(function(a){d=Math.max(this.push(a),d)}.bind(a));ia(a)}v.prototype.push=function(a){for(var b=parseFloat(a.ts),d=0,c=this.a.length;d<c;d++)if(this.a[d].c===b)return b;for(this.a.push(new ga(a,b));this.a.length>this.b;)this.a.shift();if("reaction_added"===a.type){if(d=y(this,parseFloat(a.item.ts)))c=a.reaction,a=a.user,d.a[c]||(d.a[c]=[]),d.a[c].push(a)}else"reaction_removed"===a.type&&(d=y(this,parseFloat(a.item.ts)))&&ha(d,a.reaction,a.user);return b};
+function y(a,b){for(var d=0,c=a.a.length;d<c&&b>=a.a[d].c;d++)if(a.a[d].c===b)return a.a[d];return null}function ia(a){a.a.sort(function(a,d){return a.c-d.c})}"undefined"!==typeof module&&(module.D.H=v);var z={},B;function ja(){var a;if(!a){for(var b=0,d=navigator.languages.length;b<d;b++)if(z.hasOwnProperty(navigator.languages[b])){a=navigator.languages[b];break}a||(a="en")}B=z[a];console.log("Loading language pack: "+a);if(B.g)for(b in B.g)document.getElementById(b).textContent=B.g[b]};z.fr={C:"Utilisateur inconnu",B:"Channel inconnu",w:"Nouveau message",u:"Reseau",g:{fileUploadCancel:"Annuler",neterror:"Impossible de se connecter au chat !"}};z.en={C:"Unknown member",B:"Unknown channel",w:"New message",u:"Network",g:{fileUploadCancel:"Cancel",neterror:"Cannot connect to chat !"}};var D=null,E=0;
+function ka(){var a=document.createDocumentFragment(),b=F.a.b?Object.keys(F.a.b.f):[];b.sort(function(a,b){return a[0]!==b[0]?a[0]-b[0]:(F.a.f[a]||F.a.c[a]).name.localeCompare((F.a.f[b]||F.a.c[b]).name)});b.forEach(function(b){b=F.a.f[b]||F.a.c[b];var c=document.createElement("li"),d=document.createElement("a");c.id=b.id;d.href="#"+b.id;"D"===b.id[0]?c.className="slack-context-room slack-ims":"G"===b.id[0]?c.className="slack-context-room slack-group":"C"===b.id[0]&&(c.className="slack-context-room slack-channel");d.textContent=
+b.name;c.appendChild(d);c&&a.appendChild(c)});b=F.a.a?Object.keys(F.a.a):[];b.sort(function(a,b){return F.a.a[a].name.localeCompare(F.a.a[b].name)});b.forEach(function(b){b=F.a.a[b].a;var c=document.createElement("li"),d=document.createElement("a");c.id=b.id;d.href="#"+b.id;c.className="slack-context-room";d.textContent=b.c.name;c.appendChild(d);c&&a.appendChild(c)});document.getElementById("chanList").textContent="";document.getElementById("chanList").appendChild(a);H();I()}
+function J(a){a?document.body.classList.remove("no-network"):document.body.classList.add("no-network");I()}function K(){if(D){document.body.classList.add("replyingTo");var a=document.getElementById("replyToContainer"),b=document.createElement("a");b.addEventListener("click",function(){D=null;K()});b.className="replyto-close";b.textContent="x";a.textContent="";a.appendChild(b);a.appendChild(L("reply_"+M.id,D,!0))}else document.body.classList.remove("replyingTo")}
+function la(a,b,d,c){var f=N(d);if(f){for(var e=document.createElement("li"),h=document.createElement("a"),g=document.createElement("span"),m=document.createElement("span"),p=[],q=0,l=c.length;q<l;q++){var r=k(F.a,c[q]);r&&p.push(r.name)}p.sort();m.textContent=p.join(", ");g.appendChild(f);g.className="emoji-small";h.href="javascript:toggleReaction('"+a+"', '"+b+"', '"+d+"')";h.appendChild(g);h.appendChild(m);e.className="slackmsg-reaction-item";e.appendChild(h);return e}return null}
+window.toggleReaction=function(a,b,d){var c=F.b[a];if(c){a:{for(var f=0,e=c.a.length;f<e;f++)if(c.a[f].id==b){c=c.a[f];break a}c=null}c&&(f=F.a.b.id,c.a[d]&&-1!==c.a[d].indexOf(f)?(c=new XMLHttpRequest,c.open("DELETE","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(d),!0),c.send(null)):O(a,b,d))}};
+function P(a,b,d){var c=document.createElement("div"),f=document.createElement("div"),e=document.createElement("div"),h=document.createElement("div"),g=document.createElement("img"),m=document.createElement("span"),p=document.createElement("ul"),q=document.createElement("li"),l=document.createElement("li"),r=document.createElement("ul"),t=document.createElement("ul"),x=b.b.user?F.a.a[b.b.user]:F.a.h[b.b.bot_id];c.id=a+"_"+b.c;c.className="slackmsg-item";f.className="slackmsg-ts";e.className="slackmsg-msg";
+h.className="slackmsg-author";g.className="slackmsg-author-img";m.className="slackmsg-author-name";p.className="slackmsg-hover";q.className="slackmsg-hover-reply";l.className="slackmsg-hover-reaction";f.innerHTML=Q(b.c);e.innerHTML=R(b.b.text||"");m.textContent=x?x.name:b.b.username||"?";x||b.b.username||(e.textContent=b.b.subtype||JSON.stringify(b.b));g.src=x?x.b.l:"";h.appendChild(g);h.appendChild(m);p.appendChild(q);p.appendChild(l);c.appendChild(h);c.appendChild(e);c.appendChild(f);c.appendChild(r);
+c.appendChild(t);r.className="slackmsg-attachments";t.className="slackmsg-reactions";if(!0!==d){if(b.a)for(var A in b.a)(d=la(a,b.id,A,b.a[A]))&&t.appendChild(d);b.b.attachments&&b.b.attachments.forEach(function(a){var b=document.createElement("li"),c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("a"),f=document.createElement("div"),t=document.createElement("img"),A=document.createElement("a"),g=document.createElement("div"),h=document.createElement("div"),
+x=document.createElement("img"),l=document.createElement("img"),m=document.createElement("div"),p=document.createElement("img"),q=document.createElement("span"),G=document.createElement("span");b.className="slackmsg-attachment";var C="#e3e4e6";a.color&&("#"===a.color[0]?C=a.color[0]:"good"===a.color?C="#2fa44f":"warning"===a.color?C="#de9e31":"danger"===a.color&&(C="#d50200"));c.style.borderColor=C;d.className="slackmsg-attachment-pretext";a.pretext?d.innerHTML=R(a.pretext):d.classList.add("hidden");
+e.target="_blank";a.title?(e.innerHTML=R(a.title),a.title_link&&(e.href=a.title_link),e.className="slackmsg-attachment-title"):e.className="hidden slackmsg-attachment-title";A.target="_blank";f.className="slackmsg-author";a.author_name?(A.innerHTML=R(a.author_name),A.href=a.author_link||"",A.className="slackmsg-author-name",t.className="slackmsg-author-img",a.author_icon?t.src=a.author_icon:t.classList.add("hidden")):f.classList.add("hidden");h.innerHTML=R(a.text||"");h.a="slackmsg-attachment-text";
+x.className="slackmsg-attachment-thumb";a.thumb_url?x.src=a.thumb_url:x.classList.add("hidden");l.className="slackmsg-attachment-img";a.image_url?l.src=a.image_url:l.classList.add("hidden");m.className="slackmsg-attachment-footer";q.className="slackmsg-attachment-footer-text";p.className="slackmsg-attachment-footer-icon";a.footer?(q.innerHTML=R(a.footer),a.footer_icon?p.src=a.footer_icon:p.classList.add("hidden")):(p.classList.add("hidden"),q.classList.add("hidden"));G.className="slackmsg-ts";a.ts?
+G.innerHTML=Q(a.ts):G.classList.add("hidden");f.appendChild(t);f.appendChild(A);g.appendChild(h);g.appendChild(x);m.appendChild(p);m.appendChild(q);m.appendChild(G);c.appendChild(e);c.appendChild(f);c.appendChild(g);c.appendChild(l);c.appendChild(m);b.appendChild(d);b.appendChild(c);b&&r.appendChild(b)})}c.appendChild(p);return c}function Q(a){"string"!==typeof a&&(a=parseFloat(a));return(new Date(1E3*a)).toLocaleTimeString()}
+function N(a){a:{for(var b=a,d={};!d[b];){if(a=F.a.o[b])if("alias:"==a.substr(0,6))d[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 ma(a){return a.replace(/:([^ \t]+):/g,function(b,d){var c=N(d);if(c){var f=document.createElement("span");f.className=b===a?"emoji-medium":"emoji-small";f.appendChild(c);return f.outerHTML}return b})}
+function R(a){a=a.split(/\r?\n/g);for(var b=0,d=a.length;b<d;b++){for(var c=a[b],f="",e={},h=!1,g=0,c=c.replace(RegExp("<([@#]?)([^>]*)>","g"),function(a,b,c){c=c.split("|");if("@"===b)c[1]?"@"!==c[1][0]&&(c[1]="@"+c[1]):(a=k(F.a,c[0]),c[1]=a?"@"+a.name:B.C),c[0]="#"+c[0],c[2]="slackmsg-link slackmsg-link-user";else if("#"===b)c[1]?"#"!==c[1][0]&&(c[1]="#"+c[1]):(a=u(F.a,c[0]),c[1]=a?"#"+a.name:B.B),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>"}),c=ma(c),m=c.length,p=function(a,b,c){for(;a[b];){if(" "!=a[b]&&a[b]!=c&&a[b+1]==c)return!0;b++}return!1},q=function(a){return Object.keys(e).length?'<span class="'+Object.keys(a).join(" ")+'">':""};g<m&&(" "===c[g]||"\t"===c[g]);)g++;"&gt;"===c.substr(g,4)&&(h=!0,g+=4);for(;g<m;g++){var l=c[g];if("<"===l){do f+=c[g++];while(">"!==c[g-1]);g--}else if(!e["slackmsg-style-bold"]&&
+"*"===l&&c[g+1]&&p(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-bold"]=!0,f+=q(e);else if(!e["slackmsg-style-strike"]&&"~"===l&&c[g+1]&&p(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-strike"]=!0,f+=q(e);else if(!e["slackmsg-style-code"]&&"`"===l&&c[g+1]&&p(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-code"]=!0,f+=q(e);else if(!e["slackmsg-style-italic"]&&"_"===l&&c[g+1]&&p(c,g,l))Object.keys(e).length&&(f+="</span>"),e["slackmsg-style-italic"]=
+!0,f+=q(e);else{var r=!1,f=f+l;do{if(e["slackmsg-style-bold"]&&"*"!==l&&"*"===c[g+1])delete e["slackmsg-style-bold"],r=!0;else if(e["slackmsg-style-strike"]&&"~"!==l&&"~"===c[g+1])delete e["slackmsg-style-strike"],r=!0;else if(e["slackmsg-style-code"]&&"`"!==l&&"`"===c[g+1])delete e["slackmsg-style-code"],r=!0;else if(e["slackmsg-style-italic"]&&"_"!==l&&"_"===c[g+1])delete e["slackmsg-style-italic"],r=!0;else break;l=c[++g]}while(g<m);r&&(f+="</span>"+q(e))}}e&&(f+="</span>");a[b]=h?'<span class="slackmsg-style-quote">'+
+f+"</span>":f}return a.join("<br/>")}function L(a,b,d){"me_message"===b.h?(a=P(a,b,d),a.classList.add("slackmsg-me_message")):a=P(a,b,d);return a}function I(){var a=0,b=0,d="";if(S)d="!"+B.u+" - ",document.getElementById("linkFavicon").href="favicon_err.png";else{for(var c in T)T.hasOwnProperty(c)&&(a+=T[c].m,b+=T[c].j);b?d="(!"+b+") - ":a&&(d="("+a+") - ");document.getElementById("linkFavicon").href=b||a?"favicon.png?h="+b+"&m="+a:"favicon_ok.png"}d+=F.a.s.name;document.title=d}
+function na(){if("Notification"in window)if("granted"===Notification.permission){var a=Date.now();if(E+3E4<a){var b=new Notification(B.w);E=a;setTimeout(function(){b.close()},5E3)}}else"denied"!==Notification.permission&&Notification.requestPermission()}
+function U(){var a=document.createDocumentFragment(),b=M.id;document.getElementById("chatWindow").textContent="";F.b[b]&&F.b[b].a.forEach(function(c){"message"===c.type&&(c=L(b,c),a.appendChild(c))});var d=document.getElementById("chatWindow");d.appendChild(a);d.scrollTop=d.scrollHeight-d.clientHeight}
+function oa(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 d=a.target;d!==a.currentTarget&&d&&!d.classList.contains("slackmsg-hover");){if(d.parentElement&&d.parentElement.classList.contains("slackmsg-hover")){if(a=b(a,d)){a=parseFloat(a.split("_")[1]);var c=y(F.b[M.id],a);c&&d.classList.contains("slackmsg-hover-reply")?D!==c&&(D=c,K()):c&&d.classList.contains("slackmsg-hover-reaction")&&V.A(document.body,
+function(a){a&&O(M.id,c.id,a)})}break}d=d.parentElement}}function W(){document.getElementById("msgInput").focus()}function H(){var a=document.location.hash.substr(1),b=u(F.a,a),a=k(F.a,a);b&&b!==M?X(b):a&&a.a&&X(a.a)}
+document.addEventListener("DOMContentLoaded",function(){ja();document.getElementById("chatWindow").addEventListener("click",oa);window.addEventListener("hashchange",function(){document.location.hash&&"#"===document.location.hash[0]&&H()});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),pa(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();M&&document.getElementById("fileUploadContainer").classList.remove("hidden");return!1});document.getElementById("msgForm").addEventListener("submit",function(a){a.preventDefault();a=document.getElementById("msgInput");if(M&&a.value){var b=M,d=D,c=new XMLHttpRequest,f="api/msg?room="+b.id+"&text="+encodeURIComponent(a.value);if(d){var e=k(F.a,d.i),h="Message";"C"===b.id[0]?h="Channel message":"D"===b.id[0]?
+h="Direct message":"G"===b.id[0]&&(h="Group message");f+="&attachments="+encodeURIComponent(JSON.stringify([{fallback:d.b.text||"",author_name:"<@"+e.id+"|"+e.name+">",author_icon:e.b.l,text:d.b.text||"",footer:h,ts:d.c}]))}c.open("POST",f,!0);c.send(null);a.value="";D&&(D=null,K())}W();return!1});window.addEventListener("blur",function(){window.hasFocus=!1});window.addEventListener("focus",function(){window.hasFocus=!0;E=0;M&&Y();W()});window.hasFocus=!0;(function(){var a=document.getElementById("emojiButton");
+"makeEmoji"in window?(a.innerHTML="<span class='emoji-small'>"+window.makeEmoji("smile").outerHTML+"</span>",document.getElementById("attachFile").innerHTML="<span class='emoji-small'>"+window.makeEmoji("paperclip").outerHTML+"</span>",a.addEventListener("click",function(){V.A(document.body,function(a){a&&(document.getElementById("msgInput").value+=":"+a+":")})})):a.classList.add("hidden")})();Z()});var V=function(){function a(){if(!b())return!1;r&&r(null);return!0}function b(){return e.parentElement?(e.parentElement.removeChild(h),e.parentElement.removeChild(e),!0):!1}function d(a){var b=0;a=void 0===a?q.value:a;if(f()){a=window.searchEmojis(a);for(var c in l)l[c].visible&&!a[c]&&(l[c].visible=!1,m.removeChild(l[c].g));for(c in a){var d=l[c];if(!d){var d=l,e=c,g=c,h=window.makeEmoji(a[c]),t=document.createElement("span");t.appendChild(h);t.className="emoji-medium";h=document.createElement("li");
+h.appendChild(t);h.className="emojibar-list-item";h.id="emojibar-"+g;d=d[e]={visible:!1,g:h}}d.visible||(d.visible=!0,m.appendChild(d.g));b++}}return b}function c(a){var b=document.createElement("img"),c=document.createElement("div");b.src=a;c.appendChild(b);c.className="emojibar-header";return c}function f(){return"searchEmojis"in window}var e=document.createElement("div"),h=document.createElement("div"),g=document.createElement("div"),m=document.createElement("ul"),p=document.createElement("ul"),
+q=document.createElement("input"),l={},r;h.addEventListener("click",function(b){var c=e.getBoundingClientRect();(b.screenY<c.top||b.screenY>c.bottom||b.screenX<c.left||b.screenX>c.right)&&a()});h.className="emojibar-overlay";e.className="emojibar";g.className="emojibar-emojis";m.className=p.className="emojibar-list";q.className="emojibar-search";g.appendChild(c(window.emojiProviderHeader));g.appendChild(m);g.appendChild(c("emojicustom.png"));g.appendChild(p);e.appendChild(g);e.appendChild(q);q.addEventListener("keyup",
+function(){d()});e.addEventListener("click",function(a){for(a=a.target;a!==e&&a&&"LI"!==a.nodeName;)a=a.parentElement;a&&"LI"===a.nodeName&&a.id&&"emojibar-"===a.id.substr(0,9)&&(a=a.id.substr(9),b()&&r&&r(a))});return{isSupported:f,A:function(a,b){return f()?(r=b,a.appendChild(h),a.appendChild(e),q.value="",d(),q.focus(),!0):!1},search:d,close:a}}();var F,T={};function qa(a,b){if(a&&(a!==M||!window.hasFocus)){var d=new RegExp("<@"+F.a.b.id),c=!1,f=!1;T[a.id]||(T[a.id]={j:0,m:0});b.forEach(function(b){"message"===b.type&&b.text&&("D"===a.id[0]||b.text.match(d)?(f|=!T[a.id].j,T[a.id].j++,c=!0):T[a.id].m++)});I();document.getElementById(a.id).classList.add("unread");c&&document.getElementById(a.id).classList.add("unreadHi");f&&!window.hasFocus&&na()}}
+function Y(){var a=M;T[a.id]&&(T[a.id]={j:0,m:0},I());a=document.getElementById(a.id);a.classList.remove("unread");a.classList.remove("unreadHi")}F=new function(){this.c=0;this.a=new n;this.b={}};var S=0,M=null;function ra(a){var b=new XMLHttpRequest;b.timeout=6E4;b.onreadystatechange=function(){if(4===b.readyState)if(b.status){var d=null,c=2===Math.floor(b.status/100);if(c){S&&(S=0,J(!0));d=b.response;try{d=JSON.parse(d)}catch(f){d=null}}else S?(S+=Math.floor((S||5)/2),S=Math.min(60,S)):(S=5,J(!1));a(c,d)}else S&&(S=0,J(!0)),ra(a)};b.open("GET","api?v="+F.c,!0);b.send(null)}
+function sa(a,b){if(a){if(b){var d=F;b.v&&(d.c=b.v);if(b["static"]){for(var c=d.a,f=b["static"],e=0,h=f.bots.length;e<h;e++)c.h[f.bots[e].id]=new fa(f.bots[e]);e=0;for(h=f.users.length;e<h;e++)c.a[f.users[e].id]=new ea(f.users[e]);e=0;for(h=f.ims.length;e<h;e++){var g=k(c,f.ims[e].user);g&&(g.a=new da(g,f.ims[e]),c.i[g.a.id]=g.a)}e=0;for(h=f.channels.length;e<h;e++)c.f[f.channels[e].id]=new ba(f.channels[e],c);e=0;for(h=f.groups.length;e<h;e++)c.c[f.groups[e].id]=new ca(c,f.groups[e]);c.o=f.emojis;
+c.s=new aa(f.team);c.b=k(c,f.self.id);ka()}if(b.live){for(var m in b.live)(c=d.b[m])?w(c,b.live[m]):d.b[m]=new v(m,250,b.live[m]);for(var p in b.live)qa(u(d.a,p),b.live[p]),M&&b.live[M.id]&&U()}}Z()}else setTimeout(Z,1E3*S)}function Z(){ra(sa)}
+function X(a){M&&document.getElementById(M.id).classList.remove("selected");document.getElementById(a.id).classList.add("selected");document.body.classList.remove("no-room-selected");M=a;a=M.name||(M.c?M.c.name:void 0);if(!a){a=[];for(var b in M.a)a.push(M.a[b].name);a=a.join(", ")}document.getElementById("currentRoomTitle").textContent=a;U();W();document.getElementById("fileUploadContainer").classList.add("hidden");Y();D&&(D=null,K());M.b&&!F.b[M.id]&&(b=new XMLHttpRequest,b.open("GET","api/hist?room="+
+M.id,!0),b.send(null))}function pa(a,b,d){var c=M;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?d(null):d(e.statusText))};e.open("POST","api/file?room="+c.id);e.send(f)}function O(a,b,d){var c=new XMLHttpRequest;c.open("POST","api/reaction?room="+a+"&msg="+b+"&reaction="+encodeURIComponent(d),!0);c.send(null)};

+ 9 - 0
srv/public/style.css

@@ -94,3 +94,12 @@ body {
 .emoji-medium .emoji { transform: scale(0.5); position: absolute; left: -19px; top: -16px; }
 .emoji-custom { text-indent: -9999em; image-rendering: optimizeQuality; font-size: inherit; height: 64px; width: 64px; top: -3px; position: relative; display: inline-block; margin: 0 .15em; line-height: normal; vertical-align: middle; background-repeat: no-repeat; background-size: contain; }
 
+.emojibar { position: fixed; display: flex; flex-direction: column; height: 250px; width: 300px; padding: 5px; overflow: hidden; background: #ddd; z-index: 1000; text-align: right; }
+.emojibar-emojis { display: block; flex: 1; width: 100%; overflow: auto; text-align: left; }
+.emojibar-header { height: 30px; display: block; text-align: center; }
+.emojibar-header > img { max-width: 100%; max-height: 20px; }
+.emojibar-list { list-style: none; padding: 0; margin: 0; }
+.emojibar-list-item { display: inline-block; margin: 5px; cursor: pointer; }
+.emojibar-search { width: 300px; margin: 5px auto; }
+.emojibar-overlay { position: fixed; top: 0; bottom: 0; left: 0; right: 0;  background: transparent; }
+

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.