Give the registry live display-state write-through and record-before-load
BoardRecord carries icon/iconColor; recordOpen/recordClose stamp them with the display name, and a displayStateDelegate on the store (wired in BoardWindowHost beside onFrameChanged) syncs all three through BoardRegistry.syncDisplayState on every successful reload — welcome rows now wear the board's own icon and follow in-app renames live. recordOpen now runs before the load with the folder name as a brand-new record's provisional display name, so a first open that fails fail-fast still lands in recents carrying the failure row-level (02's rule); an existing record's cached name survives a failing retry, and the welcome fallback list remains only for failures naming no record at all. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -229,6 +229,22 @@ public final class BoardStore {
|
||||
@ObservationIgnored
|
||||
public var rootChangeDelegate: (@MainActor () -> Void)?
|
||||
|
||||
/// The registry's live write-through for this board's title, icon, and iconColor
|
||||
/// (02-architecture.md § Per-board app state, "these three refresh whenever an open board's
|
||||
/// reload changes them"). Injected the same way `rootChangeDelegate` is, and for the same
|
||||
/// reason: the write-through needs this board's **registry record id**, which this store does
|
||||
/// not own — `BoardWindowHost.configureWindow` wires it once a session's recordID exists,
|
||||
/// mirroring how it wires `windowController.onFrameChanged` right beside it.
|
||||
///
|
||||
/// Called on **every** successful reload, whether or not the board-level display state
|
||||
/// actually changed. The "did it change" comparison is against the registry's *cached*
|
||||
/// record, not against this store's own previous snapshot — the registry is the only side
|
||||
/// that knows the cached value, so `BoardRegistry.syncDisplayState` is what turns a call that
|
||||
/// changed nothing into a no-op. `nil` (no watcher-backed session, a storeless test) simply
|
||||
/// means nothing is listening, exactly like `rootChangeDelegate`'s `nil`.
|
||||
@ObservationIgnored
|
||||
public var displayStateDelegate: (@MainActor () -> Void)?
|
||||
|
||||
// MARK: Reload machinery
|
||||
|
||||
/// Monotonic id of the most recently *started* reload — and therefore also the number of tree
|
||||
@@ -452,6 +468,12 @@ public final class BoardStore {
|
||||
// this one did not.
|
||||
reloadFailure = nil
|
||||
clearLockIfDisproved(by: origin)
|
||||
// The registry write-through, for the same "not board structure" reason the lock
|
||||
// clearing sits out here: whether this board's row needs a new title, icon, or
|
||||
// iconColor is the registry's question to answer (`syncDisplayState`'s own no-op
|
||||
// guard), not a decision this store makes by comparing against its own prior
|
||||
// snapshot.
|
||||
displayStateDelegate?()
|
||||
|
||||
case let .failure(error):
|
||||
// `snapshot`, `loadWarnings` and the transient state are untouched: a failed reload
|
||||
|
||||
Reference in New Issue
Block a user