Initial commit: BountyBoard Android client
Native Kotlin + Jetpack Compose (Material 3) client for the BountyBoard platform. Cookie-session + CSRF auth with a configurable base URL, the full role-based feature set (admin / consultant / developer), local + OIDC SSO sign-in, and background push notifications (WorkManager poll) for alerts and messages. Bundles the app's editorial "ledger" design system and the original Fraunces / Schibsted Grotesk / Spline Sans Mono typefaces. Includes a prebuilt debug APK (BountyBoard-debug.apk) for side-loading. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# Bounty Board — Android
|
||||
|
||||
A native Android client for the [Bounty Board](../BountyBoard) consulting work-management
|
||||
platform. Built with **Kotlin + Jetpack Compose (Material 3)**, it covers the full
|
||||
role-based feature set — admin, consultant, and developer — over the server's
|
||||
cookie-session + CSRF API.
|
||||
|
||||
The visual identity mirrors the web app's "ledger / bounty-poster" aesthetic: warm
|
||||
paper grounds, brown/amber ink, hard offset shadows (no blur), 2px corners, ◈ bounty
|
||||
chips, and the original **Fraunces / Schibsted Grotesk / Spline Sans Mono** typefaces
|
||||
(bundled, instanced from the web app's variable fonts).
|
||||
|
||||
## First run
|
||||
|
||||
The app opens on a **Login** page. The default server is
|
||||
`https://bountyboard.anypreta.com/`. Expand **Server** on the login screen to point the
|
||||
app at any other Bounty Board instance — the base URL is persisted and every request is
|
||||
retargeted at runtime. Sign in with email/password, register a developer account, or use
|
||||
"Forgot password". A forced password change is handled automatically when the server
|
||||
requires it.
|
||||
|
||||
## Features
|
||||
|
||||
- **Auth** — login (with configurable base URL), self-registration, forgot password,
|
||||
forced password change. Session + CSRF are handled transparently by a persistent
|
||||
cookie jar and a double-submit interceptor.
|
||||
- **Developer** — bounty board with search / project / min-bounty / sort filters and
|
||||
claim flow; My Tasks kanban (Assigned · In progress · In review · Done); per-task
|
||||
start / submit / abandon / withdraw; comments; time logging; metrics dashboard;
|
||||
leaderboard.
|
||||
- **Consultant** — atomization board (grouped by project, status filters, quick
|
||||
publish); subdivide / extend / edit / publish; reviews queue with an acceptance-
|
||||
criteria checklist; approve / decline claims; assign-to-AI; developer pool management;
|
||||
metrics.
|
||||
- **Admin** — users (roles, disable, force-reset, delete); projects/customers wizard
|
||||
(per-system credential fields, test connection, sync now); runtime settings; audit
|
||||
log; live service-status panel.
|
||||
- **Shared** — task detail with full role-aware action bar and timeline; real-time-feel
|
||||
messaging (DMs, group/project conversations, image + file attachments, read receipts);
|
||||
notification center with deep links; profile (avatar upload, bio/contact, theme
|
||||
picker with all six themes, leaderboard opt-out, sign-out-everywhere); public profile
|
||||
cards.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
data/ AppContainer (manual DI) · Repository · SessionManager · SettingsStore (DataStore)
|
||||
net/ Retrofit ApiService · PersistentCookieJar · CSRF + dynamic-host interceptors · DTOs
|
||||
model/ wire data classes
|
||||
ui/
|
||||
theme/ palette (6 themes) · typography · 2px shapes · hard-offset shadow modifier
|
||||
components/ BBButton · BBCard · BountyChip · StatusBadge · BBAvatar · BBTextField · dialogs · TaskCard
|
||||
nav/ AppRoot (bootstrap/auth gate) · MainShell (role drawer + NavHost) · Routes
|
||||
auth/ developer/ consultant/ admin/ task/ messaging/ shared/ profile/ feature screens + ViewModels
|
||||
```
|
||||
|
||||
- **Networking**: OkHttp + Retrofit (Gson). The base URL is dynamic — a host-selection
|
||||
interceptor rewrites scheme/host/port per request, so changing the server on the login
|
||||
screen takes effect immediately without rebuilding Retrofit. Coil shares the OkHttp
|
||||
stack so `/files/{id}` image loads carry the session cookie.
|
||||
- **Auth**: cookie-session only. `bb_session` (httpOnly) and `bb_csrf` are persisted in a
|
||||
`PersistentCookieJar`; mutating requests echo `bb_csrf` into the `X-CSRF-Token` header.
|
||||
- **State**: ViewModels expose Compose `mutableStateOf` snapshots; screens are stateless
|
||||
and driven by `LocalAppContainer`.
|
||||
|
||||
## Building
|
||||
|
||||
Requirements: **JDK 17 or 21** (AGP 8.5 does not support newer JDKs as the build JVM),
|
||||
the Android SDK with **platform 34** and **build-tools 34.0.0**, and Gradle 8.9+.
|
||||
|
||||
The easiest path is to open the project in **Android Studio** (Koala / 2024.1+), let it
|
||||
sync, and Run.
|
||||
|
||||
From the CLI (the Gradle wrapper is included; point `JAVA_HOME` at a JDK 17–21):
|
||||
|
||||
```bash
|
||||
cd BountyBoard_android
|
||||
JAVA_HOME=/path/to/jdk-21 ./gradlew assembleDebug # APK → app/build/outputs/apk/debug/
|
||||
JAVA_HOME=/path/to/jdk-21 ./gradlew installDebug # install on a connected device/emulator
|
||||
```
|
||||
|
||||
A prebuilt debug APK is committed at **`BountyBoard-debug.apk`** in the project root —
|
||||
`adb install -r BountyBoard-debug.apk` to side-load it directly.
|
||||
|
||||
`local.properties` already points `sdk.dir` at `~/Android/Sdk`; adjust if your SDK lives
|
||||
elsewhere. The app allows cleartext traffic so you can point it at a local `http://`
|
||||
dev server.
|
||||
|
||||
### Sign-in
|
||||
|
||||
Local email/password **and** OIDC SSO both work. "Sign in with SSO" opens the server's
|
||||
OIDC redirect flow in an in-app browser; once the IdP redirects back, the session cookies
|
||||
are captured into the app's HTTP stack and you're signed in. If the server has no OIDC
|
||||
configured, the app reports that instead of failing silently.
|
||||
|
||||
## Notes
|
||||
|
||||
- `minSdk 26`, `targetSdk 34`. No proprietary services; the launcher icon, splash, and
|
||||
fonts are all bundled.
|
||||
- The server contract is documented in `../BountyBoard/api/openapi.yaml` and
|
||||
`../BountyBoard/specification.md`; this client implements the §6 application API.
|
||||
Reference in New Issue
Block a user