38 lines
2.0 KiB
JavaScript
38 lines
2.0 KiB
JavaScript
/** Text and uploaded attachment references only, scoped to the signed-in account. */
|
|
export function createDraftStore(username, {storage = globalThis.localStorage, onError = () => {}} = {}) {
|
|
const key = `krishd-drafts-v1:${encodeURIComponent(username)}`;
|
|
let records = {};
|
|
let warned = false;
|
|
const report = () => { if (!warned) onError("Draft recovery is unavailable in this browser. Keep this page open to retain your draft."); warned = true; };
|
|
try {
|
|
const saved = JSON.parse(storage.getItem(key) || "{}");
|
|
if (saved && typeof saved === "object" && !Array.isArray(saved)) records = saved;
|
|
} catch { report(); }
|
|
const normalizeId = id => id == null ? "new" : String(id);
|
|
const save = () => {
|
|
for (const [id, record] of Object.entries(records)) {
|
|
if (!record.text && !record.attachments?.length) delete records[id];
|
|
}
|
|
try { storage.setItem(key, JSON.stringify(records)); } catch { report(); }
|
|
};
|
|
const update = (id, changes) => {
|
|
id = normalizeId(id);
|
|
records[id] = {...records[id], ...changes};
|
|
save();
|
|
};
|
|
const textDrafts = new Map(Object.entries(records).filter(([, record]) => typeof record?.text === "string")
|
|
.map(([id, record]) => [id === "new" ? id : Number(id), record.text]));
|
|
const set = textDrafts.set.bind(textDrafts), remove = textDrafts.delete.bind(textDrafts);
|
|
textDrafts.set = (id, text) => { update(id, {text}); return set(id, text); };
|
|
textDrafts.delete = id => { update(id, {text: ""}); return remove(id); };
|
|
return {
|
|
textDrafts,
|
|
attachments(id) {
|
|
const items = records[normalizeId(id)]?.attachments;
|
|
return Array.isArray(items) ? items.filter(item => typeof item?.id === "string" && /^[a-f0-9-]{36}$/.test(item.id)) : [];
|
|
},
|
|
setAttachments(id, attachments) { update(id, {attachments}); },
|
|
clear(id) { delete records[normalizeId(id)]; remove(id); save(); }
|
|
};
|
|
}
|