diff --git a/public/signal-view.js b/public/signal-view.js index ad646e2..95610af 100644 --- a/public/signal-view.js +++ b/public/signal-view.js @@ -154,15 +154,25 @@ function sgWireComposer() { sgq('#sgat').onclick = () => sgq('#sgfile').click(); sgq('#sgfile').onchange = e => { sg.tray.push(...e.target.files); e.target.value = ''; sgDrawTray(); }; ta.addEventListener('paste', e => { const fs = [...(e.clipboardData && e.clipboardData.files || [])]; if (fs.length) { sg.tray.push(...fs); sgDrawTray(); } }); + // The message shows up in the chat at once, dimmed as "Sending…"; Signal takes a few seconds to take it, and that happens in the background. + // If it fails, the text (and files) go back into the box so nothing is lost. sgq('#sgform').onsubmit = async e => { - e.preventDefault(); const text = ta.value, files = [...sg.tray]; if (!text.trim() && !files.length) return; - const btn = sgq('#sgsend'); btn.disabled = true; + e.preventDefault(); const text = ta.value, files = [...sg.tray], reply = sg.reply, to = sg.cur; if (!text.trim() && !files.length) return; + ta.value = ''; grow(); sg.tray = []; sg.reply = null; sgDrawTray(); sgDrawReply(); ta.focus(); + const list = sgq('#sgmsgs'), tmp = document.createElement('div'); + tmp.className = 'sgb out sgpending'; tmp.style.opacity = '.65'; + tmp.innerHTML = `${esc(text) || 'Attachment'}
`; + if (list) { list.appendChild(tmp); list.scrollTop = list.scrollHeight; } + sg.sendQ = (sg.sendQ || Promise.resolve()).then(async () => { // one at a time, so quick messages arrive in the order you wrote them try { const attachments = []; for (const f of files) attachments.push({ name: f.name, type: f.type || 'application/octet-stream', data: await sgB64(f) }); - await sgPost('/send', { to: sg.cur, text, attachments, quote: sg.reply ? sg.reply.ts : undefined }); - ta.value = ''; grow(); sg.tray = []; sg.reply = null; sgDrawTray(); sgDrawReply(); await sgRefresh(); const el = sgq('#sgmsgs'); if (el) el.scrollTop = el.scrollHeight; - } catch (err) { toast(err.message); } - btn.disabled = false; ta.focus(); + await sgPost('/send', { to, text, attachments, quote: reply ? reply.ts : undefined }); + await sgRefresh(); tmp.remove(); const el = sgq('#sgmsgs'); if (el) el.scrollTop = el.scrollHeight; + } catch (err) { + tmp.remove(); toast(err.message || 'Could not send'); + if (sg.cur === to && !ta.value) { ta.value = text; grow(); sg.tray = files; sg.reply = reply; sgDrawTray(); sgDrawReply(); } + } + }); }; } // ---- editing contacts and removing chats diff --git a/public/sw.js b/public/sw.js index 775602a..4be43ee 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,5 +1,5 @@ // App-shell cache only; Seafile/API traffic always goes to the network. -const CACHE = 'hub-v12'; +const CACHE = 'hub-v13'; const SHARE = 'hub-share'; // files shared into the app from other apps, held until the person picks a folder const SHELL = ['/icon.svg', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/apple-touch-icon.png'];