The board chooses where it lives — swipe-open settings move it between iCloud and this iPhone

A trailing swipe on a board row opens Board Settings, whose first setting is location: iCloud or Local, with a confirmed move to the other side — destructive-styled only outbound, because leaving iCloud is the direction that sheds protection. The move is setUbiquitous against the real container and a coordinated move under the DEBUG stand-in; evacuation sweeps materialization first and refuses honestly while content is still downloading. The local home is the sandbox Documents folder, published to the Files app, so a local board is still a folder the user owns.

With a second home the iCloud wall softens (user-ruled 2026-08-08): the index always reaches ready, cloud unavailability becomes an inline notice with a retry, creates land locally when there is no account, and LANEWORK_FORCE_NO_ICLOUD makes that state reproducible in tests regardless of the machine's sign-in. Known gap, now user-reachable: backup remains iCloud-only, so local boards sit outside it.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-08-08 10:56:39 -04:00
parent 1d97a2931c
commit 1c16bb4c38
10 changed files with 910 additions and 134 deletions
+4 -3
View File
@@ -47,9 +47,10 @@ struct SettingsTabView: View {
LabeledContent("Backup") {
ProgressView()
}
case .unavailable, .ready:
// `.ready` can appear briefly here too: `backupController` lags one runloop
// turn behind `index.home` resolving (MobileApp's `.task(id:)`).
case .ready:
// `.ready` is both cases now: the run with no iCloud at all, and the runloop turn
// `backupController` lags `index.home` by (MobileApp's `.task(id:)`). Backup is
// still iCloud-only a known gap now that local boards exist.
Label("Backup and restore need iCloud Drive.", systemImage: "icloud.slash")
.foregroundStyle(.secondary)
}