Files
davotoula 03bf1771e0 docs: drop in-repo quartz/quic module references after the library split
quartz and quic now come from Maven Central (libs.quartz, libs.quic), but a
few module docs and skills still described them as Gradle modules here:

- marmotQuic/README.md, nestsClient/tests/README.md: `:quic` -> quic-kmp
- cli/DEVELOPMENT.md, commonsUI/ARCHITECTURE.md: `:quartz` -> libs.quartz
- amy-expert / kotlin-multiplatform extraction recipes: protocol code is a
  quartz-repo PR (built here with -PquartzDir), not a git mv into quartz/
- AGENTS.md Tech Stack and the kotlin-multiplatform skill: the app modules
  moved to kotlinx.serialization; Jackson remains only inside quartz's JVM
  code, so the "don't migrate to kotlinx.serialization" rule is reversed
- BUILDING.md: the currentTimeMillis ban is verifyKmpPurity, not a Spotless rule
2026-10-22 15:57:32 +02:00

3.1 KiB
Raw Permalink Blame History

Extracting an Android composable, screen or ViewModel

Goal: Android and Desktop render the same code. First check the component's dependencies actually allow sharing; if one Android API remains, put it behind a port or slot rather than leaving the whole screen in amethyst/.

Steps

  1. Locate it and its callers. Android code lives in amethyst/src/main/java/.
    git grep -n "fun Name\b\|class Name\b" -- amethyst/src
    
  2. List what ties it to Android: android.* imports, Context/Intent, R.string/R.drawable, LocalContext, Android-only libraries (media3, CameraX, WebView), and app-only helpers from amethyst/.
  3. Move strings first. Keys still in amethyst/src/main/res/values/strings.xml move with tools/strings-migrate/migrate.py <keys…> (all locales, byte for byte), then R.string.x becomes Res.string.x. Rules: AGENTS.md › Strings.
  4. Pick the destination (mechanical rule in commonsUI/ARCHITECTURE.md):
    • Composables, screens, anything importing Compose UI, Coil or Res → commonsUI/src/commonMain/, same com.vitorpamplona.amethyst.commons.* package tree.
    • Headless ViewModels, state holders, services → commons/src/commonMain/ (viewmodels/ or <feature>/), never under a ui.* package.
    • Nostr protocol logic → quartz/src/commonMain/ in the quartz repo (a quartz PR; build against it here with -PquartzDir=../quartz).
  5. Replace Android APIs (table below). Each leftover platform need becomes an expect/actual verb, a port, or a slot (see SKILL.md).
  6. Repoint callers in amethyst/ to the shared version and delete the Android copy. Desktop renders the shared UI, so it usually needs no change beyond any new port/actual.
  7. Verify: compile every target the module builds, ./gradlew :commonsUI:jvmTest :commonsUI:verifyKmpPurity (or :commons:…), ./gradlew :amethyst:compilePlayDebugKotlin, then ./gradlew spotlessApply.

Common replacements

Android Shared
stringResource(R.string.x) stringRes(Res.string.x) (commons/ui/StringRes.kt); pluralStringRes(Res.plurals.x, n, …)
String outside composition loadStringRes(…) from a coroutine, or resolve in composition and pass a String
painterResource(R.drawable.x) painterRes(Res.drawable.x, …) (commons/ui/PainterRes.kt)
Toast.makeText(…) in UI accountViewModel.toastManager.toast(…)
Toast/message from headless code report a typed UserNotice (commons.notices) to a UserNoticeSink; word it in commonsUI notices/ui/UserNoticeText.kt
LocalContext.current for share / open URI rememberTextSharer(), rememberBlossomUriOpener(), Compose LocalUriHandler
LocalContext.current for anything else a port on AccountViewModelHost, a slot such as LocalNotePlatform, or a lambda parameter
Platform media/map/editor inside a note LocalNotePlatform slot
Intent to another screen the shared navigation in commonsUI (AmethystApp)
Per-window-size layout forks ScreenLayoutSpec / LocalScreenLayout
@StringRes Int field StringResource / PluralStringResource