# AGENTS.md — matrix-android Progress log and architecture notes for AI agents working on this project. --- ## Status | Component | Status | |---|---| | Build infrastructure (Gradle, version catalog) | done | | Matrix networking (Retrofit API + Session) | done | | SSO / password login flow | done | | Room list screen | done | | Chat screen (send + receive) | done | | Terminal theme (green on black, monospace) | done | | Launcher icon (vector adaptive) | done | | README | done | --- ## Design decisions ### No heavy Matrix SDK Instead of importing the full `matrix-android-sdk2` (used by Element), we call the Matrix REST API directly with Retrofit. This keeps the APK small and the code easy to follow. The trade-off is no E2E encryption support. ### SSO via Custom Tabs Login opens the homeserver's `/login/sso/redirect` endpoint in a Chrome Custom Tab. After auth the homeserver redirects to `matrixandroid://sso?loginToken=`. The app intercepts this URI via an `` in `AndroidManifest.xml` and exchanges the token for an access token. ### Single-activity Compose navigation `MainActivity` → `AppNavigation` hosts all three screens (Login, Rooms, Chat) inside a single `NavHost`. No fragments. ### MatrixSession singleton `MatrixSession` is a process-scoped singleton (companion object). It holds the Retrofit client, persists the access token in `SharedPreferences`, and runs the `/sync` long-polling loop in a coroutine scope. All screens observe `syncState: StateFlow`. ### Sync filter Initial and incremental syncs use a compact filter: - Timeline limited to 50 events per room - State events use lazy member loading - Presence and account data stripped This prevents the first sync from being huge on accounts with many rooms. --- ## Known issues / future work - **E2E encryption**: Matrix Olm/Megolm is not implemented. Encrypted rooms will show blank messages. - **Push notifications**: Not implemented. The app only receives messages while open. - **Pagination**: No scroll-back pagination for old messages. - **Room member display names**: Members are shown as their MXID, not display name. - **Image/file messages**: Silently dropped (only `m.text` is rendered). - **Error handling**: Network errors on send are silently swallowed; add a snackbar or retry UI. - **Direct messages**: DMs appear in the room list using the room ID; should resolve the other user's display name. --- ## File map ``` matrix-android/ ├── settings.gradle.kts ├── build.gradle.kts ├── gradle/ │ ├── libs.versions.toml ← version catalog │ └── wrapper/ │ └── gradle-wrapper.properties ├── app/ │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src/main/ │ ├── AndroidManifest.xml │ ├── java/com/ltadeu6/matrix/ │ │ ├── MainActivity.kt │ │ ├── navigation/AppNavigation.kt │ │ ├── auth/LoginScreen.kt │ │ ├── auth/LoginViewModel.kt │ │ ├── rooms/RoomListScreen.kt │ │ ├── chat/ChatScreen.kt │ │ ├── chat/ChatViewModel.kt │ │ ├── matrix/MatrixApi.kt │ │ ├── matrix/MatrixModels.kt │ │ ├── matrix/MatrixSession.kt │ │ └── ui/theme/Theme.kt │ └── res/ │ ├── drawable/ic_launcher_foreground.xml │ ├── mipmap-anydpi-v26/ic_launcher.xml │ ├── mipmap-anydpi-v26/ic_launcher_round.xml │ └── values/{strings,colors,themes}.xml ├── README.md └── AGENTS.md ``` --- ## Session 1 — initial build (2026-05-14) - Inspected `matrix-message` terminal app for UI reference: - `app.py`: curses chat with `< ` prefix for incoming, `> ` for outgoing - `font.py`: big pixel ASCII font for incoming banners - Color scheme: `COLOR_GREEN` on black - Created full Android project from scratch (no fork) - Chose Retrofit + kotlinx.serialization over matrix-android-sdk2 for simplicity - SSO flow: Custom Tabs → homeserver → `matrixandroid://sso` deep link → token exchange - Compose UI with monospace font, #00FF41 green, #0A0A0A background - All screens text-only, no images/icons/avatars