feat: WebDAV sync + batch DnD + clean shutdown + center-modal UX bundle

- Sync (WebDAV, auto-merge): UUID + tombstones foundations (server +
  JS), THTTPClient bridge cmds (get/put/test), runSyncNow engine with
  pull/merge/push flow, Settings UI, pre-sync backup option. Test
  connection now treats 404 as OK (snapshot not yet created) and 401/
  403 as auth failure with dedicated toast.
- Batch drag-drop: cards + table rows carry checked-set ids (CSV) when
  dragged from an active selection; folder + trash drop handlers parse
  and apply in batch via new moveEntriesToFolder helper that preserves
  TOTP / custom_fields / kind in the full PUT payload.
- Clean shutdown: WM_QUERYENDSESSION / WM_ENDSESSION captured in the
  bridge message-only window; FormCloseQuery bypasses the tray-minimize
  intercept on system shutdown / restart / logoff so FireDAC closes the
  SQLite WAL cleanly instead of leaving -shm / -wal residue after a
  force-kill.
- Center-mode modal: blur+dim backdrop via body::before pseudo-element
  in editor-position=center, swallows clicks below the panel so the
  existing outside-click handlers reliably dismiss the slideover /
  settings panel.
- Batch bar state fixes: state.checked cleared before render in
  moveEntriesToFolder, emptyTrash, and per-card restoreEntry /
  permanentDelete / deleteEntry so the action bar disappears once the
  selection is fully processed.
- Save-then-discard duplicate fix: soState reset to null before
  openSlideOver re-opens the freshly saved entry, otherwise the dirty
  check fired on the soState.id=null → newId switch and a Cancel left
  the form in new-entry mode (second Save → POST duplicate).
- TEST_SYNC.md: end-to-end checklist for validating the WebDAV sync
  with 2 real instances.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-06-30 00:32:12 +01:00
parent b00da43ab0
commit 6869b7c692
10 changed files with 1132 additions and 25 deletions
+14 -4
View File
@@ -2059,10 +2059,20 @@ body[data-editor-position="center"] #settingsPanel.is-open {
opacity: 1;
pointer-events: auto;
}
/* No dim/blur in center mode the panel doesn't actually block
interaction (cards, sidebar, topbar stay clickable without
dismissing it), so painting a modal-style backdrop would lie about
the behaviour. The panel just floats above the page. */
/* Center mode = true modal: dim + blur backdrop, click anywhere
outside the panel dismisses it (handled in JS). The backdrop is
painted via a body pseudo-element so it covers everything but
the active panel. */
body[data-editor-position="center"]:has(#slideover.is-open)::before,
body[data-editor-position="center"]:has(#settingsPanel.is-open)::before {
content: '';
position: fixed; inset: 0;
background: rgba(0, 0, 0, 0.45);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
z-index: 45; /* above topbar (40), below .slideover (50) */
pointer-events: auto; /* swallow clicks so cards/sidebar don't see them */
}
.slideover-header {
display: flex; align-items: center; justify-content: space-between;
padding: 16px 20px;