Skip to content

feat: sync prompt on workspace close#135

Merged
careck merged 13 commits into
masterfrom
feat/sync-on-close
Apr 21, 2026
Merged

feat: sync prompt on workspace close#135
careck merged 13 commits into
masterfrom
feat/sync-on-close

Conversation

@careck
Copy link
Copy Markdown
Member

@careck careck commented Apr 20, 2026

Summary

  • Intercept workspace close when unsynchronized changes exist for relay/folder peers
  • Show a dialog prompting to sync, close without syncing, or cancel
  • New global setting "Sync on Close" with three modes: Always sync, Ask before closing (default), Never sync
  • Manual peers are excluded (uses existing has_pending_sync_ops which filters them out)
  • Fix: has_pending_ops_for_any_peer() now applies the same device_id and received_from_peer filters as operations_since(), resolving false positives where the check reported pending work but poll_sync found nothing to send

Changes

  • Rust core: Fix has_pending_ops_for_any_peer to exclude peer-authored and echo ops from count
  • Rust backend: sync_on_close setting in AppSettings, CloseRequested interception via closing_windows set, close_window Tauri command
  • React frontend: SyncOnCloseDialog component, useSyncOnClose hook with cancellation guard, Settings dropdown
  • i18n: All 7 locales (en, de, es, fr, ja, ko, zh)

Test plan

  • Ask mode (default): Close workspace with pending ops → dialog appears with 3 buttons
  • Always mode: Close workspace with pending ops → spinner overlay, auto-sync, auto-close
  • Never mode: Close workspace with pending ops → closes immediately
  • No pending ops: Close workspace after syncing → closes immediately
  • Multiple windows: Closing one workspace does not affect others
  • Cancellation during sync: Escape while spinner showing → window stays open
  • False positive fix: Bob's workspace no longer shows dialog after successful sync

careck added 13 commits April 21, 2026 08:31
window.emit() broadcasts to all windows, causing other workspaces
to receive the close event and potentially close themselves.
Use emit_to() to target only the window being closed.
The global listen() from @tauri-apps/api/event receives events from
all windows. Switch to getCurrentWebviewWindow().listen() which only
receives events targeted at the current window, preventing one
window's close from triggering the handler in another window.
The pending-ops check counted ALL operations after the watermark,
but operations_since() (used by generate_delta) excludes ops authored
by the peer and ops received from the peer (echo prevention). This
caused false positives where the check reported pending work but
poll_sync found nothing to send.

Apply the same device_id and received_from_peer filters to the COUNT
query so the check agrees with the actual sync behavior.
@careck careck merged commit e85dafc into master Apr 21, 2026
@careck careck deleted the feat/sync-on-close branch April 22, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant