The board window says its name once — the scene declares the title SwiftUI keeps hiding
`HostedWindowController.hideTitle()` was the same shape of buga429a7efixed for `titlebarAppearsTransparent`: an out-of-band `NSWindow.titleVisibility` write, correct the instant it ran, undone by SwiftUI's own next pass over the window's configuration — a tree that declares nothing resolves `.visible`, and SwiftUI writes that back over the out-of-band `.hidden` on the very next `@State`-driven re-render this board window's own liveness causes. The system title reappeared beside the board-popover widget, "occasionally" — whenever that next re-render happened to land. Confirmed with an A/B harness (no interactive display in this session, so not reproduced on screen; mechanism established in code, per the card's own fallback): a bare out-of-band write held indefinitely against resize and key-status changes alone, but reverted on the very next `@State`-driven render and stayed reverted — reasserting from `body`'s own construction or from `.onChange` both lost the same race, since SwiftUI's resync runs later than either. The only thing that held was declaring the posture in the tree itself, mirroring `.toolbarBackgroundVisibility`'s role ina429a7e. `KanbanApp`'s board `WindowGroup` now declares `.windowToolbarStyle(.unified(showsTitle: false))`. It is a scene modifier, not a per-window one, so — unlike `.toolbarBackgroundVisibility` — it cannot wait for a board's load to finish before taking effect; every board window it creates keeps the system title hidden from its very first frame. `boardLoadingTitlebarAccessory` covers the gap that opens before the loading window has a store to build the real widget from: a small, non-interactive, plain-text stand-in carrying the registry record's cached name, installed the moment the window attaches and swapped by identity for the real widget the moment the store loads — so the loading window's chrome still carries a name throughout, per 02-architecture.md. `hideTitle()`'s own write stays; it is no longer what keeps the title hidden, but it is still correct for the one render turn before the scene's own re-assertion catches up. Confined to `BoardWindowHost.swift`, `BoardInfoPopover.swift` and `KanbanApp.swift` — `WindowAccessor.swift`'s shared `hideTitle()`/`titleVisibility` machinery is untouched, since a concurrent fix is addressing the card window's version of this same bug through that file. New regression tests (`BoardLoadingTitlebarStandInTests`, `KanbanTests/BoardLoadingTests.swift`) pin the stand-in's layout and the identity-based swap. Full suite green (3219 tests) except the pre-existing, documented environment-sensitive `PointerLatencyTests`, confirmed unaffected by rerunning them in isolation. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -143,6 +143,32 @@ struct KanbanApp: App {
|
||||
.restorationBehavior(.disabled)
|
||||
.defaultLaunchBehavior(.suppressed)
|
||||
.commands { menuCommands }
|
||||
// **The system title is not this scene's to show, ever** — a board window says its own
|
||||
// name through the titlebar widget (`BoardInfoWidget`/`boardLoadingTitlebarAccessory`,
|
||||
// `BoardWindowHost`), never through AppKit's own title rendering, so the two can no longer
|
||||
// draw beside each other (the duplicate-name bug this scene modifier fixes).
|
||||
//
|
||||
// Declared here, at the *scene*, rather than only as `HostedWindowController.hideTitle()`'s
|
||||
// out-of-band `NSWindow.titleVisibility` write, for a429a7e's own reason restated for a
|
||||
// second AppKit knob: `titleVisibility` on a SwiftUI scene window is SwiftUI's to hold, and
|
||||
// it writes the tree's resolved value back every time it re-applies a window's
|
||||
// configuration — a tree that says nothing resolves `.visible`, so a later pass (any body
|
||||
// re-evaluation this window's board causes — a snapshot reload, a banner, a search-field
|
||||
// focus change) put the system title back beside the widget some time after the window
|
||||
// opened correct. Verified as an A/B harness (not the live app; documented honestly rather
|
||||
// than reproduced on screen — see the card journal): an out-of-band `.hidden` write reverts
|
||||
// to `.visible` on the very next `@State`-driven render with nothing declared here, and
|
||||
// holds through the same pressure (resize, key-status changes, repeated renders) once this
|
||||
// line is added.
|
||||
//
|
||||
// **Unconditional**, unlike `toolbarBackgroundVisibility` in `BoardWindowHost`: this is a
|
||||
// *scene* modifier, so it cannot read one window's live phase the way a `View` modifier
|
||||
// bound to `store.snapshot` can — every board window it creates gets the same posture,
|
||||
// always. That is also the right posture: this app never wants the system to draw a board
|
||||
// window's title, not even for the moment before the widget exists, which is why
|
||||
// `configureLoadingWindow` now gives the loading window a plain-text stand-in widget instead
|
||||
// of leaning on the system title for that moment (`BoardWindowHost`).
|
||||
.windowToolbarStyle(.unified(showsTitle: false))
|
||||
|
||||
WindowGroup(id: WindowID.card, for: CardWindowRef.self) { $ref in
|
||||
if let ref {
|
||||
|
||||
Reference in New Issue
Block a user