Commit graph

10 commits

Author SHA1 Message Date
Lukas Brübach
6d67b76fa3 [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-05 12:51:12 +01:00
Lukas Brübach
04456b7ad3 [Client+Server] Auto deck sync with change polling 2026-11-05 12:51:12 +01:00
Lukas Brübach
ae4d40e1eb 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-05 12:51:09 +01:00
Lukas Brübach
ed3f21a155 [Client] Sync conflict dialog, onboarding and conflict default 2026-11-05 12:51:09 +01:00
Lukas Brübach
4e5c4403b2 [Server+Client] Tombstone deck deletes with purge and base snapshots 2026-11-05 12:51:05 +01:00
Lukas Brübach
34e22df5ba [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-05 12:51:01 +01:00
Lukas Brübach
aa0ab333f6 [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-05 12:51:01 +01:00
BruebachL
5b51fc8810 [DeckSync] Prefer ctor params for set-once client/provider per review 2026-11-05 12:51:01 +01:00
BruebachL
aa5cadd4eb [DeckSync] Move SyncSummary into DeckSyncManager per review 2026-11-05 12:51:01 +01:00
Lukas Brübach
9c5ddc889c [Client] Manual deck collection sync with Sync Now action 2026-11-05 12:51:01 +01:00