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:
2026-07-27 20:44:30 -04:00
parent cacd48cb0f
commit f2d9f3ad07
10 changed files with 608 additions and 41 deletions
+11
View File
@@ -31,6 +31,15 @@ struct WelcomeRow: Identifiable, Equatable {
/// the cached string rather than to a board this window must never open).
let displayName: String
/// The board's cached `icon`/`iconColor` (02-architecture.md § Per-board app state: "The row's
/// title and icon are registry-cached too with live write-through"). `nil` reads as "draw the
/// board-default glyph" the same lenient fallback the board window's own icon field gets, and
/// exactly what an unstamped or override-free record means. The row never resolves these itself;
/// that is the renderer's job (`ItemSymbol`, `Palette`), so the same record decodes into one
/// answer for both the welcome row and File Open Recent.
let icon: String?
let iconColor: String?
/// Where the board is **now**, or `nil` when its bookmark no longer resolves. The single source
/// of the row's availability: Open and Reveal need a URL, and an orphan has none.
let url: URL?
@@ -131,6 +140,8 @@ struct WelcomeRow: Identifiable, Equatable {
displayName: record.displayName.isEmpty
? URL(fileURLWithPath: record.lastKnownPath).deletingPathExtension().lastPathComponent
: record.displayName,
icon: record.icon,
iconColor: record.iconColor,
url: recent.url,
location: location(of: recent.url?.path ?? record.lastKnownPath),
laneCount: record.laneCount,