# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Build commands ```bash # First-time setup: generate the Gradle wrapper (requires Gradle installed) gradle wrapper --gradle-version 8.9 # Build debug APK (inside nix dev shell) nix develop --command gradle --no-daemon assembleDebug # Build release APK — requires android-signing-env (sets signing vars + PUSH_GATEWAY_URL) android-signing-env nix develop --command gradle --no-daemon assembleRelease # Install on connected device/emulator ./gradlew installDebug # Run lint ./gradlew lint # Clean ./gradlew clean ``` ### Secrets setup (required before release build) ```bash # Creates symlinks for google-services.json, firebase-service-account.json, .mc/credentials.json # Only needed once per boot (symlinks point into /run/agenix which is tmpfs) matrix-android-secrets /home/ltadeu6/Projetos/Codigo/matrix-android ``` ### Deploy Cloudflare Worker (push gateway) ```bash cloudflare-worker-env nix develop --command wrangler deploy --config gateway/wrangler.toml ``` The project has no unit tests yet. Android Studio is the recommended way to open, sync, and run the project. ## Architecture Single-activity Compose app. All screens live inside one `NavHost` in `AppNavigation.kt`. Navigation flow: **Login → Rooms → Chat**. ### State ownership `MatrixSession` (singleton, `matrix/MatrixSession.kt`) is the single source of truth. It: - Persists the access token in `SharedPreferences` - Owns and runs the `/sync` long-polling coroutine loop - Exposes `authState: StateFlow` and `syncState: StateFlow` All ViewModels and screens observe these flows directly — there is no local room/message database. ### Matrix transport Direct REST API via Retrofit (`MatrixApi.kt`). No Matrix SDK dependency. Only `m.room.message` text events are rendered; encrypted events are silently dropped. ### SSO login flow 1. `LoginViewModel.buildSsoUrl()` constructs `/_matrix/client/v3/login/sso/redirect?redirectUrl=matrixandroid://sso` 2. The URL opens in a Chrome Custom Tab 3. Homeserver redirects to `matrixandroid://sso?loginToken=` 4. `MainActivity.onNewIntent` (hot) or `onCreate` (cold) reads the token and calls `MatrixSession.handleSsoCallback(token)` 5. `LoginScreen` observes `session.pendingSsoToken` and calls `vm.loginWithSsoToken(token)` which POSTs to `/_matrix/client/v3/login` ### Theme `ui/theme/Theme.kt` — `MatrixGreen` (`#00FF41`) on `MatrixBackground` (`#0A0A0A`). All text uses `TerminalFont` (`FontFamily.Monospace`). No Material components with default colors — always pass explicit `colors =` overrides to `OutlinedTextField` and `Button`. ## Key conventions - `MatrixSession` is always obtained via `MatrixSession.getInstance(context)` — never constructed directly - Room IDs (`!abc:homeserver`) are URL-encoded when passed as nav arguments (`Route.chat(roomId)`) - `SyncState.messages[roomId]` is append-only and deduped by `eventId`; ordering is by `origin_server_ts` - The sync filter (`MatrixSession.syncFilter`) limits timeline to 50 events and strips presence/account data — change it here if more history is needed