<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
# 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`](https://gitea.whitlocktech.com/RunicGateway/docs)
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 (M1–M4) 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`](gradle/libs.versions.toml).

## Build

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

```bash
./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`](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**.
