Strings.kt is now generated at build time (:webHtmlApp:generateStrings,
in webHtmlApp/build.gradle.kts) by parsing shared's strings.xml
directly, rather than a hand-maintained duplicate that could silently
drift from it. Names are mechanical camelCase of the XML key, so a few
call sites got more verbose (e.g. moveUp -> moveCurrencyUpContentDescription)
in exchange for zero manual sync. Only covers the base English locale.
Also collapses currency_option_label_local into currency_option_label:
the two had identical English text and existed only as a hook for a
future translation to phrase the user's own currency differently, which
no locale currently does. Removes the info.code == localeCurrencyCode
branching (and the now-pointless localeCurrencyCode parameter/field) from
all three UI implementations - PriceScreen.kt, CurrencyPickerSheet.swift,
and HtmlCurrencyPicker.kt - plus IosConverterState.localeCurrencyCode,
which existed solely to feed that branch on the Swift side.
Fixes a real regression surfaced while verifying the above by actually
building the Xcode project (not done since currencyFlagEmoji() gained
its supportsFlagEmoji parameter): Kotlin/Native doesn't generate
default-parameter overloads for Swift/ObjC-exported functions, so both
Swift call sites needed the argument passed explicitly, via the correct
exported facade name for an expect/actual pair - the actual file's
(SystemCurrencies_appleKt), not the common one (SystemCurrenciesKt).
Also drops "(DOM)" from webHtmlApp's page title.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
webHtmlApp is a new web build using Compose HTML instead of Compose
Multiplatform UI's Skia/canvas renderer - real <select>/<input>/<button>
elements, an anchored popup menu for reordering/removing currencies
(Compose HTML has no built-in DropdownMenu), and locale-independent
English strings (moko-resources' Compose integration pulls in
compose.foundation/ui, which this module exists to avoid).
Realizing the bundle-size win needed splitting sharedUi out of shared:
the Compose Multiplatform Gradle plugin bundles Skiko's several-MB web
runtime into any js/wasmJs target whose resolved dependencies contain
org.jetbrains.compose.ui:ui anywhere, and shared previously declared it
directly for the other (Skia-based) web app's UI. shared is now pure
business/data logic with no Compose dependency; sharedUi holds App()/
PriceScreen() for androidApp, desktopApp, and webApp to render.
PriceViewModel's ViewModel supertype and CurrencyConverter's BigDecimal
params moved from implementation() to api() in shared, since they're
part of its public surface that webHtmlApp now touches directly.
Also drops the @js-joda/timezone dependency from both web builds: the
app only ever calls TimeZone.currentSystemDefault(), which resolves to
a synthetic zone backed by the native Date offset on Kotlin/JS and
never touches the tz database - confirmed empirically on both js and
wasmJs targets. Cuts webApp's js bundle by ~950 KB and webHtmlApp's by
~800 KB.
currencyFlagEmoji() gained an explicit supportsFlagEmoji parameter
(defaulting to the existing expect/actual, false on web) so webHtmlApp
can opt in - Compose HTML renders real DOM text, so flag emoji work
fine there even though they don't on Compose Multiplatform's canvas.
website/serve-local.sh now builds and serves webHtmlApp instead of
webApp's wasmJs build, so it no longer mirrors what's actually deployed
to production; docs updated to reflect the new module layout and that
divergence, and the Pages workflow's path trigger now includes
sharedUi/** so UI changes there still redeploy the site.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The GitHub Pages workflow now builds the Compose wasmJs web app and
publishes it alongside the marketing site, so it's reachable at
/app/. Add nav/hero/download links to it and list Web among the
supported platforms. Add website/serve-local.sh to reproduce the
production layout locally, and document the setup in README/AGENTS.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Web actually persists via localStorage (LocalStorageStores.kt), which
survives page reloads — only SQLDelight itself isn't used there, since
its web driver needs a worker plus a wasm sqlite binary. The doc
comments and AGENTS.md still described the in-memory state this
replaced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy
Desktop and Web are real future release targets, not permanent
dev-only/preview builds — they just lack a release/CI pipeline yet.
desktopApp already has full DMG/MSI/DEB packaging configured, and
webApp has production-build groundwork in place.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy
Drop the "developed on kmp, not main" framing now that kmp is merging
into main, which becomes the sole Kotlin Multiplatform implementation.
Keeps the warning about stale pre-rewrite branches (e.g. update-readme)
still describing the old Skip/SPM workflow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy
README: drop the stale Skip attribution line (the project moved to
Kotlin Multiplatform entirely; the "Kotlin Multiplatform" line below
it already covers the current tooling) and fix the stated minimum
Android version — androidApp's actual minSdk is 24 (Android 7.0), not
10.0.
AGENTS.md: a navigation/orientation doc for AI agents, focused on the
things that aren't obvious from reading the code or that took real
trial-and-error to establish this session — the localization
architecture constraint (no synchronous, cross-platform way to
resolve a moko-resources string outside Compose/Apple, so shared code
must return data, not sentences), the Swift-interop plain-function
convention, per-platform currency-data quirks (web's ICU-dependent
currency list, missing color-emoji font), and the verification
workflow for each platform (especially that Compose for Web renders
to a <canvas>, so headless Chrome + specific GL flags is the way to
actually see a change, not DOM inspection).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy