From 4e18fe38510bfec05ae20f8569036dd23b870af1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 13 Sep 2024 09:32:24 +0300 Subject: [PATCH 01/57] Updated on 2026-08-14 --- .../tap/common/redux/global/GlobalReducer.kt | 8 +-- .../features/home/compose/StoriesScreen.kt | 6 ++- .../tap/features/home/redux/HomeAction.kt | 2 - .../tap/features/home/redux/HomeReducer.kt | 12 ++--- .../tap/features/home/redux/HomeState.kt | 54 ++++--------------- 5 files changed, 19 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index 6b011082d2..02c839de1f 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -2,12 +2,9 @@ package com.tangem.tap.common.redux.global import com.tangem.domain.redux.domainStore import com.tangem.domain.redux.global.DomainGlobalAction -import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.AppState -import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.onboarding.OnboardingManager import com.tangem.tap.proxy.AppStateHolder -import com.tangem.tap.store import com.tangem.utils.extensions.replaceBy import org.rekotlin.Action @@ -86,10 +83,7 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde is GlobalAction.SetIfCardVerifiedOnline -> globalState.copy(cardVerifiedOnline = action.verified) is GlobalAction.FetchUserCountry.Success -> { - store.dispatchOnMain(HomeAction.UpdateCountryCode(action.countryCode)) - globalState.copy( - userCountryCode = action.countryCode, - ) + globalState.copy(userCountryCode = action.countryCode) } else -> globalState } diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt index 9f4e9fbaa9..f33229cf24 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt @@ -58,7 +58,9 @@ internal fun StoriesScreen( } StoriesScreenContent( - modifier = Modifier.fillMaxSize().testTag(TestTags.STORIES_SCREEN), + modifier = Modifier + .fillMaxSize() + .testTag(TestTags.STORIES_SCREEN), config = StoriesScreenContentConfig( storiesSize = state.stories.lastIndex, currentStoryIndex = currentStoryIndex, @@ -157,7 +159,7 @@ private fun StoriesScreenContent(config: StoriesScreenContentConfig, modifier: M duration = currentStoryDuration, ) Stories.RevolutionaryWallet -> StoriesRevolutionaryWallet() - is Stories.UltraSecureBackup -> StoriesUltraSecureBackup( + Stories.UltraSecureBackup -> StoriesUltraSecureBackup( isPaused = isPaused, stepDuration = currentStoryDuration, ) diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt index e3f0375cc1..05ba17df63 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt @@ -15,6 +15,4 @@ sealed class HomeAction : Action { data class ReadCard(val scope: CoroutineScope) : HomeAction() data class ScanInProgress(val scanInProgress: Boolean) : HomeAction() - - data class UpdateCountryCode(val userCountryCode: String) : HomeAction() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt index f9d977fdec..ab41e3d89f 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt @@ -10,16 +10,10 @@ object HomeReducer { private fun internalReduce(action: Action, appState: AppState): HomeState { if (action !is HomeAction) return appState.homeState - var state = appState.homeState - when (action) { + return when (action) { is HomeAction.ScanInProgress -> { - state = state.copy(scanInProgress = action.scanInProgress) + appState.homeState.copy(scanInProgress = action.scanInProgress) } - is HomeAction.UpdateCountryCode -> { - state.onCountryCodeUpdate(state, action.userCountryCode) - } - else -> {} + else -> appState.homeState } - - return state } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt index 2e584d3d35..5341631157 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt @@ -1,56 +1,24 @@ package com.tangem.tap.features.home.redux -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList import org.rekotlin.StateType -import java.util.Locale -@Immutable data class HomeState( val scanInProgress: Boolean = false, - val stories: List = initDefaultStories(), + val stories: ImmutableList = Stories.entries.toImmutableList(), ) : StateType { - val firstStory: Stories - get() = stories[0] + val firstStory: Stories get() = stories[0] fun stepOf(story: Stories): Int = stories.indexOf(story) - - fun onCountryCodeUpdate(homeState: HomeState, countryCode: String) { - val isNewWalletAvailable = !(countryCode == RUSSIA_COUNTRY_CODE || countryCode == BELARUS_COUNTRY_CODE) - homeState.stories.forEach { - it.isNewWalletAvailable.value = isNewWalletAvailable - } - } - - companion object { - private const val RUSSIA_COUNTRY_CODE = "ru" - private const val BELARUS_COUNTRY_CODE = "by" - fun initDefaultStories(): List = listOf( - Stories.TangemIntro, - Stories.RevolutionaryWallet, - Stories.UltraSecureBackup, - Stories.Currencies, - Stories.Web3, - Stories.WalletForEveryone, - ) - - fun isNewWalletAvailableInit(): Boolean { - val locale = Locale.getDefault().language - return !(locale == RUSSIA_COUNTRY_CODE || locale == BELARUS_COUNTRY_CODE) - } - } } -sealed class Stories( - val duration: Int, - val isNewWalletAvailable: MutableState = mutableStateOf(HomeState.isNewWalletAvailableInit()), -) { - object TangemIntro : Stories(duration = 6000) - object RevolutionaryWallet : Stories(duration = 6000) - object UltraSecureBackup : Stories(duration = 6000) - object Currencies : Stories(duration = 6000) - object Web3 : Stories(duration = 6000) - object WalletForEveryone : Stories(duration = 6000) +enum class Stories(val duration: Int = 6000) { + TangemIntro, + RevolutionaryWallet, + UltraSecureBackup, + Currencies, + Web3, + WalletForEveryone, } \ No newline at end of file From 2d670ed6c492ca5389ae77e5168c74db30a7522a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 13:30:45 +0300 Subject: [PATCH 02/57] Updated on 2026-08-14 --- .../tap/di/domain/SettingsDomainModule.kt | 14 ++++++ .../api/tangemTech/models/GeoResponse.kt | 2 + data/settings/build.gradle.kts | 1 + .../settings/DefaultSettingsRepository.kt | 48 +++++++++++++++++++ .../data/settings/di/SettingsDataModule.kt | 11 ++++- .../repositories/SettingsRepository.kt | 6 +++ .../usercountry/FetchUserCountryUseCase.kt | 28 +++++++++++ .../usercountry/GetUserCountryUseCase.kt | 34 +++++++++++++ .../usercountry/models/UserCountry.kt | 13 +++++ .../usercountry/models/UserCountryError.kt | 15 ++++++ 10 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/usercountry/FetchUserCountryUseCase.kt create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/usercountry/GetUserCountryUseCase.kt create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountry.kt create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountryError.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt index 1b5860c2c0..e175d51e25 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt @@ -10,6 +10,8 @@ import com.tangem.domain.settings.repositories.AppRatingRepository import com.tangem.domain.settings.repositories.PermissionRepository import com.tangem.domain.settings.repositories.PromoSettingsRepository 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.settings.DefaultLegacySettingsRepository import dagger.Module @@ -212,4 +214,16 @@ internal object SettingsDomainModule { return ShouldSaveAccessCodesUseCase(settingsRepository = settingsRepository) } // endregion + + @Provides + @Singleton + fun provideFetchUserCountryCodeUseCase(settingsRepository: SettingsRepository): FetchUserCountryUseCase { + return FetchUserCountryUseCase(settingsRepository) + } + + @Provides + @Singleton + fun provideGetUserCountryCodeUseCase(settingsRepository: SettingsRepository): GetUserCountryUseCase { + return GetUserCountryUseCase(settingsRepository) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/GeoResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/GeoResponse.kt index e6cdfa4b12..f444437037 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/GeoResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/GeoResponse.kt @@ -1,7 +1,9 @@ package com.tangem.datasource.api.tangemTech.models import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +@JsonClass(generateAdapter = true) data class GeoResponse( @Json(name = "code") val code: String, ) \ No newline at end of file diff --git a/data/settings/build.gradle.kts b/data/settings/build.gradle.kts index 96f4640242..6856b1236f 100644 --- a/data/settings/build.gradle.kts +++ b/data/settings/build.gradle.kts @@ -30,5 +30,6 @@ dependencies { implementation(deps.kotlin.coroutines) implementation(deps.moshi) implementation(deps.moshi.kotlin) + implementation(deps.timber) // endregion } diff --git a/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt b/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt index d9122fb1b3..6ea8cb2b4d 100644 --- a/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt +++ b/data/settings/src/main/java/com/tangem/data/settings/DefaultSettingsRepository.kt @@ -1,17 +1,31 @@ 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.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.store 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( private val appPreferencesStore: AppPreferencesStore, private val appLogsStore: AppLogsStore, + private val tangemTechApi: TangemTechApi, + private val dispatchers: CoroutineDispatcherProvider, ) : SettingsRepository { + private val userCountryFlow = MutableStateFlow(value = null) + override suspend fun shouldShowSaveUserWalletScreen(): Boolean { return appPreferencesStore.getSyncOrDefault( key = PreferencesKeys.SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY, @@ -99,4 +113,38 @@ internal class DefaultSettingsRepository( override suspend fun setMarketsTooltipShown(value: Boolean) { 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 + } + } } \ No newline at end of file diff --git a/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt b/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt index bddc8ef6e1..0ea5bce762 100644 --- a/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt +++ b/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt @@ -4,12 +4,14 @@ import com.tangem.data.settings.DefaultAppRatingRepository import com.tangem.data.settings.DefaultPermissionRepository import com.tangem.data.settings.DefaultPromoSettingsRepository 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.preferences.AppPreferencesStore import com.tangem.domain.settings.repositories.AppRatingRepository import com.tangem.domain.settings.repositories.PermissionRepository import com.tangem.domain.settings.repositories.PromoSettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -25,8 +27,15 @@ internal object SettingsDataModule { fun provideSettingsRepository( appPreferencesStore: AppPreferencesStore, appLogsStore: AppLogsStore, + tangemTechApi: TangemTechApi, + dispatchers: CoroutineDispatcherProvider, ): SettingsRepository { - return DefaultSettingsRepository(appPreferencesStore = appPreferencesStore, appLogsStore = appLogsStore) + return DefaultSettingsRepository( + appPreferencesStore = appPreferencesStore, + appLogsStore = appLogsStore, + tangemTechApi = tangemTechApi, + dispatchers = dispatchers, + ) } @Provides diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt index 6067b99a64..b342dcd2ef 100644 --- a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt +++ b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SettingsRepository.kt @@ -1,5 +1,7 @@ package com.tangem.domain.settings.repositories +import com.tangem.domain.settings.usercountry.models.UserCountry + interface SettingsRepository { suspend fun shouldShowSaveUserWalletScreen(): Boolean @@ -33,4 +35,8 @@ interface SettingsRepository { suspend fun shouldShowMarketsTooltip(): Boolean suspend fun setMarketsTooltipShown(value: Boolean) + + suspend fun getUserCountryCodeSync(): UserCountry? + + suspend fun fetchUserCountryCode() } \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/FetchUserCountryUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/FetchUserCountryUseCase.kt new file mode 100644 index 0000000000..5eab20c011 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/FetchUserCountryUseCase.kt @@ -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 { + return either { + catch( + block = { settingsRepository.fetchUserCountryCode() }, + catch = { raise(UserCountryError.DataError) }, + ) + } + } +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/GetUserCountryUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/GetUserCountryUseCase.kt new file mode 100644 index 0000000000..01768f5a6c --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/GetUserCountryUseCase.kt @@ -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 { + return either { + val userCountryCode = catch( + block = { settingsRepository.getUserCountryCodeSync() }, + catch = { raise(UserCountryError.DataError) }, + ) + + ensureNotNull(userCountryCode) { UserCountryError.NotSetup } + + userCountryCode + } + } +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountry.kt b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountry.kt new file mode 100644 index 0000000000..e212b96917 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountry.kt @@ -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) +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountryError.kt b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountryError.kt new file mode 100644 index 0000000000..8d6e483a09 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/usercountry/models/UserCountryError.kt @@ -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 +} \ No newline at end of file From caa0a0eb39bcb6a416b3ff9f1648f57760b4fa4b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 13:48:24 +0300 Subject: [PATCH 03/57] Updated on 2026-08-14 --- .../java/com/tangem/tap/ApplicationEntryPoint.kt | 6 ++++++ .../main/java/com/tangem/tap/TangemApplication.kt | 10 ++++++++++ .../home/featuretoggles/HomeFeatureToggles.kt | 12 ++++++++++++ .../com/tangem/tap/proxy/redux/DaggerGraphState.kt | 4 ++++ .../main/assets/configs/feature_toggles_config.json | 4 ++++ 5 files changed, 36 insertions(+) create mode 100644 app/src/main/java/com/tangem/tap/features/home/featuretoggles/HomeFeatureToggles.kt diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index 21ab576e7f..772a78b90d 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -24,6 +24,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase import com.tangem.domain.settings.repositories.SettingsRepository +import com.tangem.domain.settings.usercountry.GetUserCountryUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.walletmanager.WalletManagersFacade @@ -35,6 +36,7 @@ import com.tangem.features.pushnotifications.api.featuretoggles.PushNotification import com.tangem.tap.common.log.TangemAppLoggerInitializer import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles +import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles import com.tangem.tap.proxy.AppStateHolder import dagger.hilt.EntryPoint import dagger.hilt.InstallIn @@ -119,4 +121,8 @@ interface ApplicationEntryPoint { fun getPushNotificationsFeatureToggles(): PushNotificationsFeatureToggles fun getTangemAppLogger(): TangemAppLoggerInitializer + + fun getHomeFeatureToggles(): HomeFeatureToggles + + fun getGetUserCountryCodeUseCase(): GetUserCountryUseCase } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index ef8490029a..cf7f9a9347 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -37,6 +37,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase import com.tangem.domain.settings.repositories.SettingsRepository +import com.tangem.domain.settings.usercountry.GetUserCountryUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.walletmanager.WalletManagersFacade @@ -60,6 +61,7 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.tasks.product.DerivationsFinder import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles +import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles import com.tangem.tap.proxy.AppStateHolder import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider @@ -191,6 +193,12 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { private val tangemAppLoggerInitializer: TangemAppLoggerInitializer get() = entryPoint.getTangemAppLogger() + + private val homeFeatureToggles: HomeFeatureToggles + get() = entryPoint.getHomeFeatureToggles() + + private val getUserCountryUseCase: GetUserCountryUseCase + get() = entryPoint.getGetUserCountryCodeUseCase() // endregion override fun onCreate() { @@ -273,6 +281,8 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { shareManager = shareManager, appRouter = appRouter, pushNotificationsFeatureToggles = pushNotificationsFeatureToggles, + homeFeatureToggles = homeFeatureToggles, + getUserCountryUseCase = getUserCountryUseCase, ), ), ) diff --git a/app/src/main/java/com/tangem/tap/features/home/featuretoggles/HomeFeatureToggles.kt b/app/src/main/java/com/tangem/tap/features/home/featuretoggles/HomeFeatureToggles.kt new file mode 100644 index 0000000000..ce8c0bcec3 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/featuretoggles/HomeFeatureToggles.kt @@ -0,0 +1,12 @@ +package com.tangem.tap.features.home.featuretoggles + +import com.tangem.core.featuretoggle.manager.FeatureTogglesManager +import javax.inject.Inject + +class HomeFeatureToggles @Inject constructor( + private val featureTogglesManager: FeatureTogglesManager, +) { + + val isMigrateUserCountryCodeEnabled: Boolean + get() = featureTogglesManager.isFeatureEnabled(name = "MIGRATE_USER_COUNTRY_CODE_ENABLED") +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 45b2035717..81fba12558 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -22,6 +22,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase import com.tangem.domain.settings.repositories.SettingsRepository +import com.tangem.domain.settings.usercountry.GetUserCountryUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.walletmanager.WalletManagersFacade @@ -41,6 +42,7 @@ import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles +import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles import com.tangem.tap.proxy.AppStateHolder import org.rekotlin.StateType @@ -87,4 +89,6 @@ data class DaggerGraphState( val appRouter: AppRouter? = null, val pushNotificationsFeatureToggles: PushNotificationsFeatureToggles? = null, val pushNotificationsRouter: PushNotificationsRouter? = null, + val homeFeatureToggles: HomeFeatureToggles? = null, + val getUserCountryUseCase: GetUserCountryUseCase? = null, ) : StateType \ No newline at end of file diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index 652af05e72..77154a1490 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -38,5 +38,9 @@ { "name": "IS_ETHEREUM_EIP_1559_ENABLED", "version": "5.16.0" + }, + { + "name": "MIGRATE_USER_COUNTRY_CODE_ENABLED", + "version": "5.16.0" } ] From 9d91a5a6ded20e7196ccdf857b82d89ea8c5002a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 14:05:20 +0500 Subject: [PATCH 04/57] Updated on 2026-08-14 --- app/src/main/assets/testnet_tokens.json | 10 ++++++++++ .../core/ui/extensions/BlockchainIcons.kt | 5 +++++ .../main/res/drawable/ic_energy_web_22.xml | 9 +++++++++ .../main/res/drawable/img_energy_web_22.xml | 19 +++++++++++++++++++ gradle/dependencies.toml | 2 +- .../tangem/blockchainsdk/utils/Blockchain.kt | 8 +++++++- 6 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 core/ui/src/main/res/drawable/ic_energy_web_22.xml create mode 100644 core/ui/src/main/res/drawable/img_energy_web_22.xml diff --git a/app/src/main/assets/testnet_tokens.json b/app/src/main/assets/testnet_tokens.json index cb960e3694..bbac69e02e 100644 --- a/app/src/main/assets/testnet_tokens.json +++ b/app/src/main/assets/testnet_tokens.json @@ -718,6 +718,16 @@ "networkId": "sei-network/test" } ] + }, + { + "id": "energy-web-chain", + "name": "Energy Web Chain", + "symbol": "EWT", + "networks": [ + { + "networkId": "energy-web-chain/test" + } + ] } ] } diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt index 59fe1fa692..c36f4876be 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt @@ -75,6 +75,7 @@ fun getActiveIconRes(blockchainId: String): Int { "cyber", "cyber/test" -> R.drawable.img_cyber_22 "sei", "sei/test" -> R.drawable.img_sei_22 "internet-computer" -> R.drawable.img_icp_22 + "energy-web-chain", "energy-web-chain/test" -> R.drawable.img_energy_web_22 else -> R.drawable.ic_alert_24 } } @@ -151,6 +152,7 @@ fun getActiveIconResByNetworkId(networkId: String): Int { "cyber", "cyber/test" -> R.drawable.img_cyber_22 "sei", "sei/test" -> R.drawable.img_sei_22 "internet-computer" -> R.drawable.img_icp_22 + "energy-web-chain", "energy-web-chain/test" -> R.drawable.img_energy_web_22 else -> R.drawable.ic_alert_24 } } @@ -224,6 +226,7 @@ fun getActiveIconResByCoinId(coinId: String): Int { "cyber", "cyber/test" -> R.drawable.img_cyber_22 "sei", "sei/test" -> R.drawable.img_sei_22 "internet-computer" -> R.drawable.img_icp_22 + "energy-web-chain", "energy-web-chain/test" -> R.drawable.img_energy_web_22 else -> R.drawable.ic_alert_24 } } @@ -300,6 +303,7 @@ fun getGreyedOutIconRes(blockchainId: String): Int { "cyber", "cyber/test" -> R.drawable.ic_cyber_22 "sei", "sei/test" -> R.drawable.ic_sei_22 "internet-computer" -> R.drawable.ic_icp_22 + "energy-web-chain", "energy-web-chain/test" -> R.drawable.ic_energy_web_22 else -> R.drawable.ic_alert_24 } } @@ -376,6 +380,7 @@ fun getGreyedOutIconResByNetworkId(networkId: String): Int { "cyber", "cyber/test" -> R.drawable.ic_cyber_22 "sei", "sei/test" -> R.drawable.ic_sei_22 "internet-computer" -> R.drawable.ic_icp_22 + "energy-web-chain", "energy-web-chain/test" -> R.drawable.ic_energy_web_22 else -> R.drawable.ic_alert_24 } } \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/ic_energy_web_22.xml b/core/ui/src/main/res/drawable/ic_energy_web_22.xml new file mode 100644 index 0000000000..b4e0c5dc9b --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_energy_web_22.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/img_energy_web_22.xml b/core/ui/src/main/res/drawable/img_energy_web_22.xml new file mode 100644 index 0000000000..30fbdcf859 --- /dev/null +++ b/core/ui/src/main/res/drawable/img_energy_web_22.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index f7f29c6698..aaa056ecb4 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-782" +tangemBlockchainSdk = "develop-785" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-381" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt index cddafe6527..8cc1adb2f6 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt @@ -126,6 +126,8 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? { "sei-network" -> Blockchain.Sei "sei-network/test" -> Blockchain.SeiTestnet "internet-computer" -> Blockchain.InternetComputer + "energy-web-chain" -> Blockchain.EnergyWebChain + "energy-web-chain/test" -> Blockchain.EnergyWebChainTestnet else -> null } } @@ -253,6 +255,8 @@ fun Blockchain.toNetworkId(): String { Blockchain.Sei -> "sei-network" Blockchain.SeiTestnet -> "sei-network/test" Blockchain.InternetComputer -> "internet-computer" + Blockchain.EnergyWebChain -> "energy-web-chain" + Blockchain.EnergyWebChainTestnet -> "energy-web-chain/test" } } @@ -337,6 +341,7 @@ fun Blockchain.toCoinId(): String { Blockchain.Cyber, Blockchain.CyberTestnet -> "cyber-ethereum" Blockchain.Sei, Blockchain.SeiTestnet -> "sei-network" Blockchain.InternetComputer -> "internet-computer" + Blockchain.EnergyWebChain, Blockchain.EnergyWebChainTestnet -> "energy-web-chain" } } @@ -363,10 +368,11 @@ fun Blockchain.minimalAmount(): BigDecimal { private const val NODL = "NODL" private const val NODL_AMOUNT_TO_CREATE_ACCOUNT = 1.5 +// no need to add testnets private val excludedBlockchains = listOf( Blockchain.Unknown, Blockchain.Nexa, - Blockchain.NexaTestnet, Blockchain.Sei, Blockchain.InternetComputer, + Blockchain.EnergyWebChain, ) \ No newline at end of file From ec23b55dbdf6879643224dfbb081a4af3a42131c Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 20 Sep 2024 13:52:35 +0300 Subject: [PATCH 05/57] Updated on 2026-08-14 --- .../configs/feature_toggles_config.json | 4 ---- .../TokenDetailsFeatureToggles.kt | 6 ------ .../di/TokenDetailsFeatureTogglesModule.kt | 21 ------------------- .../DefaultTokenDetailsFeatureToggles.kt | 11 ---------- .../TokenDetailsSkeletonStateConverter.kt | 14 ++++++------- .../state/factory/TokenDetailsStateFactory.kt | 6 +----- .../viewmodels/TokenDetailsViewModel.kt | 11 ++++------ 7 files changed, 12 insertions(+), 61 deletions(-) delete mode 100644 features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/featuretoggles/TokenDetailsFeatureToggles.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsFeatureTogglesModule.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/featuretoggles/DefaultTokenDetailsFeatureToggles.kt diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index 77154a1490..6af370b81e 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -7,10 +7,6 @@ "name": "LOCAL_USER_LOGS_ENABLED", "version": "5.14.0" }, - { - "name": "GENERATE_XPUB_ENABLED", - "version": "5.12.0" - }, { "name": "WC_SOLANA_TX_SIGN_ENABLED", "version": "undefined" diff --git a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/featuretoggles/TokenDetailsFeatureToggles.kt b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/featuretoggles/TokenDetailsFeatureToggles.kt deleted file mode 100644 index 1fc4007823..0000000000 --- a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/featuretoggles/TokenDetailsFeatureToggles.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.tangem.features.tokendetails.featuretoggles - -interface TokenDetailsFeatureToggles { - - fun isGenerateXPubEnabled(): Boolean -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsFeatureTogglesModule.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsFeatureTogglesModule.kt deleted file mode 100644 index 21b9d911cb..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsFeatureTogglesModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.tangem.feature.tokendetails.di - -import com.tangem.core.featuretoggle.manager.FeatureTogglesManager -import com.tangem.feature.tokendetails.featuretoggles.DefaultTokenDetailsFeatureToggles -import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -internal object TokenDetailsFeatureTogglesModule { - - @Provides - @Singleton - fun provideTokenDetailsFeatureToggles(featureTogglesManager: FeatureTogglesManager): TokenDetailsFeatureToggles { - return DefaultTokenDetailsFeatureToggles(featureTogglesManager) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/featuretoggles/DefaultTokenDetailsFeatureToggles.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/featuretoggles/DefaultTokenDetailsFeatureToggles.kt deleted file mode 100644 index 96d2dbbb72..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/featuretoggles/DefaultTokenDetailsFeatureToggles.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.tangem.feature.tokendetails.featuretoggles - -import com.tangem.core.featuretoggle.manager.FeatureTogglesManager -import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles - -internal class DefaultTokenDetailsFeatureToggles( - private val featureTogglesManager: FeatureTogglesManager, -) : TokenDetailsFeatureToggles { - - override fun isGenerateXPubEnabled() = featureTogglesManager.isFeatureEnabled(name = "GENERATE_XPUB_ENABLED") -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt index 4aeac3dd4b..582ddd5560 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt @@ -17,7 +17,6 @@ import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents -import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles import com.tangem.features.tokendetails.impl.R import com.tangem.lib.crypto.BlockchainUtils.isBitcoin import com.tangem.utils.converter.Converter @@ -28,7 +27,6 @@ import kotlinx.coroutines.flow.MutableStateFlow internal class TokenDetailsSkeletonStateConverter( private val clickIntents: TokenDetailsClickIntents, - private val featureToggles: TokenDetailsFeatureToggles, private val networkHasDerivationUseCase: NetworkHasDerivationUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val userWalletId: UserWalletId, @@ -98,12 +96,14 @@ internal class TokenDetailsSkeletonStateConverter( cryptoCurrency: CryptoCurrency, ) { val userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: return - val isGenerateXPubEnabled = featureToggles.isGenerateXPubEnabled() - val isBitcoin = isBitcoin(cryptoCurrency.network.id.value) - val hasDerivations = - networkHasDerivationUseCase(userWallet.scanResponse, cryptoCurrency.network).getOrElse { false } - if (isGenerateXPubEnabled && isBitcoin && hasDerivations) { + val isBitcoin = isBitcoin(cryptoCurrency.network.id.value) + val hasDerivations = networkHasDerivationUseCase( + scanResponse = userWallet.scanResponse, + network = cryptoCurrency.network, + ).getOrElse { false } + + if (isBitcoin && hasDerivations) { add( TokenDetailsAppBarMenuConfig.MenuItem( title = resourceReference(R.string.token_details_generate_xpub), diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index 934b75a0d1..54b171bf7d 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -39,7 +39,6 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.t import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.exchange.ExchangeStatusBottomSheetConfig import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles -import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import kotlinx.collections.immutable.toImmutableList @@ -53,7 +52,6 @@ internal class TokenDetailsStateFactory( private val stakingEntryInfoProvider: Provider, private val cryptoCurrencyStatusProvider: Provider, private val clickIntents: TokenDetailsClickIntents, - private val featureToggles: TokenDetailsFeatureToggles, private val networkHasDerivationUseCase: NetworkHasDerivationUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val userWalletId: UserWalletId, @@ -65,7 +63,6 @@ internal class TokenDetailsStateFactory( private val skeletonStateConverter by lazy { TokenDetailsSkeletonStateConverter( clickIntents = clickIntents, - featureToggles = featureToggles, networkHasDerivationUseCase = networkHasDerivationUseCase, getUserWalletUseCase = getUserWalletUseCase, userWalletId = userWalletId, @@ -390,10 +387,9 @@ internal class TokenDetailsStateFactory( isSupported: Boolean, ): TokenDetailsAppBarMenuConfig? { if (cardTypesResolver.isSingleWalletWithToken()) return null - val showGenerateExtendedKey = featureToggles.isGenerateXPubEnabled() && isSupported return copy( items = buildList { - if (showGenerateExtendedKey && hasDerivations) { + if (isSupported && hasDerivations) { TokenDetailsAppBarMenuConfig.MenuItem( title = resourceReference(R.string.token_details_generate_xpub), textColorProvider = { TangemTheme.colors.text.primary1 }, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index 5d65adaf1c..c59141254e 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -71,7 +71,6 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDeta import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.exchange.ExchangeStatusBottomSheetConfig import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles -import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.coroutines.* @@ -124,7 +123,6 @@ internal class TokenDetailsViewModel @Inject constructor( private val vibratorHapticManager: VibratorHapticManager, private val clipboardManager: ClipboardManager, getUserWalletUseCase: GetUserWalletUseCase, - tokenDetailsFeatureToggles: TokenDetailsFeatureToggles, deepLinksRegistry: DeepLinksRegistry, savedStateHandle: SavedStateHandle, private val appRouter: AppRouter, @@ -159,13 +157,12 @@ internal class TokenDetailsViewModel @Inject constructor( stakingEntryInfoProvider = Provider { stakingEntryInfo }, cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, clickIntents = this, - symbol = cryptoCurrency.symbol, - decimals = cryptoCurrency.decimals, - featureToggles = tokenDetailsFeatureToggles, - stakingFeatureToggles = stakingFeatureToggles, - userWalletId = userWalletId, networkHasDerivationUseCase = networkHasDerivationUseCase, getUserWalletUseCase = getUserWalletUseCase, + userWalletId = userWalletId, + stakingFeatureToggles = stakingFeatureToggles, + symbol = cryptoCurrency.symbol, + decimals = cryptoCurrency.decimals, ) private val exchangeStatusFactory by lazy(mode = LazyThreadSafetyMode.NONE) { From a2bc98f8a838c3c4820e7c034f43e03a1145001f Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 22 Sep 2024 22:09:59 +0300 Subject: [PATCH 06/57] Updated on 2026-08-14 --- .../manager/DevFeatureTogglesManager.kt | 20 +++- .../manager/MutableFeatureTogglesManager.kt | 6 + .../ui/EnvironmentTogglesScreen.kt | 6 +- .../state/FeatureTogglesContentState.kt | 31 +++++- .../featuretoggles/ui/FeatureTogglesScreen.kt | 103 ++++++++++++++---- .../viewmodels/FeatureTogglesViewModel.kt | 41 +++++-- .../impl/src/main/res/values/strings.xml | 4 +- 7 files changed, 171 insertions(+), 40 deletions(-) diff --git a/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/DevFeatureTogglesManager.kt b/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/DevFeatureTogglesManager.kt index 9b29a65f66..303dce3c7b 100644 --- a/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/DevFeatureTogglesManager.kt +++ b/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/DevFeatureTogglesManager.kt @@ -24,6 +24,7 @@ internal class DevFeatureTogglesManager( ) : MutableFeatureTogglesManager { private var featureTogglesMap: MutableMap by Delegates.notNull() + private var localFeatureTogglesMap: Map by Delegates.notNull() override suspend fun init() { localFeatureTogglesStorage.init() @@ -32,8 +33,12 @@ internal class DevFeatureTogglesManager( key = PreferencesKeys.FEATURE_TOGGLES_KEY, ) ?: emptyMap() - featureTogglesMap = localFeatureTogglesStorage.featureToggles + val localFeatureToggles = localFeatureTogglesStorage.featureToggles .associateToggles(currentVersion = versionProvider.get().orEmpty()) + + localFeatureTogglesMap = localFeatureToggles + + featureTogglesMap = localFeatureToggles .mapValues { resultToggle -> savedFeatureToggles[resultToggle.key] ?: resultToggle.value } @@ -42,16 +47,27 @@ internal class DevFeatureTogglesManager( override fun isFeatureEnabled(name: String): Boolean = featureTogglesMap[name] ?: false + override fun isMatchLocalConfig(): Boolean = featureTogglesMap == localFeatureTogglesMap + override fun getFeatureToggles(): Map = featureTogglesMap override suspend fun changeToggle(name: String, isEnabled: Boolean) { featureTogglesMap[name] ?: return featureTogglesMap[name] = isEnabled - appPreferencesStore.storeObject(PreferencesKeys.FEATURE_TOGGLES_KEY, featureTogglesMap) + appPreferencesStore.storeFeatureToggles(value = featureTogglesMap) + } + + override suspend fun recoverLocalConfig() { + featureTogglesMap = localFeatureTogglesMap.toMutableMap() + appPreferencesStore.storeFeatureToggles(value = localFeatureTogglesMap) } @VisibleForTesting(otherwise = VisibleForTesting.NONE) fun setFeatureToggles(map: MutableMap) { featureTogglesMap = map } + + private suspend fun AppPreferencesStore.storeFeatureToggles(value: Map) { + storeObject(PreferencesKeys.FEATURE_TOGGLES_KEY, value) + } } \ No newline at end of file diff --git a/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/MutableFeatureTogglesManager.kt b/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/MutableFeatureTogglesManager.kt index 8d7a063c5d..f04b423f4f 100644 --- a/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/MutableFeatureTogglesManager.kt +++ b/core/featuretoggles/src/main/kotlin/com/tangem/core/featuretoggle/manager/MutableFeatureTogglesManager.kt @@ -7,9 +7,15 @@ package com.tangem.core.featuretoggle.manager */ interface MutableFeatureTogglesManager : FeatureTogglesManager { + /** Check if the current state of the feature toggles matches the local config state. */ + fun isMatchLocalConfig(): Boolean + /** Get feature toggles */ fun getFeatureToggles(): Map /** Change availability [isEnabled] of toggle with name [name] */ suspend fun changeToggle(name: String, isEnabled: Boolean) + + /** Recover local config state */ + suspend fun recoverLocalConfig() } \ No newline at end of file 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 b9c442ce86..10a459c2f3 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 @@ -9,7 +9,10 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.* +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.RectangleShape @@ -65,7 +68,6 @@ internal fun EnvironmentTogglesScreen(uiModel: EnvironmentTogglesScreenUM) { } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun EnvironmentButtons( uiModel: EnvironmentTogglesScreenUM.ApiInfoUM, diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/state/FeatureTogglesContentState.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/state/FeatureTogglesContentState.kt index c1e4e290bb..fb97f05a55 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/state/FeatureTogglesContentState.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/state/FeatureTogglesContentState.kt @@ -6,14 +6,37 @@ import kotlinx.collections.immutable.ImmutableList /** * Content state of feature toggles screen * + * @property topBarState top bar state + * @property appVersion app version * @property featureToggles feature toggles list * @property onBackClick the lambda to be invoked when back button is pressed * @property onToggleValueChange the lambda to be invoked when switch button is pressed - * @property onApplyChangesClick the lambda to be invoked when apply changes button is pressed + * @property onRestartAppClick the lambda to be invoked when restart app button is pressed */ internal data class FeatureTogglesContentState( + val topBarState: TopBarState, + val appVersion: String, val featureToggles: ImmutableList, - val onToggleValueChange: (String, Boolean) -> Unit, val onBackClick: () -> Unit, - val onApplyChangesClick: () -> Unit, -) \ No newline at end of file + val onToggleValueChange: (String, Boolean) -> Unit, + val onRestartAppClick: () -> Unit, +) { + + /** Top bar state */ + sealed interface TopBarState { + + /** + * Config setup + * + * @property onBackClick the lambda to be invoked when back button is pressed + */ + data object ConfigSetup : TopBarState + + /** + * Custom setup + * + * @property onRecoverClick the lambda to be invoked when recover button is pressed + */ + data class CustomSetup(val onRecoverClick: () -> Unit) : TopBarState + } +} \ No newline at end of file diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/ui/FeatureTogglesScreen.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/ui/FeatureTogglesScreen.kt index 0ebd8cadbf..6fd2e7e7e9 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/ui/FeatureTogglesScreen.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/ui/FeatureTogglesScreen.kt @@ -6,17 +6,21 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.Switch -import androidx.compose.material.SwitchDefaults -import androidx.compose.material.Text -import androidx.compose.runtime.Composable +import androidx.compose.material3.Text +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.PrimaryButton -import com.tangem.core.ui.components.appbar.AppBarWithBackButton +import com.tangem.core.ui.components.TangemSwitch +import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon +import com.tangem.core.ui.components.notifications.Notification +import com.tangem.core.ui.components.notifications.NotificationConfig +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.feature.tester.impl.R @@ -37,22 +41,35 @@ internal fun FeatureTogglesScreen(state: FeatureTogglesContentState) { .fillMaxSize() .background(TangemTheme.colors.background.secondary), ) { - stickyHeader { - AppBarWithBackButton( - onBackClick = state.onBackClick, - text = stringResource(id = R.string.feature_toggles), - ) + stickyHeader { TopAppBar(state = state.topBarState, onBackClick = state.onBackClick) } + + if (state.topBarState is FeatureTogglesContentState.TopBarState.CustomSetup) { + item(key = "warning_notification", contentType = "warning_notification") { + WarningNotification( + appVersion = state.appVersion, + modifier = Modifier + .animateItem() + .padding(horizontal = 16.dp) + .padding(bottom = 8.dp), + ) + } } - items(state.featureToggles) { featureToggle -> + + items( + items = state.featureToggles, + key = TesterFeatureToggle::name, + contentType = { "feature_toggle_item" }, + ) { featureToggle -> FeatureToggleItem( toggle = featureToggle, onCheckedChange = { isChange -> state.onToggleValueChange(featureToggle.name, isChange) }, ) } + item { PrimaryButton( - text = stringResource(id = R.string.apply_changes), - onClick = state.onApplyChangesClick, + text = stringResource(id = R.string.restart_app), + onClick = state.onRestartAppClick, modifier = Modifier .fillMaxWidth() .padding(TangemTheme.dimens.spacing16), @@ -61,12 +78,48 @@ internal fun FeatureTogglesScreen(state: FeatureTogglesContentState) { } } +@Composable +private fun TopAppBar(state: FeatureTogglesContentState.TopBarState, onBackClick: () -> Unit) { + AppBarWithBackButtonAndIcon( + onBackClick = onBackClick, + text = stringResource(id = R.string.feature_toggles), + iconRes = if (state is FeatureTogglesContentState.TopBarState.CustomSetup) { + R.drawable.ic_refresh_24 + } else { + null + }, + onIconClick = if (state is FeatureTogglesContentState.TopBarState.CustomSetup) { + state.onRecoverClick + } else { + null + }, + ) +} + +@Composable +private fun WarningNotification(appVersion: String, modifier: Modifier = Modifier) { + Notification( + config = NotificationConfig( + subtitle = resourceReference( + id = R.string.feature_toggles_custom_setup_warning_description, + wrappedList(appVersion), + ), + iconResId = R.drawable.ic_alert_triangle_20, + title = resourceReference(id = R.string.feature_toggles_custom_setup_warning_title), + ), + modifier = modifier, + ) +} + @Composable private fun FeatureToggleItem(toggle: TesterFeatureToggle, onCheckedChange: (Boolean) -> Unit) { Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = TangemTheme.dimens.spacing18), + .padding( + horizontal = TangemTheme.dimens.spacing18, + vertical = TangemTheme.dimens.spacing8, + ), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { @@ -78,14 +131,8 @@ private fun FeatureToggleItem(toggle: TesterFeatureToggle, onCheckedChange: (Boo maxLines = 1, style = TangemTheme.typography.body2, ) - Switch( - checked = toggle.isEnabled, - onCheckedChange = onCheckedChange, - colors = SwitchDefaults.colors( - checkedThumbColor = TangemTheme.colors.control.checked, - uncheckedThumbColor = TangemTheme.colors.control.unchecked, - ), - ) + + TangemSwitch(onCheckedChange = onCheckedChange, checked = toggle.isEnabled) } } @@ -94,15 +141,23 @@ private fun FeatureToggleItem(toggle: TesterFeatureToggle, onCheckedChange: (Boo @Composable private fun PreviewFeatureTogglesScreen() { TangemThemePreview { + var isCustomSetup by remember { mutableStateOf(value = true) } + FeatureTogglesScreen( state = FeatureTogglesContentState( + topBarState = if (isCustomSetup) { + FeatureTogglesContentState.TopBarState.CustomSetup(onRecoverClick = { isCustomSetup = false }) + } else { + FeatureTogglesContentState.TopBarState.ConfigSetup + }, + appVersion = "5.15", featureToggles = persistentListOf( TesterFeatureToggle(name = "FEATURE_TOGGLE_1", isEnabled = true), TesterFeatureToggle(name = "FEATURE_TOGGLE_2", isEnabled = false), ), - onToggleValueChange = { _, _ -> }, onBackClick = {}, - onApplyChangesClick = {}, + onToggleValueChange = { _, _ -> isCustomSetup = true }, + onRestartAppClick = {}, ), ) } diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/viewmodels/FeatureTogglesViewModel.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/viewmodels/FeatureTogglesViewModel.kt index 6200dd283a..2af75d3b80 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/viewmodels/FeatureTogglesViewModel.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/featuretoggles/viewmodels/FeatureTogglesViewModel.kt @@ -11,10 +11,11 @@ import com.tangem.core.navigation.finisher.AppFinisher import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle import com.tangem.feature.tester.presentation.featuretoggles.state.FeatureTogglesContentState import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter -import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.version.AppVersionProvider import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import javax.inject.Inject @@ -22,14 +23,14 @@ import javax.inject.Inject * ViewModel for screen with list of feature toggles * * @property featureTogglesManager manager for getting information about the availability of feature toggles - * @property dispatchers coroutine dispatchers provider + * @property appVersionProvider app version provider * [REDACTED_AUTHOR] */ @HiltViewModel internal class FeatureTogglesViewModel @Inject constructor( private val featureTogglesManager: FeatureTogglesManager, - private val dispatchers: CoroutineDispatcherProvider, + private val appVersionProvider: AppVersionProvider, ) : ViewModel() { /** Current ui state */ @@ -41,28 +42,54 @@ internal class FeatureTogglesViewModel @Inject constructor( "Feature toggle manager must be mutable (debug build type)" } - /** Setup navigation state property by router [router] and provides app restart method by [appRestarter] */ + /** Setup navigation state property by router [router] and provides app restart method by [appFinisher] */ fun setupInteractions(router: InnerTesterRouter, appFinisher: AppFinisher) { uiState = uiState.copy( onBackClick = router::back, - onApplyChangesClick = appFinisher::restart, + onRestartAppClick = appFinisher::restart, ) } private fun initState(): FeatureTogglesContentState { return FeatureTogglesContentState( + topBarState = getConfigSetupState(), + appVersion = appVersionProvider.versionName, featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(), onToggleValueChange = ::onToggleValueChange, onBackClick = {}, - onApplyChangesClick = {}, + onRestartAppClick = {}, ) } private fun onToggleValueChange(name: String, isEnabled: Boolean) { - viewModelScope.launch(dispatchers.main) { + viewModelScope.launch { mutableFeatureTogglesManager.changeToggle(name = name, isEnabled = isEnabled) uiState = uiState.copy(featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles()) + + // delay for smoothly update animations + delay(timeMillis = 300) + + uiState = uiState.copy(topBarState = getConfigSetupState()) + } + } + + private fun getConfigSetupState(): FeatureTogglesContentState.TopBarState { + return if (mutableFeatureTogglesManager.isMatchLocalConfig()) { + FeatureTogglesContentState.TopBarState.ConfigSetup + } else { + FeatureTogglesContentState.TopBarState.CustomSetup( + onRecoverClick = { + viewModelScope.launch { + mutableFeatureTogglesManager.recoverLocalConfig() + + uiState = uiState.copy( + topBarState = getConfigSetupState(), + featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(), + ) + } + }, + ) } } diff --git a/features/tester/impl/src/main/res/values/strings.xml b/features/tester/impl/src/main/res/values/strings.xml index dfd6f4d39c..969d34bce4 100644 --- a/features/tester/impl/src/main/res/values/strings.xml +++ b/features/tester/impl/src/main/res/values/strings.xml @@ -2,7 +2,9 @@ Tester menu Feature toggles - Apply changes + Custom setup + Feature toggles differs from v%s config + Restart app Environment toggles Tester actions Hide all currencies From c1b426ef9f3b0ac0d6d01de0e85318b80139773e Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 17:05:19 +0300 Subject: [PATCH 07/57] Updated on 2026-08-14 --- .../com/tangem/common/routing/AppRoute.kt | 5 +- .../impl/model/TokenActionsHandler.kt | 1 + .../models/ui/TokensDataStateExpress.kt | 8 +++ .../DefaultInitialToCurrencyResolver.kt | 17 ++--- .../swap/domain/InitialToCurrencyResolver.kt | 5 +- .../feature/swap/domain/SwapInteractor.kt | 3 +- .../feature/swap/domain/SwapInteractorImpl.kt | 10 +-- .../swap/domain/di/SwapDomainModule.kt | 4 -- .../feature/swap/viewmodels/SwapViewModel.kt | 63 ++++++++++++------- 9 files changed, 75 insertions(+), 41 deletions(-) diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 0d8cee2df5..2c60258331 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -220,13 +220,16 @@ sealed class AppRoute(val path: String) : Route { data class Swap( val currency: CryptoCurrency, val userWalletId: UserWalletId, - ) : AppRoute(path = "/swap/${currency.id.value}/${userWalletId.stringValue}"), RouteBundleParams { + val isInitialReverseOrder: Boolean = false, + ) : AppRoute(path = "/swap/${currency.id.value}/${userWalletId.stringValue}/$isInitialReverseOrder"), + RouteBundleParams { override fun getBundle(): Bundle = bundle(serializer()) companion object { const val CURRENCY_BUNDLE_KEY = "currency" const val USER_WALLET_ID_KEY = "userWalletId" + const val IS_INITIAL_REVERSE_ORDER = "isInitialReverseOrder" } } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt index fc2464a7f9..8d7bc12e6c 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt @@ -151,6 +151,7 @@ internal class TokenActionsHandler @AssistedInject constructor( AppRoute.Swap( currency = cryptoCurrencyData.status.currency, userWalletId = cryptoCurrencyData.userWallet.walletId, + isInitialReverseOrder = true, ), ) } diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt index 1aa9ba51d1..93e4308f49 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt @@ -18,6 +18,14 @@ data class TokensDataStateExpress( } } +fun TokensDataStateExpress.getGroupWithReverse(isReverseFromTo: Boolean): CurrenciesGroup { + return if (isReverseFromTo) { + this.fromGroup + } else { + this.toGroup + } +} + data class CurrenciesGroup( val available: List, val unavailable: List, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt index 42e6f2331b..42d6c02e93 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt @@ -2,31 +2,34 @@ package com.tangem.feature.swap.domain import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase +import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress +import com.tangem.feature.swap.domain.models.ui.getGroupWithReverse import java.math.BigDecimal internal class DefaultInitialToCurrencyResolver( - private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val swapTransactionRepository: SwapTransactionRepository, ) : InitialToCurrencyResolver { override suspend fun tryGetFromCache( + userWallet: UserWallet, initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? { - val selectedId = getSelectedWalletSyncUseCase().getOrNull() ?: return null - val id = swapTransactionRepository.getLastSwappedCryptoCurrencyId(selectedId.walletId) ?: return null + val id = swapTransactionRepository.getLastSwappedCryptoCurrencyId(userWallet.walletId) ?: return null return if (id != initialCryptoCurrency.id.value) { - state.toGroup.available.find { it.currencyStatus.currency.id.value == id }?.currencyStatus + val group = state.getGroupWithReverse(isReverseFromTo) + group.available.find { it.currencyStatus.currency.id.value == id }?.currencyStatus } else { null } } - override fun tryGetWithMaxAmount(state: TokensDataStateExpress): CryptoCurrencyStatus? { - return state.toGroup.available.maxByOrNull { + override fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): CryptoCurrencyStatus? { + val group = state.getGroupWithReverse(isReverseFromTo) + return group.available.maxByOrNull { it.currencyStatus.value.fiatAmount ?: BigDecimal.ZERO }?.currencyStatus } diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt index da0b0f1b37..6c15921326 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt @@ -2,14 +2,17 @@ package com.tangem.feature.swap.domain import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress interface InitialToCurrencyResolver { suspend fun tryGetFromCache( + userWallet: UserWallet, initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? - fun tryGetWithMaxAmount(state: TokensDataStateExpress): CryptoCurrencyStatus? + fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): CryptoCurrencyStatus? } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt index 8c6f6a8de7..3154fa4293 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt @@ -79,9 +79,10 @@ interface SwapInteractor { */ fun getTokenBalance(token: CryptoCurrencyStatus): SwapAmount - suspend fun selectInitialCurrencyToSwap( + suspend fun getInitialCurrencyToSwap( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? fun getNativeToken(networkId: String): CryptoCurrency diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index b892338148..2a1a873a96 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -965,13 +965,15 @@ internal class SwapInteractorImpl @AssistedInject constructor( return SwapAmount(token.value.amount ?: BigDecimal.ZERO, token.currency.decimals) } - override suspend fun selectInitialCurrencyToSwap( + override suspend fun getInitialCurrencyToSwap( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? { - return initialToCurrencyResolver.tryGetFromCache(initialCryptoCurrency, state) - ?: initialToCurrencyResolver.tryGetWithMaxAmount(state) - ?: state.toGroup.available.firstOrNull()?.currencyStatus + val group = state.getGroupWithReverse(isReverseFromTo) + return initialToCurrencyResolver.tryGetFromCache(userWallet, initialCryptoCurrency, state, isReverseFromTo) + ?: initialToCurrencyResolver.tryGetWithMaxAmount(state, isReverseFromTo) + ?: group.available.firstOrNull()?.currencyStatus } override fun getNativeToken(networkId: String): CryptoCurrency { diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt index 9f95b3e0c6..52e15d5933 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt @@ -5,8 +5,6 @@ import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.tokens.repository.QuotesRepository -import com.tangem.domain.transaction.usecase.* -import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.feature.swap.domain.* import com.tangem.lib.crypto.TransactionManager import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -60,11 +58,9 @@ internal class SwapDomainModule { @Provides @Singleton fun provideInitialToCurrencyResolver( - getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, swapTransactionRepository: SwapTransactionRepository, ): InitialToCurrencyResolver { return DefaultInitialToCurrencyResolver( - getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, swapTransactionRepository = swapTransactionRepository, ) } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 1958445de2..cc9b9d3132 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -84,6 +84,9 @@ internal class SwapViewModel @Inject constructor( ?.unbundle(UserWalletId.serializer()) ?: error("no expected parameter UserWalletId found") + private val isInitiallyReversed: Boolean = savedStateHandle.get(AppRoute.Swap.IS_INITIAL_REVERSE_ORDER) + ?: false + private val swapInteractor = swapInteractorFactory.create(userWalletId) private lateinit var initialCryptoCurrencyStatus: CryptoCurrencyStatus @@ -137,7 +140,7 @@ internal class SwapViewModel @Inject constructor( uiState = stateBuilder.addAlert(uiState = uiState, onClick = swapRouter::back) } else { initialCryptoCurrencyStatus = cryptoCurrencyStatus - initTokens() + initTokens(isInitiallyReversed) } } } @@ -180,18 +183,21 @@ internal class SwapViewModel @Inject constructor( analyticsEventHandler.send(SwapEvents.ChooseTokenScreenOpened(availableTokens = isAnyAvailableTokens)) } - private fun initTokens() { + private fun initTokens(isReverseFromTo: Boolean) { viewModelScope.launch(dispatchers.main) { runCatching(dispatchers.io) { swapInteractor.getTokensDataState(initialCryptoCurrency) }.onSuccess { state -> updateTokensState(state) + val selectedCurrency = swapInteractor.getInitialCurrencyToSwap( + initialCryptoCurrency = initialCryptoCurrency, + state = state, + isReverseFromTo = isReverseFromTo, + ) applyInitialTokenChoice( - state, - swapInteractor.selectInitialCurrencyToSwap( - initialCryptoCurrency, - state, - ), + state = state, + selectedCurrency = selectedCurrency, + isReverseFromTo = isReverseFromTo, ) (dataState.fromCryptoCurrency?.currency as? CryptoCurrency.Coin)?.let { @@ -215,6 +221,7 @@ internal class SwapViewModel @Inject constructor( applyInitialTokenChoice( state = TokensDataStateExpress.EMPTY, selectedCurrency = null, + isReverseFromTo = isReverseFromTo, ) uiState = stateBuilder.createInitialErrorState( @@ -227,33 +234,43 @@ internal class SwapViewModel @Inject constructor( initialCryptoCurrency.network.backendId, ), ) - initTokens() + initTokens(isReverseFromTo) } } } } - private fun applyInitialTokenChoice(state: TokensDataStateExpress, selectedCurrency: CryptoCurrencyStatus?) { - val fromCurrencyStatus = initialCryptoCurrencyStatus - dataState = dataState.copy( - fromCryptoCurrency = fromCurrencyStatus, - toCryptoCurrency = selectedCurrency, - tokensDataState = state, - ) + private fun applyInitialTokenChoice( + state: TokensDataStateExpress, + selectedCurrency: CryptoCurrencyStatus?, + isReverseFromTo: Boolean, + ) { + // exceptional case if (selectedCurrency == null) { analyticsEventHandler.send(SwapEvents.NoticeNoAvailableTokensToSwap) uiState = stateBuilder.createNoAvailableTokensToSwapState( uiStateHolder = uiState, - fromToken = fromCurrencyStatus, - ) - } else { - startLoadingQuotes( - fromToken = fromCurrencyStatus, - toToken = selectedCurrency, - amount = lastAmount.value, - toProvidersList = findSwapProviders(fromCurrencyStatus, selectedCurrency), + fromToken = initialCryptoCurrencyStatus, ) + return } + isOrderReversed = isReverseFromTo + val (fromCurrencyStatus, toCurrencyStatus) = if (isOrderReversed) { + selectedCurrency to initialCryptoCurrencyStatus + } else { + initialCryptoCurrencyStatus to selectedCurrency + } + dataState = dataState.copy( + fromCryptoCurrency = fromCurrencyStatus, + toCryptoCurrency = toCurrencyStatus, + tokensDataState = state, + ) + startLoadingQuotes( + fromToken = fromCurrencyStatus, + toToken = toCurrencyStatus, + amount = lastAmount.value, + toProvidersList = findSwapProviders(fromCurrencyStatus, toCurrencyStatus), + ) } private fun updateTokensState(tokenDataState: TokensDataStateExpress) { From 73b80b5ef9e88f7ea7c4505a5bcf746bee945210 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 13:51:48 +0300 Subject: [PATCH 08/57] Updated on 2026-08-14 --- .../common/redux/global/GlobalMiddleware.kt | 33 ++++++++------- .../tap/common/redux/global/GlobalState.kt | 1 + .../tangem/tap/features/main/MainViewModel.kt | 12 ++++++ .../features/onboarding/OnboardingHelper.kt | 42 +++++++++++++++++++ .../note/redux/OnboardingNoteMiddleware.kt | 27 +++--------- .../twins/redux/TwinCardsMiddleware.kt | 28 +++---------- .../middlewares/TradeCryptoMiddleware.kt | 39 ++++++++++------- 7 files changed, 108 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index 43d85d7fc5..65341daa53 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -92,21 +92,24 @@ private fun handleAction(action: Action, appState: () -> AppState?) { scope.launch { exchangeManager.update() } } is GlobalAction.FetchUserCountry -> { - scope.launch { - // TODO("After adding DI") get dependencies by DI - runCatching { store.state.featureRepositoryProvider.homeRepository.getUserCountryCode() } - .onSuccess { - store.dispatchOnMain( - GlobalAction.FetchUserCountry.Success(countryCode = it.code.lowercase()), - ) - } - .onFailure { - store.dispatchOnMain( - GlobalAction.FetchUserCountry.Success( - countryCode = Locale.getDefault().country.lowercase(), - ), - ) - } + val homeFeatureToggles = store.inject(DaggerGraphState::homeFeatureToggles) + + if (!homeFeatureToggles.isMigrateUserCountryCodeEnabled) { + scope.launch { + runCatching { store.state.featureRepositoryProvider.homeRepository.getUserCountryCode() } + .onSuccess { + store.dispatchOnMain( + GlobalAction.FetchUserCountry.Success(countryCode = it.code.lowercase()), + ) + } + .onFailure { + store.dispatchOnMain( + GlobalAction.FetchUserCountry.Success( + countryCode = Locale.getDefault().country.lowercase(), + ), + ) + } + } } } } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 420951087b..86573ec741 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -23,6 +23,7 @@ data class GlobalState( val scanCardFailsCounter: Int = 0, val dialog: StateDialog? = null, val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(), + @Deprecated("Use GetUserCountryCodeUseCase instead") val userCountryCode: String? = null, val appThemeMode: AppThemeMode = AppThemeMode.DEFAULT, ) : StateType diff --git a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt index 6ba358cced..2fc52d0c05 100644 --- a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt @@ -16,11 +16,13 @@ import com.tangem.domain.balancehiding.UpdateBalanceHidingSettingsUseCase import com.tangem.domain.feedback.FeedbackManagerFeatureToggles import com.tangem.domain.settings.DeleteDeprecatedLogsUseCase import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase +import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase import com.tangem.domain.staking.FetchStakingTokensUseCase import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles import com.tangem.tap.common.extensions.setContext +import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles import com.tangem.tap.features.main.model.MainScreenState import com.tangem.tap.store import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -47,6 +49,8 @@ internal class MainViewModel @Inject constructor( stakingFeatureToggles: StakingFeatureToggles, private val fetchStakingTokensUseCase: FetchStakingTokensUseCase, private val apiConfigsManager: ApiConfigsManager, + private val homeFeatureToggles: HomeFeatureToggles, + private val fetchUserCountryUseCase: FetchUserCountryUseCase, getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, ) : ViewModel(), MainIntents { @@ -67,6 +71,14 @@ internal class MainViewModel @Inject constructor( viewModelScope.launch(dispatchers.main) { incrementAppLaunchCounterUseCase() } + if (homeFeatureToggles.isMigrateUserCountryCodeEnabled) { + viewModelScope.launch { + fetchUserCountryUseCase().onLeft { + Timber.e("Unable to fetch the user country code $it") + } + } + } + updateAppCurrencies() observeFlips() displayBalancesHidingStatusToast() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index bc085c6dca..130eddc672 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -1,22 +1,31 @@ package com.tangem.tap.features.onboarding +import com.tangem.blockchain.common.WalletManager import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.common.extensions.guard import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.models.Basic +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ProductType import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.settings.usercountry.models.UserCountry import com.tangem.domain.wallets.builder.UserWalletBuilder import com.tangem.domain.wallets.builder.UserWalletIdBuilder import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter +import com.tangem.tap.common.analytics.events.AnalyticsParam +import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.redux.AppDialog +import com.tangem.tap.common.redux.global.GlobalState import com.tangem.tap.features.demo.DemoHelper +import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.saveWallet.redux.SaveWalletAction import com.tangem.tap.mainScope import com.tangem.tap.proxy.redux.DaggerGraphState @@ -138,6 +147,39 @@ object OnboardingHelper { } } + fun handleTopUpAction(walletManager: WalletManager, scanResponse: ScanResponse, globalState: GlobalState) { + val blockchain = walletManager.wallet.blockchain + val cryptoCurrency = CryptoCurrencyFactory().createCoin( + blockchain = blockchain, + extraDerivationPath = null, + derivationStyleProvider = scanResponse.derivationStyleProvider, + ) ?: return + + val topUpUrl = walletManager.getTopUpUrl(cryptoCurrency) ?: return + + val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) + Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) + + scope.launch { + val homeFeatureToggles = store.inject(DaggerGraphState::homeFeatureToggles) + + val isRussia = if (homeFeatureToggles.isMigrateUserCountryCodeEnabled) { + val getUserCountryCodeUseCase = store.inject(DaggerGraphState::getUserCountryUseCase) + + getUserCountryCodeUseCase().isRight { it is UserCountry.Russia } + } else { + globalState.userCountryCode == RUSSIA_COUNTRY_CODE + } + + if (isRussia) { + val dialogData = AppDialog.RussianCardholdersWarningDialog.Data(topUpUrl) + store.dispatchDialogShow(AppDialog.RussianCardholdersWarningDialog(dialogData)) + } else { + store.dispatchOpenUrl(topUpUrl) + } + } + } + private suspend fun proceedWithScanResponse( scanResponse: ScanResponse, backupCardsIds: List?, diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index 52af2f7d66..d47862a648 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -4,12 +4,8 @@ import com.tangem.common.CompletionResult import com.tangem.common.extensions.guard import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics - -import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.extensions.makePrimaryWalletManager import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.derivationStyleProvider -import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.* @@ -20,7 +16,6 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TapError import com.tangem.tap.domain.model.Currency import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.mainScope @@ -178,23 +173,11 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch return } - val blockchain = walletManager.wallet.blockchain - val cryptoCurrency = CryptoCurrencyFactory().createCoin( - blockchain, - null, - scanResponse.derivationStyleProvider, - ) ?: return - val topUpUrl = walletManager.getTopUpUrl(cryptoCurrency) ?: return - - val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) - Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - - if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { - val dialogData = AppDialog.RussianCardholdersWarningDialog.Data(topUpUrl) - store.dispatchDialogShow(AppDialog.RussianCardholdersWarningDialog(dialogData)) - } else { - store.dispatchOpenUrl(topUpUrl) - } + OnboardingHelper.handleTopUpAction( + walletManager = walletManager, + scanResponse = scanResponse, + globalState = globalState, + ) } is OnboardingNoteAction.Done -> { store.dispatch(GlobalAction.Onboarding.Stop) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index 047a5caaa8..ef29db32d4 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -6,16 +6,12 @@ import com.tangem.common.extensions.guard import com.tangem.common.routing.AppRoute import com.tangem.common.routing.utils.popTo import com.tangem.core.analytics.Analytics - -import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.extensions.makePrimaryWalletManager import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.wallets.builder.UserWalletIdBuilder import com.tangem.domain.wallets.legacy.asLockable -import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.* @@ -26,7 +22,6 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TapError import com.tangem.tap.domain.model.Currency import com.tangem.tap.domain.twins.TwinCardsManager -import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.mainScope @@ -301,24 +296,11 @@ private fun handle(action: Action, dispatch: DispatchFunction) { return } - val scanResponse = onboardingManager?.scanResponse ?: return - val blockchain = walletManager.wallet.blockchain - val cryptoCurrency = CryptoCurrencyFactory().createCoin( - blockchain, - null, - scanResponse.derivationStyleProvider, - ) ?: return - val topUpUrl = walletManager.getTopUpUrl(cryptoCurrency) ?: return - - val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) - Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - - if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { - val dialogData = AppDialog.RussianCardholdersWarningDialog.Data(topUpUrl) - store.dispatchDialogShow(AppDialog.RussianCardholdersWarningDialog(dialogData)) - } else { - store.dispatchOpenUrl(topUpUrl) - } + OnboardingHelper.handleTopUpAction( + walletManager = walletManager, + scanResponse = onboardingManager?.scanResponse ?: return, + globalState = globalState, + ) } TwinCardsAction.Done -> { val scanResponse = getScanResponse() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 1abdf861b9..2f26b2a39a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -5,6 +5,7 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics +import com.tangem.domain.settings.usercountry.models.UserCountry import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.NetworkAddress @@ -70,16 +71,26 @@ object TradeCryptoMiddleware { isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive, ) - if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { - val dialogData = topUrl?.let { - AppDialog.RussianCardholdersWarningDialog.Data(topUpUrl = it) - } - store.dispatchDialogShow(AppDialog.RussianCardholdersWarningDialog(data = dialogData)) - return - } + scope.launch { + val homeFeatureToggles = store.inject(DaggerGraphState::homeFeatureToggles) - if (currency is CryptoCurrency.Token && currency.network.isTestnet) { - scope.launch { + val isRussia = if (homeFeatureToggles.isMigrateUserCountryCodeEnabled) { + val getUserCountryCodeUseCase = store.inject(DaggerGraphState::getUserCountryUseCase) + + getUserCountryCodeUseCase().isRight { it is UserCountry.Russia } + } else { + state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE + } + + if (action.checkUserLocation && isRussia) { + val dialogData = topUrl?.let { + AppDialog.RussianCardholdersWarningDialog.Data(topUpUrl = it) + } + store.dispatchDialogShow(AppDialog.RussianCardholdersWarningDialog(data = dialogData)) + return@launch + } + + if (currency is CryptoCurrency.Token && currency.network.isTestnet) { val walletManager = store.inject(DaggerGraphState::walletManagersFacade) .getOrCreateWalletManager( userWalletId = action.userWallet.walletId, @@ -97,13 +108,13 @@ object TradeCryptoMiddleware { walletManager = walletManager, destinationAddress = currency.contractAddress, ) + return@launch } - return - } - topUrl?.let { - store.dispatchOpenUrl(it) - Analytics.send(Token.Topup.ScreenOpened()) + topUrl?.let { + store.dispatchOpenUrl(it) + Analytics.send(Token.Topup.ScreenOpened()) + } } } From dad8ccb8da4f1318979bd12c44d5cd166857c24b Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 22 Sep 2024 11:19:30 +0300 Subject: [PATCH 09/57] Updated on 2026-08-14 --- .../com/tangem/tap/ApplicationEntryPoint.kt | 3 - .../main/java/com/tangem/tap/MainActivity.kt | 9 +- .../java/com/tangem/tap/TangemApplication.kt | 5 - .../com/tangem/tap/common/redux/AppReducer.kt | 2 - .../com/tangem/tap/common/redux/AppState.kt | 4 - .../com/tangem/tap/domain/TapWalletManager.kt | 3 - .../domain/scanCard/LegacyScanProcessor.kt | 27 +--- .../domain/scanCard/UseCaseScanProcessor.kt | 6 +- .../domain/scanCard/chains/DisclaimerChain.kt | 38 +---- .../details/ui/details/DetailsViewModel.kt | 7 +- .../tap/features/disclaimer/Disclaimer.kt | 6 - .../disclaimer/redux/DisclaimerAction.kt | 20 --- .../disclaimer/redux/DisclaimerMiddleware.kt | 45 ------ .../disclaimer/redux/DisclaimerReducer.kt | 31 ---- .../disclaimer/redux/DisclaimerSource.kt | 5 - .../disclaimer/redux/DisclaimerState.kt | 20 --- .../disclaimer/ui/DisclaimerFragment.kt | 139 ------------------ .../disclaimer/ui/DisclaimerWebViewClient.kt | 64 -------- .../disclaimer/ui/LocalTermOfServices.kt | 66 --------- .../tap/proxy/redux/DaggerGraphState.kt | 2 - .../tangem/tap/routing/utils/ChildFactory.kt | 17 +-- .../main/res/layout/fragment_disclaimer.xml | 129 ---------------- .../configs/feature_toggles_config.json | 4 - .../PushNotificationsFeatureToggles.kt | 9 -- .../PushNotificationsFeatureTogglesModule.kt | 24 --- .../DefaultPushNotificationsFeatureToggles.kt | 11 -- .../wallet/viewmodels/WalletViewModel.kt | 5 +- 27 files changed, 24 insertions(+), 677 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerReducer.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerSource.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/disclaimer/ui/LocalTermOfServices.kt delete mode 100644 app/src/main/res/layout/fragment_disclaimer.xml delete mode 100644 features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/featuretoggles/PushNotificationsFeatureToggles.kt delete mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsFeatureTogglesModule.kt delete mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/featuretoggles/DefaultPushNotificationsFeatureToggles.kt diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index 772a78b90d..a4fe0bb116 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -32,7 +32,6 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase import com.tangem.features.details.DetailsFeatureToggles -import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles import com.tangem.tap.common.log.TangemAppLoggerInitializer import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles @@ -118,8 +117,6 @@ interface ApplicationEntryPoint { fun getAppRouter(): AppRouter - fun getPushNotificationsFeatureToggles(): PushNotificationsFeatureToggles - fun getTangemAppLogger(): TangemAppLoggerInitializer fun getHomeFeatureToggles(): HomeFeatureToggles diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 7735974a6d..312d9693a9 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -65,7 +65,6 @@ import com.tangem.tap.common.OnActivityResultCallback import com.tangem.tap.common.SnackbarHandler import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.extensions.showFragmentAllowingStateLoss import com.tangem.tap.common.redux.NotificationsHandler import com.tangem.tap.domain.sdk.TangemSdkManager @@ -78,7 +77,6 @@ import com.tangem.tap.features.main.model.Toast import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction import com.tangem.tap.proxy.AppStateHolder import com.tangem.tap.proxy.redux.DaggerGraphAction -import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.routing.RoutingComponent import com.tangem.tap.routing.configurator.AppRouterConfig import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler @@ -539,11 +537,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac } } else { lifecycleScope.launch { - val toggles = store.inject(getDependency = DaggerGraphState::pushNotificationsFeatureToggles) - val isPushPermissionEnabled = toggles.isPushNotificationsEnabled - val shouldShowTos = !cardRepository.isTangemTOSAccepted() && isPushPermissionEnabled - val wasPushInitiallyAsked = shouldInitiallyAskPermissionUseCase(PUSH_PERMISSION).getOrElse { false } - val shouldShowInitialPush = wasPushInitiallyAsked && isPushPermissionEnabled + val shouldShowTos = !cardRepository.isTangemTOSAccepted() + val shouldShowInitialPush = shouldInitiallyAskPermissionUseCase(PUSH_PERMISSION).getOrElse { false } val route = when { shouldShowTos -> AppRoute.Disclaimer(isTosAccepted = false) diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index cf7f9a9347..33de0ba637 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -45,7 +45,6 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase import com.tangem.features.details.DetailsFeatureToggles -import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles import com.tangem.tap.common.analytics.AnalyticsFactory import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler @@ -188,9 +187,6 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { private val appRouter: AppRouter get() = entryPoint.getAppRouter() - private val pushNotificationsFeatureToggles: PushNotificationsFeatureToggles - get() = entryPoint.getPushNotificationsFeatureToggles() - private val tangemAppLoggerInitializer: TangemAppLoggerInitializer get() = entryPoint.getTangemAppLogger() @@ -280,7 +276,6 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { urlOpener = urlOpener, shareManager = shareManager, appRouter = appRouter, - pushNotificationsFeatureToggles = pushNotificationsFeatureToggles, homeFeatureToggles = homeFeatureToggles, getUserCountryUseCase = getUserCountryUseCase, ), diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt index cdc2bed475..1509ffe81b 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt @@ -3,7 +3,6 @@ package com.tangem.tap.common.redux import com.tangem.tap.common.redux.global.globalReducer import com.tangem.tap.features.details.redux.DetailsReducer import com.tangem.tap.features.details.redux.walletconnect.WalletConnectReducer -import com.tangem.tap.features.disclaimer.redux.DisclaimerReducer import com.tangem.tap.features.home.redux.HomeReducer import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteReducer import com.tangem.tap.features.onboarding.products.otherCards.redux.OnboardingOtherCardsReducer @@ -28,7 +27,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder) onboardingOtherCardsState = OnboardingOtherCardsReducer.reduce(action, state), twinCardsState = TwinCardsReducer.reduce(action, state), detailsState = DetailsReducer.reduce(action, state), - disclaimerState = DisclaimerReducer.reduce(action, state), tokensState = TokensReducer.reduce(action, state), walletConnectState = WalletConnectReducer.reduce(action, state.walletConnectState), welcomeState = WelcomeReducer.reduce(action, state), diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt index bdcb0bd1c1..8c30e94166 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt @@ -10,8 +10,6 @@ import com.tangem.tap.features.details.redux.DetailsMiddleware import com.tangem.tap.features.details.redux.DetailsState import com.tangem.tap.features.details.redux.walletconnect.WalletConnectMiddleware import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState -import com.tangem.tap.features.disclaimer.redux.DisclaimerMiddleware -import com.tangem.tap.features.disclaimer.redux.DisclaimerState import com.tangem.tap.features.home.redux.HomeMiddleware import com.tangem.tap.features.home.redux.HomeState import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteMiddleware @@ -43,7 +41,6 @@ data class AppState( val onboardingOtherCardsState: OnboardingOtherCardsState = OnboardingOtherCardsState(), val twinCardsState: TwinCardsState = TwinCardsState(), val detailsState: DetailsState = DetailsState(), - val disclaimerState: DisclaimerState = DisclaimerState(), val tokensState: TokensState = TokensState(), val walletConnectState: WalletConnectState = WalletConnectState(), val welcomeState: WelcomeState = WelcomeState(), @@ -75,7 +72,6 @@ data class AppState( OnboardingOtherCardsMiddleware.handler, TwinCardsMiddleware.handler, DetailsMiddleware().detailsMiddleware, - DisclaimerMiddleware().disclaimerMiddleware, WalletConnectMiddleware().walletConnectMiddleware, BackupMiddleware().backupMiddleware, WelcomeMiddleware().middleware, diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 256c8f1bf9..c25cf8552c 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -13,8 +13,6 @@ import com.tangem.operations.attestation.Attestation import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.extensions.setContext import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.features.disclaimer.createDisclaimer -import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store @@ -62,7 +60,6 @@ class TapWalletManager( updateConfigManager(scanResponse) withMainContext { // Order is important - store.dispatch(DisclaimerAction.SetDisclaimer(card.createDisclaimer())) store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse)) store.dispatch(GlobalAction.SaveScanResponse(scanResponse)) store.dispatch(GlobalAction.SetIfCardVerifiedOnline(!attestationFailed)) diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt index ea7c4ac652..f851113e17 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt @@ -2,7 +2,6 @@ package com.tangem.tap.domain.scanCard import com.tangem.common.CompletionResult import com.tangem.common.core.TangemError -import com.tangem.common.core.TangemSdkError import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.common.routing.AppRoute @@ -18,9 +17,6 @@ import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.disclaimer.createDisclaimer -import com.tangem.tap.features.disclaimer.redux.DisclaimerAction -import com.tangem.tap.features.disclaimer.redux.DisclaimerCallback -import com.tangem.tap.features.disclaimer.redux.DisclaimerSource import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsStep @@ -102,6 +98,8 @@ internal object LegacyScanProcessor { } } + // TODO: [REDACTED_JIRA] + @Suppress("UnusedPrivateMember") private suspend inline fun showDisclaimerIfNeed( scanResponse: ScanResponse, crossinline disclaimerWillShow: () -> Unit = {}, @@ -109,7 +107,6 @@ internal object LegacyScanProcessor { crossinline onFailure: suspend (error: TangemError) -> Unit, ) { val disclaimer = scanResponse.card.createDisclaimer() - store.dispatchOnMain(DisclaimerAction.SetDisclaimer(disclaimer)) if (disclaimer.isAccepted()) { nextHandler(scanResponse) @@ -120,23 +117,9 @@ internal object LegacyScanProcessor { withContext(Dispatchers.Main.immediate) { disclaimerWillShow() - store.dispatch( - DisclaimerAction.Show( - from = DisclaimerSource.Home, - callback = DisclaimerCallback( - onAccept = { - scope.launch(Dispatchers.Main.immediate) { - nextHandler(scanResponse) - } - }, - onDismiss = { - scope.launch(Dispatchers.Main.immediate) { - onFailure(TangemSdkError.UserCancelled()) - } - }, - ), - ), - ) + store.dispatchNavigationAction { + push(AppRoute.Disclaimer(isTosAccepted = false)) + } } } } diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt index 381d348980..10646e2bfa 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt @@ -59,11 +59,7 @@ internal object UseCaseScanProcessor { ), ) add(AnalyticsChain(Basic.CardWasScanned(analyticsSource))) - val pushNotificationsToggles = - store.inject(getDependency = DaggerGraphState::pushNotificationsFeatureToggles) - if (pushNotificationsToggles.isPushNotificationsEnabled) { - add(DisclaimerChain(store, disclaimerWillShow)) - } + add(DisclaimerChain(store, disclaimerWillShow)) add(CheckForOnboardingChain(store, store.state.globalState.tapWalletManager)) } diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/DisclaimerChain.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/DisclaimerChain.kt index 8aa003b952..7bd4be874c 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/DisclaimerChain.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/DisclaimerChain.kt @@ -1,21 +1,15 @@ package com.tangem.tap.domain.scanCard.chains -import arrow.core.left import arrow.core.right +import com.tangem.common.routing.AppRoute import com.tangem.domain.card.ScanCardException import com.tangem.domain.core.chain.Chain import com.tangem.domain.core.chain.ResultChain import com.tangem.domain.models.scan.ScanResponse -import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.extensions.dispatchNavigationAction import com.tangem.tap.common.redux.AppState -import com.tangem.tap.features.disclaimer.Disclaimer import com.tangem.tap.features.disclaimer.createDisclaimer -import com.tangem.tap.features.disclaimer.redux.DisclaimerAction -import com.tangem.tap.features.disclaimer.redux.DisclaimerCallback -import com.tangem.tap.features.disclaimer.redux.DisclaimerSource -import kotlinx.coroutines.suspendCancellableCoroutine import org.rekotlin.Store -import kotlin.coroutines.resume /** * Handles disclaimer display after the card scanning operation. @@ -40,31 +34,13 @@ internal class DisclaimerChain( previousChainResult.right() } else { disclaimerWillShow() - showDisclaimer(disclaimer, previousChainResult) - } - } - private suspend fun showDisclaimer(disclaimer: Disclaimer, response: ScanResponse): ScanChainResult { - store.dispatchOnMain(DisclaimerAction.SetDisclaimer(disclaimer)) + // TODO: [REDACTED_JIRA] + store.dispatchNavigationAction { + push(route = AppRoute.Disclaimer(isTosAccepted = false)) + } - return suspendCancellableCoroutine { continuation -> - store.dispatchOnMain( - DisclaimerAction.Show( - from = DisclaimerSource.Home, - callback = DisclaimerCallback( - onAccept = { - if (continuation.isActive) { - continuation.resume(response.right()) - } - }, - onDismiss = { - if (continuation.isActive) { - continuation.resume(ScanChainException.DisclaimerWasCanceled.left()) - } - }, - ), - ), - ) + previousChainResult.right() } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt index d2c84a43db..33b8ace939 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt @@ -7,7 +7,6 @@ import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic - import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.event.consumedEvent import com.tangem.core.ui.event.triggeredEvent @@ -22,8 +21,6 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState -import com.tangem.tap.features.disclaimer.redux.DisclaimerAction -import com.tangem.tap.features.disclaimer.redux.DisclaimerSource import com.tangem.tap.features.home.LocaleRegionProvider import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.scope @@ -128,7 +125,9 @@ internal class DetailsViewModel( } private fun navigateToToS() { - store.dispatchOnMain(DisclaimerAction.Show(DisclaimerSource.Details)) + store.dispatchNavigationAction { + push(AppRoute.Disclaimer(isTosAccepted = true)) + } } private fun navigateToReferralProgram() { diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt index 9cda07b754..3524b38f40 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/Disclaimer.kt @@ -24,12 +24,6 @@ abstract class BaseDisclaimer( override suspend fun isAccepted(): Boolean = dataProvider.isAccepted() } -class DummyDisclaimer : Disclaimer { - override fun getUri(): Uri = Uri.parse("https://tangem.com/tangem_tos.html") - override suspend fun accept() {} - override suspend fun isAccepted(): Boolean = false -} - class TangemDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) { override fun getUri(): Uri = Uri.parse("$baseUrl/tangem_tos.html") } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt deleted file mode 100644 index 9611dc80b5..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.tangem.tap.features.disclaimer.redux - -import com.tangem.tap.common.entities.ProgressState -import com.tangem.tap.features.disclaimer.Disclaimer -import org.rekotlin.Action - -sealed class DisclaimerAction : Action { - - data class SetDisclaimer(val disclaimer: Disclaimer) : DisclaimerAction() - - data class Show( - val from: DisclaimerSource, - val callback: DisclaimerCallback? = null, - ) : DisclaimerAction() - - object AcceptDisclaimer : DisclaimerAction() - object OnBackPressed : DisclaimerAction() - - data class OnProgressStateChanged(val state: ProgressState?) : DisclaimerAction() -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerMiddleware.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerMiddleware.kt deleted file mode 100644 index 60ffa51781..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerMiddleware.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.tangem.tap.features.disclaimer.redux - -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.AppRouter -import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.mainScope -import com.tangem.tap.store -import kotlinx.coroutines.launch -import org.rekotlin.Action -import org.rekotlin.Middleware - -class DisclaimerMiddleware { - val disclaimerMiddleware: Middleware = { dispatch, state -> - { next -> - { action -> - state()?.let { handleDisclaimerMiddleware(action, it) } - next(action) - } - } - } -} - -private fun handleDisclaimerMiddleware(action: Action, appState: AppState) { - val state = appState.disclaimerState - - when (action) { - is DisclaimerAction.Show -> { - store.dispatchNavigationAction { - push(AppRoute.Disclaimer(isTosAccepted = action.from == DisclaimerSource.Details)) - } - } - is DisclaimerAction.AcceptDisclaimer -> { - mainScope.launch { - state.disclaimer.accept() - store.dispatchNavigationAction(AppRouter::pop) - state.callback?.onAccept?.invoke() - } - } - is DisclaimerAction.OnBackPressed -> { - store.dispatchNavigationAction(AppRouter::pop) - state.callback?.onDismiss?.invoke() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerReducer.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerReducer.kt deleted file mode 100644 index 9b655697ba..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerReducer.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.tangem.tap.features.disclaimer.redux - -import com.tangem.tap.common.redux.AppState -import org.rekotlin.Action - -object DisclaimerReducer { - fun reduce(action: Action, state: AppState): DisclaimerState = internalReduce(action, state) -} - -private fun internalReduce(action: Action, state: AppState): DisclaimerState { - if (action !is DisclaimerAction) return state.disclaimerState - - val disclaimerState = state.disclaimerState - - return when (action) { - is DisclaimerAction.SetDisclaimer -> disclaimerState.copy( - disclaimer = action.disclaimer, - ) - is DisclaimerAction.Show -> disclaimerState.copy( - showedFrom = action.from, - callback = action.callback, - ) - is DisclaimerAction.AcceptDisclaimer, is DisclaimerAction.OnBackPressed -> disclaimerState.copy( - callback = null, - progressState = null, - ) - is DisclaimerAction.OnProgressStateChanged -> disclaimerState.copy( - progressState = action.state, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerSource.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerSource.kt deleted file mode 100644 index cdfcbbdb90..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerSource.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.tangem.tap.features.disclaimer.redux - -enum class DisclaimerSource { - Home, Details -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt deleted file mode 100644 index c5ccfc7cfc..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.tangem.tap.features.disclaimer.redux - -import com.tangem.common.extensions.VoidCallback - -import com.tangem.tap.common.entities.ProgressState -import com.tangem.tap.features.disclaimer.Disclaimer -import com.tangem.tap.features.disclaimer.DummyDisclaimer -import org.rekotlin.StateType - -data class DisclaimerState( - val disclaimer: Disclaimer = DummyDisclaimer(), - val showedFrom: DisclaimerSource = DisclaimerSource.Home, - val callback: DisclaimerCallback? = null, - val progressState: ProgressState? = null, -) : StateType - -data class DisclaimerCallback( - val onAccept: VoidCallback? = null, - val onDismiss: VoidCallback? = null, -) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt deleted file mode 100644 index 9d217e6111..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.tangem.tap.features.disclaimer.ui - -import android.os.Bundle -import android.view.View -import android.view.View.OVER_SCROLL_NEVER -import android.webkit.WebView -import androidx.lifecycle.lifecycleScope -import androidx.transition.TransitionInflater -import by.kirich1409.viewbindingdelegate.viewBinding - -import com.tangem.core.ui.extensions.setStatusBarColor -import com.tangem.tap.common.entities.ProgressState -import com.tangem.tap.common.extensions.beginDelayedTransition -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.show -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.features.BaseFragment -import com.tangem.tap.features.addBackPressHandler -import com.tangem.tap.features.disclaimer.Disclaimer -import com.tangem.tap.features.disclaimer.redux.DisclaimerAction -import com.tangem.tap.features.disclaimer.redux.DisclaimerSource -import com.tangem.tap.features.disclaimer.redux.DisclaimerState -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.FragmentDisclaimerBinding -import kotlinx.coroutines.launch -import org.rekotlin.StoreSubscriber - -class DisclaimerFragment : BaseFragment(R.layout.fragment_disclaimer), StoreSubscriber { - - private val binding: FragmentDisclaimerBinding by viewBinding(FragmentDisclaimerBinding::bind) - private val webViewClient = DisclaimerWebViewClient() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - addBackPressHandler(handler = this) - - binding.apply { - toolbar.setNavigationOnClickListener { handleOnBackPressed() } - webView.apply { - settings.allowFileAccess = false - settings.javaScriptEnabled = false - overScrollMode = OVER_SCROLL_NEVER - webViewClient = this@DisclaimerFragment.webViewClient - } - webView.hide() - groupError.hide() - groupAccept.hide() - groupLoading.hide() - - btnAccept.setOnClickListener { - store.dispatch(DisclaimerAction.AcceptDisclaimer) - } - btnRepeat.setOnClickListener { - webViewClient.reset() - } - } - } - - override fun onStart() { - super.onStart() - setStatusBarColor(R.color.background_secondary) - - webViewClient.onProgressStateChanged = { store.dispatch(DisclaimerAction.OnProgressStateChanged(it)) } - store.subscribe(subscriber = this) { state -> - state - .skipRepeats { oldState, newState -> oldState.disclaimerState == newState.disclaimerState } - .select(AppState::disclaimerState) - } - } - - override fun onStop() { - webViewClient.onProgressStateChanged = null - store.unsubscribe(this) - super.onStop() - } - - override fun configureTransitions() { - val inflater = TransitionInflater.from(requireContext()) - when (store.state.disclaimerState.showedFrom) { - DisclaimerSource.Home -> { - enterTransition = inflater.inflateTransition(android.R.transition.slide_bottom) - exitTransition = inflater.inflateTransition(android.R.transition.slide_top) - } - DisclaimerSource.Details -> { - super.configureTransitions() - } - } - } - - override fun handleOnBackPressed() { - store.dispatch(DisclaimerAction.OnBackPressed) - } - - override fun newState(state: DisclaimerState) { - return with(binding) { - if (activity == null || view == null) return - - updateUiVisibility(state.disclaimer, state.progressState) - } - } - - private fun updateUiVisibility(disclaimer: Disclaimer, progressState: ProgressState?) = with(binding) { - when (progressState) { - ProgressState.Loading -> { - root.beginDelayedTransition() - webView.hide() - groupError.hide() - groupAccept.hide() - groupLoading.show() - } - ProgressState.Done -> { - root.beginDelayedTransition() - groupError.hide() - groupLoading.hide() - webView.show() - lifecycleScope.launch { - groupAccept.show(!disclaimer.isAccepted()) - } - } - ProgressState.Error -> { - root.beginDelayedTransition() - webView.show() - groupAccept.show() - groupLoading.hide() - groupError.hide() - webView.loadLocalTermsOfServices() - } - else -> { - webView.setBackgroundColor(resources.getColor(R.color.transparent, null)) - webView.loadUrl(disclaimer.getUri().toString()) - } - } - } - - private fun WebView.loadLocalTermsOfServices() { - loadData(localTermsOfServices, "text/html", "UTF-8") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt deleted file mode 100644 index c64d0b7543..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.tangem.tap.features.disclaimer.ui - -import android.graphics.Bitmap -import android.webkit.* -import com.tangem.common.extensions.ifNotNull -import com.tangem.tap.common.entities.ProgressState - -class DisclaimerWebViewClient : WebViewClient() { - - var onProgressStateChanged: ((ProgressState) -> Unit)? = null - - private var loadingUrl: String? = null - private var loadedUrl: String? = null - - private var progressState: ProgressState = ProgressState.Loading - set(value) { - field = value - onProgressStateChanged?.invoke(value) - } - - fun reset() { - loadingUrl = null - loadedUrl = null - progressState = ProgressState.Loading - } - - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { - super.onPageStarted(view, url, favicon) - - if (loadingUrl != url) progressState = ProgressState.Loading - loadingUrl = url - } - - override fun onPageFinished(view: WebView?, url: String?) { - super.onPageFinished(view, url) - - if (loadedUrl != url) progressState = ProgressState.Done - loadedUrl = url - } - - override fun onReceivedError(view: WebView?, resourceRequest: WebResourceRequest?, error: WebResourceError?) { - super.onReceivedError(view, resourceRequest, error) - error?.let { progressState = ProgressState.Error } - } - - override fun onReceivedHttpError( - view: WebView?, - resourceRequest: WebResourceRequest?, - errorResponse: WebResourceResponse?, - ) { - super.onReceivedHttpError(view, resourceRequest, errorResponse) - - ifNotNull(resourceRequest, errorResponse) { request, response -> - if (request.url?.toString() != loadingUrl || response.statusCode < RESPONSE_USER_ERROR_STATUS_CODE) return - if (progressState != ProgressState.Done) return - - progressState = ProgressState.Error - } - } - - companion object { - private const val RESPONSE_USER_ERROR_STATUS_CODE = 400 - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/LocalTermOfServices.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/LocalTermOfServices.kt deleted file mode 100644 index 6651d0fa75..0000000000 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/LocalTermOfServices.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.tangem.tap.features.disclaimer.ui - -internal val localTermsOfServices = """ - - - - - - - Legal Disclaimer - - -

Legal Disclaimer

-

    1. Tangem application (Software)

-

    The Software is intended for usage only with Tangem hardware wallets (Cards) via NFC interface. The - Software DOES NOT:

-

    a) Generate, store, transmit, or have access to private (secret) cryptographic keys to blockchain - wallets holding digital assets, including crypto-currency.

-

    b) Generate, store, transmit, or have access to secret keys, passwords, passphrases, recovery phrases - that can be used to restore or to copy private (secret) keys to blockchain wallets holding digital assets, including - crypto-currency.

-

    c) Provide exchange, trading, investment services on behalf of Tangem AG.

-

    2. Risks related to the use of Software

-

    Tangem will not be responsible for any losses, damages or claims arising from events falling within the - scope of the following five categories:

-

    a) Mistakes made by the user of any cryptocurrency-related software or service, e.g., forgotten - passwords, payments sent to wrong addresses, and accidental deletion of blockchain wallets on Cards.

-

    b) Problems of Software and/or any blockchain- or cryptocurrency- related software or service, e.g., - corrupted files, incorrectly constructed transactions, unsafe cryptographic libraries, malware.

-

    c) Technical failures in the hardware of the user, including Cards, of any cryptocurrency-related - software or service, e.g., data loss due to a faulty or damaged storage device.

-

    d) Security problems experienced by the user of any cryptocurrency-related software or service, e.g., - unauthorized access to users' wallets and/or accounts.

