Drafts survive reload

This commit is contained in:
Ian Gulliver
2026-10-16 08:42:48 -07:00
parent 14cf1f582b
commit cac24e534f
15 changed files with 556 additions and 92 deletions
+16 -24
View File
@@ -2,12 +2,11 @@ import { post } from "./api.js";
import { mountChanges } from "./changes.js";
import { ago, errorText, h, replace, showAlert } from "./dom.js";
import { image, inlineMarkdown, markdown } from "./markdown.js";
import { checkedAnswer, clearAnswer, dropTextAnswer, flushDrafts, hasTextAnswer, setCheckedAnswer, setTextAnswer, textAnswer } from "./drafts.js";
import { diagram } from "./mermaid.js";
import { reviewCard } from "./reviews.js";
import { focusTab, onEach, state } from "./state.js";
import { taskStyle } from "./taskcolor.js";
const checked = new Map();
const texts = new Map();
export function mountInbox(root) {
const list = h("div", { class: "inbox-list" });
const cards = new Map();
@@ -23,13 +22,6 @@ export function mountInbox(root) {
cards.delete(id);
}
}
for (const draft of [checked, texts]) {
for (const id of draft.keys()) {
if (!state.inbox.some((i) => i.id === id)) {
draft.delete(id);
}
}
}
const cardFor = (item) => {
const sig = JSON.stringify(item);
const cached = cards.get(item.id);
@@ -105,8 +97,7 @@ function card(item) {
lock(true);
try {
await post("/api/inbox/responses", { body: { responses: [response] } });
checked.delete(item.id);
texts.delete(item.id);
clearAnswer(item.id);
const others = state.inbox.some((i) => i.task_id === item.task_id && i.id !== item.id);
if (!others && state.focus.tab === "inbox" && state.selectedTaskId === item.task_id) {
focusTab("transcript");
@@ -136,24 +127,24 @@ function card(item) {
void submit({ item_id: item.id, type: "option", options: [text] });
});
}
const input = h("input", { type: "checkbox", checked: (checked.get(item.id) ?? []).includes(text) });
const input = h("input", { type: "checkbox", checked: checkedAnswer(item.id).includes(text) });
input.onchange = () => {
const now = (checked.get(item.id) ?? []).filter((o) => o !== text);
const now = checkedAnswer(item.id).filter((o) => o !== text);
if (input.checked) {
now.push(text);
}
checked.set(item.id, options.filter((o) => now.includes(o)));
setCheckedAnswer(item.id, options.filter((o) => now.includes(o)));
renderActions();
};
return h("label", { class: rec ? "option choice-box rec" : "option choice-box" }, h("div", { class: "choice-head" }, input, name, tag));
};
const textEntry = (label, placeholder, shared) => {
const open = texts.has(item.id);
const text = h("textarea", { rows: 3, placeholder, value: texts.get(item.id) ?? "" });
const open = hasTextAnswer(item.id);
const text = h("textarea", { rows: 3, placeholder, value: textAnswer(item.id) ?? "" });
const send = h("button", { type: "button", class: "primary", disabled: !text.value.trim() }, "Submit");
const editor = h("div", { class: "text-editor", hidden: !open }, text, !shared && h("div", { class: "submit-row" }, send));
const block = clickable(h("div", { class: "pick other", role: "button", tabIndex: 0, hidden: open }, label), () => {
texts.set(item.id, "");
setTextAnswer(item.id, "");
block.hidden = true;
editor.hidden = false;
text.focus();
@@ -169,17 +160,18 @@ function card(item) {
};
send.onclick = go;
text.oninput = () => {
texts.set(item.id, text.value);
setTextAnswer(item.id, text.value);
send.disabled = !text.value.trim();
shared?.onInput();
};
text.onblur = () => {
if (!text.value.trim() && !busy()) {
texts.delete(item.id);
dropTextAnswer(item.id);
editor.hidden = true;
block.hidden = false;
shared?.onInput();
}
flushDrafts();
};
text.onkeydown = (e) => {
if (e.key === "Enter" && !e.shiftKey && !e.isComposing) {
@@ -198,18 +190,18 @@ function card(item) {
return;
}
const send = h("button", { type: "button", class: "primary" }, "Submit");
const typed = () => (texts.get(item.id) ?? "").trim();
const typed = () => (textAnswer(item.id) ?? "").trim();
const refresh = () => {
send.disabled = !typed() && (checked.get(item.id) ?? []).length === 0;
send.disabled = !typed() && checkedAnswer(item.id).length === 0;
};
const go = () => {
const options = checked.get(item.id) ?? [];
const options = checkedAnswer(item.id);
if (options.length > 0) {
void submit({ item_id: item.id, type: "option", options, text: typed() ? texts.get(item.id) : undefined });
void submit({ item_id: item.id, type: "option", options, text: typed() ? textAnswer(item.id) : undefined });
return;
}
if (typed()) {
void submit({ item_id: item.id, type: "other", text: texts.get(item.id) });
void submit({ item_id: item.id, type: "other", text: textAnswer(item.id) });
}
};
const other = textEntry("Other…", placeholder, { onInput: refresh, onSubmit: go });