diff --git a/frontend/src/stores/labels.ts b/frontend/src/stores/labels.ts index 1890b0c..f64a182 100644 --- a/frontend/src/stores/labels.ts +++ b/frontend/src/stores/labels.ts @@ -47,6 +47,19 @@ export const useLabelsStore = defineStore("labels", () => { } async function remove(id: string): Promise { + // Labels have no trash of their own — a label is organization, not content, so + // the reversible middle step notes get would be ceremony. But deleting one is + // still irreversible and now reaches every synced device, so it asks first. The + // notes themselves survive; only the membership goes, which is the part people + // most need reassuring about. + const label = items.value.find((lb) => lb.id === id); + const subject = label ? `the label "${label.name}"` : "this label"; + const confirmed = window.confirm( + `Delete ${subject}?\n\n` + + "It will be removed from every note that uses it, on every device you sync " + + "with. The notes themselves are kept.", + ); + if (!confirmed) return; await repo.labels.remove(id); items.value = items.value.filter((lb) => lb.id !== id); } diff --git a/frontend/src/stores/notes.ts b/frontend/src/stores/notes.ts index ed54ad7..4a73525 100644 --- a/frontend/src/stores/notes.ts +++ b/frontend/src/stores/notes.ts @@ -249,6 +249,18 @@ export const useNotesStore = defineStore("notes", () => { } async function deleteForever(id: string): Promise { + // Guarded HERE rather than at the call sites (NoteCard and NoteEditor both offer + // it) so the two can't drift on the one action with no undo. Trash is the + // reversible step and already offers Undo; this is the point of no return — and + // since sync propagates a tombstone, it reaches every linked device too. + const note = items.value.find((n) => n.id === id); + const title = note?.display_title.trim(); + const subject = title ? `"${title}"` : "this note"; + const confirmed = window.confirm( + `Permanently delete ${subject}?\n\n` + + "This can't be undone, and it will be deleted from every device you sync with.", + ); + if (!confirmed) return; await repo.notes.deleteForever(id); const idx = items.value.findIndex((n) => n.id === id); if (idx >= 0) items.value.splice(idx, 1);