#24: make draft autosave replace the previous draft
The autosave I had just added appended a new message on every debounce, so a few minutes of typing would have left the Drafts folder holding a dozen copies of the same unfinished mail. Caught before deploying. The composer now returns the stored UID and sends it back as replace_uid on the next save; the use case expunges the superseded draft, but only after the replacement has committed, so a failure leaves the older draft in place rather than losing both. Expunge is a soft delete matching the expunged_at column the schema already uses, and it locates the message by mailbox as well as UID so a caller cannot delete someone else's mail by guessing a number. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
707e6ae80e
commit
0fcdd15b58
6 files changed
+218
-6
No files matched your search
@@ -54,6 +54,9 @@ export default function ComposePage({
|
||||
const [undoSeconds, setUndoSeconds] = useState<number | null>(null);
|
||||
const [draftStatus, setDraftStatus] = useState<string>("");
|
||||
const [sendError, setSendError] = useState<string | null>(null);
|
||||
// The UID of the draft already stored for this message. Sent back on each
|
||||
// autosave so the server replaces it instead of leaving another copy.
|
||||
const draftUidRef = useRef<number>(0);
|
||||
|
||||
const editorRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -81,8 +84,13 @@ export default function ComposePage({
|
||||
bcc: splitAddresses(bcc),
|
||||
subject,
|
||||
html,
|
||||
replace_uid: draftUidRef.current,
|
||||
}),
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (typeof data.uid === "number") draftUidRef.current = data.uid;
|
||||
}
|
||||
setDraftStatus(res.ok ? t("mail.draftSaved") : t("mail.draftSaveFailed"));
|
||||
} catch {
|
||||
setDraftStatus(t("mail.draftSaveFailed"));
|
||||
|
||||
Reference in new issue
Block a user