mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 02:29:55 +02:00
128 lines
4.3 KiB
Markdown
128 lines
4.3 KiB
Markdown
# AGENTS.md — `shared/` (Compose Multiplatform + KMP)
|
||
|
||
Nearest guide when editing under `shared/`. Root [`AGENTS.md`](../AGENTS.md)
|
||
still applies; this file wins for UI/KMP work.
|
||
|
||
---
|
||
|
||
## Purpose
|
||
|
||
`shared` is the multiplatform app layer: Compose UI, feature ViewModels, and
|
||
`expect`/`actual` bridges into Android, iOS, and desktop. Native transfer work
|
||
goes through UniFFI `VnidropCore` (see `crates/vnidrop`).
|
||
|
||
---
|
||
|
||
## Compose skill (required for UI work)
|
||
|
||
For screens, components, theme, navigation, resources, ViewModel↔UI wiring,
|
||
lists, animation, accessibility:
|
||
|
||
1. Load [`.codex/skills/compose-skill/SKILL.md`](../.codex/skills/compose-skill/SKILL.md).
|
||
2. Follow its workflow and defaults.
|
||
3. Open **at most one** file under `.codex/skills/compose-skill/references/` when
|
||
the skill’s Quick Routing table says you need deeper guidance.
|
||
4. Do **not** invent a parallel Compose style guide.
|
||
|
||
### Project policy (overrides generic skill defaults)
|
||
|
||
| Topic | Do this |
|
||
|-------|---------|
|
||
| Architecture | Keep **MVVM-style** ViewModels: immutable `*State`, `StateFlow`, **named methods**. Do not force MVI `onEvent` sealed hierarchies unless asked. |
|
||
| Structure | Feature packages under `com.vnidrop.app.feature.*`; thin route/wiring + screen/composables. |
|
||
| Theme | Only `LocalVniDropColors` / `VniDropThemeTokens` (`ui/theme/VniDropTheme.kt`). Brand primary light ≈ `#A855F7` (HSL 271, 91%, 65%). |
|
||
| Strings | CMP composeResources / `Res.string.*` — not Android `R` in `commonMain`. |
|
||
| DI | Follow existing `AppGraph` construction; no unprompted Hilt/Koin migration. |
|
||
| Platform | `androidMain` / `iosMain` / `jvmMain` for pickers, SAF, security-scoped URLs, NFC/QR. |
|
||
| Dependencies | Before adding Jetpack/AndroidX to `commonMain`, verify multiplatform artifacts for all targets. |
|
||
|
||
compose-skill “Existing Project Policy”: adapt to this repo; do not force-migrate.
|
||
|
||
---
|
||
|
||
## Commands
|
||
|
||
From repo root:
|
||
|
||
```bash
|
||
./gradlew :shared:jvmTest
|
||
./gradlew :shared:compileKotlinJvm
|
||
```
|
||
|
||
Optional:
|
||
|
||
```bash
|
||
./gradlew :shared:testAndroidHostTest
|
||
./gradlew :shared:iosSimulatorArm64Test
|
||
./gradlew :desktopApp:run
|
||
./gradlew :androidApp:assembleDebug
|
||
```
|
||
|
||
CI `:shared:jvmTest` currently runs on **macOS**. Gobley host cargo follows the
|
||
current host and architecture, including Linux and Windows; use macOS only when
|
||
exact CI parity is required.
|
||
|
||
When Kotlin changes touch UniFFI-generated APIs, rebuild/test with a full
|
||
`jvmTest` so Gobley/native pieces stay aligned.
|
||
|
||
---
|
||
|
||
## Layout
|
||
|
||
```
|
||
src/
|
||
commonMain/kotlin/com/vnidrop/app/
|
||
core/ # models, CoreGateway, FilePicker interfaces
|
||
feature/send|receive|approvals|settings|app/
|
||
ui/ # theme, components, navigation, feedback, state helpers
|
||
commonMain/composeResources/
|
||
androidMain|iosMain|jvmMain/
|
||
commonTest|jvmTest|...
|
||
```
|
||
|
||
### Platform file bridging (must preserve)
|
||
|
||
- **Android share:** open content URIs as FDs; expand **folder trees** to per-file
|
||
documents with relative `displayName` paths before calling Rust
|
||
(`FileSystemService.android.kt` / `expandShareDirectory`).
|
||
- **Android receive:** MediaStore Downloads sink and/or SAF tree write sink.
|
||
- **iOS:** keep security-scoped leases alive while Rust reads paths.
|
||
- **Desktop:** filesystem paths; directories may be marked `isDirectory` for Rust walk.
|
||
|
||
Never pass a directory as a single Android FD into `SourceKind.FILE_DESCRIPTOR`.
|
||
|
||
---
|
||
|
||
## Code style (Kotlin)
|
||
|
||
- Match existing feature style (imports, naming, state updates via `update { }`).
|
||
- Composables render state and invoke callbacks; no business rules in `@Composable`
|
||
bodies (network, share creation, ticket parse — ViewModel/core).
|
||
- Prefer stable list keys from domain IDs.
|
||
- Comments only for non-obvious platform or concurrency reasons.
|
||
- Do not hard-code brand colors; use theme tokens.
|
||
|
||
---
|
||
|
||
## Testing
|
||
|
||
- Logic: `src/commonTest/` (e.g. ViewModel fakes, `AppUiModels` progress helpers).
|
||
- Compose/JVM: `src/jvmTest/`.
|
||
- Add/adjust tests when changing state machines, progress aggregation, or
|
||
share/receive eligibility.
|
||
- Prefer fakes in `commonTest` support over real UniFFI in pure unit tests.
|
||
|
||
```bash
|
||
./gradlew :shared:jvmTest
|
||
```
|
||
|
||
---
|
||
|
||
## Anti-patterns
|
||
|
||
- Streaming transfer bytes through Kotlin as the main design
|
||
- Directory FDs on Android
|
||
- New DI framework “because best practice”
|
||
- Loading every compose-skill reference file for a small UI tweak
|
||
- Android `R.string` in `commonMain`
|