Vectrum
Sign In
92 lines · 5.3 KB

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):

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, 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 <token>. 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 } → { token, user }
POST /api/v1/signup{ username, email, password, name } → { token, user }, when sign-ups are open
GET /api/v1/user, /home, /explore?q=, /users/<name>
GET /api/v1/repos/<owner>/<repo>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/<sha>, …/branches, …/events
GET …/issues, GET, PATCH …/issues/<n>, POST …/issues, POST …/issues/<n>/comments
GET …/pulls?state=, GET, PATCH …/pulls/<n>, GET …/pulls/<n>/files
POST …/pulls/<n>/comments, …/pulls/<n>/reviews, …/pulls/<n>/merge
GET …/runs?page=, …/runs/<n>, …/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