Hide refresh for Manual, seed its rate from another source
Refreshing has no meaning for a manually-typed rate, so the button (and its loading spinner) is now hidden while Manual is selected. Switching to Manual for the first time now seeds its rate field from whichever source was active before, falling back to any other source's last cached rate for the default currency. When neither is available, the rate and amount fields are left empty instead of showing stale values. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy
This commit is contained in:
@@ -65,15 +65,17 @@ struct ContentView: View {
|
|||||||
} else {
|
} else {
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
if state.isLoading {
|
if !state.isManualSource {
|
||||||
ProgressView()
|
if state.isLoading {
|
||||||
} else {
|
ProgressView()
|
||||||
Button {
|
} else {
|
||||||
viewModel.refresh()
|
Button {
|
||||||
} label: {
|
viewModel.refresh()
|
||||||
Image(systemName: "arrow.clockwise")
|
} label: {
|
||||||
|
Image(systemName: "arrow.clockwise")
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderless)
|
||||||
}
|
}
|
||||||
.buttonStyle(.borderless)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,14 +195,16 @@ fun PriceScreen(
|
|||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state.isLoading) {
|
if (!state.isManualSource) {
|
||||||
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
if (state.isLoading) {
|
||||||
} else {
|
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
||||||
IconButton(onClick = { viewModel.refresh() }) {
|
} else {
|
||||||
Icon(
|
IconButton(onClick = { viewModel.refresh() }) {
|
||||||
Icons.Default.Refresh,
|
Icon(
|
||||||
contentDescription = stringResource(MR.strings.refresh_content_description),
|
Icons.Default.Refresh,
|
||||||
)
|
contentDescription = stringResource(MR.strings.refresh_content_description),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ class PriceViewModel(
|
|||||||
|
|
||||||
fun onSourceSelected(displayName: String) {
|
fun onSourceSelected(displayName: String) {
|
||||||
val selected = sources.firstOrNull { it.displayName == displayName } ?: return
|
val selected = sources.firstOrNull { it.displayName == displayName } ?: return
|
||||||
|
val previousRates = rates
|
||||||
currentSource = selected
|
currentSource = selected
|
||||||
rates = null
|
rates = null
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
@@ -216,6 +217,27 @@ class PriceViewModel(
|
|||||||
rateDisplays = emptyMap(),
|
rateDisplays = emptyMap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selected === manualSource && manualSource.rate == null) {
|
||||||
|
// Switching to Manual for the first time: seed it with whatever rate is already
|
||||||
|
// known for the default currency — the source just switched away from, or else
|
||||||
|
// whatever other source was last fetched — rather than starting blank.
|
||||||
|
viewModelScope.launch {
|
||||||
|
selectedSourceStore.saveSelectedSourceId(selected.id)
|
||||||
|
val seedRate = previousRates?.rates?.get(defaultCurrencyCode) ?: fallbackManualRate()
|
||||||
|
if (seedRate != null) {
|
||||||
|
manualSource.rate = seedRate
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(manualRateInput = formatAmount(seedRate, decimalDigitsFor(defaultCurrencyCode)))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_uiState.update { it.copy(pricedCurrencyCodes = emptySet()) }
|
||||||
|
}
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
selectedSourceStore.saveSelectedSourceId(selected.id)
|
selectedSourceStore.saveSelectedSourceId(selected.id)
|
||||||
seedFromCache(selected)
|
seedFromCache(selected)
|
||||||
@@ -223,6 +245,12 @@ class PriceViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The default currency's last known rate from any non-Manual source's cache, if any. */
|
||||||
|
private suspend fun fallbackManualRate(): BigDecimal? =
|
||||||
|
sources.filterNot { it === manualSource }.firstNotNullOfOrNull { source ->
|
||||||
|
exchangeRateStore.loadLastKnownRates(source.id)?.rates?.get(defaultCurrencyCode)
|
||||||
|
}
|
||||||
|
|
||||||
fun onManualRateChanged(value: String) {
|
fun onManualRateChanged(value: String) {
|
||||||
val sanitized = sanitizeDecimalInput(value)
|
val sanitized = sanitizeDecimalInput(value)
|
||||||
_uiState.update { it.copy(manualRateInput = sanitized) }
|
_uiState.update { it.copy(manualRateInput = sanitized) }
|
||||||
|
|||||||
Reference in New Issue
Block a user