Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-19 13:30:45 +03:00
parent 54216a69e5
commit 2d670ed6c4
10 changed files with 171 additions and 1 deletions

View file

@ -10,6 +10,8 @@ import com.tangem.domain.settings.repositories.AppRatingRepository
import com.tangem.domain.settings.repositories.PermissionRepository import com.tangem.domain.settings.repositories.PermissionRepository
import com.tangem.domain.settings.repositories.PromoSettingsRepository import com.tangem.domain.settings.repositories.PromoSettingsRepository
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
import com.tangem.tap.domain.sdk.TangemSdkManager import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.domain.settings.DefaultLegacySettingsRepository import com.tangem.tap.domain.settings.DefaultLegacySettingsRepository
import dagger.Module import dagger.Module
@ -212,4 +214,16 @@ internal object SettingsDomainModule {
return ShouldSaveAccessCodesUseCase(settingsRepository = settingsRepository) return ShouldSaveAccessCodesUseCase(settingsRepository = settingsRepository)
} }
// endregion // endregion
@Provides
@Singleton
fun provideFetchUserCountryCodeUseCase(settingsRepository: SettingsRepository): FetchUserCountryUseCase {
return FetchUserCountryUseCase(settingsRepository)
}
@Provides
@Singleton
fun provideGetUserCountryCodeUseCase(settingsRepository: SettingsRepository): GetUserCountryUseCase {
return GetUserCountryUseCase(settingsRepository)
}
} }

View file

@ -1,7 +1,9 @@
package com.tangem.datasource.api.tangemTech.models package com.tangem.datasource.api.tangemTech.models
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class GeoResponse( data class GeoResponse(
@Json(name = "code") val code: String, @Json(name = "code") val code: String,
) )

View file

@ -30,5 +30,6 @@ dependencies {
implementation(deps.kotlin.coroutines) implementation(deps.kotlin.coroutines)
implementation(deps.moshi) implementation(deps.moshi)
implementation(deps.moshi.kotlin) implementation(deps.moshi.kotlin)
implementation(deps.timber)
// endregion // endregion
} }

View file

