# Android app `apps/mobile/` is Vectrum for Android, in Kotlin with Jetpack Compose. It looks like the website: MetalUI's bone and graphite colorways, raised plates and sunk wells, Geist and Geist Mono, engraved mono labels. What it does: - **Home**: a greeting, counts of your repositories, open issues and pull requests, your repositories, and the event feed of everything that happened in them (pushes, issues, reviews, workflow runs) - **Explore**: search the repositories you can see - **Repositories**: README, files and folders on any branch or tag, code with syntax highlighting and line numbers (or wrapped), images, Markdown previews, clone addresses - **Issues**: grouped by status like the website's list, with Active / Backlog / All / Closed scopes; open one, comment, and (with push access) change its status, priority, assignee and labels - **Pull requests**: conversation, reviews and line comment threads, commits, the diff of every file, checks and merge requirements; comment, approve or request changes, merge (merge commit or squash), close and reopen - **Commits**: history by day with CI status, and each commit's diff - **Actions**: workflow runs, their jobs and steps, and each step's log, live while it runs - **Releases**: notes and files to download - Light, dark or following the system, like the website's theme switch ## Building Needs JDK 17+ and the Android SDK (platform 37, build tools 36). With `ANDROID_HOME` set (or `sdk.dir` in `apps/mobile/local.properties`): ```bash cd apps/mobile ./gradlew assembleDebug # app/build/outputs/apk/debug/app-debug.apk ./gradlew installDebug # onto a connected device or emulator ./gradlew assembleRelease # minified, signed with the debug key; sign with your own key to publish ``` From the repository root, `bun run mobile:build` and `bun run mobile:deploy` do the first two. The app runs on Android 8.0 (API 26) and newer. ## Setting up The first time it opens, the app walks through three steps: 1. **Welcome**: what Vectrum is and what the app does. 2. **Server**: *Vectrum Cloud* (vectrum.cc) or *Self-hosted*, with the server's address (`git.example.com`, `192.168.1.10:3000`). Plain HTTP is fine; without `http://` or `https://`, HTTPS is tried first, then HTTP. The app checks that the server is a Vectrum new enough for the app before going on. 3. **Account**: sign in with a username or email and password (and a code from your authenticator app if two-factor authentication is on), or create an account when the server takes sign-ups (not with `SIGNUPS_DISABLED`). After signing out, the app opens on the account step for the same server, with *Change* to pick another. From the Android emulator, the computer running `bun dev` is `http://10.0.2.2:3000`. The app gets the same 30-day session token the website keeps in its cookie, and stores it in the app's private storage; *Sign Out* forgets it. Changing your password ends the session, as on the website. Plain `http://` is allowed for self-hosted servers on a local network; the sign-in screen warns before a password goes to a non-local server without HTTPS. ## The API The app talks to `/api/v1` (`apps/web/app/api/v1/[...path]/route.ts`, `apps/web/lib/app-api.ts`): JSON, with the session token as `Authorization: Bearer `. It acts as the signed-in person and applies the website's permission checks, so the app can't do anything the website wouldn't let that person do: private repositories are "not found" to others, anyone who can read a repository may open issues and comment, and changing issues, approving, requesting changes and merging need push access and the base branch's rules. | Request | | | --- | --- | | `GET /api/v1/server` | `{ name, api, signups }`: what the setup checks before signing in | | `POST /api/v1/session` | `{ login, password, code? }` → `{ token, user }`. With two-factor authentication on, it answers 401 `{ twoFactor: true }` until `code` (from the authenticator app, or a recovery code) is sent too | | `POST /api/v1/signup` | `{ username, email, password, name }` → `{ token, user }`, when sign-ups are open | | `GET /api/v1/user`, `/home`, `/explore?q=`, `/users/` | | | `GET /api/v1/repos//` | the repository, its README, root files, branches and counts | | `GET …/tree?ref=&path=`, `…/blob?ref=&path=`, `…/raw?ref=&path=`, `…/image` | | | `GET …/commits?ref=&page=`, `…/commits/`, `…/branches`, `…/events` | | | `GET …/issues`, `GET, PATCH …/issues/`, `POST …/issues`, `POST …/issues//comments` | | | `GET …/pulls?state=`, `GET, PATCH …/pulls/`, `GET …/pulls//files` | | | `POST …/pulls//comments`, `…/pulls//reviews`, `…/pulls//merge` | | | `GET …/runs?page=`, `…/runs/`, `…/releases` | | Errors are `{ "error": "…" }` with a 4xx status; 401 means the session ended. ## Code layout In `apps/mobile/app/src/main/java/cc/vectrum/app/`: - `data/`: the API's models (`Models.kt`), the HTTP client (`Api.kt`) and the stored session (`Session.kt`) - `ui/theme/`: MetalUI's colorways (`Palette.kt`), type roles (`Type.kt`) and materials (`Materials.kt`: plates, wells and caps as stacks of shadows, from MetalUI's tokens) - `ui/icons/`: the website's glyphs as vectors - `ui/components/`: buttons, fields, the segmented control, pills and LEDs, avatars and identicons, Markdown, the code highlighter and viewer, diffs, sheets and toasts - `ui/screens/`: one file per area; `ui/App.kt` holds the navigation and the tab bar - `ui/Loader.kt`: screen data kept in view models, with pull to refresh and paging