Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fun SplashScreen(navigator: DestinationsNavigator) {
portfolioComponent.assetsRepo(),
coreComponent.prefs(),
coreComponent.buildConfigFieldsProvider().provide(),
coreComponent.currencyRepo(),
),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dev.arkbuilders.rate.presentation.splash
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import dev.arkbuilders.rate.core.domain.BuildConfigFields
import dev.arkbuilders.rate.core.domain.repo.CurrencyRepo
import dev.arkbuilders.rate.core.domain.repo.PreferenceKey
import dev.arkbuilders.rate.core.domain.repo.Prefs
import dev.arkbuilders.rate.feature.portfolio.domain.repo.PortfolioRepo
Expand All @@ -22,11 +23,14 @@ class SplashViewModel(
private val portfolioRepo: PortfolioRepo,
private val prefs: Prefs,
private val buildConfigFields: BuildConfigFields,
private val currencyRepo: CurrencyRepo,
) : ViewModel(), ContainerHost<Unit, SplashScreenEffect> {
override val container: Container<Unit, SplashScreenEffect> = container(Unit)

init {
intent {
currencyRepo.initialize()

val currentVersionCode = buildConfigFields.versionCode
val previousVersionCode = prefs.get(PreferenceKey.CurrentVersionCode)

Expand Down Expand Up @@ -70,13 +74,15 @@ class SplashViewModelFactory(
private val portfolioRepo: PortfolioRepo,
private val prefs: Prefs,
private val buildConfigFields: BuildConfigFields,
private val currencyRepo: CurrencyRepo,
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SplashViewModel(
quickRepo,
portfolioRepo,
prefs,
buildConfigFields,
currencyRepo,
) as T
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import arrow.core.left
import arrow.core.right
import dev.arkbuilders.rate.core.data.mapper.CryptoRateResponseMapper
import dev.arkbuilders.rate.core.data.network.api.CryptoAPI
import dev.arkbuilders.rate.core.domain.model.CurrencyCode
import dev.arkbuilders.rate.core.domain.model.CurrencyName
import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType
import javax.inject.Inject
Expand All @@ -27,6 +25,4 @@ class CryptoCurrencyDataSource @Inject constructor(
e.left()
}
}

override suspend fun getCurrencyName(): Map<CurrencyCode, CurrencyName> = emptyMap()
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package dev.arkbuilders.rate.core.data.repo.currency

import arrow.core.Either
import dev.arkbuilders.rate.core.domain.model.CurrencyCode
import dev.arkbuilders.rate.core.domain.model.CurrencyName
import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType

interface CurrencyDataSource {
val currencyType: CurrencyType

suspend fun fetchRemote(): Either<Throwable, List<CurrencyRate>>

suspend fun getCurrencyName(): Map<CurrencyCode, CurrencyName>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package dev.arkbuilders.rate.core.data.repo.currency

import android.content.Context
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import dev.arkbuilders.rate.core.data.R
import dev.arkbuilders.rate.core.domain.model.CurrencyCode
import dev.arkbuilders.rate.core.domain.model.CurrencyInfo
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CurrencyInfoDataSource @Inject constructor(
private val ctx: Context,
) {
suspend fun provide(): Map<CurrencyCode, CurrencyInfo> =
withContext(Dispatchers.IO) {
val nameDef: Deferred<Map<String, String>> =
async {
val codeNameText =
ctx.resources.openRawResource(R.raw.code_name).bufferedReader().use {
it.readText()
}
val codeNameType = object : TypeToken<Map<String, String>>() {}.type
Gson().fromJson(codeNameText, codeNameType)
}

val countryDef: Deferred<Map<String, List<String>>> =
async {
val codeCountryText =
ctx.resources.openRawResource(R.raw.code_country).bufferedReader().use {
it.readText()
}
val codeCountryType = object : TypeToken<Map<String, List<String>>>() {}.type
Gson().fromJson(codeCountryText, codeCountryType)
}

val codeToName = nameDef.await()
val codeToCountry = countryDef.await()

return@withContext codeToName.mapValues { (code, name) ->
CurrencyInfo(code, name, codeToCountry[code] ?: emptyList())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import arrow.core.Either
import arrow.core.left
import arrow.core.right
import dev.arkbuilders.rate.core.domain.AppConfig
import dev.arkbuilders.rate.core.domain.model.CurrencyName
import dev.arkbuilders.rate.core.domain.model.CurrencyCode
import dev.arkbuilders.rate.core.domain.model.CurrencyInfo
import dev.arkbuilders.rate.core.domain.model.CurrencyRate
import dev.arkbuilders.rate.core.domain.model.CurrencyType
import dev.arkbuilders.rate.core.domain.model.TimestampType
import dev.arkbuilders.rate.core.domain.repo.CurrencyRepo
import dev.arkbuilders.rate.core.domain.repo.NetworkStatus
Expand All @@ -28,10 +28,17 @@ class CurrencyRepoImpl @Inject constructor(
private val cryptoDataSource: CryptoCurrencyDataSource,
private val localCurrencyDataSource: LocalCurrencyDataSource,
private val fallbackRatesProvider: FallbackRatesProvider,
private val currencyInfoDataSource: CurrencyInfoDataSource,
private val timestampRepo: TimestampRepo,
private val networkStatus: NetworkStatus,
) : CurrencyRepo {
private val mutex = Mutex()
private val updateRatesMutex = Mutex()
private val loadInfoMutex = Mutex()
private var infoMap: Map<CurrencyCode, CurrencyInfo> = emptyMap()

override suspend fun initialize() {
loadInfo()
}

override suspend fun getCurrencyRates(): List<CurrencyRate> =
withContext(Dispatchers.IO) {
Expand All @@ -49,30 +56,27 @@ class CurrencyRepoImpl @Inject constructor(
}
}

override suspend fun getCurrencyNames(): List<CurrencyName> {
override suspend fun getCurrencyInfo(): List<CurrencyInfo> {
val rates = getCurrencyRates()

val fiatNames = fiatDataSource.getCurrencyName()
val cryptoNames = cryptoDataSource.getCurrencyName()
infoMap.ifEmpty { loadInfo() }

val names =
val ratesInfo =
rates.map { rate ->
var name =
when (rate.type) {
CurrencyType.FIAT -> fiatNames[rate.code]
CurrencyType.CRYPTO -> cryptoNames[rate.code]
}
if (name == null)
name = CurrencyName(rate.code, "")

name
infoMap[rate.code] ?: CurrencyInfo.emptyWithCode(rate.code)
}

return names.sortedBy { it.code }
return ratesInfo.sortedBy { it.code }
}

override suspend fun infoByCode(code: CurrencyCode): CurrencyInfo {
infoMap.ifEmpty { loadInfo() }

return infoMap[code] ?: CurrencyInfo.emptyWithCode(code)
}

private suspend fun updateRates(): Either<Throwable, List<CurrencyRate>> =
mutex.withLock {
updateRatesMutex.withLock {
val updatedDate =
timestampRepo
.getTimestamp(TimestampType.FetchRates)
Expand All @@ -96,6 +100,13 @@ class CurrencyRepoImpl @Inject constructor(
return rates
}

private suspend fun loadInfo() =
loadInfoMutex.withLock {
if (infoMap.isNotEmpty()) return@withLock

infoMap = currencyInfoDataSource.provide()
}

private fun hasUpdateIntervalPassed(updatedDate: OffsetDateTime?) =
updatedDate == null ||
Duration.between(updatedDate, OffsetDateTime.now())
Expand Down
Loading