Fix PushAllEntities firing on every app launch
Details
StartSyncForWorkspace unconditionally called PushAllEntities, which
re-uploads every entity in the store as a FullSnapshot to S3. Since
AutoStartSyncAsync calls StartSyncForWorkspace on every app launch,
this caused a full re-upload of all entities (seed data, categories,
accounts, metadata — everything) on every restart, regardless of
whether anything actually changed.
Added a pushAllEntities parameter (default false) so only first-time
setup paths (enable cloud sync, acknowledge recovery kit, after cloud
clean/purge) trigger the full push. Auto-start and manual resume use
the incremental path via SyncOutboundService.PushEvent instead.
Let Ctrl+Tab bubble through RTE for block-level indent
Details
The RTE's Tab handler now checks for Ctrl/Cmd modifier first and skips
handling, allowing the event to bubble up to the parent view for
block-level indent/outdent. Plain Tab and Shift+Tab behavior unchanged.
Fix code block language pill not responding to clicks
Details
Switch the language pill click handler from PointerReleased to
PointerPressed. When the AvaloniaEdit TextEditor has focus, it captures
the pointer on press, preventing PointerReleased from reaching the
pill overlay. PointerPressed always fires on the element under the
cursor regardless of capture state.
Fix phantom cloud sync uploads after wipe + purge
Details
After wiping local data and purging the cloud workspace, stale cursor
state in the local cloud_sync_cursors table caused the sync engine to
re-upload entities that plugins recreate on startup. The server-side
purge cleared S3 batches and API cursors, but the local DuckDB cursor
table was never cleared — so when sync restarted and PushAllEntities()
ran, the engine treated the re-created entities as new changes.
Adds privstack_cloudsync_clear_cursors FFI export that calls the
existing EntityStore::clear_cloud_cursors() method, wires it through
NativeLibrary → ICloudSyncService → CloudSyncService, and calls it
in SeedDataService.PurgeCloudWorkspaceIfConnectedAsync() immediately
after the server-side purge succeeds.
Purge cloud workspace data on local wipe/reseed/reset
Details
When the user wipes data (Wipe, Reseed, or Reset Data on unlock screen),
the local DuckDB cursors are destroyed but the server-side sync_batches
and sync_cursors remain. On next sync startup the device's cursor resets
to 0, causing getPendingChanges to report the device's own old batches
as pending — triggering an infinite download loop of stale data every
poll cycle.
Fix: call the server's /api/cloud/workspace/purge endpoint before wiping
local data. This clears batches, cursors, snapshots, blobs, and S3
objects server-side so the sync engine starts clean.
- SeedDataService: add PurgeCloudWorkspaceIfConnectedAsync() as step 0
in WipeAllPluginDataAsync (covers both Wipe and Reseed paths)
- SetupWizardViewModel: add PurgeCloudWorkspaceAsync() before runtime
shutdown in ConfirmResetData (covers unlock screen Reset Data)
- Both methods are best-effort — cloud purge failure doesn't block
local wipe
Get notified about new releases