mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-15 11:22:21 +02:00
* refactor(notes): decompose Notes into feature-owned modules * fix(notes): avoid HTML interpolation in reminder picker * docs(notes): drop checkpoint archives, session logs and publication drafts The N0-N6 tarballs and raw pytest/node logs are not read by any script or test, and the logs carry absolute home-directory paths. Once squashed into dev they would stay in history for good. notes-pr.md and notes-issue.md were the drafts used to open #6712 and #6713, not documentation. notes-validation.md keeps the counts, the checkpoint hashes and implementation.sha256 as the record; local interpreter paths and the local Docker image name are replaced with portable placeholders. * fix(notes): keep the state store raw and stop masonry re-observing after close - state: writes built from views (filter, spread, splice) stored nested read-only views in the store, so structuredClone on a stored note threw DataCloneError. Store writes now unwrap nested views. - layout: a save that resolves after closePanel re-renders the leaving pane and re-created the masonry ResizeObserver that teardown had disposed. Skip creating it once Notes is closed. - index.js: drop 30 imported or declared names that were never used and group the imports at the top. Import order is unchanged. - Revert unrelated punctuation edits in .gitattributes and keep the header comment and docstring first in compare/vote.js and test_notes_dom_xss_helpers.py. Both fixes have a node test that fails on the previous head. * test(notes): make script rejection assertion case-insensitive Address CodeQL js/bad-tag-filter alert #1150 in test-only assertion and refresh Notes evidence manifest checksum. --------- Co-authored-by: Léo <leograndcontact@gmail.com>
69 lines
3.0 KiB
JavaScript
69 lines
3.0 KiB
JavaScript
/** Checklist item workflows. Supplied feedback callbacks update the invoking view. */
|
|
export function createChecklistOperations({
|
|
app,
|
|
api,
|
|
effects,
|
|
uid
|
|
}) {
|
|
const state = app.state;
|
|
function itemNote(id, index) {
|
|
const note = state.notes.find(n => n.id === id);
|
|
return note && Array.isArray(note.items) && note.items[index] ? note : null;
|
|
}
|
|
function removeItem(id, index) {
|
|
const note = itemNote(id, index);
|
|
if (!note) return;
|
|
const removed = note.items[index];
|
|
app.mergeNote(note, { items: note.items.filter((_, i) => i !== index) });
|
|
effects.render();
|
|
api.patchNote(id, { items: note.items }).catch(() => {
|
|
app.spliceItems(note, index, 0, removed); effects.render(); effects.showError('Failed to remove item');
|
|
});
|
|
}
|
|
function editItem(note, index, text) {
|
|
const oldText = (note.items[index].text || '').trim();
|
|
if (text === oldText) { effects.render(); return; }
|
|
const oldItem = note.items[index];
|
|
if (!text) app.spliceItems(note, index, 1);
|
|
else app.updateItem(note, index, { text });
|
|
api.patchNote(note.id, { items: note.items }).catch(() => {
|
|
if (!text) app.spliceItems(note, index, 0, oldItem);
|
|
else app.updateItem(note, index, { text: oldText });
|
|
effects.render(); effects.showError('Failed to update item');
|
|
});
|
|
effects.render();
|
|
}
|
|
function addItem(id, text, added) {
|
|
const note = state.notes.find(n => n.id === id);
|
|
if (!note) return;
|
|
const items = Array.isArray(note.items) ? [...note.items] : [];
|
|
items.push({ id: uid(), text, done: false });
|
|
app.mergeNote(note, { items });
|
|
added(); effects.render();
|
|
return () => api.patchNote(id, { items }).catch(() => {
|
|
app.mergeNote(note, { items: items.slice(0, -1) }); effects.render(); effects.showError('Failed to add item');
|
|
});
|
|
}
|
|
function toggleItem(id, index, changed, completed) {
|
|
const note = itemNote(id, index);
|
|
if (!note) return;
|
|
const wasDone = note.items.length > 0 && note.items.every(it => it.done);
|
|
app.updateItem(note, index, { done: !note.items[index].done });
|
|
changed(note.items[index].done);
|
|
if (!wasDone && note.items.length > 0 && note.items.every(it => it.done)) completed();
|
|
api.patchNote(id, { items: note.items }).catch(() => {
|
|
app.updateItem(note, index, { done: !note.items[index].done }); changed(note.items[index].done);
|
|
});
|
|
}
|
|
async function toggleTodayStep(id, index, changed, completed) {
|
|
const note = itemNote(id, index);
|
|
if (!note) return;
|
|
app.updateItem(note, index, { done: !note.items[index].done }); changed();
|
|
try {
|
|
await api.patchNote(id, { items: note.items }); effects.render();
|
|
if (note.items.every(it => it.done)) completed();
|
|
} catch { app.updateItem(note, index, { done: !note.items[index].done }); }
|
|
}
|
|
return { removeItem, editItem, addItem, toggleItem, toggleTodayStep };
|
|
}
|