Merge pull request 'docs(android): M12 phase 1 as landed' (#113) from docs/android-theming-nav-phase-1 into edge
Reviewed-on: #113
This commit is contained in:
@@ -1042,7 +1042,10 @@ push, and Play (M6–M8) follow the designed app.
|
||||
appearance store) carries a hard rule: it must change nothing on screen. **Phase 0 landed
|
||||
2026-08-08** (Android-app#33 / docs#112): `SiteAppearance` now holds the brand, the resolved
|
||||
theme tokens and the parsed `nav_public`, refreshed on resume, with nothing yet reading the last
|
||||
two — see THEMING_AND_NAV.md "Phase 0 as landed".
|
||||
two — see THEMING_AND_NAV.md "Phase 0 as landed". **Phase 1 landed 2026-08-08**
|
||||
(Android-app#34 / docs#113): the fifteen color tokens now resolve into a `ShardPalette` that
|
||||
feeds both the Material scheme and a `LocalShardPalette`, and the no-op invariant is a test —
|
||||
the shipped palette reproduces the pre-M12 `ColorScheme` role for role.
|
||||
|
||||
### Deferred (not a milestone)
|
||||
|
||||
|
||||
@@ -484,7 +484,7 @@ PR against `main`.
|
||||
| # | Phase | Ships |
|
||||
|---|---|---|
|
||||
| **0** ✅ | **Contract & appearance store** | `SettingsDto` gains `theme` and `nav_public`; `SiteAppearance` replaces the bare `BrandDto` in `AppViewModel`; second-stage JSON parse; resume refresh (§5.5). **No visual change** — this phase must be invisible |
|
||||
| **1** | **Colors** | `ShardPalette` + `LocalShardPalette`; all direct `Color.kt` imports migrated; `RunicGatewayTheme(appearance)`; AC-1 + AC-2 tests |
|
||||
| **1** ✅ | **Colors** | `ShardPalette` + `LocalShardPalette`; all direct `Color.kt` imports migrated; `RunicGatewayTheme(appearance)`; AC-1 + AC-2 tests |
|
||||
| **2** | **Radii & shadow** | Ratio-scaled `Shapes` (§5.2), elevation map (§5.4) |
|
||||
| **3** | **Fonts** | Seven bundled families + licenses; stack → `FontFamily` resolution; `Type.kt` takes its three families from the resolved theme. APK size recorded |
|
||||
| **4** | **Brand assets** | Logo in the drawer header and top bar, hero on Home (§5.6). Coil + `LocalAssetResolver` already exist; renders nothing when unset |
|
||||
@@ -537,6 +537,55 @@ proven not to have moved anything.
|
||||
concrete classes with `Context`/prefs dependencies, and all of the phase's
|
||||
logic is in the two pure modules above.
|
||||
|
||||
### Phase 1 as landed
|
||||
|
||||
- **`ColorScheme` does not implement `equals`.** AC-1 asks for "the full
|
||||
`ColorScheme` equality, not a spot check", and material3 1.3.0 simply has no
|
||||
`equals`/`hashCode` on it (checked against the artifact, not assumed). The
|
||||
proof is therefore a **field-by-field compare by reflection** over every
|
||||
`Color`-valued getter — 36 roles in 1.3.0 — rather than a hand-written list of
|
||||
the roles the mapping happens to set. A role added to Material, or one the
|
||||
mapping forgets, cannot escape the assertion, and a guard on the role count
|
||||
fails if the reflection ever stops seeing them. The expected value is a
|
||||
**verbatim copy of the pre-M12 `ShardColorScheme`** held in the test, the same
|
||||
device the website used to lock `htmlShell`'s output: the proof is against what
|
||||
the app used to do, not against what the new code does today.
|
||||
- **`ShardPillFg` is derived, not a sixteenth token.** §5.1 lists it among
|
||||
`ThemeComponents.kt`'s themable imports but the token table has fifteen rows
|
||||
and none of them is it — because its value *is* `ShardCta`'s, both
|
||||
`--accent-bright`. It follows `cta` under the same rule §5.1 states for
|
||||
`ShardOnCta`, so the neutral pill's text tracks the CTA fill rather than
|
||||
freezing at today's literal.
|
||||
- **An env-accent instance changes, and that is the intended fix.** §5.1 called
|
||||
the old `RunicGatewayTheme(accent)` "wrong twice over"; correcting it has a
|
||||
visible consequence worth stating plainly. A shard with a `BRAND_ACCENT_COLOR`
|
||||
and **no** `theme_visual` row previously had that color on
|
||||
`primary`/`secondary`/`tertiary` — so its filled CTA buttons carried the accent.
|
||||
It now seeds `--accent` only, which is `secondary`/`tertiary`, and `primary`
|
||||
returns to `--accent-bright`. Links and highlights keep the brand color; filled
|
||||
buttons go back to the light CTA fill the design specifies. An instance that
|
||||
wants its buttons accented sets the accent from Admin → Appearance, which is
|
||||
what the token map is for.
|
||||
- **The palette resolution is pure and the theme is the only composable.**
|
||||
`ShardPalette.resolve(theme, brandAccent)` takes a token map, and
|
||||
`shardColorScheme(palette)` takes a palette — neither knows about
|
||||
`SiteAppearance`, so both AC-1 and AC-2 are plain JVM assertions with no
|
||||
Compose test rule. `RunicGatewayTheme` is the one place the two meet.
|
||||
- **The §5.1 grep came out exactly as predicted.** After the migration,
|
||||
`ui.theme.Shard` imports outside `ui/theme/` are the seven semantic constants
|
||||
in `ThemeComponents.kt` and the two in `ShardComponents.kt` — nothing themable
|
||||
left behind, which was the phase's stated correctness risk.
|
||||
- **`toneColors` became `@Composable`** to read the palette. It is private and
|
||||
called only from `StatusPill`, so this costs nothing; the alternative — passing
|
||||
a palette parameter through the pill's public signature — would have leaked the
|
||||
theme into every call site.
|
||||
- Tests: `ShardPaletteTest` (9 — the shipped no-op, all fifteen tokens landing in
|
||||
the right field, AC-2's one-good-four-bad map, unknown tokens ignored, the
|
||||
brand-accent fallback and the token beating it, a malformed brand accent, and
|
||||
both derived colors) and `ShardColorSchemeTest` (4). **373 unit tests green**,
|
||||
`lintDebug` and `assembleDebug` clean. Not exercised on device — that is AC-5,
|
||||
in phase 8.
|
||||
|
||||
### Phase 7, cancelled
|
||||
|
||||
Reading `nav_admin` / `nav_player` is **not scheduled**. The measurement in §6.4
|
||||
|
||||
Reference in New Issue
Block a user