Files
Android-app/README.md
wtclaude 21b6ddc29b
Some checks failed
PR Checks / android-build (pull_request) Failing after 42m5s
fix(notifications): resolve an item's relative url, and document the CI trigger
Two things the live rig found, and the README half of the trigger change.

Phase 7 specifies an inbox item's `url` is RELATIVE-ONLY and validates it as
such — right for a browser already on the site, a dead link on a phone. The
first cut here only opened `http(s)`-prefixed strings, so on the rig every link
in the inbox did nothing at all. `InboxViewModel.linkFor` now resolves against
the configured base with OkHttp's `HttpUrl.resolve`, which absolutises the path
and returns null for anything that would not end up http(s) — so a `javascript:`
or `intent:` url in a notification body opens nothing.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-31 09:27:39 -05:00

76 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 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 (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`](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` **and `edge`** 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.
**`edge` is in the trigger deliberately**: a workstream that lands its phases on a working branch
before one cutover PR into `main` otherwise gets no CI at all until the cutover — which is what
happened to all nine M12 phase PRs (`docs/website/ENGAGEMENT.md` §7.1 Q8). `sonarqube.yml` is
unaffected: it is a push-on-`main` analysis, not a PR gate.
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**.