Compare commits

..

18 commits

Author SHA1 Message Date
Lukas Brübach
87635bd974 [Client+Server] Deck version history with restore 2026-11-01 22:16:27 +01:00
Lukas Brübach
ad37bee0a3 [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-01 22:16:06 +01:00
Lukas Brübach
1433af321d Fix ZeldaZach review for PR 7496: deck path in ctor, server-time baseline, single-query sync check 2026-11-01 22:15:54 +01:00
Lukas Brübach
477605d1e0 [Client+Server] Auto deck sync with change polling 2026-11-01 22:15:54 +01:00
Lukas Brübach
829d378640 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-01 22:15:37 +01:00
Lukas Brübach
0f413b1466 Fix ZeldaZach review for PR 7495: three-way baseHash check before conflict 2026-11-01 22:15:37 +01:00
Lukas Brübach
339d712308 [Client] Sync conflict dialog, onboarding and conflict default 2026-11-01 22:15:37 +01:00
Lukas Brübach
b0f5cb4c42 [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:15:23 +01:00
Lukas Brübach
f1f92880fa Fix ZeldaZach review for PR 7494: match by remoteId/guid before remote-delete, only tombstone when file truly missing 2026-11-01 22:15:17 +01:00
Lukas Brübach
34844c52b0 [Server+Client] Tombstone deck deletes with purge and base snapshots 2026-11-01 22:15:17 +01:00
Lukas Brübach
8d0468402e [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:14:18 +01:00
Lukas Brübach
4fd03576e5 [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:13:43 +01:00
BruebachL
f9cbeb2f21 [Format] Fix include order in tab_deck_storage.h 2026-11-01 22:13:43 +01:00
BruebachL
f22256886f [DeckSync] Use designated initializer for ServerFile per review 2026-11-01 22:13:43 +01:00
BruebachL
0cd238d296 [DeckSync] Prefer ctor params for set-once client/provider per review 2026-11-01 22:13:43 +01:00
BruebachL
d4ce4759c5 [DeckSync] Move SyncSummary into DeckSyncManager per review 2026-11-01 22:13:43 +01:00
Lukas Brübach
0ba9bd531b Fix ZeldaZach review for PR 7493: match uploads by sidecar remoteId/guid, validate server paths 2026-11-01 22:13:43 +01:00
Lukas Brübach
3bed5ae5f5 [Client] Manual deck collection sync with Sync Now action 2026-11-01 22:13:43 +01:00

View file

@ -1,5 +1,6 @@
#include "deck_sync_manager.h"
#include "../deck_loader/deck_file_format.h"
#include "../deck_loader/deck_loader.h"
#include "deck_sync_sidecar.h"
@ -15,7 +16,6 @@
#include <QUuid>
#include <QtGlobal>
#include <libcockatrice/deck_list/deck_diff.h>
#include <libcockatrice/deck_list/deck_file_format.h>
#include <libcockatrice/deck_list/deck_list.h>
#include <libcockatrice/network/client/abstract/abstract_client.h>
#include <libcockatrice/protocol/pb/command_deck_del.pb.h>