mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-08 01:43:07 +00:00
* feat(android): offer web-parity color theme presets in appearance settings Bring the web client's color-theme catalog (Default plus 16 named palettes) to Android as an appearance choice. Each preset carries five seed colors per scheme and derives every other tone with the web client's exact math — per-channel elevation mixes, the WCAG-luminance dark/light call, and tie-up rounding — so a preset renders the same on both clients. A selected preset overrides the dynamic and OLED schemes (OLED renders the preset's dark seeds, like the web layering), while Default keeps Material You and the built-in light/dark/OLED schemes. The picker reuses the expressive choice dialog: every card shows the preset's light/dark canvas split plus its accent strip, and longer catalogs scroll inside the dialog so they stay usable on small screens. Material You switches off with an explanatory note while a preset is active, since presets pin their own palettes. Persistence is one DataStore key over the existing theme prefs, with unknown ids degrading to Default. Strings land in en/ru/zh in matching order; the proper-noun preset names stay untranslated, matching the web locales. Co-Authored-By: Claude Code <noreply@anthropic.com> via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * test(android): pin the HapiTheme scheme resolution order with a matrix The preset > oled > dynamic > static ordering and the OLED-yields-to-dark- seeds rule (preset.palette(dark = darkTheme || oled)) lived inline in the HapiTheme composable where no JVM test could reach them -- reordering the when (a stack-conflict surgery hazard) would pass every gate silently. Extract the order into a pure resolver (resolveThemeSchemeSource returns a descriptor; the composable maps it to schemes, with a local SDK guard lint can see) and pin it with an exhaustive matrix: all 16 named presets x every darkTheme/oled/dynamicColor/sdk combination resolve to the preset palette, DEFAULT+oled beats dynamic color, dynamic color only fires on S+ when enabled, and Nord-under-OLED-with-light-system asserts concrete dark-seed hexes. Verified discriminating by mutation: dropping `|| oled` fails 2 tests, hoisting dynamic above oled fails 1. Co-Authored-By: Claude Code <noreply@anthropic.com> --------- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: HAPI <noreply@hapi.run>