Commit graph

18 commits

Author SHA1 Message Date
Lukas Brübach
875e87d1bc [DeckSync] Address auto-sync review: disconnect, backfill and modal conflicts
- Fail the run when the connection drops while a sync is running, and clear
  the active conflict, so the queue is not sent on a dead client and a
  re-login as another account never receives this profile's uploads.
- Backfill last_modified from upload_time in the 37 -> 38 migration and drop
  the "last_modified is null" arm from the sync-check query, so rows that
  predate the column stop reporting as changed on every poll.
- Skip conflicts during auto runs and report how many were skipped, instead
  of opening the modal conflict dialog from a timer or a file-watcher event.
2026-11-03 18:10:12 +01:00
Lukas Brübach
8bb0a9b98a Fix ZeldaZach review for PR 7496: deck path in ctor, server-time baseline, single-query sync check 2026-11-03 18:10:12 +01:00
Lukas Brübach
e73fcd602c [Client+Server] Auto deck sync with change polling 2026-11-03 18:10:12 +01:00
Lukas Brübach
dcccb0f332 Fix remaining review threads on the conflict classification
- Remove the duplicated download loop and the stray '<' plus extra brace
  that left the head unbuildable.
- Skip the fallback upload under DownloadMode so a local-only deck is not
  pushed when the user asked for downloads only.
- Treat a server row without a hash as unknown rather than changed, so
  pre-migration decks are not re-downloaded on every sync.
2026-11-02 21:58:07 +01:00
Lukas Brübach
9e4d734373 Fix ZeldaZach review for PR 7495: three-way baseHash check before conflict 2026-11-02 21:58:07 +01:00
Lukas Brübach
d2e2e722e7 [Client] Sync conflict dialog, onboarding and conflict default 2026-11-02 21:58:07 +01:00
Lukas Brübach
de3468cc33 [DeckSync] Address tombstone review: remote deletes, revival and purge clock
- Treat a record whose server row is gone as a remote delete only when the
  local file still matches the sidecar's base hash. An edit made after the
  remote delete is newer than the delete, so it uploads and revives the row
  instead of being removed.
- Revive a tombstone with the same user and guid in cmdDeckUpload instead of
  inserting a second row next to it, so the deck keeps its id and version
  history and the promise in servatrice.ini.example holds.
- Run tombstone purging on its own clock, driven by the new
  [deck_sync] purge_interval option, so disabling share cleanup no longer
  disables purging silently.
- Write the base snapshot through QSaveFile and log a failed commit, so a
  crash or a full disk cannot leave a truncated base for DeckDiff::merge().
2026-11-01 22:25:56 +01:00
Lukas Brübach
157e63b179 Fix ZeldaZach review for PR 7494: match by remoteId/guid before remote-delete, only tombstone when file truly missing 2026-11-01 22:25:51 +01:00
Lukas Brübach
e43862c3bc [Server+Client] Tombstone deck deletes with purge and base snapshots 2026-11-01 22:25:51 +01:00
Lukas Brübach
2916fa45af [DeckSync] Match server rows by identity and hash the whole deck
Sync keyed local files to server rows by path, but the server names a row
after the deck, not after the file, so any deck whose file name and deck name
differ uploaded again on every run. A second pass then brought the server copy
back as an extra local file.

- Match by the sidecar's row id, then guid, then content, and only then by the
  server path, so renaming either side no longer duplicates a deck.
- Key the server tree by row id: the server allows several rows with the same
  name in one folder, and keying by path silently dropped all but one.
- Stop discarding rows whose name contains '/' ("U/W Control"). They stay
  matchable, and only the download file name is sanitised.
- Build the download path from the folder plus a sanitised row name, including
  every folder segment, so a hostile server name cannot escape the deck folder.
- Download a colliding server row under a unique name and count it, instead of
  skipping it without a trace.
- Hash the whole deck instead of the card hash: SHA-1 over the native deck
  string covers name, printings, banner, tokens and sideboard plans. The client
  and the server hash the exact bytes they exchange, so both agree.

Adds deck_content_hash_test for the client/server hashing invariant and for the
name-only change the card hash cannot see.
2026-11-01 22:23:25 +01:00
Lukas Brübach
ad0da98a86 [DeckSync] Pass the sync summary through the signal and tidy the manager API
- Emit SyncSummary from syncFinished() instead of four positional ints, and
  build it from a single currentSummary() helper, so the counts cannot drift
  between the status message and the signal.
- Use a designated initializer for LocalFile, like the other records.
- Drop setClient() and setColorIdentityProvider(): both fields are already
  constructor parameters and the setters had no callers. setProfile() and
  setDeckPath() stay, since the tab re-reads them before every run.
- Fix the include paths in tab_deck_storage.h and the narrowing conversion of
  the tree item id, so the branch builds again.
2026-11-01 22:23:25 +01:00
BruebachL
0757d3d867 [DeckSync] Use designated initializer for ServerFile per review 2026-11-01 22:23:25 +01:00
BruebachL
8a541531da [DeckSync] Prefer ctor params for set-once client/provider per review 2026-11-01 22:23:25 +01:00
BruebachL
e1a9f7766d [DeckSync] Move SyncSummary into DeckSyncManager per review 2026-11-01 22:23:25 +01:00
Lukas Brübach
ad1cb8f133 Fix ZeldaZach review for PR 7493: match uploads by sidecar remoteId/guid, validate server paths 2026-11-01 22:23:25 +01:00
Lukas Brübach
e63b72fe11 [Client] Manual deck collection sync with Sync Now action 2026-11-01 22:23:25 +01:00
Lukas Brübach
f661468069 Fix ZeldaZach review for PR 7492: preserve printing in DeckDiff::merge, atomic sidecar save with QSaveFile 2026-11-01 22:11:40 +01:00
Lukas Brübach
be072ffd68 [Client] DeckSyncProfile + sidecar + DeckDiff with tests 2026-11-01 22:11:40 +01:00