@ -1,17 +1,31 @@
package com.tangem.data.settings package com.tangem.data.settings
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.GeoResponse
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
import com.tangem.datasource.local.preferences.utils.store import com.tangem.datasource.local.preferences.utils.store
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.models.UserCountry
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.util.Locale
internal class DefaultSettingsRepository( internal class DefaultSettingsRepository(
private val appPreferencesStore: AppPreferencesStore, private val appPreferencesStore: AppPreferencesStore,
private val appLogsStore: AppLogsStore, private val appLogsStore: AppLogsStore,
private val tangemTechApi: TangemTechApi,
private val dispatchers: CoroutineDispatcherProvider,
) : SettingsRepository { ) : SettingsRepository {
private val userCountryFlow = MutableStateFlow<UserCountry?>(value = null)
override suspend fun shouldShowSaveUserWalletScreen(): Boolean { override suspend fun shouldShowSaveUserWalletScreen(): Boolean {
return appPreferencesStore.getSyncOrDefault( return appPreferencesStore.getSyncOrDefault(
key = PreferencesKeys.SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY, key = PreferencesKeys.SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY,
@ -99,4 +113,38 @@ internal class DefaultSettingsRepository(
override suspend fun setMarketsTooltipShown(value: Boolean) { override suspend fun setMarketsTooltipShown(value: Boolean) {
appPreferencesStore.store(key = PreferencesKeys.SHOULD_SHOW_MARKETS_TOOLTIP_KEY, value = !value) appPreferencesStore.store(key = PreferencesKeys.SHOULD_SHOW_MARKETS_TOOLTIP_KEY, value = !value)
} }
override suspend fun getUserCountryCodeSync(): UserCountry? {
// If user country code is already set, return it
val countryCode = userCountryFlow.value
if (countryCode != null) return countryCode
coroutineScope {
launch { fetchUserCountryCode() }
}
return null
}
override suspend fun fetchUserCountryCode() {
Timber.i("Start fetching user country code")
withContext(dispatchers.io) {
val country = runCatching { tangemTechApi.getUserCountryCode() }
.fold(
onSuccess = GeoResponse::code,
onFailure = { Locale.getDefault().country },
)
.lowercase()
val code = when (country) {
UserCountry.Russia.code -> UserCountry.Russia
else -> UserCountry.Other(code = country)
}
Timber.i("User code country is $code")
userCountryFlow.value = code
}
}
} }

View file

@ -4,12 +4,14 @@ import com.tangem.data.settings.DefaultAppRatingRepository
import com.tangem.data.settings.DefaultPermissionRepository import com.tangem.data.settings.DefaultPermissionRepository
import com.tangem.data.settings.DefaultPromoSettingsRepository import com.tangem.data.settings.DefaultPromoSettingsRepository
import com.tangem.data.settings.DefaultSettingsRepository import com.tangem.data.settings.DefaultSettingsRepository
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.settings.repositories.AppRatingRepository import com.tangem.domain.settings.repositories.AppRatingRepository
import com.tangem.domain.settings.repositories.PermissionRepository import com.tangem.domain.settings.repositories.PermissionRepository
import com.tangem.domain.settings.repositories.PromoSettingsRepository import com.tangem.domain.settings.repositories.PromoSettingsRepository
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -25,8 +27,15 @@ internal object SettingsDataModule {
fun provideSettingsRepository( fun provideSettingsRepository(
appPreferencesStore: AppPreferencesStore, appPreferencesStore: AppPreferencesStore,
appLogsStore: AppLogsStore, appLogsStore: AppLogsStore,
tangemTechApi: TangemTechApi,
dispatchers: CoroutineDispatcherProvider,
): SettingsRepository { ): SettingsRepository {
return DefaultSettingsRepository(appPreferencesStore = appPreferencesStore, appLogsStore = appLogsStore) return DefaultSettingsRepository(
appPreferencesStore = appPreferencesStore,
appLogsStore = appLogsStore,
tangemTechApi = tangemTechApi,
dispatchers = dispatchers,
)
} }
@Provides @Provides

View file

@ -1,5 +1,7 @@
package com.tangem.domain.settings.repositories package com.tangem.domain.settings.repositories
import com.tangem.domain.settings.usercountry.models.UserCountry
interface SettingsRepository { interface SettingsRepository {
suspend fun shouldShowSaveUserWalletScreen(): Boolean suspend fun shouldShowSaveUserWalletScreen(): Boolean
@ -33,4 +35,8 @@ interface SettingsRepository {
suspend fun shouldShowMarketsTooltip(): Boolean suspend fun shouldShowMarketsTooltip(): Boolean
suspend fun setMarketsTooltipShown(value: Boolean) suspend fun setMarketsTooltipShown(value: Boolean)
suspend fun getUserCountryCodeSync(): UserCountry?
suspend fun fetchUserCountryCode()
} }

View file

@ -0,0 +1,28 @@
package com.tangem.domain.settings.usercountry
import arrow.core.Either
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.models.UserCountryError
/**
* Fetch user country use case
*
* @property settingsRepository settings repository
*
[REDACTED_AUTHOR]
*/
class FetchUserCountryUseCase(
private val settingsRepository: SettingsRepository,
) {
suspend operator fun invoke(): Either<UserCountryError, Unit> {
return either {
catch(
block = { settingsRepository.fetchUserCountryCode() },
catch = { raise(UserCountryError.DataError) },
)
}
}
}

View file

@ -0,0 +1,34 @@
package com.tangem.domain.settings.usercountry
import arrow.core.Either
import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.raise.ensureNotNull
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.models.UserCountry
import com.tangem.domain.settings.usercountry.models.UserCountryError
/**
* Get user country code use case
*
* @property settingsRepository settings repository
*
[REDACTED_AUTHOR]
*/
class GetUserCountryUseCase(
private val settingsRepository: SettingsRepository,
) {
suspend operator fun invoke(): Either<UserCountryError, UserCountry> {
return either {
val userCountryCode = catch(
block = { settingsRepository.getUserCountryCodeSync() },
catch = { raise(UserCountryError.DataError) },
)
ensureNotNull(userCountryCode) { UserCountryError.NotSetup }
userCountryCode
}
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.domain.settings.usercountry.models
/**
* User country
*
[REDACTED_AUTHOR]
*/
sealed class UserCountry(open val code: String) {
data object Russia : UserCountry("ru")
data class Other(override val code: String) : UserCountry(code)
}

View file

@ -0,0 +1,15 @@
package com.tangem.domain.settings.usercountry.models
/**
* User country error
*
[REDACTED_AUTHOR]
*/
sealed interface UserCountryError {
/** User country is still loading */
data object NotSetup : UserCountryError
/** Data error */
data object DataError : UserCountryError
}