matrix-android/CLAUDE.md
2026-05-14 23:22:06 -03:00

63 lines
2.5 KiB
Markdown

# 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
./gradlew assembleDebug
# Build release APK
./gradlew assembleRelease
# Install on connected device/emulator
./gradlew installDebug
# Run lint
./gradlew lint
# Clean
./gradlew clean
```
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<AuthState>` and `syncState: StateFlow<SyncState>`
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 `<homeserver>/_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=<token>`
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