var Chat = { left : null, right: null, date: null, separator: null, currentDate: null, edit: false, // Scroll lastHeight: null, lastScroll: null, // Intersection discussion observer discussionObserver: null, // Chat state composing: false, since: null, sended: false, // Autocomplete vars. autocompleteList: null, lastAutocomplete: null, searchAutocomplete: null, // Touch startX: 0, startY: 0, translateX: 0, translateY: 0, slideAuthorized: false, autocomplete: function(event, jid) { RoomsUtils_ajaxMucUsersAutocomplete(jid); }, onAutocomplete: function(usersList) { Chat.autocompleteList = usersList; usersList = Object.values(usersList); var textarea = Chat.getTextarea(); var words = textarea.value.toLowerCase().trim().split(' '); var last = words[words.length - 1].trim(); if (last == '') { // Space or nothing, so we put the first one in the list textarea.value += usersList[0] + ' '; Chat.lastAutocomplete = usersList[0]; Chat.searchAutocomplete = null; } else if (typeof Chat.lastAutocomplete === 'string' && Chat.lastAutocomplete.toLowerCase() == last && Chat.searchAutocomplete == null) { var index = (usersList.indexOf(Chat.lastAutocomplete) == usersList.length - 1) ? -1 : usersList.indexOf(Chat.lastAutocomplete); if (textarea.value.slice(-1) == ' ') textarea.value = textarea.value.trim() + ' '; // Full complete, so we iterate Chat.lastAutocomplete = usersList[index + 1]; textarea.value = textarea.value.slice(0, -last.length - 1) + Chat.lastAutocomplete + ' '; Chat.searchAutocomplete = null; } else { // Searching for nicknames starting with if (Chat.lastAutocomplete == null || last != Chat.lastAutocomplete.toLowerCase()) { Chat.searchAutocomplete = last; Chat.lastAutocomplete = null; } var start = (typeof Chat.lastAutocomplete === 'string') ? usersList.indexOf(Chat.lastAutocomplete) + 1 : start = 0; for (var i = start; i < usersList.length; i++) { if (Chat.searchAutocomplete == usersList[i].substring(0, Chat.searchAutocomplete.length).toLowerCase()) { textarea.value = textarea.value.trim().slice(0, -last.length) + usersList[i] + ' '; Chat.lastAutocomplete = usersList[i]; break; } } } }, quoteMUC: function(nickname, add) { var textarea = Chat.getTextarea(); if (add) { if (textarea.value.search(nickname) === -1) { textarea.value = nickname + ' ' + textarea.value; } } else { textarea.value = nickname + ' '; } textarea.focus(); }, insertAtCursor: function(textToInsert) { textarea = Chat.getTextarea(); const value = textarea.value; const start = textarea.selectionStart; const end = textarea.selectionEnd; textarea.value = value.slice(0, start) + textToInsert + value.slice(end); textarea.selectionStart = textarea.selectionEnd = start + textToInsert.length; textarea.focus(); Chat.toggleAction(); }, sendMessage: function() { var textarea = Chat.getTextarea(); var text = textarea.value; var muc = Boolean(textarea.dataset.muc); var jid = textarea.dataset.jid; Chat.removeSeparator(); Chat.scrollTotally(); // In case it was in edit mode textarea.classList.remove('edit'); textarea.focus(); if (!Chat.sended) { Chat.sended = true; document.querySelector('.chat_box span.send').classList.add('sending'); let xhr; if (Chat.edit) { Chat.edit = false; xhr = Chat_ajaxHttpDaemonCorrect(jid, text, textarea.dataset.mid); delete textarea.dataset.mid; } else { var reply = document.querySelector('#reply > div'); replyMid = false; if (reply) { replyMid = reply.dataset.mid; reply.remove(); }; xhr = Chat_ajaxHttpDaemonSendMessage(jid, text, muc, false, null, null, replyMid); } xhr.onreadystatechange = function() { if (this.readyState == 4) { if (this.status >= 200 && this.status < 400) { Chat.sendedMessage(); } if (this.status >= 400 || this.status == 0) { Chat.failedMessage(); } } }; } }, sendedMessage: function() { Chat.sended = false; document.querySelector('.chat_box span.send').classList.remove('sending'); var textarea = Chat.getTextarea(); localStorage.removeItem(textarea.dataset.jid + '_message'); Chat.clearReplace(); Chat.toggleAction(); }, failedMessage: function() { Notification.toast(Chat.delivery_error); Chat.sended = false; document.querySelector('.chat_box span.send').classList.remove('sending'); }, clearReplace: function() { Chat.edit = false; var textarea = Chat.getTextarea(); textarea.value = localStorage.getItem(textarea.dataset.jid + '_message'); MovimUtils.textareaAutoheight(textarea); }, editPrevious: function() { var textarea = Chat.getTextarea(); if (textarea.value == '' && Boolean(textarea.dataset.muc) == false) { Chat_ajaxLast(textarea.dataset.jid); } }, editMessage: function(mid) { var textarea = Chat.getTextarea(); if (textarea.value == '' && Boolean(textarea.dataset.muc) == false) { Chat_ajaxEdit(mid); } }, resolveMessage: function(mid) { ChatActions_ajaxHttpResolveMessage(mid); }, refreshMessage: function(mid) { Chat_ajaxRefreshMessage(mid); }, focus: function() { Chat.sended = false; Chat.composing = false; Chat.clearReplace(); Chat.toggleAction(); var textarea = Chat.getTextarea(); textarea.onkeydown = function(event) { if ((event.keyCode == 37 && Chat.tryPreviousEmoji()) || (event.keyCode == 39 && Chat.tryNextEmoji())) { event.preventDefault(); return; } if (this.dataset.muc && event.keyCode == 9) { event.preventDefault(); if (Chat.autocompleteList == null) { Chat.autocomplete(event, this.dataset.jid); } else { Chat.onAutocomplete(Chat.autocompleteList); } return; } if (event.keyCode == 38) { Chat.editPrevious(); } else if (event.keyCode == 40 && (this.value == '' || Chat.edit == true)) { localStorage.removeItem(textarea.dataset.jid + '_message'); Chat.clearReplace(); } }; textarea.onkeypress = function(event) { if (event.keyCode == 13) { // An emoji was selected var emoji = document.querySelector('.chat_box .emojis img.selected'); if (emoji) { Chat.selectEmoji(emoji); event.preventDefault(); return; } if ((MovimUtils.isMobile() && !event.shiftKey) || (!MovimUtils.isMobile() && event.shiftKey)) { return; } Chat.composing = false; Chat.sendMessage(); return false; } else if (Chat.composing === false) { Chat.composing = true; Chat_ajaxSendComposing(this.dataset.jid, Boolean(this.dataset.muc)); Chat.since = new Date().getTime(); } }; textarea.onkeyup = function(event) { localStorage.setItem(this.dataset.jid + '_message', this.value); // A little timeout to not spam the server with composing states setTimeout(function() { if (Chat.since + 3000 < new Date().getTime()) { Chat.composing = false; } }, 3000); Chat.toggleAction(); }; textarea.oninput = function() { MovimUtils.textareaAutoheight(this); Chat.checkEmojis(this.value); Chat.scrollRestore(); } textarea.onchange = function() { Chat.toggleAction(); }; if (document.documentElement.clientWidth > 1024) { textarea.focus(); } Chat.autocompleteList = null; }, checkEmojis: function(value, reaction, noColon) { value = value.toLowerCase(); listSelector = reaction ? '#emojisearchbar + .emojis .results' : '.chat_box .emojis'; var emojisList = document.querySelector(listSelector); emojisList.innerHTML = ''; if (!value) return; if (noColon || value.lastIndexOf(':') > -1 && value.length > value.lastIndexOf(':') + 2) { var first = true; Object.keys(emojis).filter(key => key.indexOf( value.substr(value.lastIndexOf(':') + 1) ) > -1) .slice(0, 40) .forEach(found => { var img = document.createElement('img'); img.setAttribute('src','theme/img/emojis/svg/' + emojis[found].c + '.svg'); img.classList.add('emoji'); if (reaction) img.classList.add('large'); if (first) { img.classList.add('selected'); first = false; } img.title = ':' + found + ':'; img.dataset.emoji = emojis[found].e; if (!reaction) { img.addEventListener('click', e => { Chat.selectEmoji(e.target); }); } emojisList.appendChild(img); }); } }, selectEmoji: function(emoji) { var emojisList = document.querySelector('.chat_box .emojis'); var textarea = Chat.getTextarea(); textarea.value = textarea.value.substr(0, textarea.value.lastIndexOf(':')); emojisList.innerHTML = ''; Chat.insertAtCursor(emoji.dataset.emoji + ' '); }, tryNextEmoji: function() { var currentEmoji = document.querySelector('.chat_box .emojis img.selected'); if (currentEmoji && currentEmoji.nextSibling) { currentEmoji.classList.remove('selected'); currentEmoji.nextSibling.classList.add('selected'); return true; } return false; }, tryPreviousEmoji: function() { var currentEmoji = document.querySelector('.chat_box .emojis img.selected'); if (currentEmoji && currentEmoji.previousSibling) { currentEmoji.classList.remove('selected'); currentEmoji.previousSibling.classList.add('selected'); return true; } return false; }, setTextarea: function(value, mid) { Chat.edit = true; var textarea = Chat.getTextarea(); textarea.value = value; textarea.classList.add('edit'); if (mid) { textarea.dataset.mid = mid; } MovimUtils.textareaAutoheight(textarea); textarea.focus(); }, setGeneralElements(date, separator) { var div = document.createElement('div'); Chat.currentDate = null; div.innerHTML = date; Chat.date = div.firstChild.cloneNode(true); div.innerHTML = separator; Chat.separator = div.firstChild.cloneNode(true); }, setSpecificElements : function(left, right) { var div = document.createElement('div'); Chat.currentDate = null; div.innerHTML = left; Chat.left = div.firstChild.cloneNode(true); div.innerHTML = right; Chat.right = div.firstChild.cloneNode(true); }, setScrollBehaviour : function() { var discussion = Chat.getDiscussion(); if (discussion == null) return; discussion.onscroll = function() { if (this.scrollTop < 1 && discussion.querySelectorAll('ul li div.bubble p').length >= Chat.pagination) { Chat_ajaxGetHistory( Chat.getTextarea().dataset.jid, Chat.currentDate, Chat.getTextarea().dataset.muc, true); } Chat.setScroll(); }; Chat.setScroll(); }, setScroll : function () { var discussion = Chat.getDiscussion(); if (discussion == null) return; Chat.lastHeight = discussion.scrollHeight; Chat.lastScroll = discussion.scrollTop + discussion.clientHeight; Chat.scrollToggleButton(); }, isScrolled : function () { return Chat.lastHeight -5 <= Chat.lastScroll; }, scrollRestore : function () { var discussion = Chat.getDiscussion(); if (!discussion) return; if (Chat.isScrolled()) { Chat.scrollTotally(); } else { discussion.scrollTop = Chat.lastScroll - discussion.clientHeight; } }, scrollTotally : function () { var discussion = Chat.getDiscussion(); if (discussion == null) return; discussion.scrollTop = discussion.scrollHeight; }, setObservers : function () { var options = { root: Chat.getDiscussion(), rootMargin: '0px', threshold: 1.0 }; Chat.discussionObserver = new IntersectionObserver((entries) => { entries.forEach((entrie) => { if (entrie.target.classList.contains('gif') && entrie.isIntersecting == true) { entrie.target.play(); } else { entrie.target.pause(); } }); }, options); }, scrollToSeparator : function () { var discussion = Chat.getDiscussion(); if (discussion == null) return; var separator = discussion.querySelector('.separator'); if (separator) { discussion.scrollTop = separator.offsetTop - 65; Chat.setScroll(); } }, scrollToggleButton : function () { var discussion = Chat.getDiscussion(); if (discussion == null) return; var button = discussion.querySelector('.button.action'); if (Chat.isScrolled()) { button.classList.remove('show'); } else { button.classList.add('show'); } }, removeSeparator: function() { var separator = Chat.getDiscussion().querySelector('li.separator'); if (separator) separator.remove(); }, setReactionButtonBehaviour : function() { let reactions = document.querySelectorAll('#chat_widget span.reaction'); let i = 0; while (i < reactions.length) { reactions[i].onclick = function() { Stickers_ajaxReaction(this.dataset.mid); } i++; } }, setParentScrollBehaviour : function() { let toParents = document.querySelectorAll('#chat_widget div.parent'); let i = 0; while (i < toParents.length) { toParents[i].onclick = function() { var parentMsg = document.getElementById(this.dataset.parentId); if (!parentMsg) { parentMsg = document.getElementById(this.dataset.parentReplaceId) } if (parentMsg) { scrollToLi = parentMsg.parentNode.parentNode; document.querySelector('#chat_widget .contained').scrollTo({ top: scrollToLi.offsetTop - 60, left: 0, behavior: 'smooth' }); } } i++; } }, setVideoObserverBehaviour : function() { document.querySelectorAll('.file video').forEach((video) => { Chat.discussionObserver.observe(video); }); }, setReplyButtonBehaviour : function() { let replies = document.querySelectorAll('#chat_widget span.reply'); let i = 0; while (i < replies.length) { replies[i].onclick = function() { Chat_ajaxHttpDaemonReply(this.dataset.mid); } i++; } }, setActionsButtonBehaviour : function() { let actions = document.querySelectorAll('#chat_widget .contained:not(.muc) span.actions'); let i = 0; while (i < actions.length) { actions[i].onclick = function() { ChatActions_ajaxShowMessageDialog(this.dataset.mid); } i++; } }, checkDiscussion : function(page) { for (var firstKey in page) break; if (page[firstKey] == null) return false; for (var firstMessageKey in page[firstKey]) break; var firstMessage = page[firstKey][firstMessageKey]; if (firstMessage == null) return false; var contactJid = firstMessage.user_id == firstMessage.jidfrom ? firstMessage.jidto : firstMessage.jidfrom; if (document.getElementById(MovimUtils.cleanupId(contactJid) + '-discussion') == null) return false; return true; }, appendMessagesWrapper : function(page, prepend) { var discussion = Chat.getDiscussion(); if (page && Chat.checkDiscussion(page)) { if (discussion == null) return; Chat.setScroll(); for(date in page) { if (prepend === undefined || prepend === false) { Chat.appendDate(date, prepend); } for(speakertime in page[date]) { if (!Chat.currentDate) { Chat.currentDate = page[date][speakertime].published; } Chat.appendMessage(speakertime, page[date][speakertime], prepend); } if (prepend && date) { Chat.appendDate(date, prepend); } } if (prepend) { // And we scroll where we were var scrollDiff = discussion.scrollHeight - Chat.lastHeight; discussion.scrollTop += scrollDiff; Chat.setScroll(); } else { Chat.scrollRestore(); } var chat = document.querySelector('#chat_widget'); var lastMessage = chat.querySelector('ul li:not(.oppose):last-child div.bubble > div:last-child'); var textarea = Chat.getTextarea(); if (textarea && lastMessage) { Chat_ajaxDisplayed( textarea.dataset.jid, lastMessage.id ); } } else if (discussion !== null) { if (discussion.querySelector('ul').innerHTML === '') { discussion.querySelector('ul').classList.remove('spin'); discussion.querySelector('.placeholder').classList.add('show'); } } Chat.setScrollBehaviour(); Chat.setReactionButtonBehaviour(); Chat.setReplyButtonBehaviour(); Chat.setActionsButtonBehaviour(); Chat.setParentScrollBehaviour(); Chat.setVideoObserverBehaviour(); }, appendMessage : function(idjidtime, data, prepend) { if (data.body === null) return; var bubble = null, mergeMsg = false, msgStack, refBubble; var isMuc = (document.querySelector('#chat_widget div.contained').dataset.muc == 1); var jidtime = idjidtime.substring(idjidtime.indexOf('<') + 1); if (prepend) { refBubble = document.querySelector('#chat_widget .contained section > ul > li:first-child'); msgStack = document.querySelector("[data-bubble='" + jidtime + "']"); } else { refBubble = document.querySelector("#chat_widget .contained section > ul > li:last-child"); var stack = document.querySelectorAll("[data-bubble='" + jidtime + "']"); msgStack = stack[stack.length-1]; } if (msgStack != null && msgStack.parentNode == refBubble && data.url === false && (data.file === undefined || data.file === null) && (data.sticker === undefined || data.sticker === null) && !refBubble.querySelector('div.bubble').classList.contains('sticker') && !refBubble.querySelector('div.bubble').classList.contains('file') && ['jingle_start'].indexOf(data.type) < 0 ) { bubble = msgStack.parentNode; mergeMsg = true; } else { if (data.user_id == data.jidfrom || data.mine) { bubble = Chat.right.cloneNode(true); if (data.mine) { id = data.jidfrom; } else { id = data.jidto; } } else { bubble = Chat.left.cloneNode(true); id = data.jidfrom; } id = MovimUtils.cleanupId(id) + '-conversation'; bubble.querySelector('div.bubble').dataset.bubble = jidtime; bubble.querySelector('div.bubble').dataset.publishedprepared = data.publishedPrepared; } if (isMuc) { bubble.dataset.resource = data.resource; } if (refBubble.dataset.resource == bubble.dataset.resource && mergeMsg == false && isMuc) { if (prepend) { refBubble.classList.add('sequel'); } else { bubble.classList.add('sequel'); } } if (['jingle_start'].indexOf(data.type) >= 0) { bubble.querySelector('div.bubble').classList.add('call'); } var msg = bubble.querySelector('div.bubble > div'); var span = msg.querySelector('span:not(.reaction)'); var p = msg.getElementsByTagName('p')[0]; var reaction = msg.querySelector('span.reaction'); var reply = msg.querySelector('span.reply'); var actions = msg.querySelector('span.actions'); var reactions = msg.querySelector('ul.reactions'); // If there is already a msg in this bubble, create another div (next msg or replacement) if (bubble.querySelector('div.bubble p') && bubble.querySelector('div.bubble p').innerHTML != '') { msg = document.createElement('div'); span = document.createElement('span'); span.className = 'info'; p = document.createElement('p'); reaction = reaction.cloneNode(true); if (reply) { reply = reply.cloneNode(true); } if (actions) { actions = actions.cloneNode(true); } reactions = document.createElement('ul'); reactions.className = 'reactions'; } if (data.retracted) { p.classList.add('retracted'); } if (data.encrypted) { p.classList.add('encrypted'); } if (data.body.match(/^\/me\s/)) { p.classList.add('quote'); data.body = data.body.substr(4); } if (data.body.match(/^\/code\s/)) { p.classList.add('code'); data.body = data.body.substr(6).trim(); } if (data.id != null) { msg.setAttribute('id', data.id); } if (data.rtl) { msg.setAttribute('dir', 'rtl'); } if (data.sticker != null) { bubble.querySelector('div.bubble').classList.add('sticker'); p.appendChild(Chat.getStickerHtml(data.sticker)); if (data.file != null) { p.classList.add('previewable'); } } else { p.innerHTML = data.body; } if (data.file != null && data.card === undefined && data.file.type !== 'xmpp') { bubble.querySelector('div.bubble').classList.add('file'); // Ugly fix to clear the paragraph if the file contains a similar link if (p.querySelector('a') && p.querySelector('a').href == data.file.uri) { p.innerHTML = ''; } p.appendChild(Chat.getFileHtml(data.file, data.sticker)); } if (data.oldid) { span.appendChild(Chat.getEditedIcoHtml()); } if (data.user_id == data.jidfrom) { if (data.displayed) { span.appendChild(Chat.getDisplayedIcoHtml(data.displayed)); } else if (data.delivered) { span.appendChild(Chat.getDeliveredIcoHtml(data.delivered)); } } if (data.reactionsHtml !== undefined) { reactions.innerHTML = data.reactionsHtml; } if (isMuc) { var resourceSpan = document.createElement('span'); resourceSpan.classList.add('resource'); resourceSpan.classList.add(data.color); resourceSpan.innerText = data.resource; msg.appendChild(resourceSpan); } if (data.card) { bubble.querySelector('div.bubble').classList.add('file'); msg.appendChild(Chat.getCardHtml(data.card)); } // Parent if (data.parent) { msg.appendChild(Chat.getParentHtml(data.parent)); } msg.appendChild(p); msg.appendChild(reactions); msg.appendChild(span); if (data.thread !== null) { reply.dataset.mid = data.mid; msg.appendChild(reply); } reaction.dataset.mid = data.mid; msg.appendChild(reaction); if (actions) { actions.dataset.mid = data.mid; msg.appendChild(actions); } var elem = document.getElementById(data.oldid); if (!elem) { elem = document.getElementById(data.id); } if (elem) { elem.parentElement.replaceChild(msg, elem); mergeMsg = true; // If the previous message was not a file or card and is replaced by it if (data.file != null || data.card != null) { msg.parentElement.classList.add('file'); } if (data.sticker != null) { msg.parentElement.classList.add('sticker'); } } else { if (prepend) { bubble.querySelector('div.bubble').insertBefore(msg, bubble.querySelector('div.bubble').firstChild); } else { bubble.querySelector('div.bubble').appendChild(msg); } } /* MUC specific */ if (isMuc) { if (data.moderator) { bubble.querySelector('div.bubble').classList.add('moderator'); } icon = bubble.querySelector('span.primary.icon'); if (icon.querySelector('img') == undefined) { if (data.icon_url) { var img = document.createElement('img'); img.setAttribute('src', data.icon_url); icon.appendChild(img); } else { icon.classList.add('color'); icon.classList.add(data.color); icon.innerHTML = data.icon; } icon.dataset.resource = data.resource; } if (data.quoted) { bubble.querySelector('div.bubble').classList.add('quoted'); } } if (prepend) { Chat.currentDate = data.published; // We prepend if (!mergeMsg) { MovimTpl.prepend('#' + id, bubble.outerHTML); } } else { if (!mergeMsg) { MovimTpl.append('#' + id, bubble.outerHTML); } } }, appendDate: function(date, prepend) { var list = document.querySelector('#chat_widget > div ul'); if (document.getElementById(MovimUtils.cleanupId(date)) && !prepend) return; dateNode = Chat.date.cloneNode(true); dateNode.dataset.value = date; dateNode.querySelector('p').innerHTML = date; dateNode.id = MovimUtils.cleanupId(date); var dates = list.querySelectorAll('li.date'); if (prepend) { // If the date was already displayed we remove it if (dates.length > 0 && dates[0].dataset.value == date) { dates[0].parentNode.removeChild(dates[0]); } list.insertBefore(dateNode, list.firstChild); } else { if (dates.length > 0 && dates[dates.length-1].dataset.value == date) { return; } list.appendChild(dateNode); } }, insertSeparator: function(counter) { separatorNode = Chat.separator.cloneNode(true); var list = document.querySelector('#chat_widget > div ul'); if (!list || list.querySelector('li.separator')) return; var messages = document.querySelectorAll('#chat_widget > div ul div.bubble p'); if (messages.length > counter && counter > 0) { var p = messages[messages.length - counter]; list.insertBefore(separatorNode, p.parentNode.parentNode.parentNode); } }, getStickerHtml: function(sticker) { var img = document.createElement('img'); if (sticker.url) { if (sticker.thumb) { img.setAttribute('src', sticker.thumb); } else { img.setAttribute('src', sticker.url); } if (sticker.width) img.setAttribute('width', sticker.width); if (sticker.height) { img.setAttribute('height', sticker.height); } else { img.setAttribute('height', '170'); } } if (sticker.title) { img.title = sticker.title; } if (sticker.picture) { img.classList.add('active'); img.setAttribute('onclick', 'Preview_ajaxShow("' + sticker.url + '")'); } return img; }, getCardHtml: function(card) { var ul = document.createElement('ul'); ul.setAttribute('class', 'card list middle noanim'); ul.innerHTML = card; if (ul.querySelector('li').getAttribute('onclick')) { ul.classList.add('active'); } return ul; }, getFileHtml: function(file, sticker) { var div = document.createElement('div'); div.setAttribute('class', 'file'); if (file.name) { if (file.type == 'video/webm' || file.type == 'video/mp4') { var video = document.createElement('video'); video.setAttribute('src', file.uri); video.setAttribute('loop', 'loop'); if (file.thumbnail) { video.setAttribute('poster', file.thumbnail.uri); video.setAttribute('width', file.thumbnail.width); video.setAttribute('height', file.thumbnail.height); } // Tenor implementation if (file.host && file.host == 'media.tenor.com') { video.classList.add('gif'); } else { video.setAttribute('controls', 'controls'); } div.appendChild(video); } // Tenor implementation if (file.host && file.host == 'media.tenor.com') { return div; } var a = document.createElement('a'); if (sticker == null) { var link = document.createElement('p'); link.textContent = file.name; link.setAttribute('title', file.name); a.appendChild(link); } a.setAttribute('href', file.uri); a.setAttribute('target', '_blank'); a.setAttribute('rel', 'noopener'); div.appendChild(a); if (file.host) { var host = document.createElement('span'); host.innerHTML = file.host; host.setAttribute('class', 'host'); a.appendChild(host); } var span = document.createElement('span'); span.innerHTML = file.cleansize; span.setAttribute('class', 'size'); a.appendChild(span); } return div; }, getEditedIcoHtml: function() { var i = document.createElement('i'); i.className = 'material-icons'; i.innerText = 'edit'; return i; }, getDeliveredIcoHtml: function(delivered) { var i = document.createElement('i'); i.className = 'material-icons'; i.innerText = 'check'; i.setAttribute('title', delivered); return i; }, getParentHtml: function(parent) { var div = document.createElement('div'); div.classList.add('parent'); div.dataset.parentReplaceId = parent.replaceid div.dataset.parentId = parent.id; var span = document.createElement('span'); if (parent.color) { span.classList.add('resource'); span.classList.add(parent.color); } span.classList.add('from'); span.innerHTML = parent.fromName; div.appendChild(span); var p = document.createElement('p'); p.innerHTML = parent.body; div.appendChild(p); return div; }, getDisplayedIcoHtml: function(displayed) { var i = document.createElement('i'); i.className = 'material-icons'; i.innerText = 'done_all'; i.setAttribute('title', displayed); return i; }, toggleAction: function() { var chatBox = document.querySelector('#chat_widget .chat_box'); if (chatBox) { if (Chat.getTextarea().value.length > 0) { chatBox.classList.add('compose'); Chat.toggleAttach(true); } else { chatBox.classList.remove('compose'); } } }, toggleAttach: function(forceDisabled) { var attach = document.querySelector('#chat_widget .chat_box span.attach'); if (attach) { if (forceDisabled) { attach.classList.remove('enabled'); } else { attach.classList.toggle('enabled'); } } }, getTextarea: function() { var textarea = document.querySelector('#chat_textarea'); if (textarea) return textarea; }, getDiscussion: function() { return document.querySelector('#chat_widget div.contained'); }, touchEvents: function() { var chat = document.querySelector('#chat_widget'); clientWidth = Math.abs(document.body.clientWidth); chat.addEventListener('touchstart', function(event) { Chat.startX = event.targetTouches[0].pageX; Chat.startY = event.targetTouches[0].pageY; chat.classList.remove('moving'); }, true); chat.addEventListener('touchmove', function(event) { moveX = event.targetTouches[0].pageX; moveY = event.targetTouches[0].pageY; delay = 20; Chat.translateX = parseInt(moveX - Chat.startX); Chat.translateY = parseInt(moveY - Chat.startY); if (Chat.translateX > delay && Chat.translateX <= clientWidth) { // If the horizontal movement is allowed and the vertical one is not important // we authorize the slide if (Math.abs(Chat.translateY) < delay) { Chat.slideAuthorized = true; } if (Chat.slideAuthorized) { chat.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + (Chat.translateX - delay) + ', 0, 0, 1)'; } } }, true); chat.addEventListener('touchend', function(event) { chat.classList.add('moving'); if (Chat.translateX > (clientWidth / 4) && Chat.slideAuthorized) { MovimTpl.hidePanel(); Chat_ajaxGet(null, true); } chat.style.transform = ''; Chat.slideAuthorized = false; Chat.startX = Chat.translateX = Chat.startY = Chat.translateY = 0; }, true); } }; MovimWebsocket.attach(function() { Chat_ajaxInit(); var jid = MovimUtils.urlParts().params[0]; var room = (MovimUtils.urlParts().params[1] === 'room'); if (jid) { if (Boolean(document.getElementById(MovimUtils.cleanupId(jid) + '-conversation'))) { Chat_ajaxGetHistory(jid, Chat.currentDate, room, false); } else { if (room) { Chat_ajaxGetRoom(jid); } else { Chat_ajaxGet(jid); } } } else { Notification.current('chat'); } }); if (typeof Upload != 'undefined') { Upload.attach(function(file) { Chat_ajaxHttpDaemonSendMessage( Chat.getTextarea().dataset.jid, false, Boolean(Chat.getTextarea().dataset.muc), false, null, file ); }); } movimAddFocus(function() { if (MovimWebsocket.connection) { var jid = MovimUtils.urlParts().params[0]; if (jid) { Chat_ajaxGetHeader(jid, (MovimUtils.urlParts().params[1] === 'room')); } } }); document.addEventListener('focus', function() { var textarea = Chat.getTextarea(); if (textarea) textarea.focus(); }); window.addEventListener('resize', function() { Chat.scrollRestore(); }); movimAddOnload(function() { Chat.touchEvents(); }); var state = 0;