-

    e) Actions or inactions of third parties and/or events experienced by third parties, e.g., bankruptcy - of service providers, information security attacks on service providers, and fraud conducted by third parties.

-

    3. Trading and Investment risks

-

    There is considerable exposure to risk in any crypto-currency or other digital asset exchange - transaction. Any transaction involving currencies involves risks including, but not limited to, the potential for - changing economic conditions that may substantially affect the price or liquidity of a currency. Investments in - crypto-currency exchange speculation may also be susceptible to sharp rises and falls as the relevant market values - fluctuate. It is for this reason that when speculating in such markets it is advisable to use only risk capital.

-

    4. Electronic Trading Risks

-

    Before you engage in transactions using an electronic system, you should carefully review the rules and - regulations of the exchanges offering the system and/or listing the instruments you intend to trade. Online trading - has inherent risk due to system response and access times that may vary due to market conditions, system - performance, and other factors. You should understand these and additional risks before trading.

-

    5. Compliance with tax obligations        

-

    The users of the Software are solely responsible to determinate what, if any, taxes apply to their - crypto-currency transactions. The owners of, or contributors to, the Software are NOT responsible for determining - the taxes that apply to crypto-currency transactions.        

-

    6. No warranties        

-

    The Software is provided on an "as is" basis without any warranties of any kind regarding the - Software and/or any content, data, materials and/or services provided on the Software.       -  

