From aa9cd3f0e1d85af0239424e302fbbad8e76564de Mon Sep 17 00:00:00 2001 From: Vitor Capretz Date: Fri, 15 Sep 2017 23:09:00 -0300 Subject: [PATCH] [NEW] Adds drag-and-drop on sidebar (#539) * Adds drag-and-drop on sidebar it allows you to reorder it and then saves it using localstorage * Set active to the dragged server when dropping the dragged server on the final position it should be set as the active one --- src/scripts/sidebar.js | 95 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/src/scripts/sidebar.js b/src/scripts/sidebar.js index fa245579d65d..57d0d31ebaf6 100644 --- a/src/scripts/sidebar.js +++ b/src/scripts/sidebar.js @@ -9,13 +9,16 @@ class SideBar extends EventEmitter { constructor () { super(); - this.hostCount = 0; + this.sortOrder = JSON.parse(localStorage.getItem(this.sortOrderKey)) || []; + localStorage.setItem(this.sortOrderKey, JSON.stringify(this.sortOrder)); this.listElement = document.getElementById('serverList'); - servers.forEach((host) => { - this.add(host); - }); + Object.values(servers.hosts) + .sort((a, b) => this.sortOrder.indexOf(a.url) - this.sortOrder.indexOf(b.url)) + .forEach((host) => { + this.add(host); + }); servers.on('host-added', (hostUrl) => { this.add(servers.get(hostUrl)); @@ -48,6 +51,10 @@ class SideBar extends EventEmitter { } + get sortOrderKey () { + return 'rocket.chat.sortOrder'; + } + add (host) { let name = host.title.replace(/^https?:\/\/(?:www\.)?([^\/]+)(.*)/, '$1'); name = name.split('.'); @@ -69,14 +76,21 @@ class SideBar extends EventEmitter { img.style.display = 'initial'; initials.style.display = 'none'; }; - // img.src = `${host.url}/assets/favicon.svg?v=${Math.round(Math.random()*10000)}`; + + let hostOrder = 0; + if (this.sortOrder.includes(host.url)) { + hostOrder = this.sortOrder.indexOf(host.url) + 1; + } else { + hostOrder = this.sortOrder.length + 1; + this.sortOrder.push(host.url); + } const hotkey = document.createElement('div'); hotkey.classList.add('name'); if (process.platform === 'darwin') { - hotkey.innerHTML = '⌘' + (++this.hostCount); + hotkey.innerHTML = `⌘${hostOrder}`; } else { - hotkey.innerHTML = '^' + (++this.hostCount); + hotkey.innerHTML = `^${hostOrder}`; } const item = document.createElement('li'); @@ -87,16 +101,68 @@ class SideBar extends EventEmitter { item.appendChild(hotkey); item.dataset.host = host.url; + item.dataset.sortOrder = hostOrder; item.setAttribute('server', host.url); item.classList.add('instance'); + item.setAttribute('draggable', true); + + item.ondragstart = (event) => { + window.dragged = event.target.nodeName !== 'LI' ? event.target.closest('li') : event.target; + event.dataTransfer.effectAllowed = 'move'; + event.dataTransfer.dropEffect = 'move'; + event.target.style.opacity = .5; + }; + + item.ondragover = (event) => { + event.preventDefault(); + }; + + item.ondragenter = (event) => { + if (this.isBefore(window.dragged, event.target)) { + event.currentTarget.parentNode.insertBefore(window.dragged, event.currentTarget); + } else if (event.currentTarget !== event.currentTarget.parentNode.lastChild) { + event.currentTarget.parentNode.insertBefore(window.dragged, event.currentTarget.nextSibling); + } else { + event.currentTarget.parentNode.appendChild(window.dragged); + } + }; + + item.ondragend = (event) => { + event.target.style.opacity = ''; + }; + + item.ondrop = (event) => { + event.preventDefault(); + + const newSortOrder = []; + Array.from(event.currentTarget.parentNode.children) + .map((sideBarElement) => { + const url = sideBarElement.dataset.host; + newSortOrder.push(url); + this.remove(url); + + return sideBarElement; + }) + .map((sideBarElement) => { + this.sortOrder = newSortOrder; + localStorage.setItem(this.sortOrderKey, JSON.stringify(this.sortOrder)); + + const url = sideBarElement.dataset.host; + const host = { url, title: sideBarElement.querySelector('div.tooltip').innerHTML }; + this.add(host); + this.setImage(url); + }); + + this.setActive(window.dragged.dataset.host); + }; + item.onclick = () => { servers.setActive(host.url); }; this.listElement.appendChild(item); - - menus.addServer(host, this.hostCount); + menus.addServer(host, hostOrder); } setImage (hostUrl) { @@ -220,6 +286,17 @@ class SideBar extends EventEmitter { isHidden () { return localStorage.getItem('sidebar-closed') === 'true'; } + + isBefore (a, b) { + if (a.parentNode === b.parentNode) { + for (let cur = a; cur; cur = cur.previousSibling) { + if (cur === b) { + return true; + } + } + } + return false; + } } export default new SideBar();