diff --git a/iosApp/iosApp/ContentView.swift b/iosApp/iosApp/ContentView.swift
index ebe6d1b..53759a7 100644
--- a/iosApp/iosApp/ContentView.swift
+++ b/iosApp/iosApp/ContentView.swift
@@ -37,6 +37,21 @@ struct ContentView: View {
: state.fiatRows
}
+ /// Nil for Manual (a manually typed rate has no "last updated" moment to show). Doesn't name
+ /// the price source — just when the rate was last fetched.
+ private func statusText(for state: IosConverterState) -> String? {
+ if state.isManualSource {
+ return nil
+ }
+ if let dateTime = state.lastUpdatedDateTime {
+ return IosLocalizationKt.localizedFormattedString(
+ resource: MR.strings.shared.updated_status,
+ args: [dateTime]
+ )
+ }
+ return IosLocalizationKt.localizedString(resource: MR.strings.shared.loading_rates_status)
+ }
+
#if os(macOS)
/// [codes] with [moving] relocated to sit right before [target] — how macOS's manual
/// drag-and-drop (see `.dropDestination` above) computes its new currency order, since
@@ -56,8 +71,8 @@ struct ContentView: View {
Form {
Section(
footer: Group {
- if !state.statusLine.isEmpty {
- Text(state.statusLine)
+ if let statusText = statusText(for: state) {
+ Text(statusText)
}
}
) {
diff --git a/shared/src/appleMain/kotlin/xyz/tyiu/satsprice/IosPriceViewModel.kt b/shared/src/appleMain/kotlin/xyz/tyiu/satsprice/IosPriceViewModel.kt
index 357b116..7c59a8e 100644
--- a/shared/src/appleMain/kotlin/xyz/tyiu/satsprice/IosPriceViewModel.kt
+++ b/shared/src/appleMain/kotlin/xyz/tyiu/satsprice/IosPriceViewModel.kt
@@ -9,9 +9,9 @@ import xyz.tyiu.satsprice.ui.PriceViewModel
import xyz.tyiu.satsprice.ui.currentCurrency
import xyz.tyiu.satsprice.ui.defaultCurrencyRate
import xyz.tyiu.satsprice.ui.exceedsMaxSupply
+import xyz.tyiu.satsprice.ui.lastUpdatedDateTime
import xyz.tyiu.satsprice.ui.oneCurrencyToSats
import xyz.tyiu.satsprice.ui.selectedOtherCurrencies
-import xyz.tyiu.satsprice.ui.statusLine
import xyz.tyiu.satsprice.ui.unselectedCurrencies
data class FiatRow(val code: String, val amount: String, val rateDisplay: String)
@@ -34,7 +34,7 @@ data class IosConverterState(
val manualSatsPerCurrencyInput: String,
val isLoading: Boolean,
val errorMessage: String?,
- val statusLine: String,
+ val lastUpdatedDateTime: String?,
val defaultCurrencyRate: String,
val oneCurrencyToSats: String,
)
@@ -89,7 +89,7 @@ private fun ConverterUiState.toIosState(): IosConverterState = IosConverterState
manualSatsPerCurrencyInput = manualSatsPerCurrencyInput,
isLoading = isLoading,
errorMessage = errorMessage,
- statusLine = statusLine(),
+ lastUpdatedDateTime = lastUpdatedDateTime(),
defaultCurrencyRate = defaultCurrencyRate(),
oneCurrencyToSats = oneCurrencyToSats(),
)
diff --git a/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/ConverterUiStateDisplay.kt b/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/ConverterUiStateDisplay.kt
index 357bbb5..24945ff 100644
--- a/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/ConverterUiStateDisplay.kt
+++ b/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/ConverterUiStateDisplay.kt
@@ -11,10 +11,16 @@ import kotlin.time.Instant
/** Derived display strings/flags shared between the Compose UI and the iOS SwiftUI bridge. */
-fun ConverterUiState.statusLine(): String {
- if (isManualSource) return ""
- val updated = lastUpdated?.let { "updated ${it.toDateTimeString()}" } ?: "loading rates…"
- return if (sourceName.isEmpty()) updated else "via $sourceName, $updated"
+/**
+ * The current platform's locale-formatted rendering of [ConverterUiState.lastUpdated] — just the
+ * date/time itself, not the surrounding localized "Updated ..."/"Loading rates…" text, since this
+ * shared code has no Composable/moko-resources context to resolve a localized string from; the UI
+ * layer supplies that around whatever this returns. Null while manual (nothing to show — a
+ * manually typed rate has no "last updated" moment) or before the first fetch completes.
+ */
+fun ConverterUiState.lastUpdatedDateTime(): String? {
+ if (isManualSource) return null
+ return lastUpdated?.toDateTimeString()
}
fun ConverterUiState.exceedsMaxSupply(): Boolean {
diff --git a/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt b/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt
index f1e7183..1ecf2b3 100644
--- a/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt
+++ b/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt
@@ -141,8 +141,13 @@ fun PriceScreen(
) {
Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) {
Text("SatsPrice", style = MaterialTheme.typography.headlineMedium)
- val statusLine = state.statusLine()
- if (statusLine.isNotEmpty()) {
+ val statusLine = if (state.isManualSource) {
+ null
+ } else {
+ state.lastUpdatedDateTime()?.let { stringResource(MR.strings.updated_status, it) }
+ ?: stringResource(MR.strings.loading_rates_status)
+ }
+ if (statusLine != null) {
Text(
text = statusLine,
style = MaterialTheme.typography.bodySmall,
diff --git a/shared/src/commonMain/moko-resources/base/strings.xml b/shared/src/commonMain/moko-resources/base/strings.xml
index 442d3b2..2129553 100644
--- a/shared/src/commonMain/moko-resources/base/strings.xml
+++ b/shared/src/commonMain/moko-resources/base/strings.xml
@@ -15,6 +15,7 @@
%1$s to Sats
Done
Exceeds the %1$s maximum supply
+ Loading rates…
Move down
Move to bottom
Move to top
@@ -31,4 +32,5 @@
Search currencies
Selected Currencies
Unpriced Currencies
+ Updated %1$s