docs: update all Dagger/Anvil/KAPT references to Metro

Replace stale DI documentation across the codebase:
- CONTRIBUTING.md: DI stack description
- .github/copilot-instructions.md: architecture, di/ comment, DI pattern, build note
- CLAUDE.md: tech stack, build comments, di/ listing, DI patterns,
  common issues, Kotlin version note, Copilot context section
- project-resources/prd/product-requirements-document.md: ARCH-04 row
This commit is contained in:
Hossain Khan
2026-04-03 09:23:22 -04:00
parent 4d7685faaf
commit 1ecb17a06f
4 changed files with 19 additions and 18 deletions
+4 -4
View File
@@ -11,7 +11,7 @@ This document provides essential information for GitHub Copilot agents working o
- Build System: Gradle 8.13
- Min SDK: 28 (Android 9.0 Pie)
- Target SDK: 36 (Android 16.0)
- Architecture: Modern Android with Jetpack Compose, Circuit UDF, Dagger DI
- Architecture: Modern Android with Jetpack Compose, Circuit UDF, Metro DI
## Critical Build & Test Commands
@@ -70,7 +70,7 @@ app/src/main/java/ink/trmnl/android/
├── MainActivity.kt # App entry point (138 lines)
├── TrmnlDisplayMirrorApp.kt # Application class (51 lines)
├── data/ # Repositories, DataStore implementations
├── di/ # Dagger dependency injection modules
├── di/ # Metro dependency injection modules
├── model/ # Data models (TrmnlDeviceConfig, etc.)
├── network/ # Retrofit API service, response models
├── ui/ # Jetpack Compose screens (Circuit UDF)
@@ -89,7 +89,7 @@ app/src/main/java/ink/trmnl/android/
### Key Architectural Patterns
- **UI Framework:** Jetpack Compose with Circuit (Slack's UDF architecture)
- **DI:** Dagger with Anvil for code generation
- **DI:** Metro (dev.zacsweers.metro) for compile-time code generation
- **Background Work:** WorkManager (15 min minimum interval)
- **Networking:** Retrofit + OkHttp + Moshi for JSON parsing
- **Data Storage:** DataStore (preferences) for settings/tokens
@@ -134,7 +134,7 @@ All workflows are in `.github/workflows/`:
**Solution:** This is informational only. The file is optional for local dev (used for release keystores). Debug builds work without it.
### Issue: First Build Takes 2-3 Minutes
**Solution:** Expected behavior. Gradle downloads dependencies and builds annotation processors (KSP, KAPT). Subsequent builds are much faster (~1 minute) due to caching.
**Solution:** Expected behavior. Gradle downloads dependencies and runs Metro compiler plugin + KSP. Subsequent builds are much faster (~1 minute) due to caching.
### Issue: Test Warning "Sharing is only supported for boot loader classes"
**Solution:** Harmless warning from Robolectric tests. Can be ignored. Tests still pass.
+13 -12
View File
@@ -11,7 +11,7 @@ TRMNL Android is a native Android app that displays TRMNL e-ink device content o
- Build: Gradle 8.13 with AGP 8.9.2
- Min SDK: 28 (Android 9.0 Pie), Target SDK: 36 (Android 16.0)
- UI: Jetpack Compose with Circuit UDF architecture (Slack's unidirectional data flow)
- DI: Dagger 2.56.2 with Anvil 0.4.1 for code generation
- DI: Metro 0.12.1 (dev.zacsweers.metro) with MetroX Android for compile-time DI
- Background Work: WorkManager 2.10.1 (15-minute minimum interval limitation)
- Networking: Retrofit 2.11.0 + OkHttp 4.12.0 + Moshi 1.15.2
- Image Loading: Coil 3.2.0 with OkHttp integration
@@ -25,14 +25,14 @@ TRMNL Android is a native Android app that displays TRMNL e-ink device content o
**CRITICAL: On a fresh clone, you MUST build first to generate code:**
```bash
# 1. Build debug APK (generates Dagger/Circuit code via KSP/KAPT)
# 1. Build debug APK (generates Metro/Circuit code via compiler plugin + KSP)
./gradlew assembleDebug --parallel --daemon
# 2. Now you can run tests
./gradlew testDebugUnitTest --parallel --daemon
```
**Why?** Running tests before building will fail with Dagger errors about missing generated modules. The build step generates necessary code via KSP (Circuit) and KAPT (Dagger).
**Why?** Running tests before building will fail with Metro errors about missing generated modules. The build step generates necessary code via Metro compiler plugin (DI) and KSP (Circuit).
### Regular Development (After Initial Build)
@@ -72,8 +72,8 @@ app/src/main/java/ink/trmnl/android/
│ ├── TrmnlDeviceConfigDataStore.kt # Device config (token, server)
│ ├── ImageMetadataStore.kt # Image state management
│ ├── log/ # Refresh log management
├── di/ # Dagger modules
│ ├── AppComponent.kt # Main app component
├── di/ # Metro DI modules
│ ├── AppGraph.kt # Main app dependency graph
│ ├── NetworkModule.kt # Retrofit, OkHttp, Moshi
│ ├── CircuitModule.kt # Circuit UI setup
├── model/ # Data models
@@ -98,15 +98,16 @@ app/src/main/java/ink/trmnl/android/
### Key Architectural Patterns
**Circuit UDF (Unidirectional Data Flow):**
- All screens use `@CircuitInject` annotation for DI with Anvil
- All screens use `@CircuitInject` annotation for DI with Metro
- Presenter pattern: State + Event → Presenter → Updated State
- Example: `TrmnlMirrorDisplayScreen` with presenter handling events
**Dependency Injection:**
- Dagger with Anvil for compile-time code generation
- Metro for compile-time code generation via Kotlin compiler plugin (no KAPT)
- `@ContributesTo(AppScope::class)` for module contribution
- `@SingleIn(AppScope::class)` for app-scoped singletons
- Circuit integration: `arg("anvil-ksp-extraContributingAnnotations", "com.slack.circuit.codegen.annotations.CircuitInject")`
- `@DependencyGraph(AppScope::class)` on `AppGraph` as the root component
- Circuit integration: `arg("circuit.codegen.mode", "metro")`
**Background Work:**
- WorkManager with 15-minute minimum interval (Android OS limitation)
@@ -198,13 +199,13 @@ The project uses optimized Gradle settings based on best practices from the [Now
## Common Issues
- **Tests fail on fresh checkout**: Must run `./gradlew assembleDebug` first to generate Dagger/Circuit code
- **Tests fail on fresh checkout**: Must run `./gradlew assembleDebug` first to generate Metro/Circuit code
- **"secret.properties not found"**: Informational only, debug builds work without it
- **First build slow**: Expected for clean builds, ~1-2 minutes with optimized Gradle settings
- **"Sharing is only supported for boot loader classes"**: Harmless Robolectric warning, tests still pass
- **"INVISIBLE_REFERENCE" in NetworkingTools.kt:56**: Expected, uses internal Kotlin API (documented warning)
- **WorkManager 15-min minimum**: Android OS limitation, not a bug
- **Dagger KAPT errors about missing modules**: Run `assembleDebug` first to generate code
- **Metro codegen errors about missing modules**: Run `assembleDebug` first to generate code
## Code Style
@@ -243,7 +244,7 @@ The project uses optimized Gradle settings based on best practices from the [Now
- **Authentication**: Token-based auth required (TRMNL access token or device ID/MAC address)
- **BYOS Support**: Supports custom server URLs for BYOS installations
- **Screen Wake Lock**: `FLAG_KEEP_SCREEN_ON` doesn't work reliably on e-Ink tablets due to aggressive battery optimization
- **Kotlin Version**: Capped at 2.1.10 due to Dagger 2.56.2 compatibility (see libs.versions.toml comment)
- **Kotlin Version**: 2.3.20+ (Metro removed the Dagger/KAPT compatibility constraint)
- **No Product Flavors**: Only debug/release build types exist
## Copilot Instructions Context
@@ -253,5 +254,5 @@ From `.github/copilot-instructions.md`:
- Use Circuit's `@CircuitInject` for UI components
- WorkManager periodic work has 15-min minimum interval
- Image loading handles HTTP 403 auto-refresh for expired URLs
- Dagger KSP support is in Alpha - using KAPT for now
- Metro uses a Kotlin compiler plugin — no KAPT, no KSP for DI itself
- Trust the documented build commands - they're CI-validated
+1 -1
View File
@@ -17,7 +17,7 @@ The app uses a modern Android architecture with the following components:
- **UI**: Jetpack Compose with Circuit UDF architecture
- **Background Processing**: WorkManager for scheduled image (re)loading
- **Networking**: Retrofit and OkHttp for API communication
- **DI**: Dagger with Anvil for dependency injection
- **DI**: Metro for dependency injection
- **Data Storage**: DataStore for preferences and token storage
#### Key Features/Screens
@@ -190,7 +190,7 @@ This document outlines the requirements for the TRMNL Android application.
| ARCH-01 | UI Framework | Jetpack Compose with Circuit UDF architecture |
| ARCH-02 | Background Processing | WorkManager for scheduled image refreshes |
| ARCH-03 | Networking | Retrofit and OkHttp with EitherNet for API communication |
| ARCH-04 | Dependency Injection | Dagger with Anvil |
| ARCH-04 | Dependency Injection | Metro (dev.zacsweers.metro) |
| ARCH-05 | Data Storage | DataStore for preferences and token storage |
| ARCH-06 | Image Loading | Coil for image loading and caching |
| ARCH-07 | Logging | Timber for debug logging |