diff --git a/client/message.js b/client/message.js index 4091023..a963099 100644 --- a/client/message.js +++ b/client/message.js @@ -56,6 +56,8 @@ function loadMessages(callback) { let user; if (message.user.name) user = message.user; + else if (message.user.id.indexOf('@') === -1) + message.user.id = 'deleted user'; else { user = users[message.user.id]; if (user === undefined) diff --git a/client/thread.js b/client/thread.js index 816b7ee..5039db2 100644 --- a/client/thread.js +++ b/client/thread.js @@ -14,49 +14,35 @@ function setVisibility() { 'only members can post' : 'some members can post'}`; } -function chooseThread() { +function openThread(div, pushState) { if (!document.getElementById('removemember').classList.contains('hidden')) document.getElementById('member').classList.add('hidden'); - const edit = document.getElementById('edit'); - let thread = this.thread; - let url = new URL(location); - if (window.currentThread) { - window.currentThread.div.classList.remove('active'); - let editform = document.getElementById('editthread'); - if (editform) { - editform.remove(); - edit.textContent = 'edit'; - } - url.searchParams.delete('tab'); - if (window.currentThread.id === thread.id) - url.searchParams.delete('thread'); - window.history.pushState(null, '', url.toString()); - if (window.currentThread.id === thread.id) { - document.getElementById('thread').classList.add('hidden'); - window.currentThread = null; - return; - } + if (!div) { + document.getElementById('thread').classList.add('hidden'); + window.currentThread = null; + return; } - else - document.getElementById('thread').classList.remove('hidden'); - if (thread.permissions.admin) { + document.getElementById('thread').classList.remove('hidden'); + const edit = document.getElementById('edit'); + if (div.thread.permissions.admin) { edit.classList.remove('hidden'); document.getElementById('membersadd').classList.remove('hidden'); } else { edit.classList.add('hidden'); document.getElementById('membersadd').classList.add('hidden'); } - document.getElementById('threadname').textContent = thread.name; - this.classList.add('active'); - window.currentThread = thread; - window.currentInstance = thread.instance; - let div = this; - window.currentInstance.emit('get_thread', { thread: thread.id }, async msg => { + document.getElementById('threadname').textContent = div.thread.name; + if (window.currentThread) + window.currentThread.div.classList.remove('active'); + div.classList.add('active'); + window.currentThread = div.thread; + window.currentInstance = div.thread.instance; + window.currentInstance.emit('get_thread', { thread: div.thread.id }, async msg => { if (!msg.success) { console.log('get_thread failed:', msg.message); return; } - Object.assign(thread, msg.thread); + Object.assign(div.thread, msg.thread); setVisibility(); document.getElementById('memberlist').replaceChildren( ...await Promise.all(msg.thread.members.map(async member => { @@ -78,16 +64,11 @@ function chooseThread() { })) ); loadCall(); - let tab = url.searchParams.get('tab'); - if (!['message', 'space', 'call'].includes(tab)) - tab = null; - if (tab || this.tab) { - if (tab) - this.tab = tab + 'tab'; - switchTab(document.getElementById(this.tab)); - if (this.tab === 'messagetab') + if (div.tab) { + switchTab(document.getElementById(div.tab)); + if (div.tab === 'messagetab') loadMessages(); - else if (this.tab === 'spacetab') + else if (div.tab === 'spacetab') loadSpace(); } else // load first tab that has any content @@ -100,27 +81,51 @@ function chooseThread() { loadSpace(spans => { if (spans.length) switchTab(document.getElementById(div.tab = 'spacetab')); - else if (window.currentThread.streams.length) + else if (Object.keys(currentThread.call).length || currentThread.streams.length) switchTab(document.getElementById(div.tab = 'calltab')); else switchTab(document.getElementById( div.tab = spans.length ? 'spacetab' : - window.currentThread.streams.length ? 'calltab' : 'messagetab')); + Object.keys(currentThread.call).length || currentThread.streams.length + ? 'calltab' : 'messagetab')); resolve(); }); }); }); - if (window.currentInstance === window.instancelist[0]) { - url.searchParams.set('thread', thread.id); - url.searchParams.set('tab', div.tab.substring(0, div.tab.length - 3)); - } else { + if (pushState) { + let url = new URL(window.location); + // put instance before thread and tab url.searchParams.delete('thread'); url.searchParams.delete('tab'); + if (currentInstance === instancelist[0]) + url.searchParams.delete('instance'); + else + url.searchParams.set('instance', currentInstance.url); + url.searchParams.set('thread', div.thread.id); + url.searchParams.set('tab', div.tab.substring(0, div.tab.length - 3)); + window.history.pushState(null, '', url.toString()); } - window.history.pushState(null, '', url.toString()); }); } +window.onpopstate = event => { + let params = new URLSearchParams(window.location.search); + let thread = params.get('thread'); + if (!thread) { + openThread(); + return; + } + let url = params.get('instance'); + let div = document.querySelector( + `#instance${(url ? instancelist.find(i => i.url === url) : instancelist[0])?.id} #thread${thread}`); + if (!div) + return; + let tab = params.get('tab'); + if (['message', 'space', 'call'].includes(tab)) + div.tab = tab + 'tab'; + openThread(div); +}; + function switchTab(tab) { document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active')); document.querySelectorAll('.tabcontent').forEach(tab => tab.classList.add('hidden')); @@ -204,8 +209,8 @@ function newThread(instance) { } // since the form exists, this will perform cleanup newThread(); - chooseThread.call(this.parentElement.parentElement.children['threadlist'] - .children['thread' + msg.id]); + openThread(this.parentElement.parentElement.children['threadlist'] + .children['thread' + msg.id], true); } ); }}> @@ -366,7 +371,27 @@ async function loadThreads(instancediv, select) { function makeThread(thread) { thread.instance = instancediv.instance; let node = html.node` -