Updated on 2026-08-14
This commit is contained in:
parent
c500f45307
commit
a25cbc8d24
5 changed files with 209 additions and 0 deletions
|
|
@ -0,0 +1,43 @@
|
|||
package com.tangem.datasource.api.common
|
||||
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import okio.IOException
|
||||
|
||||
/**
|
||||
* Switch base url [Interceptor]
|
||||
*
|
||||
* @property id api config id [ApiConfig.ID]
|
||||
* @property apiConfigsManager api configs manager
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class SwitchBaseUrlInterceptor(
|
||||
private val id: ApiConfig.ID,
|
||||
private val apiConfigsManager: ApiConfigsManager,
|
||||
) : Interceptor {
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
var request = chain.request()
|
||||
val builder = request.newBuilder()
|
||||
|
||||
request = builder
|
||||
.url(url = request.url.adjustBaseUrl())
|
||||
.build()
|
||||
|
||||
return chain.proceed(request)
|
||||
}
|
||||
|
||||
private fun HttpUrl.adjustBaseUrl(): HttpUrl {
|
||||
val host = apiConfigsManager.getBaseUrl(id).toHttpUrl().host
|
||||
|
||||
return this.newBuilder()
|
||||
.host(host)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.tangem.datasource.api.common.config.managers
|
||||
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectMap
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
/**
|
||||
* Implementation of [ApiConfigsManager] in DEV environment
|
||||
*
|
||||
* @property appPreferencesStore app preferences store
|
||||
* @property dispatchers coroutine dispatcher provider
|
||||
*/
|
||||
internal class DevApiConfigsManager(
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MutableApiConfigsManager {
|
||||
|
||||
override val configs: Flow<List<ApiConfig>> get() = _apiConfigs
|
||||
|
||||
private val _apiConfigs = MutableStateFlow(value = ApiConfig.values())
|
||||
|
||||
override suspend fun initialize() {
|
||||
// We can't use appPreferencesStore.getObjectMap as base flow,
|
||||
// because we should keep possibility to work with configs synchronous.
|
||||
// See [getBaseUrl]
|
||||
appPreferencesStore.getObjectMap<ApiEnvironment>(PreferencesKeys.apiConfigsEnvironmentKey)
|
||||
.onEach { savedEnvironments ->
|
||||
_apiConfigs.value = _apiConfigs.value.map { config ->
|
||||
val savedEnvironment = savedEnvironments[config.id.name]
|
||||
|
||||
if (savedEnvironment != null) {
|
||||
config.copySealed(currentEnvironment = savedEnvironment)
|
||||
} else {
|
||||
config
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(CoroutineScope(dispatchers.main))
|
||||
}
|
||||
|
||||
override fun getBaseUrl(id: ApiConfig.ID): String {
|
||||
val config = _apiConfigs.value.firstOrNull { it.id == id }
|
||||
?: error("Api config with id [$id] not found. Check ApiConfig implementations")
|
||||
|
||||
return config.environments[config.currentEnvironment]
|
||||
?: error(
|
||||
"Api config with id [$id] doesn't contain environment [${config.currentEnvironment}]. " +
|
||||
"Check ApiConfig implementations",
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun changeEnvironment(id: String, environment: ApiEnvironment) {
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
val updatedMap = mutablePreferences.getObjectMap<ApiEnvironment>(PreferencesKeys.apiConfigsEnvironmentKey)
|
||||
.toMutableMap()
|
||||
.apply { put(id, environment) }
|
||||
|
||||
mutablePreferences.setObjectMap(PreferencesKeys.apiConfigsEnvironmentKey, updatedMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.datasource.api.common.config.managers
|
||||
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
|
||||
/** Implementation of [ApiConfigsManager] in PROD environment */
|
||||
internal class ProdApiConfigsManager : ApiConfigsManager {
|
||||
|
||||
override fun getBaseUrl(id: ApiConfig.ID): String {
|
||||
val config = ApiConfig.values().firstOrNull { it.id == id }
|
||||
?: error("Api config with id [$id] not found. Check ApiConfig implementations")
|
||||
|
||||
return config.environments[config.currentEnvironment]
|
||||
?: error(
|
||||
"Api config with id [$id] doesn't contain " +
|
||||
"environment [${config.currentEnvironment}]. Check ApiConfig implementations",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -95,6 +95,8 @@ object PreferencesKeys {
|
|||
booleanPreferencesKey(name = "isTokenSwapPromoOkxShown")
|
||||
}
|
||||
|
||||
val apiConfigsEnvironmentKey by lazy { stringPreferencesKey(name = "apiConfigsEnvironment") }
|
||||
|
||||
// region Permission
|
||||
fun getShouldShowPermission(permission: String) = booleanPreferencesKey("shouldShowPushPermission_$permission")
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
package com.tangem.datasource.api.common.config.managers
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.datasource.BuildConfig
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.DEBUG_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.EXTERNAL_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.INTERNAL_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD_TYPE
|
||||
import com.tangem.datasource.api.common.config.Express
|
||||
import com.tangem.datasource.api.common.config.TangemTech
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@RunWith(Parameterized::class)
|
||||
internal class ProdApiConfigsManagerTest(private val model: Model) {
|
||||
|
||||
private val manager = ProdApiConfigsManager()
|
||||
|
||||
@Test
|
||||
fun test_getBaseUrl() {
|
||||
val actual = manager.getBaseUrl(id = model.id)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(model.expected)
|
||||
}
|
||||
|
||||
data class Model(val id: ApiConfig.ID, val expected: String)
|
||||
|
||||
private companion object {
|
||||
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters
|
||||
fun data(): Collection<Model> = ApiConfig.values().map {
|
||||
when (it) {
|
||||
is Express -> createExpressModel()
|
||||
is TangemTech -> createTangemTechModel()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createExpressModel(): Model {
|
||||
return Model(
|
||||
id = ApiConfig.ID.Express,
|
||||
expected = when (BuildConfig.BUILD_TYPE) {
|
||||
DEBUG_BUILD_TYPE -> "[REDACTED_ENV_URL]"
|
||||
INTERNAL_BUILD_TYPE,
|
||||
MOCKED_BUILD_TYPE,
|
||||
-> "[REDACTED_ENV_URL]"
|
||||
EXTERNAL_BUILD_TYPE,
|
||||
RELEASE_BUILD_TYPE,
|
||||
-> "https://express.tangem.com/v1/"
|
||||
else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun createTangemTechModel(): Model {
|
||||
return Model(
|
||||
id = ApiConfig.ID.TangemTech,
|
||||
expected = when (BuildConfig.BUILD_TYPE) {
|
||||
DEBUG_BUILD_TYPE,
|
||||
INTERNAL_BUILD_TYPE,
|
||||
-> "https://devapi.tangem-tech.com/v1/"
|
||||
MOCKED_BUILD_TYPE,
|
||||
EXTERNAL_BUILD_TYPE,
|
||||
RELEASE_BUILD_TYPE,
|
||||
-> "https://api.tangem-tech.com/v1/"
|
||||
else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue