Fix stale docs claiming web persistence is in-memory only

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
This commit is contained in:
2026-09-11 07:21:56 +03:00
co-authored by Claude Sonnet 5
parent feaa637c53
commit 3f15757449
3 changed files with 15 additions and 15 deletions
+8 -9
View File
@@ -12,12 +12,9 @@ and Android (see README's Supported Platforms/Download and Install). Web and
Desktop/JVM are real future release targets too — `desktopApp` already has
full native packaging configured (DMG/MSI/DEB, see its `build.gradle.kts`) —
but neither has a release/CI pipeline set up yet, so treat them as
not-yet-shipped rather than dev-only. Web specifically also has no real
persistence yet (see `data/db/SqlDelightStores.kt`'s doc comment: no
SQLDelight driver, in-memory only, nothing survives a page reload) — worth
keeping in mind if that platform's release plans firm up. The app converts
between BTC, Sats, and fiat currencies using live exchange rates (Coinbase,
CoinGecko, or a manually typed-in rate).
not-yet-shipped rather than dev-only. The app converts between BTC, Sats,
and fiat currencies using live exchange rates (Coinbase, CoinGecko, or a
manually typed-in rate).
This is a from-scratch rewrite of an earlier Skip-based (Swift-transpiled-to-
Kotlin) implementation — `main` is now this Kotlin Multiplatform project.
@@ -146,9 +143,11 @@ to call.
SQLDelight (`data/db/SqlDelightStores.kt` + platform-specific driver
`actual`s) backs `ExchangeRateStore`/`SelectedCurrenciesStore`/
`SelectedSourceStore`, each exposed via an `expect fun createXStore()`
factory. Web has no real SQLDelight driver — it gets an in-memory-only
fallback (nothing persists across a page reload). This is a known gap to
close if/when Web's release plans firm up, not a permanent design choice.
factory. Web has no real SQLDelight driver — SQLDelight's web driver needs a
worker plus a wasm sqlite binary — so it gets a `localStorage`-backed
fallback instead (`data/db/LocalStorageStores.kt`), which does survive page
reloads, just scoped to the browser profile/origin (cleared by clearing
site data, not shared across browsers/devices).
## Testing and verification
@@ -10,8 +10,8 @@ import kotlin.time.Instant
/**
* Shared by every platform that opens a real [AppDatabase] (Android, Desktop, iOS/macOS) only
* driver construction differs per platform, so that's the only expect/actual boundary needed.
* Web isn't a shipped platform (see README's Supported Platforms) and gets an in-memory fallback
* instead of a real driver.
* Web has no real SQLDelight driver and uses a `localStorage`-backed fallback instead (see
* `LocalStorageStores.kt`).
*/
internal class SqlDelightExchangeRateStore(private val database: AppDatabase) : ExchangeRateStore {
override suspend fun loadLastKnownRates(sourceId: String): ExchangeRates? = withContext(Dispatchers.Default) {
@@ -10,10 +10,11 @@ import xyz.tyiu.satsprice.data.ExchangeRates
import kotlin.time.Instant
/**
* Web isn't a shipped platform (see README's Supported Platforms) and SQLDelight's web driver
* needs a worker plus a wasm sqlite binary, so persistence here goes through the browser's
* localStorage instead of a real database plenty for this small amount of data, and it
* survives page reloads unlike the in-memory state it replaced.
* SQLDelight's web driver needs a worker plus a wasm sqlite binary, so persistence here goes
* through the browser's localStorage instead of a real database plenty for this small amount
* of data, and it survives page reloads like the other platforms' real databases do. Scoped to
* the browser profile/origin, though: it won't survive a cleared site data / private window, and
* doesn't sync or back up anywhere.
*/
private val json = Json { ignoreUnknownKeys = true }