From 41d216b4a861f0a6186c4df1ef7c4cfd61710507 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 15 Jul 2025 15:14:43 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../api/common/config/ApiEnvironment.kt | 3 + .../datasource/api/common/config/Express.kt | 7 ++ .../visa/DefaultVisaActivationRepository.kt | 1 + .../ui/EnvironmentTogglesScreen.kt | 119 +++++++++++------- .../utils/ApiEnvironmentComparator.kt | 7 +- 5 files changed, 91 insertions(+), 46 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiEnvironment.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiEnvironment.kt index 19fc906239..c6e72a8a75 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiEnvironment.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiEnvironment.kt @@ -13,6 +13,9 @@ enum class ApiEnvironment { @Json(name = "DEV") DEV, + @Json(name = "DEV_2") + DEV_2, + @Json(name = "STAGE") STAGE, diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt index af3ce61013..23b46cf40b 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt @@ -27,6 +27,7 @@ internal class Express( override val environmentConfigs: List = listOf( createDevEnvironment(), + createDev2Environment(), createStageEnvironment(), createMockedEnvironment(), createProdEnvironment(), @@ -53,6 +54,12 @@ internal class Express( headers = createHeaders(isProd = false), ) + private fun createDev2Environment(): ApiEnvironmentConfig = ApiEnvironmentConfig( + environment = ApiEnvironment.DEV_2, + baseUrl = "[REDACTED_ENV_URL]", + headers = createHeaders(isProd = false), + ) + private fun createStageEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig( environment = ApiEnvironment.STAGE, baseUrl = "[REDACTED_ENV_URL]", diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt index db2117b06a..30457ea047 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt @@ -166,6 +166,7 @@ internal class DefaultVisaActivationRepository @AssistedInject constructor( val rsaPublicKey = visaLibLoader.getOrCreateConfig().rsaPublicKey return when (env) { ApiEnvironment.DEV, + ApiEnvironment.DEV_2, ApiEnvironment.STAGE, ApiEnvironment.MOCK, -> rsaPublicKey.dev diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/ui/EnvironmentTogglesScreen.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/ui/EnvironmentTogglesScreen.kt index 06ad56fc8e..21a0d5aad5 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/ui/EnvironmentTogglesScreen.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/ui/EnvironmentTogglesScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.SegmentedButton @@ -29,6 +30,8 @@ import com.tangem.feature.tester.impl.R import com.tangem.feature.tester.presentation.environments.state.EnvironmentTogglesScreenUM import kotlinx.collections.immutable.persistentSetOf +private const val SCROLLABLE_BUTTONS_RESTRICTION = 4 + /** * Screen with environment toggles list * @@ -53,15 +56,13 @@ internal fun EnvironmentTogglesScreen(uiModel: EnvironmentTogglesScreenUM) { items = uiModel.apiInfoList.toTypedArray(), key = { _, info -> info.name }, ) { index, info -> - EnvironmentButtons( + val isLastItem = index == uiModel.apiInfoList.toTypedArray().lastIndex + + EnvironmentConfigBlock( uiModel = info, onSelect = { isChange -> uiModel.onEnvironmentSelect(info.name, isChange) }, modifier = Modifier.padding( - bottom = if (index == uiModel.apiInfoList.toTypedArray().lastIndex) { - TangemTheme.dimens.spacing0 - } else { - TangemTheme.dimens.spacing10 - }, + bottom = if (isLastItem) 0.dp else 10.dp, ), ) } @@ -69,18 +70,20 @@ internal fun EnvironmentTogglesScreen(uiModel: EnvironmentTogglesScreenUM) { } @Composable -private fun EnvironmentButtons( +private fun EnvironmentConfigBlock( uiModel: EnvironmentTogglesScreenUM.ApiInfoUM, onSelect: (String) -> Unit, modifier: Modifier = Modifier, ) { Column( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = TangemTheme.dimens.spacing16), - verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6), + modifier = modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(space = 6.dp), ) { - Column(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) { Text( text = uiModel.name, color = TangemTheme.colors.text.primary1, @@ -99,33 +102,50 @@ private fun EnvironmentButtons( } } - SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) { - uiModel.environments.onEachIndexed { index, environment -> - key(environment) { - SegmentedButton( - selected = environment == uiModel.select, - onClick = { onSelect(environment) }, - shape = when (index) { - 0 -> RoundedCornerShape( - topStart = TangemTheme.dimens.radius12, - bottomStart = TangemTheme.dimens.radius12, - ) - uiModel.environments.toTypedArray().lastIndex -> RoundedCornerShape( - topEnd = TangemTheme.dimens.radius12, - bottomEnd = TangemTheme.dimens.radius12, - ) - else -> RectangleShape - }, - colors = SegmentedButtonDefaults.colors( - activeContainerColor = TangemTheme.colors.control.checked, - activeContentColor = TangemTheme.colors.text.primary2, - inactiveContainerColor = TangemTheme.colors.control.unchecked, - inactiveContentColor = TangemTheme.colors.text.primary1, - ), - border = BorderStroke(0.dp, TangemTheme.colors.background.tertiary), - ) { - Text(text = environment, style = TangemTheme.typography.subtitle2) - } + EnvironmentButtonsContainer(uiModel.environments.size) { + EnvironmentButtons(uiModel = uiModel, onSelect = onSelect) + } + } +} + +@Composable +private fun EnvironmentButtonsContainer(environmentsCount: Int, block: @Composable () -> Unit) { + if (environmentsCount > SCROLLABLE_BUTTONS_RESTRICTION) { + LazyRow(contentPadding = PaddingValues(horizontal = 16.dp)) { + item { block() } + } + } else { + Box(modifier = Modifier.padding(horizontal = 16.dp)) { + block() + } + } +} + +@Composable +private fun EnvironmentButtons(uiModel: EnvironmentTogglesScreenUM.ApiInfoUM, onSelect: (String) -> Unit) { + SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) { + uiModel.environments.onEachIndexed { index, environment -> + key(environment) { + SegmentedButton( + selected = environment == uiModel.select, + onClick = { onSelect(environment) }, + shape = when (index) { + 0 -> RoundedCornerShape(topStart = 12.dp, bottomStart = 12.dp) + uiModel.environments.toTypedArray().lastIndex -> RoundedCornerShape( + topEnd = 12.dp, + bottomEnd = 12.dp, + ) + else -> RectangleShape + }, + colors = SegmentedButtonDefaults.colors( + activeContainerColor = TangemTheme.colors.control.checked, + activeContentColor = TangemTheme.colors.text.primary2, + inactiveContainerColor = TangemTheme.colors.control.unchecked, + inactiveContentColor = TangemTheme.colors.text.primary1, + ), + border = BorderStroke(0.dp, TangemTheme.colors.background.tertiary), + ) { + Text(text = environment, style = TangemTheme.typography.subtitle2) } } } @@ -137,7 +157,14 @@ private fun EnvironmentButtons( @Composable private fun PreviewFeatureTogglesScreen() { TangemThemePreview { - var select by remember { mutableStateOf(ApiEnvironment.DEV.name) } + var select by remember { + mutableStateOf( + mapOf( + "Express" to ApiEnvironment.DEV.name, + "TangemTech" to ApiEnvironment.DEV.name, + ), + ) + } EnvironmentTogglesScreen( uiModel = EnvironmentTogglesScreenUM( @@ -145,17 +172,19 @@ private fun PreviewFeatureTogglesScreen() { apiInfoList = persistentSetOf( EnvironmentTogglesScreenUM.ApiInfoUM( name = ApiConfig.ID.Express.name, - select = select, + select = select[ApiConfig.ID.Express.name] ?: ApiEnvironment.DEV.name, url = "https://api.express.tangem.com", environments = persistentSetOf( ApiEnvironment.DEV.name, + ApiEnvironment.DEV_2.name, ApiEnvironment.STAGE.name, + ApiEnvironment.MOCK.name, ApiEnvironment.PROD.name, ), ), EnvironmentTogglesScreenUM.ApiInfoUM( name = ApiConfig.ID.TangemTech.name, - select = select, + select = select[ApiConfig.ID.TangemTech.name] ?: ApiEnvironment.DEV.name, url = "https://api.express.tangem.com", environments = persistentSetOf( ApiEnvironment.DEV.name, @@ -163,7 +192,11 @@ private fun PreviewFeatureTogglesScreen() { ), ), ), - onEnvironmentSelect = { _: String, s1: String -> select = s1 }, + onEnvironmentSelect = { id, env -> + select = select.toMutableMap().apply { + this[id] = env + } + }, onBackClick = {}, ), ) diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/utils/ApiEnvironmentComparator.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/utils/ApiEnvironmentComparator.kt index d20eb06ced..cdf172d0c4 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/utils/ApiEnvironmentComparator.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/environments/utils/ApiEnvironmentComparator.kt @@ -13,9 +13,10 @@ internal object ApiEnvironmentComparator : Comparator { private val apiEnvironmentPriorityMap = ApiEnvironment.entries.associateWith { when (it) { ApiEnvironment.DEV -> 0 - ApiEnvironment.STAGE -> 1 - ApiEnvironment.MOCK -> 2 - ApiEnvironment.PROD -> 3 + ApiEnvironment.DEV_2 -> 1 + ApiEnvironment.STAGE -> 2 + ApiEnvironment.MOCK -> 3 + ApiEnvironment.PROD -> 4 } }