--- id: "0154" title: "matrix-client-android scaffold: Kotlin + Compose + login MAS" status: pending priority: high created: 2026-05-24 related_flows: ["0011"] related_issues: ["0155", "0162"] dependencies: ["0162"] tags: [matrix, android, kotlin, compose, mas, oidc, scaffold] --- ## Objetivo Crear `projects/element_agents/apps/matrix_client_android/` con `init_kotlin_app` (pipeline ya existente del registry). Configurar Compose + Material 3 + tema propio. Implementar login MAS OIDC via Chrome Custom Tabs. Tokens persistidos en EncryptedSharedPreferences. Resultado: APK debug que abre Custom Tab al MAS, retorna con token y muestra perfil del usuario. ## Tareas 1. `./fn run init_kotlin_app matrix_client_android` — usa pipeline existente del registry (ver issues completados 0073-0078). 2. Sub-repo Gitea: `git init -b master` + crear `dataforge/matrix_client_android` + push inicial. **Antes** de salir del worktree (ver `apps_subrepo.md`). 3. `app.md` con frontmatter: - `lang: kotlin`, `framework: jetpack-compose`, `dir_path: projects/element_agents/apps/matrix_client_android`. - `tags: [matrix, android, kotlin, compose]`. - `uses_functions: []` (irlo rellenando issue a issue). 4. `build.gradle.kts`: - `compileSdk = 34`, `minSdk = 28`, `targetSdk = 34`. - Compose BOM `2024.x`. - `matrix-rust-sdk` Kotlin bindings (`org.matrix.rustcomponents:sdk-android:0.x`). - `androidx.security:security-crypto` para EncryptedSharedPreferences. - `androidx.browser:browser` para Chrome Custom Tabs. 5. Login MAS: - `LoginActivity` con boton "Sign in with Matrix". - Generar PKCE code_verifier + state. - Abrir Chrome Custom Tab a `/oauth/authorize?...`. - `MainActivity` con intent-filter para `matrix-client-android://callback` redirect. - Intercambiar code -> access_token + refresh_token. - Guardar en EncryptedSharedPreferences (`SecurityCryptoUserPrefs`). 6. `HomeScreen` Compose con `Text("Hola @")` + boton Logout. 7. Tema Material 3 propio (paleta accent acorde a flow 0010 cliente PC para coherencia). 8. Test instrumented: `LoginInstrumentedTest` que mocka MAS y verifica flow callback -> token saved. ## Funciones del registry a crear - `matrix_client_kotlin_infra` — facade sobre `matrix-rust-sdk` (init, login, sync, logout). - `mas_oidc_kotlin_infra` — Chrome Custom Tabs + PKCE + callback handler. - `encrypted_prefs_kotlin_core` — wrapper EncryptedSharedPreferences (idempotente, generic put/get). - `LoginScreen_kotlin_ui` — Compose screen Material 3. - `HomeScreen_kotlin_ui` — Compose screen perfil + logout. ## Acceptance - [ ] `./gradlew assembleDebug` produce APK valido. - [ ] APK instala en Android 9+ y arranca. - [ ] Login: boton -> Custom Tab MAS -> consent -> callback -> perfil visible. - [ ] Token persiste entre re-aperturas (no re-login si vigente). - [ ] `app.md` con frontmatter completo + 5 `uses_functions`. - [ ] Sub-repo `dataforge/matrix_client_android` con commit inicial. - [ ] Test instrumented `LoginInstrumentedTest` pasa en emulator API 31. ## Notas - Chrome Custom Tabs > WebView para OAuth (security: comparte cookies con browser principal del user, mejor UX). - Refresh token: implementar refresh proactivo 5min antes de expiry (corutina + WorkManager periodic). - Gotcha conocido (ver issue 0074): `local.properties` con `sdk.dir` obligatorio en setup nuevo. El scaffolder lo crea. - Gotcha (issue 0075): Material 3 sin AppCompat — usar `MaterialTheme` directamente, no `Theme.AppCompat.*`.