From b6770d394c7df94a219281c467cea6556586953d Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Sat, 23 May 2026 20:04:04 +0200 Subject: [PATCH] =?UTF-8?q?feat(ui):=20app-shell=20core=20=E2=80=94=20sing?= =?UTF-8?q?le-route=20dispatcher,=20route=20collapse,=20nav=E2=86=92state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collapse the game UI to one route (`/`): a screen dispatcher renders login/lobby/lobby-create/game from `appScreen`/`activeView` state instead of URL routes. Move screen components to lib/screens & lib/game; the game shell reads the game id from `appScreen.gameId` and re-inits per-game stores via an $effect; in-game views render from `activeView`. Flip ~23 goto/href nav sites to store mutations; drop the `?sidebar=` URL coupling. Auth gate is now state-based. WIP: browser-history (Back→lobby), restore-validation, the return-to-lobby button, push deep-links, and the test migration are follow-ups on this branch. Co-Authored-By: Claude Opus 4.7 (1M context) --- ui/frontend/src/lib/active-view/battle.svelte | 7 +- .../lib/active-view/designer-science.svelte | 13 +- ui/frontend/src/lib/active-view/mail.svelte | 4 +- ui/frontend/src/lib/active-view/map.svelte | 55 ++++-- ui/frontend/src/lib/active-view/report.svelte | 5 +- .../lib/active-view/report/report-toc.svelte | 17 +- .../active-view/report/section-battles.svelte | 28 ++- .../src/lib/active-view/table-sciences.svelte | 16 +- .../game/game-shell.svelte} | 186 +++++++++++------- ui/frontend/src/lib/header/header.svelte | 5 +- ui/frontend/src/lib/header/view-menu.svelte | 32 +-- .../screens/lobby-create-screen.svelte} | 15 +- .../screens/lobby-screen.svelte} | 19 +- .../screens/login-screen.svelte} | 5 +- .../src/lib/sidebar/bottom-tabs.svelte | 48 ++--- .../src/lib/sidebar/calculator-tab.svelte | 4 +- ui/frontend/src/lib/sidebar/sidebar.svelte | 44 +---- ui/frontend/src/routes/+layout.svelte | 23 +-- ui/frontend/src/routes/+page.svelte | 44 +++-- ui/frontend/src/routes/games/[id]/+layout.ts | 8 - ui/frontend/src/routes/games/[id]/+page.ts | 12 -- .../[id]/battle/[[battleId]]/+page.svelte | 16 -- .../science/[[scienceId]]/+page.svelte | 5 - .../src/routes/games/[id]/mail/+page.svelte | 5 - .../src/routes/games/[id]/map/+page.svelte | 5 - .../src/routes/games/[id]/report/+page.svelte | 47 ----- .../games/[id]/table/[entity]/+page.svelte | 6 - ui/frontend/src/routes/lobby/+page.ts | 6 - ui/frontend/src/routes/lobby/create/+page.ts | 2 - ui/frontend/src/routes/login/+page.ts | 6 - 30 files changed, 294 insertions(+), 394 deletions(-) rename ui/frontend/src/{routes/games/[id]/+layout.svelte => lib/game/game-shell.svelte} (77%) rename ui/frontend/src/{routes/lobby/create/+page.svelte => lib/screens/lobby-create-screen.svelte} (94%) rename ui/frontend/src/{routes/lobby/+page.svelte => lib/screens/lobby-screen.svelte} (96%) rename ui/frontend/src/{routes/login/+page.svelte => lib/screens/login-screen.svelte} (98%) delete mode 100644 ui/frontend/src/routes/games/[id]/+layout.ts delete mode 100644 ui/frontend/src/routes/games/[id]/+page.ts delete mode 100644 ui/frontend/src/routes/games/[id]/battle/[[battleId]]/+page.svelte delete mode 100644 ui/frontend/src/routes/games/[id]/designer/science/[[scienceId]]/+page.svelte delete mode 100644 ui/frontend/src/routes/games/[id]/mail/+page.svelte delete mode 100644 ui/frontend/src/routes/games/[id]/map/+page.svelte delete mode 100644 ui/frontend/src/routes/games/[id]/report/+page.svelte delete mode 100644 ui/frontend/src/routes/games/[id]/table/[entity]/+page.svelte delete mode 100644 ui/frontend/src/routes/lobby/+page.ts delete mode 100644 ui/frontend/src/routes/lobby/create/+page.ts delete mode 100644 ui/frontend/src/routes/login/+page.ts diff --git a/ui/frontend/src/lib/active-view/battle.svelte b/ui/frontend/src/lib/active-view/battle.svelte index befaa40..a0eec71 100644 --- a/ui/frontend/src/lib/active-view/battle.svelte +++ b/ui/frontend/src/lib/active-view/battle.svelte @@ -12,9 +12,8 @@ header now — we just hand the routes down as callbacks so the viewer keeps its prop-driven contract. --> diff --git a/ui/frontend/src/lib/active-view/designer-science.svelte b/ui/frontend/src/lib/active-view/designer-science.svelte index dfd3753..e89e9cb 100644 --- a/ui/frontend/src/lib/active-view/designer-science.svelte +++ b/ui/frontend/src/lib/active-view/designer-science.svelte @@ -25,10 +25,8 @@ fractions is a Phase 21 decision documented in `ui/docs/science-designer-ux.md`. -->
- +
diff --git a/ui/frontend/src/lib/active-view/report/report-toc.svelte b/ui/frontend/src/lib/active-view/report/report-toc.svelte index aa7a6df..c8ab49a 100644 --- a/ui/frontend/src/lib/active-view/report/report-toc.svelte +++ b/ui/frontend/src/lib/active-view/report/report-toc.svelte @@ -3,9 +3,10 @@ Phase 23 Report View table of contents. Responsibilities: - "Back to map" button at the top — visible on both desktop sidebar - and mobile sticky toolbar. Navigates via `$app/navigation.goto` so - active-view-host scroll restoration plays through SvelteKit's - history machinery and the layout's `mobileTool` resets naturally. + and mobile sticky toolbar. Switches the active view to the map + through `activeView.select("map")`; the shell's tool gate resets + the `mobileTool` overlay naturally once the map is no longer the + active view. - Desktop / tablet sidebar: a vertical list of anchor links, one per section. The active link gets `aria-current="location"` and a `.active` style. Click scrolls the active-view-host (not the @@ -20,8 +21,7 @@ The active section is computed by the orchestrator `activeSlug` prop. The TOC itself owns no observers. --> diff --git a/ui/frontend/src/lib/active-view/report/section-battles.svelte b/ui/frontend/src/lib/active-view/report/section-battles.svelte index d071c7f..fb0b373 100644 --- a/ui/frontend/src/lib/active-view/report/section-battles.svelte +++ b/ui/frontend/src/lib/active-view/report/section-battles.svelte @@ -1,15 +1,14 @@
{i18n.t("game.report.section.battles.id_label")} - openBattle(b.id)} data-testid="report-battle-row" data-id={b.id} - >{b.id} + >{b.id} {/each} @@ -90,10 +93,15 @@ decision log called out. font-size: 0.7rem; } .uuid { + padding: 0; + border: 0; + background: transparent; + font: inherit; color: var(--color-accent); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; text-decoration: underline; text-underline-offset: 2px; + cursor: pointer; } .uuid:hover { color: var(--color-text); diff --git a/ui/frontend/src/lib/active-view/table-sciences.svelte b/ui/frontend/src/lib/active-view/table-sciences.svelte index 0b7bbf2..fffc86d 100644 --- a/ui/frontend/src/lib/active-view/table-sciences.svelte +++ b/ui/frontend/src/lib/active-view/table-sciences.svelte @@ -11,16 +11,14 @@ The four tech proportions are stored on the wire as fractions in `[0, 1]` and surfaced here as percentages with one decimal so the table matches the designer's input units. -The component sits inside the active-view slot owned by -`routes/games/[id]/+layout.svelte`, so it inherits the per-game +The component sits inside the active-view area owned by +`lib/game/game-shell.svelte`, so it inherits the per-game `OrderDraftStore` and `RenderedReportSource` through context. No -data fetching is performed here — the layout is responsible. +data fetching is performed here — the shell is responsible. -->