Reading goals for e-books and the family; subtasks on iCloud lists; watch stats in Movies & TV

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-27 11:30:40 -04:00
1 parent 435f442761
commit 275ef2009f
12 files changed
+74 -11

No files matched your search

+8 -2
View File
@@ -44,9 +44,10 @@ function parseTodos(text) {
else if (l.name === 'STATUS') cur.status = l.value.toUpperCase();
else if (l.name === 'PERCENT-COMPLETE') cur.percent = parseInt(l.value, 10);
else if (l.name === 'COMPLETED') cur.completed = true;
else if (l.name === 'RELATED-TO' && !/^(CHILD|SIBLING)$/i.test((l.params && l.params.RELTYPE) || '')) cur.parent = cal.unesc(l.value);
else if (l.name === 'DUE') { const d = cal.parseDate(l.value, l.params); if (d) cur.due = `${d.y}-${String(d.mo).padStart(2, '0')}-${String(d.d).padStart(2, '0')}`; }
}
return out.map(t => ({ id: t.uid, title: t.title || '(No title)', notes: t.notes || '', due: t.due || '', done: t.status === 'COMPLETED' || t.percent === 100 || !!t.completed }));
return out.map(t => ({ id: t.uid, title: t.title || '(No title)', notes: t.notes || '', due: t.due || '', done: t.status === 'COMPLETED' || t.percent === 100 || !!t.completed, parent: t.parent || '' }));
}
// ---- Repeating tasks (NE Hub lists): finishing one moves its due date to the next occurrence instead of closing it.
@@ -139,7 +140,12 @@ async function handle(req, res) {
if (b.href) { // edit an iCloud task: patch the latest copy so alarms/priority/etc. survive
const cur = await caldav.getResource(b.list, b.href);
await caldav.putEvent(b.list, null, ics.patchTodo(cur.ics, f), { href: b.href, etag: cur.etag });
} else { const uid = ics.newUid(); await caldav.putEvent(b.list, uid, ics.buildTodoCalendar([{ uid, fields: f }])); }
} else {
if (f.parent) { // a subtask goes under a main task of the same list (and a subtask cannot have subtasks)
const mine = []; for (const r of await caldav.listTodoRaw(b.list)) mine.push(...parseTodos(r.ics)); const par = mine.find(x => x.id === f.parent);
if (!par || par.parent) throw new Error('A subtask can only go under a main task in the same list'); }
const uid = ics.newUid(); await caldav.putEvent(b.list, uid, ics.buildTodoCalendar([{ uid, fields: f }]));
}
return json(res, 200, { ok: true });
}
if (p === '/api/tasks/toggle' && req.method === 'POST') {