122 lines
6.0 KiB
Markdown
122 lines
6.0 KiB
Markdown
# Phase 5: Blazor Hybrid Host + Theme + Localization
|
|
|
|
**Status:** ⬜ Not Started
|
|
**Parent plan:** [PLAN.md](./PLAN.md)
|
|
**Domain:** frontend
|
|
**Implementer:** Opus + frontend-design skill
|
|
|
|
## Objective
|
|
|
|
Create the WPF + BlazorWebView host that loads `Marathon.UI` (Razor Class Library),
|
|
establish the design system / theme using MudBlazor, set up bilingual (RU/EN)
|
|
localization end-to-end, and wire up DI to compose Application + Infrastructure layers.
|
|
|
|
## Tasks
|
|
|
|
- [ ] In `src/Marathon.Hosts.WpfBlazor/Marathon.Hosts.WpfBlazor.csproj`:
|
|
- Set `<UseWPF>true</UseWPF>`, `<UseWindowsForms>false</UseWindowsForms>`
|
|
- SDK: `Microsoft.NET.Sdk.Razor` (so Razor + WPF interop works)
|
|
- Add packages:
|
|
- `Microsoft.AspNetCore.Components.WebView.Wpf`
|
|
- `MudBlazor`
|
|
- `Microsoft.Extensions.Hosting`
|
|
- `Serilog.Extensions.Hosting`
|
|
- `Serilog.Sinks.File`
|
|
- `Serilog.Sinks.Console`
|
|
- [ ] In `src/Marathon.UI/Marathon.UI.csproj`:
|
|
- SDK: `Microsoft.NET.Sdk.Razor`
|
|
- `<TargetFramework>net8.0</TargetFramework>` with WebView for Razor Components
|
|
- Add `MudBlazor` (so components in this RCL can use MudBlazor)
|
|
- [ ] Create `Marathon.UI/_Imports.razor` with namespace and component imports
|
|
(Microsoft.AspNetCore.Components.*, MudBlazor, project namespaces).
|
|
- [ ] Create `Marathon.UI/wwwroot/index.html` (Blazor host HTML for the WebView).
|
|
- [ ] Create `Marathon.UI/MainLayout.razor` with MudBlazor `MudLayout` + `MudAppBar` +
|
|
`MudDrawer` navigation. Include locale switcher (RU/EN) in the AppBar.
|
|
- [ ] Create `Marathon.UI/Pages/Home.razor` placeholder dashboard.
|
|
- [ ] Create `Marathon.UI/Pages/Settings.razor` — bound to all `appsettings.json`
|
|
options (ScrapingOptions, WorkerOptions, StorageOptions, AnomalyOptions,
|
|
LocalizationOptions). Live save via `IOptionsMonitor` + writing back to
|
|
`appsettings.Local.json`.
|
|
- [ ] Establish theme tokens in `Marathon.UI/Theme/MarathonTheme.cs` — distinctive
|
|
palette per frontend-design guidance, NOT generic AI-default. Include:
|
|
- Primary, secondary, accent
|
|
- Surface tones for light + dark mode
|
|
- Typography stack (RU-friendly font for Cyrillic — e.g., Inter or Manrope which
|
|
have full Cyrillic coverage)
|
|
- Spacing scale, radius scale, shadow scale as CSS variables in a `app.css`
|
|
- [ ] Wire MudBlazor theme via `MudThemeProvider` in `MainLayout.razor`.
|
|
- [ ] Localization:
|
|
- Add `Microsoft.Extensions.Localization` to `Marathon.UI`
|
|
- Create `Marathon.UI/Resources/SharedResource.cs` (marker class for `IStringLocalizer`)
|
|
- Add `Marathon.UI/Resources/SharedResource.ru.resx` and `SharedResource.en.resx`
|
|
with all UI strings used in this phase + placeholders for later phases
|
|
- Configure supported cultures in host: `ru-RU`, `en-US`
|
|
- Locale switcher persists choice to `appsettings.Local.json` and reloads UI
|
|
- [ ] In `src/Marathon.Hosts.WpfBlazor/MainWindow.xaml`:
|
|
- Single `BlazorWebView` filling the window
|
|
- `HostPage="wwwroot/index.html"`
|
|
- `RootComponents` add `<RootComponent Selector="#app" ComponentType="{x:Type ui:MainLayout}" />`
|
|
- [ ] In `src/Marathon.Hosts.WpfBlazor/App.xaml.cs`:
|
|
- Build `IHost` via `Host.CreateApplicationBuilder()`
|
|
- Call `services.AddMarathonInfrastructure(config)`
|
|
- Call `services.AddMarathonApplication(config)`
|
|
- Call `services.AddWpfBlazorWebView()`
|
|
- Add MudBlazor: `services.AddMudServices()`
|
|
- Configure Serilog (rolling file at `./logs/marathon-.log`, console)
|
|
- Start the host on `OnStartup`, stop on `OnExit`
|
|
- [ ] Add `appsettings.json` to `Marathon.Hosts.WpfBlazor/` (move from Phase 3 if
|
|
placed there) with all sections. Add `appsettings.Development.json` template.
|
|
- [ ] Tests in `Marathon.UI.Tests` (using bUnit):
|
|
- Test: `MainLayout` renders without errors
|
|
- Test: locale switcher changes culture
|
|
- Test: theme tokens are applied (CSS variables present in DOM)
|
|
|
|
## Files to Modify/Create
|
|
|
|
- `src/Marathon.UI/_Imports.razor`
|
|
- `src/Marathon.UI/MainLayout.razor`
|
|
- `src/Marathon.UI/Pages/Home.razor`, `Pages/Settings.razor`
|
|
- `src/Marathon.UI/Theme/MarathonTheme.cs`, `Theme/app.css`
|
|
- `src/Marathon.UI/wwwroot/index.html`
|
|
- `src/Marathon.UI/Resources/SharedResource.{cs,ru.resx,en.resx}`
|
|
- `src/Marathon.UI/Components/LocaleSwitcher.razor`
|
|
- `src/Marathon.Hosts.WpfBlazor/App.xaml`, `App.xaml.cs`
|
|
- `src/Marathon.Hosts.WpfBlazor/MainWindow.xaml`, `MainWindow.xaml.cs`
|
|
- `src/Marathon.Hosts.WpfBlazor/appsettings.json`, `appsettings.Development.json`
|
|
- `src/Marathon.Hosts.WpfBlazor/Properties/AssemblyInfo.cs`
|
|
- `tests/Marathon.UI.Tests/MainLayoutTests.cs`, `LocaleSwitcherTests.cs`
|
|
|
|
## Acceptance Criteria
|
|
|
|
- Host project compiles (Big Bang smoke check).
|
|
- `Marathon.UI` is a clean RCL — usable from any host (verifies portability).
|
|
- Theme is distinct, not generic — implementer should follow `frontend-design` skill
|
|
guidance for typography, color, motion, spatial composition.
|
|
- Locale switcher works (toggles between RU and EN strings on the same page).
|
|
- Settings page surfaces every configurable parameter from `appsettings.json`.
|
|
|
|
## Notes
|
|
|
|
- This phase is parallelizable with Phases 2 and 3 (only depends on Phase 1 Domain,
|
|
but the orchestrator can run all three after Phase 1 completes).
|
|
- The frontend-design skill content is provided to the agent in `FRONTEND_DESIGN_SKILL`
|
|
context block. Follow it precisely.
|
|
- Use Cyrillic-friendly fonts (Inter, Manrope, IBM Plex Sans, JetBrains Mono).
|
|
- For BlazorWebView in WPF, the project SDK MUST be `Microsoft.NET.Sdk.Razor` and
|
|
the OutputType set to `WinExe` with WPF enabled.
|
|
|
|
## Review Checklist
|
|
|
|
- [ ] Compiles
|
|
- [ ] `Marathon.UI` references no host-specific code (BlazorWebView, WPF)
|
|
- [ ] Theme not generic — distinctive palette + typography
|
|
- [ ] All `appsettings.json` keys reachable via the Settings page
|
|
- [ ] RU + EN both renderable (placeholder strings ok for later phases)
|
|
- [ ] Accessibility: keyboard navigation in nav drawer, focus indicators
|
|
|
|
## Handoff to Next Phase
|
|
|
|
<!-- Filled by Phase 5 implementer. Critical: document the theme tokens, component
|
|
layout patterns, and the IStringLocalizer key naming convention so Phase 6
|
|
remains consistent. -->
|