Keep email composer open during fast edits
This commit is contained in:
parent
4f387e089a
commit
baecea2681
3 changed files with 39 additions and 34 deletions
|
|
@ -219,8 +219,8 @@
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="/static/style.css?v=20260630emailtype">
|
<link rel="stylesheet" href="/static/style.css?v=20260630emailrace">
|
||||||
<link rel="modulepreload" href="/static/app.js?v=20260630emailtype">
|
<link rel="modulepreload" href="/static/app.js?v=20260630emailrace">
|
||||||
<link rel="modulepreload" href="/static/js/chat.js">
|
<link rel="modulepreload" href="/static/js/chat.js">
|
||||||
<link rel="modulepreload" href="/static/js/ui.js">
|
<link rel="modulepreload" href="/static/js/ui.js">
|
||||||
<link rel="modulepreload" href="/static/js/sessions.js">
|
<link rel="modulepreload" href="/static/js/sessions.js">
|
||||||
|
|
@ -2512,7 +2512,7 @@
|
||||||
<script type="module" src="/static/js/settings.js"></script>
|
<script type="module" src="/static/js/settings.js"></script>
|
||||||
<script type="module" src="/static/js/admin.js"></script>
|
<script type="module" src="/static/js/admin.js"></script>
|
||||||
<script type="module" src="/static/js/assistant.js"></script>
|
<script type="module" src="/static/js/assistant.js"></script>
|
||||||
<script type="module" src="/static/app.js?v=20260630emailtype"></script> <!-- app.js must be LAST -->
|
<script type="module" src="/static/app.js?v=20260630emailrace"></script> <!-- app.js must be LAST -->
|
||||||
<script type="module" src="/static/js/init.js"></script>
|
<script type="module" src="/static/js/init.js"></script>
|
||||||
<script type="module" src="/static/js/a11y.js"></script>
|
<script type="module" src="/static/js/a11y.js"></script>
|
||||||
<script nonce="{{CSP_NONCE}}">if('serviceWorker' in navigator){navigator.serviceWorker.register('/static/sw.js').catch(()=>{});}</script>
|
<script nonce="{{CSP_NONCE}}">if('serviceWorker' in navigator){navigator.serviceWorker.register('/static/sw.js').catch(()=>{});}</script>
|
||||||
|
|
|
||||||
|
|
@ -2668,6 +2668,15 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
summary.title = summary.textContent;
|
summary.title = summary.textContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _setEmailHeaderInputValue(id, value, { preserveFocused = true, preserveNonEmpty = false } = {}) {
|
||||||
|
const el = document.getElementById(id);
|
||||||
|
if (!el) return;
|
||||||
|
const next = value || '';
|
||||||
|
if (preserveFocused && document.activeElement === el) return;
|
||||||
|
if (preserveNonEmpty && !next && el.value) return;
|
||||||
|
if (el.value !== next) el.value = next;
|
||||||
|
}
|
||||||
|
|
||||||
function _setEmailHeaderCollapsed(collapsed, { manual = true } = {}) {
|
function _setEmailHeaderCollapsed(collapsed, { manual = true } = {}) {
|
||||||
const header = document.getElementById('doc-email-header');
|
const header = document.getElementById('doc-email-header');
|
||||||
const btn = document.getElementById('doc-email-collapse-btn');
|
const btn = document.getElementById('doc-email-collapse-btn');
|
||||||
|
|
@ -2730,13 +2739,10 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
document.getElementById('doc-editor-highlight')?.classList.add('email-mode');
|
document.getElementById('doc-editor-highlight')?.classList.add('email-mode');
|
||||||
let fields = _parseEmailHeader(doc.content || '');
|
let fields = _parseEmailHeader(doc.content || '');
|
||||||
fields = _emailFieldsWithLocalDraft(fields);
|
fields = _emailFieldsWithLocalDraft(fields);
|
||||||
const toInput = document.getElementById('doc-email-to');
|
|
||||||
const subjectInput = document.getElementById('doc-email-subject');
|
const subjectInput = document.getElementById('doc-email-subject');
|
||||||
const inReplyTo = document.getElementById('doc-email-in-reply-to');
|
|
||||||
const refs = document.getElementById('doc-email-references');
|
|
||||||
const textarea = document.getElementById('doc-editor-textarea');
|
const textarea = document.getElementById('doc-editor-textarea');
|
||||||
if (toInput) toInput.value = fields.to;
|
_setEmailHeaderInputValue('doc-email-to', fields.to, { preserveNonEmpty: true });
|
||||||
if (subjectInput) subjectInput.value = fields.subject;
|
_setEmailHeaderInputValue('doc-email-subject', fields.subject, { preserveNonEmpty: true });
|
||||||
_setEmailHeaderCollapsed(!!(doc && doc._emailHeaderCollapsed), { manual: false });
|
_setEmailHeaderCollapsed(!!(doc && doc._emailHeaderCollapsed), { manual: false });
|
||||||
if (subjectInput && !subjectInput._emailTabBodyBound) {
|
if (subjectInput && !subjectInput._emailTabBodyBound) {
|
||||||
subjectInput._emailTabBodyBound = true;
|
subjectInput._emailTabBodyBound = true;
|
||||||
|
|
@ -2747,12 +2753,10 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (inReplyTo) inReplyTo.value = fields.inReplyTo;
|
_setEmailHeaderInputValue('doc-email-in-reply-to', fields.inReplyTo, { preserveNonEmpty: true });
|
||||||
if (refs) refs.value = fields.references;
|
_setEmailHeaderInputValue('doc-email-references', fields.references, { preserveNonEmpty: true });
|
||||||
const sourceUid = document.getElementById('doc-email-source-uid');
|
_setEmailHeaderInputValue('doc-email-source-uid', fields.sourceUid || '', { preserveNonEmpty: true });
|
||||||
const sourceFolder = document.getElementById('doc-email-source-folder');
|
_setEmailHeaderInputValue('doc-email-source-folder', fields.sourceFolder || '', { preserveNonEmpty: true });
|
||||||
if (sourceUid) sourceUid.value = fields.sourceUid || '';
|
|
||||||
if (sourceFolder) sourceFolder.value = fields.sourceFolder || '';
|
|
||||||
// Show/hide unread button only if we have a source UID (came from inbox)
|
// Show/hide unread button only if we have a source UID (came from inbox)
|
||||||
const unreadBtn = document.getElementById('doc-email-unread-btn');
|
const unreadBtn = document.getElementById('doc-email-unread-btn');
|
||||||
if (unreadBtn) unreadBtn.style.display = fields.sourceUid ? '' : 'none';
|
if (unreadBtn) unreadBtn.style.display = fields.sourceUid ? '' : 'none';
|
||||||
|
|
@ -2875,11 +2879,14 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
const ccRow = document.getElementById('doc-email-cc-row');
|
const ccRow = document.getElementById('doc-email-cc-row');
|
||||||
const bccRow = document.getElementById('doc-email-bcc-row');
|
const bccRow = document.getElementById('doc-email-bcc-row');
|
||||||
const ccToggle = document.getElementById('doc-email-show-cc');
|
const ccToggle = document.getElementById('doc-email-show-cc');
|
||||||
const ccInput = document.getElementById('doc-email-cc');
|
_setEmailHeaderInputValue('doc-email-cc', fields.cc || '', { preserveNonEmpty: true });
|
||||||
const bccInput = document.getElementById('doc-email-bcc');
|
_setEmailHeaderInputValue('doc-email-bcc', fields.bcc || '', { preserveNonEmpty: true });
|
||||||
if (ccInput) ccInput.value = fields.cc || '';
|
const hasCcBcc = !!(
|
||||||
if (bccInput) bccInput.value = fields.bcc || '';
|
fields.cc ||
|
||||||
const hasCcBcc = !!(fields.cc || fields.bcc);
|
fields.bcc ||
|
||||||
|
document.getElementById('doc-email-cc')?.value ||
|
||||||
|
document.getElementById('doc-email-bcc')?.value
|
||||||
|
);
|
||||||
if (ccRow) ccRow.style.display = hasCcBcc ? '' : 'none';
|
if (ccRow) ccRow.style.display = hasCcBcc ? '' : 'none';
|
||||||
if (bccRow) bccRow.style.display = hasCcBcc ? '' : 'none';
|
if (bccRow) bccRow.style.display = hasCcBcc ? '' : 'none';
|
||||||
if (ccToggle) ccToggle.style.display = hasCcBcc ? 'none' : '';
|
if (ccToggle) ccToggle.style.display = hasCcBcc ? 'none' : '';
|
||||||
|
|
@ -2898,19 +2905,14 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const setValue = (id, value) => {
|
_setEmailHeaderInputValue('doc-email-to', fields.to, { preserveNonEmpty: true });
|
||||||
const el = document.getElementById(id);
|
_setEmailHeaderInputValue('doc-email-subject', fields.subject, { preserveNonEmpty: true });
|
||||||
const next = value || '';
|
_setEmailHeaderInputValue('doc-email-in-reply-to', fields.inReplyTo, { preserveNonEmpty: true });
|
||||||
if (el && el.value !== next) el.value = next;
|
_setEmailHeaderInputValue('doc-email-references', fields.references, { preserveNonEmpty: true });
|
||||||
};
|
_setEmailHeaderInputValue('doc-email-source-uid', fields.sourceUid || '', { preserveNonEmpty: true });
|
||||||
setValue('doc-email-to', fields.to);
|
_setEmailHeaderInputValue('doc-email-source-folder', fields.sourceFolder || '', { preserveNonEmpty: true });
|
||||||
setValue('doc-email-subject', fields.subject);
|
_setEmailHeaderInputValue('doc-email-cc', fields.cc || '', { preserveNonEmpty: true });
|
||||||
setValue('doc-email-in-reply-to', fields.inReplyTo);
|
_setEmailHeaderInputValue('doc-email-bcc', fields.bcc || '', { preserveNonEmpty: true });
|
||||||
setValue('doc-email-references', fields.references);
|
|
||||||
setValue('doc-email-source-uid', fields.sourceUid || '');
|
|
||||||
setValue('doc-email-source-folder', fields.sourceFolder || '');
|
|
||||||
setValue('doc-email-cc', fields.cc || '');
|
|
||||||
setValue('doc-email-bcc', fields.bcc || '');
|
|
||||||
|
|
||||||
const unreadBtn = document.getElementById('doc-email-unread-btn');
|
const unreadBtn = document.getElementById('doc-email-unread-btn');
|
||||||
if (unreadBtn) unreadBtn.style.display = fields.sourceUid ? '' : 'none';
|
if (unreadBtn) unreadBtn.style.display = fields.sourceUid ? '' : 'none';
|
||||||
|
|
@ -4029,7 +4031,7 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
const prevId = activeDocId;
|
const prevId = activeDocId;
|
||||||
if (prevId && prevId !== docId && docs.has(prevId)) {
|
if (prevId && prevId !== docId && docs.has(prevId)) {
|
||||||
const prev = docs.get(prevId);
|
const prev = docs.get(prevId);
|
||||||
if (!(prev.content || '').trim() && !(prev.title || '').trim()) {
|
if (prev.language !== 'email' && !(prev.content || '').trim() && !(prev.title || '').trim()) {
|
||||||
fetch(`${API_BASE}/api/document/${prevId}`, { method: 'DELETE' }).catch(() => {});
|
fetch(`${API_BASE}/api/document/${prevId}`, { method: 'DELETE' }).catch(() => {});
|
||||||
docs.delete(prevId);
|
docs.delete(prevId);
|
||||||
_syncDocIndicator();
|
_syncDocIndicator();
|
||||||
|
|
@ -8828,6 +8830,9 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (res.status === 404) {
|
if (res.status === 404) {
|
||||||
|
if (silent && localDoc?.language === 'email') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Streaming/empty email drafts can leave a local tab pointing at a temp
|
// Streaming/empty email drafts can leave a local tab pointing at a temp
|
||||||
// or already-deleted document. Do not keep surfacing autosave errors for
|
// or already-deleted document. Do not keep surfacing autosave errors for
|
||||||
// a document the backend no longer knows about.
|
// a document the backend no longer knows about.
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
// - Other static assets (images/fonts/libs): cache-first with bg refresh.
|
// - Other static assets (images/fonts/libs): cache-first with bg refresh.
|
||||||
// - API / non-GET: never cached.
|
// - API / non-GET: never cached.
|
||||||
// Bump CACHE_NAME whenever the precache list or SW logic changes.
|
// Bump CACHE_NAME whenever the precache list or SW logic changes.
|
||||||
const CACHE_NAME = 'odysseus-v332';
|
const CACHE_NAME = 'odysseus-v333';
|
||||||
|
|
||||||
// Core shell precached on install so repeat opens are instant without any
|
// Core shell precached on install so repeat opens are instant without any
|
||||||
// network wait. Keep this list in sync with the <script type="module"> tags
|
// network wait. Keep this list in sync with the <script type="module"> tags
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue