diff --git a/public/mail.js b/public/mail.js index 2aa0373..692656a 100644 --- a/public/mail.js +++ b/public/mail.js @@ -138,6 +138,15 @@ async function mailAdminCard() { async function viewMail(args = []) { const v = $('#view'); if (!cfg.mail) { v.innerHTML = '

Mail

Mail is not available to you.

'; return; } + // Moving between messages (or back to the list) in the same folder changes only the reader and the highlighted row: the page is not rebuilt, + // so there is no flash, and the list keeps its place. + const shell = document.querySelector('.mailapp'), k0 = args[0], key0 = args[1]; + if (shell && v.contains(shell) && mail.st && mail.st.connected && mail.accts.length && (k0 === 'm' || k0 === undefined) && (k0 !== 'm' || !String(key0).includes('~') || String(key0).split('~')[0] === mail.acct)) { + const view = $('#view'); + if (k0 === 'm') { if (shell.dataset.mode !== 'read') mail.listScroll = view.scrollTop; shell.dataset.mode = 'read'; mailMarkSel(key0); mailOpen(key0); } + else { shell.dataset.mode = 'list'; mail.msg = null; mailDrawReader(); mailMarkSel(''); requestAnimationFrame(() => { if (mail.listScroll) view.scrollTop = mail.listScroll; }); } + return; + } // The accounts come from the server without any network call to the mail providers ("light"), so the page can draw at once; the folders, the message // list and the real unread counts then load side by side instead of one after another. let st = mail.st; @@ -228,6 +237,7 @@ async function mailLoadList(reset) { mailDrawList(); } catch (e) { if (showing) return; const el = $('#mrows'); if (el) el.innerHTML = `

${esc(e.message)}

`; if (/Connect again/.test(e.message)) { mail.st = null; mcClear(); setTimeout(route, 1200); } } } +function mailMarkSel(id) { document.querySelectorAll('a.mrow').forEach(a => a.classList.toggle('sel', !!id && decodeURIComponent(a.getAttribute('href').slice(9)) === id)); } function mailDrawList() { const rows = $('#mrows'); if (!rows) return; const sel = (location.hash.match(/^#\/mail\/m\/([^/]+)/) || [])[1];