Skip to content

Add setting to sync clipboard history across Macs via iCloud - #1

Open
chamika wants to merge 1 commit into
mainfrom
add-icloud-history-sync-setting
Open

Add setting to sync clipboard history across Macs via iCloud#1
chamika wants to merge 1 commit into
mainfrom
add-icloud-history-sync-setting

Conversation

@chamika

@chamika chamika commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a Data → iCloud settings toggle that keeps clipboard history in sync on every Mac signed in to the same Apple Account, backed by a CloudKit private database.

  • CloudSyncManager owns the preference, checks CKAccountStatus, and tracks whether the running store is actually CloudKit-backed.
  • SwiftData cannot move a store between local and CloudKit at runtime, so the preference is read once while building the ModelContainer. Settings surfaces this and offers a Relaunch button rather than pretending the change is live.
  • If the CloudKit store fails to open (missing entitlement, unusable account), the app falls back to the local store instead of trapping, and Settings explains why sync is off.
  • DataSettingsView moved out of SettingsView.swift into its own file, matching the other settings views.

Sync is gated off in this build

Apple does not grant the iCloud capability to free personal development teams — Xcode refuses to issue a provisioning profile for it at all. So CloudSyncManager.isSupported is false, the entitlements file ships unreferenced, and the toggle is disabled with an explanation. The re-enabling steps (flip the flag, restore CODE_SIGN_ENTITLEMENTS + APS_ENVIRONMENT, add the capability in Xcode) are documented on the flag itself. project.pbxproj is unchanged by this PR.

Note on the schema change

#Unique<ClipboardItem>([\.contentHash]) is removed. CloudKit-backed stores reject unique constraints, and the model has to stay CloudKit-compatible regardless of the toggle since both modes share one schema — so this had to be unconditional. ClipboardMonitor now collapses duplicate hashes on lookup (keeping the newest, preserving a pin if any duplicate had one), which is equivalent for local-only use and additionally covers the same content being copied on two Macs.

Removing a uniqueness constraint is a lightweight Core Data migration, so existing local histories should open fine — but that is the one thing not verified against a real populated store.

Test plan

  • Signed Debug build succeeds, no warnings
  • Signed Release build succeeds, no warnings
  • VoltPasteTests pass
  • Signed binary entitlements verified: app-sandbox and files.user-selected.read-only intact, no iCloud keys, no stray .entitlements copied into the bundle
  • End-to-end sync between two Macs — not possible until signed by a paid team

🤖 Generated with Claude Code

Adds a Data settings toggle that keeps clipboard history in sync on every
Mac signed in to the same Apple Account, backed by a CloudKit private
database.

CloudSyncManager owns the preference and reports whether the running store
is actually CloudKit-backed. SwiftData cannot move a store between local
and CloudKit at runtime, so the preference is read once while building the
ModelContainer and Settings offers a relaunch when it changes. If the
CloudKit store fails to open, the app falls back to the local store instead
of trapping, and Settings explains why sync is off.

Removes the #Unique constraint on contentHash: CloudKit-backed stores
reject unique constraints, and the model has to stay CloudKit-compatible
regardless of the toggle since both modes share one schema. ClipboardMonitor
collapses duplicate hashes instead, which also covers the same content being
copied on two Macs.

Sync is gated off by default via CloudSyncManager.isSupported. Apple does
not grant the iCloud capability to free personal development teams, so the
entitlements file ships unreferenced and the toggle is disabled until the
app is signed by a paid team. Re-enabling steps are documented on the flag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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