Skip to content

refactor(sync-queue): separate change state from sync action in UX #137

Description

@ClaudiaFang

Separate change state (repository tree: M/A/D badges) from sync action (queue: ↑↓↺🗑 glyphs) so the Sync Queue shows what will happen, not what already happened.

Scope

Confined to the source-control layer (src/logic/source-control/* + src/ui/source-control/*). The src/logic/** sync domain (SyncManager/SyncPlanner/SyncExecutor/SyncPlanModal) is not touched.

Changes (7 stages)

  1. SyncAction model — new src/logic/source-control/SyncAction.ts: SyncAction = 'upload'|'download'|'restore'|'delete-remote', resolveAction(kind), requiresChoice(kind), SyncActionItem.
  2. SyncActionQueue — new src/logic/source-control/SyncActionQueue.ts (replaces PushSelectionStore): Map<ChangeId, SyncAction|undefined> with enqueue/dequeue/enqueueMany/dequeueMany/clear/has/getAction/getChangeIds/size/refresh. Action optional on enqueue; ViewModel resolves default at projection.
  3. Queue presentationChangePresentation.ts drops changeOperation/ChangeOperation; adds ActionView/ACTION_ORDER/presentAction (glyph ↑↓↺🗑). ChangeItem.ts renderQueueItem uses .scv-action-glyph (no .scv-badge).
  4. View routingSourceControlView.ts groups the queue by ACTION_ORDER (group labels only when >1 action); runSync routes by item.action (upload→push, download/restore→pull, delete-remote→remote delete); toggleSelect triggers chooser for requires-choice (local-deleted).
  5. Local-deleted chooser — new src/ui/source-control/LocalDeletedActionChooser.ts modal: Restore (CTA) / Delete remote / Cancel; wired in SourceControlItemView.
  6. Callback wiringSourceControlItemView.ts: onDeleteRemoteactionService.deleteRemote, onResolveLocalDeleted→chooser.
  7. Tests — new SyncAction.test.ts + SyncActionQueue.test.ts; deleted PushSelectionStore.test.ts; mechanical rename across all affected tests + e2e.

Verification

  • npx eslint . → 0 errors
  • npm run build → clean (tsc + Obsidian 1.11.0 compat + esbuild)
  • npx vitest run → 64 files / 712 tests pass
  • ./init.sh → green
  • Manual Obsidian verification (desktop + mobile): pending

Out of scope (deferred)

SyncPlanModal (driven by SyncPlan/PushCoordinator/PullCoordinator confirmPlan) still shows state-based plan rows during coordinator execution — fully refactoring it to action-based review would cross the src/logic/** sync-domain boundary.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions