Files
amethyst/commons/plans
Claude a33942f2a2 feat: move the app's string catalog to commons Compose resources [WIP: not yet compiled]
Wave 1 of building the Android app for JVM/desktop: a screen cannot move to
commonsUI while its labels come from amethyst/src/main/res.

Compose resources has no blocking, Context-free accessor - outside composition
getString() is suspend - so the 458 `stringRes(context, R.string.x)` call sites
had to be converted before any key could move. Deferring them was not an option:
only 167 of 1,912 keys are used exclusively at composable call sites, and a key
can only live in one resource system.

No runBlocking bridge, per maintainer decision. By scope:
  264  @Composable                      -> drop the context argument
   46  already inside launch { }        -> loadStringRes(id)
  ~80  plain fn, caller in a coroutine  -> the function becomes suspend
  ~68  plain fn, no coroutine in reach  -> label hoisted into composition

The notification stack (NotificationCategory, NotificationUtils, CallNotifier,
the four notifiers, RelayPurposeSummary, ConversationShortcuts) went suspend as
one component; its public entry points already were. That rippled into
NotificationChannels.Entry and the notification settings screen, which now
drives them from repeatOnLifecycle + produceState. FlowProgressForegroundService
.render is suspend, so are the POW-mining and Blossom-sync services.
ScheduledPostNotifier went suspend on both implementations (its only driver is
CoroutineWorker.doWork, and ScheduledPostPublisher's callbacks were already
suspend, so desktop is unaffected). PowDuration needed a @Composable pair and a
suspend pair - it is read from three screens and from the mining service.
TimeAgoFormatter became @Composable and lost its context parameter entirely.

Catalog: 1,906 keys moved, 67,275 elements across 57 locale dirs.
amethyst/res 2,051 -> 143 keys; commonsUI 3,016 -> 4,926. Four keys referenced
from AndroidManifest/res-xml (app_name, save, rename, block_hide_user) are
copied rather than moved; two that already existed in commons had their app-side
duplicates dropped. Nine keys using bare %d/%s were made positional across 480
elements - positional form is valid for Android too, so behaviour is unchanged.

tools/strings-migrate/migrate.py: the %% literal was read as a bare conversion
(the second % of `%1$d%% of all` started a fresh match and the space flag let
`% o` look like one), and a bulk @keyfile mode replaces ~110k per-key file
rewrites with one pass per file. Verified byte-identical to the old path on a
40-key sample across all 57 locale dirs.

StringResourceCache.kt keeps only painterRes - drawables are still Android
resources. The R.string overloads and the LruCache behind them are gone with the
last R.string reference; compose-resources caches each locale file itself.

Verified:
  - zero R.string / R.plurals references left in Kotlin
  - all 6,883 Res.string/Res.plurals references resolve to real catalog keys,
    no string-vs-plurals kind mismatches
  - .claude/hooks/orphan_strings_check.py passes; all 58 XML files parse
  - a per-key per-file reference guard confirms no key was lost (it caught a
    real bug: a Context-detector that matched any two-argument call ate the key
    in `stringRes(Res.string.x, arg)`, 344 references - the detector now uses an
    allowlist of expressions that are genuinely a Context)

NOT verified - this has never compiled. The container's shared egress IP is
rate-limited by Maven Central (~50% of requests answer 429) and Gradle disables
a repository on the first failure, so :amethyst:compileFdroidDebugKotlin could
not be driven to completion. Still needing a compiler: the scope classifications
(a stringRes(id) inside a non-composable lambda and a loadStringRes(id) outside
a coroutine are both compile errors), the 98 Int -> StringResource retypings,
and unused imports/vals left by the hoisting. Next: compile-fix loop,
spotlessApply, then lintFdroidBenchmark for ExtraTranslation.

Rationale and the per-file decisions are in
commons/plans/2026-09-22-strings-to-compose-resources.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXvKXakvup4inNFfAhhr4L
2026-09-22 15:06:49 +00:00
..

commons plans

Audited 2026-06-30 (+ 2026-09-12 split entry). 7 plans: 3 shipped, 2 in-progress, 2 queued, 0 abandoned.

In progress

Plan Summary
2026-05-04-custom-feeds-plan.md Custom feed creation/discovery/management for Desktop; core model + builder + kind 31890 + desktop UI shipped, but relay-filter layer, DVM marketplace, kind 10090 sync, and list resolution still pending.
2026-05-06-nest-subscription-manager-extraction.md Split the per-speaker subscription state machine out of NestViewModel; only the ActiveSubscription stepping-stone is extracted so far.

Queued

Plan Summary
2026-04-21-event-renderer.md Cross-platform UI-agnostic RenderedEvent subsystem shared by Amy, Desktop, and Android; not started.
2026-05-30-amethyst-to-commons-migration.md Roadmap to move shared amethyst Android code into commons; keystone Account/LocalCache extraction not begun.
2026-08-03-poll-results-page.md Extended NIP-88 poll results page (per-option counts + who voted for what) for Android and Desktop; also specifies four tally-correctness fixes and the missing poll-relay subscription. Proposed, not started.

Shipped

Plan Summary
2026-09-12-audit-findings.md Bug/performance audit of commons + commonsUI after the split: 34 verified fixes shipped, 4 deferred with rationale, 6 rejected.
2026-09-12-commons-ui-split.md Split the Compose half of commons into the new :commonsUI module (same packages, api(:commons)), so cli no longer carries Compose/Skiko; records the classification method and follow-ups.

Archived (shipped)

Plan Summary
archive/2026-05-04-custom-feeds-testing-sheet.md Test sheet recording the completed custom-feeds phases (unit + manual coverage).
archive/2026-05-05-feed-builder-enhancements-plan.md Six FeedBuilderDialog enhancements (npub decode, author search, kind filters, edit/delete, save-as-feed, exclude authors) — all landed.