Remove the App Group wholesale — one sandbox, one bookmark, one flag
Phase 2 of the one-app pivot (DESIGN 12 ▸ App-side state, re-ruled
2026-07-30; reworks 566deab). AppGroup retires; what remains is
AppStateHome — ordinary sandbox Application Support as the one home for
the registry, clipboard staging and template stores, keeping the
unit-test-host redirect (the test host is the app and would sweep real
state). Scalar defaults return to UserDefaults.standard.
BoardRecord's per-edition grant slots and openNow flags collapse to one
bookmark + one isOpenNow; the legacy-key decode and adopt-in-memory
paths go (nothing shipped with group-era records), while the founding
four-keys-required / defaults-for-everything-since decode policy stays —
a bookmarkless record decodes as the born-orphan row rather than
quarantining the list. needsReopen and the pre-anchored re-grant panel
are removed whole: the only state that flow served — a record granted by
a sibling sandbox — is unrepresentable now, and a dead bookmark of our
own was already the orphan case by explicit comment. The
indexOfRecord path fallback dies with it; path is never a key again.
The cross-process freshness stamp (mtime+size re-read) and
BoardEditionPresence with its popover "Also open in…" line retire; the
clipboard prune keeps its atomic .sweeping/ claim-then-delete, reframed
for crash residue and open -n copies rather than sibling editions. The
application-groups entitlement key is gone.
1880 tests in 317 suites green (13 cross-edition tests retired with
their subject).
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -244,13 +244,12 @@ struct WelcomeView: View {
|
||||
|
||||
// MARK: Actions
|
||||
|
||||
/// Opens a row's board — through `AppModel.open(_:)`, which owns the two ways a row can lead to
|
||||
/// one (an available URL, or the re-grant panel a cross-edition row needs first). Welcome closes
|
||||
/// itself on the way in — that is the board window host's job ("Opening a board from welcome
|
||||
/// closes welcome"), not this view's, because the close has to wait for the load to actually
|
||||
/// succeed.
|
||||
/// Opens a row's board. Welcome closes itself on the way in — that is the board window host's
|
||||
/// job ("Opening a board from welcome closes welcome"), not this view's, because the close has to
|
||||
/// wait for the load to actually succeed.
|
||||
private func open(_ row: WelcomeRow) {
|
||||
appModel.open(row)
|
||||
guard let url = row.url else { return }
|
||||
appModel.openBoard(at: url)
|
||||
}
|
||||
|
||||
private func reveal(_ row: WelcomeRow) {
|
||||
@@ -321,9 +320,8 @@ private struct RecentBoardRow: View {
|
||||
}
|
||||
.padding(.vertical, BoardMetrics.em(0.3, bodyPointSize: WelcomeView.pointSize))
|
||||
// Dimmed when the board cannot be reached — the row stays, with Forget, rather than
|
||||
// disappearing (02 § Graceful orphaning). A cross-edition row is *not* dimmed: it opens on one
|
||||
// click like any other, and dimming it would advertise a loss that has not happened.
|
||||
.opacity(row.canOpen ? 1 : 0.55)
|
||||
// disappearing (02 § Graceful orphaning).
|
||||
.opacity(row.isAvailable ? 1 : 0.55)
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
|
||||
@@ -365,14 +363,6 @@ private struct RecentBoardRow: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
case .needsReopen:
|
||||
// Not a warning tone: nothing is wrong and nothing is lost — this board came from the
|
||||
// other edition's list and needs one grant (12-editions.md ▸ Distribution). The words say
|
||||
// what the click will do, since the click is the whole remedy.
|
||||
Label("Open once to grant access", systemImage: "hand.raised")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
case let .failed(message):
|
||||
// The warning tint, and the whole of fail-fast's specifics — this row *is* the failure
|
||||
// surface (02 § Launch and window lifecycle).
|
||||
@@ -395,10 +385,7 @@ private struct RecentBoardRow: View {
|
||||
/// turned off and then turns it back on.
|
||||
struct SettingsView: View {
|
||||
|
||||
/// `store:` named explicitly, and it has to be: the key lives in the group's shared suite
|
||||
/// (`AppPreferences`), and `@AppStorage`'s default domain is `.standard` — a different one. A
|
||||
/// toggle bound to the wrong domain would write a preference the launch flow never reads.
|
||||
@AppStorage(AppPreferences.restoreOpenBoardsAtLaunchKey, store: AppGroup.defaults)
|
||||
@AppStorage(AppPreferences.restoreOpenBoardsAtLaunchKey)
|
||||
private var restoreOpenBoardsAtLaunch = true
|
||||
|
||||
var body: some View {
|
||||
|
||||
Reference in New Issue
Block a user