11package com.getcode.opencode.internal.exchange
22
33import com.getcode.opencode.exchange.Exchange
4+ import com.getcode.opencode.internal.extensions.fromCode
5+ import com.getcode.opencode.internal.extensions.getClosestLocale
46import com.getcode.opencode.internal.network.services.CurrencyService
57import com.getcode.opencode.model.financial.Currency
68import com.getcode.opencode.model.financial.CurrencyCode
79import com.getcode.opencode.model.financial.Rate
8- import com.getcode.opencode.model.financial.RegionCode
910import com.getcode.services.opencode.R
1011import com.getcode.util.format
1112import com.getcode.util.locale.LocaleHelper
@@ -17,17 +18,13 @@ import com.getcode.utils.trace
1718import kotlinx.coroutines.CoroutineScope
1819import kotlinx.coroutines.Dispatchers
1920import kotlinx.coroutines.async
20- import kotlinx.coroutines.awaitAll
2121import kotlinx.coroutines.flow.Flow
2222import kotlinx.coroutines.flow.MutableStateFlow
2323import kotlinx.coroutines.launch
24- import kotlinx.coroutines.runBlocking
2524import kotlinx.coroutines.withContext
2625import kotlinx.datetime.Clock
2726import kotlinx.datetime.Instant
2827import java.util.Date
29- import java.util.Locale
30- import java.util.concurrent.ConcurrentHashMap
3128import javax.inject.Inject
3229import kotlin.time.Duration
3330import kotlin.time.Duration.Companion.minutes
@@ -38,16 +35,6 @@ internal class OpenCodeExchange @Inject constructor(
3835 private val locale : LocaleHelper ,
3936) : Exchange, CoroutineScope by CoroutineScope(Dispatchers .IO ) {
4037
41- private val currencies: List <Currency > by lazy {
42- runBlocking {
43- initCurrencies()
44- }
45- }
46-
47- private val currenciesMap: Map <String , Currency > by lazy {
48- currencies.associateBy { it.code }
49- }
50-
5138 private val _balanceRate = MutableStateFlow (Rate .oneToOne)
5239 override val balanceRate
5340 get() = _balanceRate .value
@@ -100,18 +87,18 @@ internal class OpenCodeExchange @Inject constructor(
10087
10188 override suspend fun getCurrenciesWithRates (rates : Map <CurrencyCode , Rate >): List <Currency > =
10289 withContext(Dispatchers .Default ) {
103- return @withContext currencies
104- .mapNotNull {
105- val code = CurrencyCode .tryValueOf(it.code) ? : return @mapNotNull null
90+ return @withContext CurrencyCode .entries
91+ .mapNotNull { code ->
10692 val rate = rates[code]?.fx ? : 0.0
107- it.copy(rate = rate)
93+ getCurrencyWithRate(code.name, rate)
10894 }
10995 }
11096
111- override fun getCurrency (code : String ): Currency ? = currenciesMap[code.uppercase()]
97+ override fun getCurrency (code : String ): Currency ? =
98+ CurrencyCode .tryValueOf(code)?.let { Currency .fromCode(it, resources) }
11299
113100 override fun getCurrencyWithRate (code : String , rate : Double ): Currency ? =
114- currenciesMap[code.uppercase()] ?.copy(rate = rate)
101+ getCurrency(code) ?.copy(rate = rate)
115102
116103 override fun getFlagByCurrency (currencyCode : String? ): Int? {
117104 currencyCode ? : return null
@@ -258,14 +245,10 @@ internal class OpenCodeExchange @Inject constructor(
258245 }
259246 }
260247
261- private fun getLocale (region : RegionCode ? ): Locale {
262- return Locale (Locale .getDefault().language, region?.name.orEmpty())
263- }
264-
265248 private suspend fun getCurrency (code : CurrencyCode , scope : CoroutineScope ): Currency {
266249 val resId = scope.async { getFlagByCurrency(code.name) }
267250 val currencyJava = scope.async { java.util.Currency .getInstance(code.name) }
268- val locale = scope.async { getLocale( code.getRegion() ) }
251+ val locale = scope.async { code.getClosestLocale( ) }
269252
270253 return Currency (
271254 code = currencyJava.await().currencyCode,
@@ -274,35 +257,6 @@ internal class OpenCodeExchange @Inject constructor(
274257 symbol = currencyJava.await().getSymbol(locale.await())
275258 )
276259 }
277-
278- private suspend fun initCurrencies (): List <Currency > {
279- val scope = CoroutineScope (Dispatchers .Default )
280-
281- val currencyMap = ConcurrentHashMap <String , Currency >()
282-
283- val chunkSize = 25
284- val chunks = CurrencyCode .entries.chunked(chunkSize)
285-
286- // Process each chunk asynchronously
287- val jobs = chunks.map { chunk ->
288- scope.async {
289- chunk.forEach { currencyCode ->
290- try {
291- val currency = getCurrency(currencyCode, scope)
292- currencyMap[currency.name] = currency
293- } catch (_: Exception ) {
294- // Handle exceptions if needed
295- }
296- }
297- }
298- }
299-
300- // Wait for all jobs to complete
301- jobs.awaitAll()
302-
303- // Sort the currencies by name
304- return currencyMap.values.sortedBy { it.name }
305- }
306260}
307261
308262private data class RatesBox (val dateMillis : Long , val rates : Map <CurrencyCode , Rate >) {
0 commit comments