4.2 KiB
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=<token>. The app intercepts this URI via an <intent-filter> 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<SyncState>.
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.textis 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-messageterminal app for UI reference:app.py: curses chat with<prefix for incoming,>for outgoingfont.py: big pixel ASCII font for incoming banners- Color scheme:
COLOR_GREENon 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://ssodeep link → token exchange - Compose UI with monospace font, #00FF41 green, #0A0A0A background
- All screens text-only, no images/icons/avatars