From 4f749c46708fabe995f72aa1517faf0beefaabaf Mon Sep 17 00:00:00 2001 From: Fabian DEVEL Date: Tue, 31 Mar 2026 08:41:45 +0200 Subject: [PATCH] chore(Agents): Add agents.md --- AGENTS.md | 105 +++++++++++++++++++++++ app/AGENTS.md | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 AGENTS.md create mode 100644 app/AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..bef12f0c2b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,105 @@ +# kDrive Android + +## Project Snapshot + +Modular Android application for kDrive cloud storage by Infomaniak. Uses MVVM architecture with Hilt DI, Realm for offline data, Ktor for API calls. Supports 3 build flavors (standard, fdroid, preprod) via Gradle composite builds with Infomaniak Core library. + +**Languages**: Kotlin (100%), XML layouts (migrating to Compose) + +**Key Architecture**: MVVM + Repository pattern with Hilt dependency injection + +## Root Setup Commands + +```bash +# Build entire project +./gradlew assembleStandardDebug + +# Run all unit tests +./gradlew test + +# Build specific flavor +./gradlew assembleFdroidDebug +./gradlew assemblePreprodDebug + +# Clean build +./gradlew clean + +# Install debug on connected device +./gradlew installStandardDebug +``` + +## Universal Conventions + +- **Kotlin code style**: Official style guide (enforced via `.editorconfig`) +- **Commit format**: Conventional commits recommended +- **Branch strategy**: Feature branches → main, create issue before PR +- **PR requirements**: CI must pass, at least one review for significant changes +- **Never commit**: API tokens, credentials, or local.properties values + +## Security & Secrets + +- Never commit `.env`, `local.properties`, or API keys to repository +- Drive API tokens stored in Room database (encrypted) +- User files cached in Realm with offline support +- Bug tracker credentials defined in build.gradle.kts (safe values only) + +## JIT Index + +### Module Structure + +- **Main App**: `app/` → [see app/AGENTS.md](app/AGENTS.md) +- **Core Libraries**: `Core/` → [see Core/AGENTS.md](Core/AGENTS.md) + +### Core Sub-modules (Composite Build) + +Key modules consumed via Gradle composite builds: + +- `Core:Auth` - OAuth2 authentication flow +- `Core:Network` - Ktor HTTP client configuration +- `Core:Ui:View` - Shared UI components (XML-based) +- `Core:Ui:Compose` - Shared Compose components +- `Core:Common` - Extensions and utilities +- `Core:Legacy` - Legacy support module + +### Quick Find Commands + +```bash +# Find ViewModels +rg -n "class.*ViewModel" app/src/ Core/ + +# Find Hilt-injected components +rg -n "@AndroidEntryPoint|@HiltViewModel" app/src/main/ + +# Search API endpoints +rg -n "ApiRepository|suspend fun.*Api" app/src/main/ + +# Find Realm models +rg -n "open class.*RealmObject|@RealmClass" app/src/main/ + +# Locate UI fragments +rg -n "class.*Fragment" app/src/main/java/com/infomaniak/drive/ui/ + +# Find test files +find . -name "*Test.kt" -o -name "*Test.java" + +# Search string resources +rg -n "R\.string\." app/src/main/ +``` + +## Build Flavors + +| Flavor | Description | API Endpoints | +|----------|--------------------------------|-------------------------------------------------------| +| standard | Google Play (default) | Production kDrive API | +| fdroid | F-Droid release | Production API, no proprietary dependencies | +| preprod | Pre-production testing | kdrive.preprod.dev.infomaniak.ch staging servers | + +## Definition of Done + +- [ ] Code compiles without warnings: `./gradlew compileStandardDebugKotlin` +- [ ] Unit tests pass: `./gradlew test` +- [ ] No hardcoded strings in UI (use `strings.xml`) +- [ ] New features include proper ViewModel separation +- [ ] Hilt DI used for dependencies (no manual instantiation) +- [ ] Background work uses WorkManager (not raw threads) +- [ ] File operations use kDrive-specific utilities diff --git a/app/AGENTS.md b/app/AGENTS.md new file mode 100644 index 0000000000..65e92981b8 --- /dev/null +++ b/app/AGENTS.md @@ -0,0 +1,233 @@ +# kDrive Main App + +## Package Identity + +Primary kDrive Android application module. Handles cloud storage synchronization, file management, sharing, and collaboration +features. Uses MVVM architecture with Hilt DI, Realm offline cache, and Ktor for API calls. + +## Setup & Run + +```bash +# Build debug APK +./gradlew app:assembleStandardDebug + +# Install on device +./gradlew app:installStandardDebug + +# Run unit tests +./gradlew app:test + +# Build F-Droid flavor +./gradlew app:assembleFdroidDebug + +# Build pre-production +./gradlew app:assemblePreprodDebug +``` + +## Architecture Patterns + +### MVVM Structure + +``` +app/src/main/java/com/infomaniak/drive/ +├── data/ # Repositories, API, cache, models +├── ui/ # Activities, Fragments, ViewModels +├── di/ # Hilt modules (ApplicationModule, ActivityModule) +├── extensions/ # Kotlin extensions +└── utils/ # Utility classes +``` + +### Data Layer + +- **api/**: Ktor API clients and repository implementations +- **cache/**: Realm database configuration and DAOs +- **models/**: Data classes (File, Drive, User, etc.) +- **sync/**: Background synchronization logic +- **services/**: Foreground services for uploads/downloads + +### Key Dependencies Management + +- Hilt modules: `di/ApplicationModule.kt`, `di/ActivityModule.kt` +- Token provider: `TokenInterceptorListenerProvider.kt` +- App initialization: `MainApplication.kt` + +## Patterns & Conventions + +### ViewModel Creation + +- **DO**: Inject dependencies via constructor + ```kotlin + @HiltViewModel + class FileListViewModel @Inject constructor( + private val fileRepository: FileRepository, + savedStateHandle: SavedStateHandle + ) : ViewModel() + ``` +- **DON'T**: Use AndroidViewModel unless absolutely necessary (e.g., need Application context) + +### Fragment Pattern + +- **DO**: Use Navigation Component with Safe Args + - Example: `ui/fileList/FileListFragment.kt` +- **DON'T**: Use FragmentTransaction directly + +### Background Work + +- **DO**: Use WorkManager for sync operations + - Location: `data/sync/` for workers +- **DON'T**: Use raw Threads or AsyncTask + +### API Calls + +- **DO**: Use repository pattern with Ktor + - Example: `data/api/ApiRepository.kt` + - Wrapper: `data/api/ApiService.kt` + +### Realm Models + +- **DO**: Use `@RealmClass` annotation, open classes + - Example: `data/models/File.kt` +- **DON'T**: Use Room for file data (Realm only) + +### Activity Injection + +- **DO**: Annotate with `@AndroidEntryPoint` + - Example: `ui/MainActivity.kt` +- **DON'T**: Manually instantiate ViewModels + +### Image Loading + +- **DO**: Use Coil (configured via Core) +- **DON'T**: Use Glide or other loaders + +## Key Files Reference + +### Entry Points + +- Application: `MainApplication.kt` (Hilt entry) +- Main Activity: `ui/MainActivity.kt` +- File List: `ui/fileList/FileListFragment.kt` + +### ViewModels (35+ files) + +- Main: `ui/MainViewModel.kt` +- File List: `ui/fileList/FileListViewModel.kt` +- Search: `ui/fileList/SearchViewModel.kt` +- Settings: `ui/menu/settings/SettingsViewModel.kt` + +### Data Repositories + +- API service: `data/api/ApiService.kt` +- File repository: `data/api/ApiRepository.kt` +- Cache manager: `data/cache/FileController.kt` + +### Models + +- File: `data/models/File.kt` +- Drive: `data/models/Drive.kt` +- User: `data/models/UiSettings.kt` + +### Sync & Services + +- Sync adapter: `data/sync/SyncAdapter.kt` +- Upload service: `data/services/UploadWorker.kt` + +### String resources + +- After every change in strings.xml files, raise a warning for the user that he MUST mirror the changes to Loco + +## UI Organization + +```bash +ui/ +├── fileList/ # File browsing (FileListFragment, FileAdapter) +├── menu/ # Navigation drawer, settings, trash +│ └── settings/ # Sync settings, preferences +├── home/ # Home dashboard +├── login/ # Authentication flow +├── dropbox/ # Dropbox creation/management +├── bottomSheetDialogs/ # Bottom sheets (share, move, etc.) +├── addFiles/ # New folder, upload options +├── publicShare/ # Public sharing UI +└── selectPermission/ # Permission selection +``` + +## JIT Index + +### Find ViewModels + +```bash +rg -n "@HiltViewModel|class.*ViewModel" app/src/main/ +``` + +### Find API endpoints + +```bash +# Repository methods +rg -n "suspend fun.*upload|suspend fun.*delete" app/src/main/java/com/infomaniak/drive/data/api/ + +# Data models +rg -n "open class" app/src/main/java/com/infomaniak/drive/data/models/ +``` + +### Find UI components + +```bash +# Fragments +rg -n "class.*Fragment" app/src/main/java/com/infomaniak/drive/ui/ + +# Activities +rg -n "class.*Activity" app/src/main/java/com/infomaniak/drive/ui/ + +# Adapters +rg -n "class.*Adapter" app/src/main/java/com/infomaniak/drive/ +``` + +### Search strings + +```bash +rg -n "R\.string\." app/src/main/java/ | head -20 +``` + +### Find extensions + +```bash +ls app/src/main/java/com/infomaniak/drive/extensions/ +``` + +## Testing + +### Unit Tests + +- Location: `app/src/test/` +- Framework: JUnit 5 (via `junit5` plugin) +- Example: `app/src/test/kotlin/RootFileTreeCategoryTest.kt` + +### Instrumented Tests + +- Location: `app/src/androidTest/` +- Env setup: Copy `Env-Example` to `Env.kt` (disable 2FA for test account) + +### Run Commands + +```bash +# All tests +./gradlew app:test + +# Single test class +./gradlew app:test --tests "com.infomaniak.drive.RootFileTreeCategoryTest" +``` + +## Common Gotchas + +- **Realm transactions**: Always use `realm.executeTransactionAwait()` with coroutines +- **File operations**: All file I/O must use kDrive utilities in `utils/` package +- **Background sync**: Requires `FOREGROUND_SERVICE_DATA_SYNC` permission for Android 14+ +- **Media permissions**: Android 13+ uses granular `READ_MEDIA_*` permissions +- **Hilt modules**: Keep provider methods in `di/ApplicationModule.kt` + +## Pre-PR Checks + +```bash +./gradlew app:assembleStandardDebug && ./gradlew app:testStandardDebugUnitTest +```