sync: stop deleting a note's checklist items because it isn't a "list"
`_apply_note_items` didn't ignore items on a non-list note — it deleted them. That was survivable only because nothing in the product could produce a note holding both a body and items. M13 makes exactly that the normal shape: a checklist is something a note HAS, not something a note IS. Against that shape this guard is a data-loss path — the first sync after adding a checklist to a note would wipe it. Landing it before the UI that can create the state, so there is never a window where the two disagree. `kind` itself, and the rest of the merge, follow.
This commit is contained in:
+14
-4
@@ -209,12 +209,22 @@ def _assign_note_fields(note: Note, ch: dict) -> None:
|
|||||||
|
|
||||||
|
|
||||||
async def _apply_note_items(db, note: Note, ch: dict) -> None:
|
async def _apply_note_items(db, note: Note, ch: dict) -> None:
|
||||||
"""Replace the note's checklist items with the client's (items sync inline)."""
|
"""Replace the note's checklist items with the client's (items sync inline).
|
||||||
if note.kind != "list":
|
|
||||||
await db.execute(sa_delete(NoteItem).where(NoteItem.note_id == note.id))
|
Applies to ANY note. This used to delete every item when the note wasn't
|
||||||
return
|
`kind == "list"`, which was survivable only because nothing could produce a note
|
||||||
|
holding both a body and items. M13 makes that the normal shape — a checklist is
|
||||||
|
something a note HAS, not something a note IS — and against that shape the old
|
||||||
|
guard was a data-loss path: the first sync after adding a checklist to a note
|
||||||
|
would have wiped it.
|
||||||
|
|
||||||
|
Removed ahead of the UI that can create the state, deliberately, so there is no
|
||||||
|
window in which the two disagree.
|
||||||
|
"""
|
||||||
items = ch.get("items")
|
items = ch.get("items")
|
||||||
if not isinstance(items, list):
|
if not isinstance(items, list):
|
||||||
|
# Absent means "not telling us", not "empty". A client that omits the key
|
||||||
|
# leaves what the server has; only an explicit [] clears it.
|
||||||
return
|
return
|
||||||
await db.execute(sa_delete(NoteItem).where(NoteItem.note_id == note.id))
|
await db.execute(sa_delete(NoteItem).where(NoteItem.note_id == note.id))
|
||||||
for pos, it in enumerate(items):
|
for pos, it in enumerate(items):
|
||||||
|
|||||||
Reference in New Issue
Block a user