Files
amethyst/tools/strings-migrate
Claude 3d03c82970 fix: audit follow-ups for the commons move - Compose string whitespace, backup labels, store edge cases
The one real regression predates this branch: Compose resources draw a value's
XML whitespace verbatim, where aapt collapsed it. Values wrapped over indented
lines rendered with a leading line break and eight spaces, which turns the
account-backup tips' markdown heading into a code block, and Crowdin's stray
translator edge spaces (" miejsca zniknęły", Hindi's " दि॰" suffix) showed up.
fix_escapes.py now applies aapt's rule to line-break/tab runs and trims an
edge space a translation has but its source lacks. The Crowdin workflow
already runs it after each sync, and compose_escaping_check.py now fails on raw
line breaks. 598 values across 54 files repaired.

Also:
- rememberPresentation resolves only the labels its diff type writes, instead
  of all 16 on every recomposition. A test pins the list against presentationOf.
- ScheduledPostStore: a failed stat is "no file" (okio posix throws on EACCES
  where File.exists() did not), symlinked stores still count, no chmod against
  an injected non-system FileSystem, the cleanup log keeps its throwable.
- ClickableEmail percent-encodes '%' in the mailto: URI.
- Dropped a misleading WatchScrollToTop import, a stray blank line, and a stale
  doc path; noted the Base64 pad-bit difference beside the decoder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjQQN9CgWHVtNCSWqnKoqY
2026-09-26 22:03:54 +00:00
..

strings-migrate

Moves string keys from the Android app's res/ into commons Compose resources (commonsUI/src/commonMain/composeResources) across all locales in one shot, preserving each element byte-for-byte so Crowdin sees a pure move. Both trees are Crowdin-managed with the same android layout (see crowdin.yml), so a migrated key keeps its translations.

tools/strings-migrate/migrate.py copy_to_clipboard relay_info

After migrating, repoint the code: R.string.key becomes Res.string.key (com.vitorpamplona.amethyst.commons.resources), and the composable keeps calling stringRes(...) via the commons bridge (com.vitorpamplona.amethyst.commons.ui.stringRes).

The tool refuses keys whose value uses bare %s/%d: compose-resources only formats positional %1$s args. Rewrite those keys (code and every locale) first.