wtclaude b84a973559 fix(theme): let the shard's panel color and pill radius reach Material's defaults (M12 phase 8)
Two defects found on device by phase 8's AC-5 walk, both the same trap phase 2
hit with card elevation: Material takes these values as DEFAULT ARGUMENTS, not
from the theme, so mapping the token is not enough on its own.

1. Every ShardCard drew in Material's grey, not the shard's panel color.
   CardDefaults.cardColors() takes its container from surfaceContainerHighest -
   FilledCardTokens.ContainerColor, checked in the material3 1.3.0 artifact's
   bytecode - and shardColorScheme mapped surfaceContainer, High and Low but not
   Highest. All 26 ShardCard sites across 20 files were affected. Themed
   instances showed it worst: on Fantasy the page went brown and the cards
   stayed grey.

   This is NOT an M12 regression. The untouched app draws the same grey cards
   and has since M5; M12 only made it obvious by theming everything around them.
   Fixing it therefore changes the untouched app too - cards move from Material's
   grey to --panel-flat - which is the milestone's second deliberate change to a
   shard that has set nothing, alongside phase 2's card shadow. AC-1 is updated
   to record that rather than absorb it: every other role is still asserted
   byte-for-byte against the verbatim pre-M12 scheme, and the two that moved are
   named, given their new values, and checked to have actually differed before.

   surfaceContainerLowest is mapped alongside it for consistency with
   surfaceContainerLow. It has no reader in this app - the phase 8 sweep checked
   every Material component the app draws against the roles the mapping leaves at
   Material defaults, and surfaceContainerHighest was the only live one. The
   drawer scrim reads the unmapped `scrim`, which stays Material's black
   deliberately.

2. The drawer's selected row ignored --radius-pill. NavigationDrawerItem takes
   `shape` as a default argument (CircleShape); the three call sites set `colors`
   but never `shape`, so on Fantasy every other radius went square while the
   selected row stayed fully round.

Verified on device against a Fantasy-themed local instance: the three ShardCards
on the shard screen now paint --panel-flat, and the selected drawer row is the
4px rectangle the preset asks for.

477 unit tests green (476 + 1), lintDebug clean.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-08 11:00:06 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00
2026-07-19 01:38:07 -05:00

Runic Gateway — Android app

A native Android client for a Runic Gateway shard's public site + player self-service. It is purely an API client of the website backend — it never talks to the link/ sidecar or the game shard directly, and it ships none of the shard/sidecar wiring. It surfaces the same content and player features as the website's browser client, minus every administrative/management console.

The authoritative design contract is docs/android/PLAN.md in the RunicGateway/docs repo. The authoritative API reference is the committed OpenAPI spec at website/server/swagger/swagger-output.json.

Status

M0 — repo scaffold. Gradle + Compose + Hilt skeleton with CI (lint + unit test + debug build). The functional Kotlin pass (M1M4) and the design pass (M5) follow — see the plan's milestones (§9).

Stack

Concern Choice
Language / UI Kotlin + Jetpack Compose (Material 3)
Navigation Navigation-Compose, single-activity
HTTP Retrofit + OkHttp, kotlinx.serialization
Async Coroutines + Flow
DI Hilt
Prefs / base URL Jetpack DataStore
Tokens at rest EncryptedSharedPreferences
Images Coil
Min SDK Android 10 (API 29)
Target / compile SDK 35

Dependency and plugin versions are pinned in gradle/libs.versions.toml.

Build

Requires JDK 17 and the Android SDK (ANDROID_HOME / local.properties).

./gradlew assembleDebug     # build a debug APK -> app/build/outputs/apk/debug/
./gradlew test              # JVM unit tests
./gradlew lint              # Android lint
./gradlew installDebug      # install on a connected device/emulator

The app self-configures its server URL on first run (PLAN.md §3), so a single build works against any shard's website — there is no compiled-in API host.

CI

.gitea/workflows/pr-checks.yml gates PRs into main with ./gradlew lint test assembleDebug on the org's self-hosted runner (JDK 17 + Android SDK). Debug builds are auto-signed, so the gate needs no secrets. This pipeline is verified green end-to-end on the runner (M0). A signed release APK attached to a Gitea release comes at M6.

The workflow carries a few runner-specific accommodations (each explained in comments in the file), because this self-hosted runner differs from a stock GitHub runner:

  • JDK 17 is installed via apt (not actions/setup-java) — the runner can't resolve api.adoptium.net, while the Ubuntu mirrors are reachable.
  • SDK packages are installed explicitly via sdkmanager, with set +o pipefail so yes dying of SIGPIPE doesn't fail the step.
  • gradlew is chmod +x'd in the run step — the runner's checkout does not preserve the git executable bit, so ./gradlew alone fails with "Permission denied".

Contributing

See CONTRIBUTING.md. AI-assisted contributions must be disclosed (org policy): tick the PR box naming the tool and add a Co-Authored-By trailer to AI-authored commits. Licensed GPL-3.0-or-later.

Description
No description provided
Readme 10 MiB
v0.5.0 Latest
2026-08-08 16:28:50 +00:00
Languages
Kotlin 99.8%
Python 0.2%