Coverage Summary for Class: GetExchangeRatesUseCase (com.georgeci.moneysurfer.domain.usecase)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| GetExchangeRatesUseCase |
100%
(5/5)
|
90%
(9/10)
|
100%
(15/15)
|
100%
(32/32)
|
| GetExchangeRatesUseCase$baseCurrency$$inlined$flatMapLatest$1 |
0%
(0/1)
|
|
| GetExchangeRatesUseCase$baseCurrency$lambda$0$$inlined$map$1 |
0%
(0/2)
|
|
| GetExchangeRatesUseCase$baseCurrency$lambda$0$$inlined$map$1$1 |
|
| GetExchangeRatesUseCase$baseCurrency$lambda$0$$inlined$map$1$2 |
0%
(0/1)
|
|
| GetExchangeRatesUseCase$baseCurrency$lambda$0$$inlined$map$1$2$1 |
|
| GetExchangeRatesUseCase$invoke$$inlined$flatMapLatest$1 |
0%
(0/1)
|
|
| GetExchangeRatesUseCase$ratesFor$1 |
100%
(1/1)
|
|
100%
(2/2)
|
100%
(43/43)
|
| GetExchangeRatesUseCase$ratesFor$1$1 |
100%
(1/1)
|
|
100%
(1/1)
|
100%
(25/25)
|
| GetExchangeRatesUseCase$ratesFor$1$2 |
100%
(1/1)
|
|
100%
(1/1)
|
100%
(11/11)
|
| Total |
61.5%
(8/13)
|
90%
(9/10)
|
100%
(19/19)
|
100%
(111/111)
|
package com.georgeci.moneysurfer.domain.usecase
import com.georgeci.moneysurfer.domain.auth.SessionPointers
import com.georgeci.moneysurfer.domain.model.ExchangeRateSnapshot
import com.georgeci.moneysurfer.domain.primitives.CurrencyCode
import com.georgeci.moneysurfer.domain.repositories.ExchangeRateRepository
import com.georgeci.moneysurfer.domain.repositories.WorkspaceRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import org.koin.core.annotation.Single
/**
* Rates for whatever base currency the active workspace is on, kept current.
*
* The refresh is launched *beside* the cache stream rather than before it: collectors get the
* cached table (possibly `null`) on the first frame and the refreshed one whenever it lands, so
* a slow or dead network delays nothing on screen. Switching workspace — or changing the
* workspace currency — re-points both halves at the new base.
*
* Emits `null` while no workspace is selected.
*/
@Single
@OptIn(ExperimentalCoroutinesApi::class)
class GetExchangeRatesUseCase(
private val session: SessionPointers,
private val workspaceRepository: WorkspaceRepository,
private val exchangeRates: ExchangeRateRepository,
) {
operator fun invoke(): Flow<ExchangeRateSnapshot?> =
baseCurrency()
.distinctUntilChanged()
.flatMapLatest { base ->
if (base == null) flowOf(null) else ratesFor(base)
}
private fun baseCurrency(): Flow<CurrencyCode?> =
session.currentWorkspaceId.flatMapLatest { workspaceId ->
if (workspaceId == null) {
flowOf(null)
} else {
workspaceRepository.getAll()
.map { workspaces -> workspaces.firstOrNull { it.id == workspaceId }?.baseCurrency }
}
}
private fun ratesFor(base: CurrencyCode): Flow<ExchangeRateSnapshot> = channelFlow {
launch { exchangeRates.refreshIfStale(base) }
exchangeRates.observe(base).collect { table -> send(ExchangeRateSnapshot(base, table)) }
}
}