refactor: WalletViewModel extract FiatViewModel
This commit is contained in:
@@ -13,22 +13,18 @@ import com.bitcointxoko.gudariwallet.util.RouteHintAnalyzer
|
||||
import com.bitcointxoko.gudariwallet.util.SendInputDetector
|
||||
import com.bitcointxoko.gudariwallet.util.SendInputType
|
||||
import com.bitcointxoko.gudariwallet.util.WalletConstants
|
||||
import com.bitcointxoko.gudariwallet.util.satsToFiat
|
||||
import com.bitcointxoko.gudariwallet.util.parseApiError
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import com.bitcointxoko.gudariwallet.util.lnurlProtocolError
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.bitcointxoko.gudariwallet.api.RouteHintHop
|
||||
import com.bitcointxoko.gudariwallet.data.BalancePrefsStore
|
||||
import com.bitcointxoko.gudariwallet.data.FiatRateCache
|
||||
import com.bitcointxoko.gudariwallet.ui.balance.BalanceViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.fiat.FiatViewModel
|
||||
import com.bitcointxoko.gudariwallet.util.BiometricHelper
|
||||
|
||||
private const val TAG = "WalletViewModel"
|
||||
@@ -40,60 +36,22 @@ class WalletViewModel(
|
||||
val paymentCache: PaymentCacheRepository,
|
||||
private val balancePrefs: BalancePrefsStore,
|
||||
val balanceVm : BalanceViewModel,
|
||||
val fiatVm : FiatViewModel
|
||||
) : ViewModel() {
|
||||
|
||||
// ── Balance state ─────────────────────────────────────────────────────────
|
||||
val balanceState: StateFlow<BalanceState> get() = balanceVm.balanceState
|
||||
// ── Balance visible state ─────────────────────────────────────────────────
|
||||
private val _balanceHidden = MutableStateFlow(balancePrefs.isBalanceHidden)
|
||||
val balanceHidden: StateFlow<Boolean> = _balanceHidden
|
||||
fun toggleBalanceVisibility() {
|
||||
val next = !_balanceHidden.value
|
||||
_balanceHidden.value = next
|
||||
balancePrefs.setBalanceHidden(next)
|
||||
}
|
||||
|
||||
// ── Fiat cache ────────────────────────────────────────────────────────────
|
||||
private val fiatCache = FiatRateCache(balancePrefs)
|
||||
val fiatRate: Double?
|
||||
get() = fiatCache.currentRate
|
||||
val fiatCurrency: String? get() = _selectedCurrency.value
|
||||
val fiatSatsPerUnit: StateFlow<Double?> = balanceVm.balanceState
|
||||
.mapNotNull { state ->
|
||||
(state as? BalanceState.Success)?.let { s ->
|
||||
if (s.fiatAmount != null && s.sats > 0)
|
||||
s.sats.toDouble() / s.fiatAmount
|
||||
else null
|
||||
}
|
||||
}
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = null
|
||||
)
|
||||
private val _selectedCurrency = MutableStateFlow(balancePrefs.selectedCurrency)
|
||||
val selectedCurrency: StateFlow<String?> = _selectedCurrency
|
||||
|
||||
fun setSelectedCurrency(currency: String?) {
|
||||
if (currency == _selectedCurrency.value) return
|
||||
_selectedCurrency.value = currency
|
||||
balancePrefs.setSelectedCurrency(currency)
|
||||
fiatCache.invalidateRate()
|
||||
Log.d(TAG, "FIAT [CURRENCY ] changed to ${currency ?: "none"} — cache invalidated")
|
||||
if (currency != null) {
|
||||
viewModelScope.launch { fetchAndApplyFiatRate() }
|
||||
} else {
|
||||
balanceVm.applyFiat(null, null) // ← fix
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val RATE_TTL_MS = 5 * 60 * 1_000L // 5 minutes
|
||||
}
|
||||
val balanceHidden: StateFlow<Boolean> get() = fiatVm.balanceHidden
|
||||
val selectedCurrency: StateFlow<String?> get() = fiatVm.selectedCurrency
|
||||
val fiatSatsPerUnit: StateFlow<Double?> get() = fiatVm.fiatSatsPerUnit
|
||||
fun toggleBalanceVisibility() = fiatVm.toggleBalanceVisibility()
|
||||
fun setSelectedCurrency(c: String?) = fiatVm.setSelectedCurrency(c)
|
||||
suspend fun getSupportedCurrencies() = fiatVm.getSupportedCurrencies()
|
||||
val fiatRate: Double? get() = fiatVm.fiatRate
|
||||
val fiatCurrency: String? get() = fiatVm.fiatCurrency
|
||||
|
||||
|
||||
// ── Other states ──────────────────────────────────────────────────────────
|
||||
|
||||
private val _receiveState = MutableStateFlow<ReceiveState>(ReceiveState.Idle)
|
||||
val receiveState: StateFlow<ReceiveState> = _receiveState
|
||||
private val _sendState = MutableStateFlow<SendState>(SendState.Idle)
|
||||
@@ -110,48 +68,7 @@ class WalletViewModel(
|
||||
fetchLightningAddress()
|
||||
}
|
||||
|
||||
// ── Fiat rate fetch + apply ───────────────────────────────────────────────
|
||||
private suspend fun fetchAndApplyFiatRate() {
|
||||
val currency = _selectedCurrency.value ?: return
|
||||
|
||||
val rate: Double = fiatCache.getRate(currency, RATE_TTL_MS)
|
||||
?: run {
|
||||
runCatching { repo.getFiatRate(currency) }
|
||||
.getOrElse { e ->
|
||||
Log.w(TAG, "FIAT [RATE ERROR ] $currency — ${e.message}")
|
||||
Log.w(TAG, "FIAT [RATE MISS ] $currency — no fallback available, suppressing fiat display")
|
||||
return
|
||||
}
|
||||
.also { fresh -> fiatCache.putRate(currency, fresh) }
|
||||
}
|
||||
|
||||
// ← fix: delegate to balanceVm instead of writing to _balanceState
|
||||
val currentSats = (balanceVm.balanceState.value as? BalanceState.Success)?.sats ?: return
|
||||
val fiat = satsToFiat(currentSats, rate)
|
||||
Log.d(TAG, "FIAT [APPLY ] $currentSats sats ÷ $rate sats/$currency = $fiat $currency")
|
||||
balanceVm.applyFiat(fiat, currency)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ── Currency list ────────────────────────────────────────────────────────
|
||||
suspend fun getSupportedCurrencies(): List<String> {
|
||||
fiatCache.getCurrencies()?.let { return it }
|
||||
// Cache miss (memory + disk) — fetch from network
|
||||
return fetchAndCacheCurrencies()
|
||||
}
|
||||
|
||||
private suspend fun fetchAndCacheCurrencies(): List<String> {
|
||||
return runCatching { repo.getSupportedCurrencies() }
|
||||
.getOrElse { e ->
|
||||
Log.w(TAG, "FIAT [CURRENCIES] network fetch failed — ${e.message}")
|
||||
emptyList()
|
||||
}
|
||||
.also { list -> fiatCache.putCurrencies(list) }
|
||||
}
|
||||
|
||||
// ── WebSocket event collection ────────────────────────────────────────────
|
||||
|
||||
private fun observePaymentEvents() {
|
||||
viewModelScope.launch {
|
||||
balanceVm.incomingPayment.collect { event ->
|
||||
|
||||
Reference in New Issue
Block a user