Files
vnidrop/shared/AGENTS.md

4.3 KiB
Raw Blame History

AGENTS.md — shared/ (Compose Multiplatform + KMP)

Nearest guide when editing under shared/. Root 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.
  2. Follow its workflow and defaults.
  3. Open at most one file under .codex/skills/compose-skill/references/ when the skills 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:

./gradlew :shared:jvmTest
./gradlew :shared:compileKotlinJvm

Optional:

./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.
./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