Part of EPIC #193. Depends on #198, #200.
Description
Replace the single WindowGroup in RelayApp.body with:
Window("Welcome to Relay", id: "welcome") { WelcomeSceneRoot(store: scopedStore) } — singleton scene
WindowGroup("Project", for: ProjectID.self) { $projectID in ProjectSceneRoot(projectID: projectID, store: scopedStore) } — data-driven
Each scene receives a scoped store: on appear, dispatch AppFeature.Action.windowDidAppear(windowID:) which adds a new WindowFeature.State to AppFeature.State.windows; on disappear, dispatch windowDidClose(windowID:) to remove it. The global AppFeature store continues to exist; only the per-window slice changes.
Acceptance Criteria
Module / Layer
Relay / RelayApp (scene composition)
Complexity
Large
Part of EPIC #193. Depends on #198, #200.
Description
Replace the single
WindowGroupinRelayApp.bodywith:Window("Welcome to Relay", id: "welcome") { WelcomeSceneRoot(store: scopedStore) }— singleton sceneWindowGroup("Project", for: ProjectID.self) { $projectID in ProjectSceneRoot(projectID: projectID, store: scopedStore) }— data-drivenEach scene receives a scoped store: on appear, dispatch
AppFeature.Action.windowDidAppear(windowID:)which adds a newWindowFeature.StatetoAppFeature.State.windows; on disappear, dispatchwindowDidClose(windowID:)to remove it. The globalAppFeaturestore continues to exist; only the per-window slice changes.Acceptance Criteria
File → New Welcomeactivates the existing one, never creates a duplicateopenWindow(value: projectID)on an already-openprojectIDactivates the existing window rather than creating a duplicate (verified via manual test + unit test)Cmd+Q+ relaunch opens all previously open project windowsModule / Layer
Relay / RelayApp (scene composition)
Complexity
Large