docs(android): build contract for admin theming & navigation parity (M12)
The website merged runtime admin theming, brand assets and nav overrides to main (website#126 / docs#109). The app reads exactly one field of it -- brand.accent -- and renders a hardcoded APP_MENU, so an admin who re-skins the site and restructures the header sees none of it on the phone. Adds docs/android/THEMING_AND_NAV.md as the design of record for M12, and the PLAN.md §9 entry that anchors it. Plan only: no app code, no backend work. Everything consumed is already live on website/main. The points that shaped it: - The app's ui/theme/Color.kt palette is already, value for value, the runic-gateway preset -- M5 was drawn from the same theme.css the preset was later extracted from. So "an untouched instance is unchanged" carries over as a testable ColorScheme equality assertion, not an approximation. - Radii apply as a ratio against that baseline, not as literal dp. The app's Shapes came from the M5 mockup and genuinely differ (medium 12dp vs --radius-card 10px); a literal mapping would restyle the untouched app the day this ships, and copying the app's scale into the server would be a second source of truth. - Fonts are bundled, not downloadable: the Play Store font provider makes a de-Googled device fall back silently. Seven families join the bundled Cinzel. - Nav overrides are keyed by website paths, so the app needs a path -> route table -- the one new cross-repo coupling here. An override for a path the app does not surface in its menu is ignored: a nav override may never introduce navigation. - The gates are untouched. MenuAccess and MenuEntry.feature still run after the merge, so hidden:false cannot un-hide what a role or the shard's visibility config withholds. - Read the resolved theme/brand fields, never the raw theme_visual/brand_assets rows that ride along in the same payload -- re-deriving a palette from them would be a second resolveThemeTokens in Kotlin, guaranteed to drift. Nine phases into a fresh edge in both repos, reaching main as one edge -> main merge, the same shape the website side used. Phase 0 must change nothing on screen. Phase 7 (the authenticated navs) is marked optional: nav_player reaches two app rows and nav_admin two, which is a thin return for a new authenticated fetch and its cache teardown. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TgfKv5cz5pbY3dPeofSE5a
This commit is contained in:
@@ -990,6 +990,55 @@ push, and Play (M6–M8) follow the designed app.
|
||||
Visibility, Spawn Atlas and Cliloc import — alongside the hero/CMS block editor, Discord-bot
|
||||
config, uo-link config and OAuth-provider setup.
|
||||
|
||||
13. **M12 — Admin theming & navigation parity** (post-v1; scoped 2026-08-08). The website merged
|
||||
runtime admin theming, brand assets and nav overrides to `main` (website#126 / docs#109). The app
|
||||
reads exactly one field of it — `brand.accent` — and renders a hardcoded `APP_MENU`, so an admin
|
||||
who re-skins the site and restructures the header sees none of it on the phone. This milestone
|
||||
makes the app a full consumer of that contract.
|
||||
|
||||
**Design of record: [`THEMING_AND_NAV.md`](./THEMING_AND_NAV.md)** — the token map, the phase
|
||||
list and the locked decisions live there rather than here, mirroring how the website side kept
|
||||
[`../website/THEMING_AND_NAV.md`](../website/THEMING_AND_NAV.md) separate from its own plan.
|
||||
|
||||
**No backend work.** Everything consumed is already live on `website/main`:
|
||||
`GET /public/settings` gained `theme` (the full resolved token map) and `nav_public`, its `brand`
|
||||
block now returns *effective* values, and `GET /api/v1/settings/nav` serves the admin/player
|
||||
overrides to any authenticated account.
|
||||
|
||||
The points that shaped the plan, and that a reader of this file should know without opening it:
|
||||
|
||||
- **The app's palette is already the `runic-gateway` preset**, value for value — M5 was drawn
|
||||
from the same `theme.css` the preset was later extracted from. So the website's governing
|
||||
invariant (an untouched instance renders byte-for-byte as before) carries over as a *testable
|
||||
equality assertion* on the resolved `ColorScheme`, not an approximation.
|
||||
- **Radii apply as a ratio, not as literal dp.** The app's `Shapes` came from the M5 mockup and
|
||||
genuinely differ from the web tokens (`medium` 12dp vs `--radius-card` 10px); a literal mapping
|
||||
would restyle the untouched app the day this ships. A ratio against the `runic-gateway`
|
||||
baseline makes an untouched instance a provable no-op while still tracking the admin's intent.
|
||||
- **Fonts are bundled, not downloadable.** Seven families join the already-bundled Cinzel
|
||||
(~1.5–2.5 MB, against a 4.2 MB signed release). Downloadable fonts were rejected: they need the
|
||||
Play Store provider, so a de-Googled device silently falls back.
|
||||
- **Nav overrides are keyed by *website* paths**, so the app needs a path → route table — the one
|
||||
new cross-repo coupling here. Two asymmetries are decided rather than papered over: an override
|
||||
for a path the app does not surface in its menu (champs / guilds / governors / houses, which
|
||||
live behind the Shard hub) is **ignored**, because a nav override may never *introduce*
|
||||
navigation; and the app's own entries with no web counterpart keep their coded order.
|
||||
- **The gates are untouched.** `MenuAccess` and `MenuEntry.feature` still run *after* the merge,
|
||||
so `hidden: false` cannot un-hide what a role or the shard's visibility config withholds — the
|
||||
same boundary the website's §7 draws.
|
||||
- **The authenticated navs are thinner than they look.** `nav_player` reaches two app rows and
|
||||
`nav_admin` two (`/player`, `/account`, `/admin`, `/admin/moderation`); the sidebar's other
|
||||
~18 rows are admin *configuration* the app excludes, and two of the app's four staff entries
|
||||
are aggregates with no single web row. That is why they honor `label` and `hidden` only — and
|
||||
why that phase is scheduled **last and marked optional**, so it can be dropped on its merits
|
||||
once the rest is working.
|
||||
- **Excluded**, in the same class as M10's and M11's exclusions: the admin *configuration* panels
|
||||
themselves. The app does not gain Appearance or Navigation editors; it is a consumer.
|
||||
|
||||
Nine phases into a fresh `edge` in both repos, reaching `main` as one `edge` → `main` merge —
|
||||
the same shape the website side used. Phase 0 (the contract and the appearance store) carries a
|
||||
hard rule: it must change nothing on screen.
|
||||
|
||||
### Deferred (not a milestone)
|
||||
|
||||
- **`/api/mobile` facade migration + app-version floor** — briefly planned as its own milestone
|
||||
|
||||
Reference in New Issue
Block a user