-

    7. Limitation of liability

-

    Unless otherwise required by law, in no event shall the owners of, or contributors to, the Software be - liable for any damages of any kind, including, but not limited to, loss of use, loss of profits, or loss of data - arising out of or in any way connected with the use of the Software. In no way are the owners of, or contributors - to, the Software responsible for the actions, decisions, or other behavior taken or not taken by you in reliance - upon the Software.

-

    8. Last amendment

-

    This disclaimer was amended for the last time on October 1st, 2020.

- -""".trimIndent() \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 81fba12558..bd0c5cdfc2 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -31,7 +31,6 @@ import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase import com.tangem.feature.qrscanning.QrScanningRouter import com.tangem.features.details.DetailsFeatureToggles -import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.features.send.api.navigation.SendRouter import com.tangem.features.staking.api.navigation.StakingRouter @@ -87,7 +86,6 @@ data class DaggerGraphState( val urlOpener: UrlOpener? = null, val shareManager: ShareManager? = null, val appRouter: AppRouter? = null, - val pushNotificationsFeatureToggles: PushNotificationsFeatureToggles? = null, val pushNotificationsRouter: PushNotificationsRouter? = null, val homeFeatureToggles: HomeFeatureToggles? = null, val getUserCountryUseCase: GetUserCountryUseCase? = null, diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 6d8ea8f746..9f8063d750 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -12,7 +12,6 @@ import com.tangem.features.disclaimer.api.components.DisclaimerComponent import com.tangem.features.managetokens.ManageTokensToggles import com.tangem.features.managetokens.component.ManageTokensComponent import com.tangem.features.markets.details.MarketsTokenDetailsComponent -import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.features.send.api.navigation.SendRouter import com.tangem.features.staking.api.navigation.StakingRouter @@ -28,7 +27,6 @@ import com.tangem.tap.features.details.ui.details.DetailsFragment import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment -import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment import com.tangem.tap.features.home.HomeFragment import com.tangem.tap.features.main.ui.ModalNotificationBottomSheetFragment import com.tangem.tap.features.onboarding.products.note.OnboardingNoteFragment @@ -59,7 +57,6 @@ internal class ChildFactory @Inject constructor( private val stakingRouter: StakingRouter, private val testerRouter: TesterRouter, private val detailsFeatureToggles: DetailsFeatureToggles, - private val pushNotificationsFeatureToggles: PushNotificationsFeatureToggles, private val manageTokensToggles: ManageTokensToggles, private val pushNotificationRouter: PushNotificationsRouter, ) { @@ -111,15 +108,11 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { SecurityModeFragment() }) } is AppRoute.Disclaimer -> { - if (pushNotificationsFeatureToggles.isPushNotificationsEnabled) { - route.asComponentChild( - contextProvider = contextProvider(route, contextFactory), - params = DisclaimerComponent.Params(route.isTosAccepted), - componentFactory = disclaimerComponentFactory, - ) - } else { - route.asFragmentChild(Provider { DisclaimerFragment() }) - } + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = DisclaimerComponent.Params(route.isTosAccepted), + componentFactory = disclaimerComponentFactory, + ) } is AppRoute.Home -> { route.asFragmentChild(Provider { HomeFragment() }) diff --git a/app/src/main/res/layout/fragment_disclaimer.xml b/app/src/main/res/layout/fragment_disclaimer.xml deleted file mode 100644 index 346cab4f03..0000000000 --- a/app/src/main/res/layout/fragment_disclaimer.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - -