Updated on 2026-08-14
This commit is contained in:
commit
6d0b295ca3
219 changed files with 3720 additions and 1687 deletions
|
|
@ -36,6 +36,8 @@ import com.tangem.domain.apptheme.model.AppThemeMode
|
|||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManagerFeatureToggles
|
||||
import com.tangem.domain.wallets.legacy.asLockable
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.features.managetokens.navigation.ManageTokensUi
|
||||
import com.tangem.features.send.api.navigation.SendRouter
|
||||
|
|
@ -140,6 +142,12 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
@Inject
|
||||
lateinit var deepLinksRegistry: DeepLinksRegistry
|
||||
|
||||
@Inject
|
||||
lateinit var userWalletsListManagerFeatureToggles: UserWalletsListManagerFeatureToggles
|
||||
|
||||
@Inject
|
||||
lateinit var generalUserWalletsListManager: UserWalletsListManager
|
||||
|
||||
internal val viewModel: MainViewModel by viewModels()
|
||||
|
||||
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode?>
|
||||
|
|
@ -438,7 +446,12 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
}
|
||||
|
||||
private fun navigateToInitialScreen(intentWhichStartedActivity: Intent?) {
|
||||
val canSaveWallets = userWalletsListManager is BiometricUserWalletsListManager
|
||||
val canSaveWallets = if (userWalletsListManagerFeatureToggles.isGeneralManagerEnabled) {
|
||||
runCatching { userWalletsListManager.asLockable()?.isLockedSync }
|
||||
.fold(onSuccess = { true }, onFailure = { false })
|
||||
} else {
|
||||
userWalletsListManager is BiometricUserWalletsListManager
|
||||
}
|
||||
val hasSavedWallets = userWalletsListManager.hasUserWallets
|
||||
|
||||
if (canSaveWallets && hasSavedWallets) {
|
||||
|
|
|
|||
|
|
@ -30,11 +30,15 @@ import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
|||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManagerFeatureToggles
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggles
|
||||
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
|
||||
|
|
@ -155,6 +159,21 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
|
||||
@Inject
|
||||
lateinit var accountCreator: AccountCreator
|
||||
|
||||
@Inject
|
||||
lateinit var userWalletsListManagerFeatureToggles: UserWalletsListManagerFeatureToggles
|
||||
|
||||
@Inject
|
||||
lateinit var generalUserWalletsListManager: UserWalletsListManager
|
||||
|
||||
@Inject
|
||||
lateinit var wasTwinsOnboardingShownUseCase: WasTwinsOnboardingShownUseCase
|
||||
|
||||
@Inject
|
||||
lateinit var saveTwinsOnboardingShownUseCase: SaveTwinsOnboardingShownUseCase
|
||||
|
||||
@Inject
|
||||
lateinit var cardRepository: CardRepository
|
||||
// endregion Injected
|
||||
|
||||
override fun onCreate() {
|
||||
|
|
@ -183,8 +202,13 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
// TODO: Try to performance and user experience.
|
||||
// [REDACTED_JIRA]
|
||||
runBlocking {
|
||||
initUserWalletsListManager()
|
||||
featureTogglesManager.init()
|
||||
|
||||
if (userWalletsListManagerFeatureToggles.isGeneralManagerEnabled) {
|
||||
store.dispatch(GlobalAction.UpdateUserWalletsListManager(generalUserWalletsListManager))
|
||||
} else {
|
||||
initUserWalletsListManager()
|
||||
}
|
||||
}
|
||||
|
||||
val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.sdkMoshi, BuildConfig.ENVIRONMENT)
|
||||
|
|
@ -232,6 +256,11 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
sendFeatureToggles = sendFeatureToggles,
|
||||
blockchainDataStorage = blockchainDataStorage,
|
||||
accountCreator = accountCreator,
|
||||
userWalletsListManagerFeatureToggles = userWalletsListManagerFeatureToggles,
|
||||
generalUserWalletsListManager = generalUserWalletsListManager,
|
||||
wasTwinsOnboardingShownUseCase = wasTwinsOnboardingShownUseCase,
|
||||
saveTwinsOnboardingShownUseCase = saveTwinsOnboardingShownUseCase,
|
||||
cardRepository = cardRepository,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -128,18 +128,13 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
|||
AppScreen.OnboardingTwins -> OnboardingTwinsFragment()
|
||||
AppScreen.OnboardingOther -> OnboardingOtherCardsFragment()
|
||||
AppScreen.Wallet -> {
|
||||
store.state.daggerGraphState
|
||||
.get(getDependency = DaggerGraphState::walletRouter)
|
||||
.getEntryFragment()
|
||||
store.inject(getDependency = DaggerGraphState::walletRouter).getEntryFragment()
|
||||
}
|
||||
AppScreen.Send -> {
|
||||
val featureToggles = store.state.daggerGraphState.get(
|
||||
getDependency = DaggerGraphState::sendFeatureToggles,
|
||||
)
|
||||
val featureToggles = store.inject(getDependency = DaggerGraphState::sendFeatureToggles)
|
||||
|
||||
if (featureToggles.isRedesignedSendEnabled) {
|
||||
store.state.daggerGraphState
|
||||
.get(getDependency = DaggerGraphState::sendRouter)
|
||||
.getEntryFragment()
|
||||
store.inject(getDependency = DaggerGraphState::sendRouter).getEntryFragment()
|
||||
} else {
|
||||
SendFragment()
|
||||
}
|
||||
|
|
@ -154,15 +149,11 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
|||
AppScreen.ManageTokens -> TokensListFragment()
|
||||
AppScreen.AddCustomToken -> AddCustomTokenFragment()
|
||||
AppScreen.WalletDetails -> {
|
||||
store.state.daggerGraphState
|
||||
.get(getDependency = DaggerGraphState::tokenDetailsRouter)
|
||||
.getEntryFragment()
|
||||
store.inject(getDependency = DaggerGraphState::tokenDetailsRouter).getEntryFragment()
|
||||
}
|
||||
AppScreen.WalletConnectSessions -> WalletConnectFragment()
|
||||
AppScreen.QrScanning -> {
|
||||
store.state.daggerGraphState
|
||||
.get(getDependency = DaggerGraphState::qrScanningRouter)
|
||||
.getEntryFragment()
|
||||
store.inject(getDependency = DaggerGraphState::qrScanningRouter).getEntryFragment()
|
||||
}
|
||||
AppScreen.ReferralProgram -> ReferralFragment()
|
||||
AppScreen.Swap -> SwapFragment()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.domain.wallets.models.UserWallet
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -87,4 +88,10 @@ fun Store<*>.dispatchOpenUrl(url: String) {
|
|||
|
||||
fun Store<*>.dispatchShare(url: String) {
|
||||
dispatch(NavigationAction.Share(url))
|
||||
}
|
||||
|
||||
inline fun <reified T> Store<AppState>.inject(getDependency: DaggerGraphState.() -> T?): T {
|
||||
return requireNotNull(state.daggerGraphState.getDependency()) {
|
||||
"${T::class.simpleName} isn't initialized "
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ suspend fun WalletManager.safeUpdate(isDemoCard: Boolean): Result<Wallet> = try
|
|||
} catch (exception: Exception) {
|
||||
Timber.e(exception)
|
||||
|
||||
val networkConnectionManager = store.state.daggerGraphState.get(DaggerGraphState::networkConnectionManager)
|
||||
val networkConnectionManager = store.inject(DaggerGraphState::networkConnectionManager)
|
||||
if (!networkConnectionManager.isOnline) {
|
||||
Result.Failure(TapError.NoInternetConnection)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.common.redux
|
||||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -20,7 +21,7 @@ class AccessCodeRequestPolicyMiddleware {
|
|||
}
|
||||
|
||||
private fun updateAccessCodeRequestPolicy(scanResponse: ScanResponse) {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes && scanResponse.card.isAccessCodeSet,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
|
|||
primaryRules = CardExchangeRules(cardProvider),
|
||||
)
|
||||
// TODO: for refactoring (after remove old design refactor CurrencyExchangeManager and use 1 instance)
|
||||
store.state.daggerGraphState.get(DaggerGraphState::appStateHolder).exchangeService = exchangeManager
|
||||
store.inject(DaggerGraphState::appStateHolder).exchangeService = exchangeManager
|
||||
store.dispatchOnMain(GlobalAction.ExchangeManager.Init.Success(exchangeManager))
|
||||
store.dispatchOnMain(GlobalAction.ExchangeManager.Update)
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
|
|||
}
|
||||
}
|
||||
is GlobalAction.UpdateUserWalletsListManager -> {
|
||||
val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManagersFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
|
||||
/*
|
||||
* If implementation of the UserWalletsListManager is changed,
|
||||
|
|
@ -186,7 +186,7 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
|
|||
|
||||
private fun restoreAppCurrency() {
|
||||
scope.launch {
|
||||
val currency = store.state.daggerGraphState.get(DaggerGraphState::appCurrencyRepository)
|
||||
val currency = store.inject(DaggerGraphState::appCurrencyRepository)
|
||||
.getSelectedAppCurrency()
|
||||
.firstOrNull()
|
||||
?: AppCurrency.Default
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ 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.extensions.inject
|
||||
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.preferencesStorage
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.utils.extensions.replaceBy
|
||||
import org.rekotlin.Action
|
||||
|
|
@ -20,8 +21,7 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
|
|||
|
||||
return when (action) {
|
||||
is GlobalAction.Onboarding.Start -> {
|
||||
val usedCardsPrefStorage = preferencesStorage.usedCardsPrefStorage
|
||||
val onboardingManager = OnboardingManager(action.scanResponse, usedCardsPrefStorage)
|
||||
val onboardingManager = OnboardingManager(action.scanResponse)
|
||||
globalState.copy(onboardingState = OnboardingState(true, onboardingManager))
|
||||
}
|
||||
is GlobalAction.Onboarding.StartForUnfinishedBackup -> {
|
||||
|
|
@ -95,10 +95,17 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
|
|||
)
|
||||
}
|
||||
is GlobalAction.UpdateUserWalletsListManager -> {
|
||||
appStateHolder.userWalletsListManager = action.manager
|
||||
globalState.copy(
|
||||
userWalletsListManager = action.manager,
|
||||
)
|
||||
val featureToggles = store.inject(DaggerGraphState::userWalletsListManagerFeatureToggles)
|
||||
|
||||
if (featureToggles.isGeneralManagerEnabled) {
|
||||
val generalUserWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
|
||||
appStateHolder.userWalletsListManager = generalUserWalletsListManager
|
||||
globalState.copy(userWalletsListManager = generalUserWalletsListManager)
|
||||
} else {
|
||||
appStateHolder.userWalletsListManager = action.manager
|
||||
globalState.copy(userWalletsListManager = action.manager)
|
||||
}
|
||||
}
|
||||
is GlobalAction.ChangeAppThemeMode -> globalState.copy(
|
||||
appThemeMode = action.appThemeMode,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.repository.OnboardingRepository
|
||||
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 OnboardingDomainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWasTwinsOnboardingShownUseCase(
|
||||
onboardingRepository: OnboardingRepository,
|
||||
): WasTwinsOnboardingShownUseCase {
|
||||
return WasTwinsOnboardingShownUseCase(onboardingRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSaveTwinsOnboardingShownUseCase(
|
||||
onboardingRepository: OnboardingRepository,
|
||||
): SaveTwinsOnboardingShownUseCase {
|
||||
return SaveTwinsOnboardingShownUseCase(onboardingRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.di.domain
|
|||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.txhistory.repository.TxHistoryRepository
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetFixedTxHistoryItemsUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import dagger.Module
|
||||
|
|
@ -34,4 +35,10 @@ internal object TxHistoryDomainModule {
|
|||
): GetExplorerTransactionUrlUseCase {
|
||||
return GetExplorerTransactionUrlUseCase(repository = txHistoryRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun providesGetFixedTxHistoryItemsUseCase(txHistoryRepository: TxHistoryRepository): GetFixedTxHistoryItemsUseCase {
|
||||
return GetFixedTxHistoryItemsUseCase(repository = txHistoryRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.common.util.cardTypesResolver
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
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.details.redux.walletconnect.WalletConnectAction
|
||||
|
|
@ -44,8 +45,8 @@ class TapWalletManager(
|
|||
val walletManagerFactory: WalletManagerFactory by lazy {
|
||||
WalletManagerFactory(
|
||||
config = blockchainSdkConfig,
|
||||
accountCreator = store.state.daggerGraphState.get(DaggerGraphState::accountCreator),
|
||||
blockchainDataStorage = store.state.daggerGraphState.get(DaggerGraphState::blockchainDataStorage),
|
||||
accountCreator = store.inject(DaggerGraphState::accountCreator),
|
||||
blockchainDataStorage = store.inject(DaggerGraphState::blockchainDataStorage),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,14 @@ import com.tangem.common.core.TangemError
|
|||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
|
||||
// TODO: Remove this object after feature toggle was removed and use ScanCardUseCase instead
|
||||
internal class DefaultScanCardProcessor : ScanCardProcessor {
|
||||
private val isNewCardScanningEnabled: Boolean
|
||||
get() = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::customTokenFeatureToggles)
|
||||
.isNewCardScanningEnabled
|
||||
get() = store.inject(DaggerGraphState::customTokenFeatureToggles).isNewCardScanningEnabled
|
||||
|
||||
override suspend fun scan(
|
||||
cardId: String?,
|
||||
|
|
|
|||
|
|
@ -13,12 +13,8 @@ import com.tangem.domain.common.TapWorkarounds.canSkipBackup
|
|||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.common.util.twinsIsTwinned
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor
|
||||
import com.tangem.tap.common.extensions.addContext
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
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
|
||||
|
|
@ -26,6 +22,10 @@ import com.tangem.tap.features.disclaimer.redux.DisclaimerCallback
|
|||
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
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -165,7 +165,10 @@ internal object LegacyScanProcessor {
|
|||
navigateTo(appScreen) { onProgressStateChange(it) }
|
||||
} else {
|
||||
Analytics.setContext(scanResponse)
|
||||
if (scanResponse.twinsIsTwinned() && !preferencesStorage.wasTwinsOnboardingShown()) {
|
||||
|
||||
val wasTwinsOnboardingShown = store.inject(DaggerGraphState::wasTwinsOnboardingShownUseCase).invokeSync()
|
||||
|
||||
if (scanResponse.twinsIsTwinned() && !wasTwinsOnboardingShown) {
|
||||
onWalletNotCreated()
|
||||
store.dispatchOnMain(TwinCardsAction.SetStepOfScreen(TwinCardsStep.WelcomeOnly(scanResponse)))
|
||||
navigateTo(AppScreen.OnboardingTwins) { onProgressStateChange(it) }
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import com.tangem.core.navigation.NavigationAction
|
|||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.domain.scanCard.chains.*
|
||||
import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
|
||||
|
|
@ -24,7 +24,7 @@ internal object UseCaseScanProcessor {
|
|||
cardId: String? = null,
|
||||
allowsRequestAccessCodeFromRepository: Boolean = false,
|
||||
): CompletionResult<ScanResponse> {
|
||||
val scanCardUseCase = store.state.daggerGraphState.get(DaggerGraphState::scanCardUseCase)
|
||||
val scanCardUseCase = store.inject(DaggerGraphState::scanCardUseCase)
|
||||
return scanCardUseCase(cardId, allowsRequestAccessCodeFromRepository)
|
||||
.fold(
|
||||
ifLeft = { CompletionResult.Failure(scanCardExceptionConverter.convertBack(it)) },
|
||||
|
|
@ -45,14 +45,14 @@ internal object UseCaseScanProcessor {
|
|||
) = progressScope(onProgressStateChange) {
|
||||
onScanStateChange(true)
|
||||
|
||||
val scanCardUseCase = store.state.daggerGraphState.get(DaggerGraphState::scanCardUseCase)
|
||||
val scanCardUseCase = store.inject(DaggerGraphState::scanCardUseCase)
|
||||
val chains = buildList {
|
||||
add(ScanningFinishedChain { onScanStateChange(false) })
|
||||
if (analyticsEvent != null) {
|
||||
add(AnalyticsChain(analyticsEvent))
|
||||
}
|
||||
add(DisclaimerChain(store, disclaimerWillShow))
|
||||
add(CheckForOnboardingChain(store, store.state.globalState.tapWalletManager, preferencesStorage))
|
||||
add(CheckForOnboardingChain(store, store.state.globalState.tapWalletManager))
|
||||
}
|
||||
|
||||
scanCardUseCase(cardId, afterScanChains = chains)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import arrow.core.left
|
|||
import arrow.core.right
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.common.TapWorkarounds.canSkipBackup
|
||||
import com.tangem.domain.common.util.twinsIsTwinned
|
||||
|
|
@ -13,6 +12,7 @@ import com.tangem.domain.core.chain.Chain
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.addContext
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -20,6 +20,7 @@ import com.tangem.tap.domain.TapWalletManager
|
|||
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
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
|
||||
import kotlinx.coroutines.delay
|
||||
import org.rekotlin.Store
|
||||
|
|
@ -32,14 +33,12 @@ import org.rekotlin.Store
|
|||
*
|
||||
* @param store the [Store] that holds the state of the app.
|
||||
* @param tapWalletManager manager responsible for handling operations related to the Wallet.
|
||||
* @param preferencesStore data source for user preferences.
|
||||
*
|
||||
* @see Chain for more information about the Chain interface.
|
||||
*/
|
||||
class CheckForOnboardingChain(
|
||||
private val store: Store<AppState>,
|
||||
private val tapWalletManager: TapWalletManager,
|
||||
private val preferencesStore: PreferencesDataSource,
|
||||
) : Chain<ScanCardException.ChainException, ScanResponse> {
|
||||
|
||||
override suspend fun invoke(
|
||||
|
|
@ -63,8 +62,12 @@ class CheckForOnboardingChain(
|
|||
}
|
||||
else -> {
|
||||
Analytics.setContext(previousChainResult)
|
||||
|
||||
val wasTwinsOnboardingShown = store.inject(DaggerGraphState::wasTwinsOnboardingShownUseCase)
|
||||
.invokeSync()
|
||||
|
||||
// If twins was twinned previously but twins welcome not shown
|
||||
if (previousChainResult.twinsIsTwinned() && !preferencesStore.wasTwinsOnboardingShown()) {
|
||||
if (previousChainResult.twinsIsTwinned() && !wasTwinsOnboardingShown) {
|
||||
store.dispatchOnMain(
|
||||
TwinCardsAction.SetStepOfScreen(TwinCardsStep.WelcomeOnly(previousChainResult)),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,9 +32,12 @@ import com.tangem.operations.backup.StartPrimaryCardLinkingTask
|
|||
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
||||
import com.tangem.operations.files.ReadFilesTask
|
||||
import com.tangem.operations.issuerAndUserData.ReadIssuerDataCommand
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.domain.TapSdkError
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.mainScope
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.collections.set
|
||||
|
||||
|
|
@ -186,23 +189,28 @@ private class ScanWalletProcessor(
|
|||
session: CardSession,
|
||||
callback: (result: CompletionResult<ScanResponse>) -> Unit,
|
||||
) {
|
||||
val activationInProgress = preferencesStorage.usedCardsPrefStorage.isActivationInProgress(card.cardId)
|
||||
mainScope.launch {
|
||||
val activationInProgress = store.inject(DaggerGraphState::cardRepository)
|
||||
.isActivationInProgress(card.cardId)
|
||||
|
||||
@Suppress("ComplexCondition")
|
||||
if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty() && activationInProgress) {
|
||||
StartPrimaryCardLinkingTask().run(session) { linkingResult ->
|
||||
when (linkingResult) {
|
||||
is CompletionResult.Success -> {
|
||||
primaryCard = linkingResult.data
|
||||
deriveKeysIfNeeded(card, session, callback)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
deriveKeysIfNeeded(card, session, callback)
|
||||
@Suppress("ComplexCondition")
|
||||
if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty() &&
|
||||
activationInProgress
|
||||
) {
|
||||
StartPrimaryCardLinkingTask().run(session) { linkingResult ->
|
||||
when (linkingResult) {
|
||||
is CompletionResult.Success -> {
|
||||
primaryCard = linkingResult.data
|
||||
deriveKeysIfNeeded(card, session, callback)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
deriveKeysIfNeeded(card, session, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deriveKeysIfNeeded(card, session, callback)
|
||||
}
|
||||
} else {
|
||||
deriveKeysIfNeeded(card, session, callback)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.tap.domain.userWalletList
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManagerFeatureToggles
|
||||
|
||||
internal class DefaultUserWalletsListManagerFeatureToggles(
|
||||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : UserWalletsListManagerFeatureToggles {
|
||||
|
||||
override val isGeneralManagerEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "GENERAL_USER_WALLETS_LIST_MANAGER_ENABLED")
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.tap.domain.userWalletList.di
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManagerFeatureToggles
|
||||
import com.tangem.tap.domain.userWalletList.DefaultUserWalletsListManagerFeatureToggles
|
||||
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 UserWalletsListManagerFeatureTogglesModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserWalletsListManagerFeatureToggles(
|
||||
featureTogglesManager: FeatureTogglesManager,
|
||||
): UserWalletsListManagerFeatureToggles {
|
||||
return DefaultUserWalletsListManagerFeatureToggles(featureTogglesManager)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package com.tangem.tap.domain.userWalletList.di
|
||||
|
||||
import android.content.Context
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import com.tangem.common.authentication.AuthenticatedStorage
|
||||
import com.tangem.common.json.TangemSdkAdapter
|
||||
import com.tangem.common.services.secure.SecureStorage
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.sdk.storage.AndroidSecureStorage
|
||||
import com.tangem.sdk.storage.createEncryptedSharedPreferences
|
||||
import com.tangem.tap.domain.userWalletList.implementation.BiometricUserWalletsListManager
|
||||
import com.tangem.tap.domain.userWalletList.implementation.GeneralUserWalletsListManager
|
||||
import com.tangem.tap.domain.userWalletList.implementation.RuntimeUserWalletsListManager
|
||||
import com.tangem.tap.domain.userWalletList.repository.DelegatedKeystoreManager
|
||||
import com.tangem.tap.domain.userWalletList.repository.UserWalletsKeysStoreDecorator
|
||||
import com.tangem.tap.domain.userWalletList.repository.implementation.BiometricUserWalletsKeysRepository
|
||||
import com.tangem.tap.domain.userWalletList.repository.implementation.DefaultSelectedUserWalletRepository
|
||||
import com.tangem.tap.domain.userWalletList.repository.implementation.DefaultUserWalletsPublicInformationRepository
|
||||
import com.tangem.tap.domain.userWalletList.repository.implementation.DefaultUserWalletsSensitiveInformationRepository
|
||||
import com.tangem.tap.domain.userWalletList.utils.json.*
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object UserWalletsListManagerModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGeneralUserWalletsListManager(
|
||||
@ApplicationContext applicationContext: Context,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): UserWalletsListManager {
|
||||
return GeneralUserWalletsListManager(
|
||||
runtimeUserWalletsListManager = RuntimeUserWalletsListManager(),
|
||||
biometricUserWalletsListManager = createBiometricUserWalletsListManager(applicationContext),
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createBiometricUserWalletsListManager(applicationContext: Context): UserWalletsListManager {
|
||||
val moshi = Moshi.Builder()
|
||||
.add(WalletDerivedKeysMapAdapter())
|
||||
.add(ScanResponseDerivedKeysMapAdapter())
|
||||
.add(ByteArrayKeyAdapter())
|
||||
.add(ExtendedPublicKeysMapAdapter())
|
||||
.add(CardBackupStatusAdapter())
|
||||
.add(DerivationPathAdapterWithMigration())
|
||||
.add(TangemSdkAdapter.DateAdapter())
|
||||
.add(TangemSdkAdapter.DerivationNodeAdapter())
|
||||
.add(TangemSdkAdapter.FirmwareVersionAdapter()) // For PrimaryCard model
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()
|
||||
|
||||
val secureStorage = AndroidSecureStorage(
|
||||
preferences = SecureStorage.createEncryptedSharedPreferences(
|
||||
context = applicationContext,
|
||||
storageName = USER_WALLETS_STORAGE_NAME,
|
||||
),
|
||||
)
|
||||
|
||||
val authenticatedStorage = AuthenticatedStorage(
|
||||
secureStorage = UserWalletsKeysStoreDecorator(
|
||||
featureStorage = secureStorage,
|
||||
cardSdkStorageProvider = Provider { tangemSdkManager.secureStorage },
|
||||
),
|
||||
keystoreManager = DelegatedKeystoreManager(
|
||||
keystoreManagerProvider = Provider { tangemSdkManager.keystoreManager },
|
||||
),
|
||||
)
|
||||
|
||||
val keysRepository = BiometricUserWalletsKeysRepository(
|
||||
moshi = moshi,
|
||||
secureStorage = secureStorage,
|
||||
authenticatedStorage = authenticatedStorage,
|
||||
)
|
||||
|
||||
val publicInformationRepository = DefaultUserWalletsPublicInformationRepository(
|
||||
moshi = moshi,
|
||||
secureStorage = secureStorage,
|
||||
)
|
||||
|
||||
val sensitiveInformationRepository = DefaultUserWalletsSensitiveInformationRepository(
|
||||
moshi = moshi,
|
||||
secureStorage = secureStorage,
|
||||
)
|
||||
|
||||
val selectedUserWalletRepository = DefaultSelectedUserWalletRepository(secureStorage = secureStorage)
|
||||
|
||||
return BiometricUserWalletsListManager(
|
||||
keysRepository = keysRepository,
|
||||
publicInformationRepository = publicInformationRepository,
|
||||
sensitiveInformationRepository = sensitiveInformationRepository,
|
||||
selectedUserWalletRepository = selectedUserWalletRepository,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import com.tangem.tap.domain.userWalletList.utils.json.*
|
|||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.utils.Provider
|
||||
|
||||
private const val USER_WALLETS_STORAGE_NAME = "user_wallets_storage"
|
||||
internal const val USER_WALLETS_STORAGE_NAME = "user_wallets_storage"
|
||||
|
||||
fun UserWalletsListManager.Companion.provideBiometricImplementation(
|
||||
applicationContext: Context,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
package com.tangem.tap.domain.userWalletList.implementation
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.get
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* General implementation of [UserWalletsListManager] that helps to switch between Runtime and Biometric
|
||||
* implementations.
|
||||
*
|
||||
* @property runtimeUserWalletsListManager runtime user wallets list manager
|
||||
* @property biometricUserWalletsListManager biometric user wallets list manager
|
||||
* @property appPreferencesStore app preferences store
|
||||
* @property dispatchers coroutine dispatcher provider
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
internal class GeneralUserWalletsListManager(
|
||||
private val runtimeUserWalletsListManager: UserWalletsListManager,
|
||||
private val biometricUserWalletsListManager: UserWalletsListManager,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : UserWalletsListManager.Lockable {
|
||||
|
||||
private val applicationScope = CoroutineScope(dispatchers.io)
|
||||
private val implementation = MutableStateFlow(runtimeUserWalletsListManager)
|
||||
|
||||
init {
|
||||
subscribeOnCurrentManager()
|
||||
}
|
||||
|
||||
override val userWallets: Flow<List<UserWallet>>
|
||||
get() = implementation.flatMapLatest { it.userWallets }
|
||||
|
||||
override val selectedUserWallet: Flow<UserWallet>
|
||||
get() = implementation.flatMapLatest { it.selectedUserWallet }
|
||||
|
||||
override val selectedUserWalletSync: UserWallet?
|
||||
get() = implementation.value.selectedUserWalletSync
|
||||
|
||||
override val hasUserWallets: Boolean
|
||||
get() = implementation.value.hasUserWallets
|
||||
|
||||
override val walletsCount: Int
|
||||
get() = implementation.value.walletsCount
|
||||
|
||||
override val isLocked: Flow<Boolean>
|
||||
get() = implementation.flatMapLatest {
|
||||
if (it is UserWalletsListManager.Lockable) {
|
||||
it.isLocked
|
||||
} else {
|
||||
error("RuntimeUserWalletsListManager is not lockable")
|
||||
}
|
||||
}
|
||||
|
||||
override val isLockedSync: Boolean
|
||||
get() {
|
||||
val implementation = implementation.value
|
||||
return if (implementation is UserWalletsListManager.Lockable) {
|
||||
implementation.isLockedSync
|
||||
} else {
|
||||
error("RuntimeUserWalletsListManager is not lockable")
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun select(userWalletId: UserWalletId): CompletionResult<UserWallet> {
|
||||
return implementation.value.select(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun save(userWallet: UserWallet, canOverride: Boolean): CompletionResult<Unit> {
|
||||
return implementation.value.save(userWallet, canOverride)
|
||||
}
|
||||
|
||||
override suspend fun update(
|
||||
userWalletId: UserWalletId,
|
||||
update: suspend (UserWallet) -> UserWallet,
|
||||
): CompletionResult<UserWallet> {
|
||||
return implementation.value.update(userWalletId, update)
|
||||
}
|
||||
|
||||
override suspend fun delete(userWalletIds: List<UserWalletId>): CompletionResult<Unit> {
|
||||
return implementation.value.delete(userWalletIds)
|
||||
}
|
||||
|
||||
override suspend fun clear(): CompletionResult<Unit> {
|
||||
return implementation.value.clear()
|
||||
}
|
||||
|
||||
override suspend fun get(userWalletId: UserWalletId): CompletionResult<UserWallet> {
|
||||
return implementation.value.get(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun unlock(throwIfNotAllWalletsUnlocked: Boolean): CompletionResult<UserWallet> {
|
||||
val implementation = implementation.value
|
||||
return if (implementation is UserWalletsListManager.Lockable) {
|
||||
implementation.unlock()
|
||||
} else {
|
||||
error("RuntimeUserWalletsListManager is not lockable")
|
||||
}
|
||||
}
|
||||
|
||||
override fun lock() {
|
||||
val implementation = implementation.value
|
||||
return if (implementation is UserWalletsListManager.Lockable) {
|
||||
implementation.lock()
|
||||
} else {
|
||||
error("RuntimeUserWalletsListManager is not lockable")
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeOnCurrentManager() {
|
||||
appPreferencesStore.get(key = PreferencesKeys.SAVE_USER_WALLETS_KEY, default = false)
|
||||
.distinctUntilChanged()
|
||||
.onEach { shouldSaveUserWallets ->
|
||||
val manager = if (shouldSaveUserWallets) {
|
||||
biometricUserWalletsListManager.copyFrom(runtimeUserWalletsListManager)
|
||||
} else {
|
||||
runtimeUserWalletsListManager.copyFrom(biometricUserWalletsListManager)
|
||||
}
|
||||
|
||||
Timber.d("Switch to ${manager::class.java.simpleName}")
|
||||
|
||||
implementation.value = manager
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(applicationScope)
|
||||
}
|
||||
|
||||
/** Copy data from [old] manager and clean it */
|
||||
private suspend fun UserWalletsListManager.copyFrom(old: UserWalletsListManager): UserWalletsListManager {
|
||||
old.selectedUserWalletSync?.let { this.save(it) }
|
||||
old.clear()
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import com.tangem.core.analytics.models.Basic
|
|||
import com.tangem.core.analytics.models.Basic.TransactionSent.MemoType
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.operations.sign.SignHashCommand
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.extensions.toFormattedString
|
||||
import com.tangem.tap.domain.walletconnect.BnbHelper.toWCBinanceTradeOrder
|
||||
|
|
@ -59,7 +60,7 @@ class WalletConnectSdkHelper {
|
|||
val decimals = wallet.blockchain.decimals()
|
||||
|
||||
val value = (transaction.value ?: "0").hexToBigDecimal()
|
||||
?.movePointLeft(decimals) ?: return null
|
||||
.movePointLeft(decimals) ?: return null
|
||||
|
||||
val gasLimit = getGasLimitFromTx(value, walletManager, transaction)
|
||||
|
||||
|
|
@ -118,8 +119,7 @@ class WalletConnectSdkHelper {
|
|||
|
||||
private suspend fun getWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager? {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync ?: return null
|
||||
val walletManagerFacade = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManagerFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
return walletManagerFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWallet.walletId,
|
||||
blockchain = blockchain,
|
||||
|
|
@ -172,7 +172,7 @@ class WalletConnectSdkHelper {
|
|||
val result = (data.walletManager as TransactionSender).send(
|
||||
transactionData = data.transaction,
|
||||
signer = CommonSigner(
|
||||
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
cardId = cardId,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.domain.model.Currency
|
||||
import com.tangem.tap.features.customtoken.impl.domain.models.FoundToken
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -31,8 +32,8 @@ class DefaultCustomTokenInteractor(
|
|||
|
||||
// TODO: Move to DI
|
||||
private val addCryptoCurrenciesUseCase by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository)
|
||||
val networksRepository = store.state.daggerGraphState.get(DaggerGraphState::networksRepository)
|
||||
val currenciesRepository = store.inject(DaggerGraphState::currenciesRepository)
|
||||
val networksRepository = store.inject(DaggerGraphState::networksRepository)
|
||||
|
||||
AddCryptoCurrenciesUseCase(currenciesRepository, networksRepository)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ internal class AddCustomTokenViewModel @Inject constructor(
|
|||
currentCryptoCurrencies = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { selectedWallet ->
|
||||
getCurrenciesUseCase(selectedWallet.walletId).fold(
|
||||
getCurrenciesUseCase.getSync(selectedWallet.walletId).fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { it },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,10 +24,7 @@ import com.tangem.domain.wallets.legacy.isLockedSync
|
|||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -268,7 +265,7 @@ class DetailsMiddleware {
|
|||
}
|
||||
|
||||
private fun changeAppThemeMode(appThemeMode: AppThemeMode) {
|
||||
val repository = store.state.daggerGraphState.get(DaggerGraphState::appThemeModeRepository)
|
||||
val repository = store.inject(DaggerGraphState::appThemeModeRepository)
|
||||
|
||||
scope.launch {
|
||||
repository.changeAppThemeMode(appThemeMode)
|
||||
|
|
@ -278,7 +275,7 @@ class DetailsMiddleware {
|
|||
}
|
||||
|
||||
private fun changeBalanceHiding(hideBalance: Boolean) {
|
||||
val repository = store.state.daggerGraphState.get(DaggerGraphState::balanceHidingRepository)
|
||||
val repository = store.inject(DaggerGraphState::balanceHidingRepository)
|
||||
|
||||
scope.launch {
|
||||
val newState = repository.getBalanceHidingSettings().copy(
|
||||
|
|
@ -292,7 +289,8 @@ class DetailsMiddleware {
|
|||
|
||||
private fun toggleSaveWallets(state: DetailsState, enable: Boolean) = scope.launch {
|
||||
// Nothing to change
|
||||
val walletsRepository = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
|
||||
|
||||
if (walletsRepository.shouldSaveUserWalletsSync() == enable) {
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.SwitchPrivacySetting.Success)
|
||||
return@launch
|
||||
|
|
@ -360,6 +358,19 @@ class DetailsMiddleware {
|
|||
private suspend fun saveCurrentWallet(
|
||||
scanResponse: ScanResponse?,
|
||||
enableAccessCodesSaving: Boolean,
|
||||
): CompletionResult<Unit> {
|
||||
val featureToggles = store.inject(DaggerGraphState::userWalletsListManagerFeatureToggles)
|
||||
|
||||
return if (featureToggles.isGeneralManagerEnabled) {
|
||||
saveCurrentWalletByNewWay(scanResponse, enableAccessCodesSaving)
|
||||
} else {
|
||||
saveCurrentWalletByOldWay(scanResponse, enableAccessCodesSaving)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveCurrentWalletByOldWay(
|
||||
scanResponse: ScanResponse?,
|
||||
enableAccessCodesSaving: Boolean,
|
||||
): CompletionResult<Unit> {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync
|
||||
?: scanResponse?.let { UserWalletBuilder(it).build() }
|
||||
|
|
@ -381,8 +392,26 @@ class DetailsMiddleware {
|
|||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
|
||||
preferencesStorage.shouldShowSaveUserWalletScreen = false
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.saveShouldSaveUserWallets(item = true)
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
|
||||
}
|
||||
.doOnFailure { error ->
|
||||
Timber.e(error, "Unable to save user wallet")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveCurrentWalletByNewWay(
|
||||
scanResponse: ScanResponse?,
|
||||
enableAccessCodesSaving: Boolean,
|
||||
): CompletionResult<Unit> {
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
|
||||
|
||||
return if (enableAccessCodesSaving) {
|
||||
saveAccessCodes(scanResponse)
|
||||
} else {
|
||||
CompletionResult.Success(Unit)
|
||||
}
|
||||
.doOnSuccess {
|
||||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
}
|
||||
.doOnFailure { error ->
|
||||
Timber.e(error, "Unable to save user wallet")
|
||||
|
|
@ -390,13 +419,22 @@ class DetailsMiddleware {
|
|||
}
|
||||
|
||||
private suspend fun deleteSavedWalletsAndAccessCodes(): CompletionResult<Unit> {
|
||||
val featureToggles = store.inject(DaggerGraphState::userWalletsListManagerFeatureToggles)
|
||||
|
||||
return if (featureToggles.isGeneralManagerEnabled) {
|
||||
deleteSavedWalletsAndAccessCodesByNewWay()
|
||||
} else {
|
||||
deleteSavedWalletsAndAccessCodesByOldWay()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun deleteSavedWalletsAndAccessCodesByOldWay(): CompletionResult<Unit> {
|
||||
return userWalletsListManager.clear()
|
||||
.doOnSuccess {
|
||||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
deleteSavedAccessCodes()
|
||||
updateUserWalletsListManager(enableUserWalletsSaving = false)
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.saveShouldSaveUserWallets(item = false)
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = false)
|
||||
|
||||
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
|
|
@ -405,12 +443,22 @@ class DetailsMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun deleteSavedWalletsAndAccessCodesByNewWay(): CompletionResult<Unit> {
|
||||
Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
|
||||
deleteSavedAccessCodes()
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = false)
|
||||
|
||||
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
|
||||
return CompletionResult.Success(Unit)
|
||||
}
|
||||
|
||||
private fun saveAccessCodes(scanResponse: ScanResponse?): CompletionResult<Unit> {
|
||||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
store.state.daggerGraphState
|
||||
.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = scanResponse?.card?.isAccessCodeSet == true)
|
||||
|
||||
return CompletionResult.Success(Unit)
|
||||
|
|
@ -422,8 +470,7 @@ class DetailsMiddleware {
|
|||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
|
||||
preferencesStorage.shouldSaveAccessCodes = false
|
||||
store.state.daggerGraphState
|
||||
.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = false)
|
||||
}
|
||||
.doOnFailure { error ->
|
||||
|
|
@ -482,7 +529,7 @@ class DetailsMiddleware {
|
|||
}
|
||||
|
||||
private fun scanCard(state: DetailsState) = scope.launch {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor)
|
||||
store.inject(DaggerGraphState::scanCardProcessor)
|
||||
.scan(allowsRequestAccessCodeFromRepository = true)
|
||||
.doOnSuccess { scanResponse ->
|
||||
// if we use biometric, scanResponse in GlobalState is null, and crashes NPE on twin cards
|
||||
|
|
@ -512,7 +559,7 @@ class DetailsMiddleware {
|
|||
}
|
||||
|
||||
private fun scanAndSaveUserWallet() = scope.launch(Dispatchers.IO) {
|
||||
val cardSdkConfigRepository = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
val cardSdkConfigRepository = store.inject(DaggerGraphState::cardSdkConfigRepository)
|
||||
|
||||
val prevUseBiometricsForAccessCode = cardSdkConfigRepository.isBiometricsRequestPolicy()
|
||||
|
||||
|
|
@ -521,7 +568,7 @@ class DetailsMiddleware {
|
|||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
store.inject(DaggerGraphState::scanCardProcessor).scan(
|
||||
analyticsEvent = Basic.CardWasScanned(CoreAnalyticsParam.ScannedFrom.MyWallets),
|
||||
onWalletNotCreated = {
|
||||
// No need to rollback policy, continue with the policy set before the card scan
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import com.tangem.domain.apptheme.model.AppThemeMode
|
|||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.extensions.signedHashesCount
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
|
@ -76,12 +78,12 @@ private fun handlePrepareScreen(action: DetailsAction.PrepareScreen): DetailsSta
|
|||
saveAccessCodes = preferencesStorage.shouldSaveAccessCodes,
|
||||
selectedAppCurrency = store.state.globalState.appCurrency,
|
||||
selectedThemeMode = runBlocking {
|
||||
store.state.daggerGraphState
|
||||
.get { appThemeModeRepository }.getAppThemeMode().firstOrNull() ?: AppThemeMode.DEFAULT
|
||||
store.inject(DaggerGraphState::appThemeModeRepository).getAppThemeMode().firstOrNull()
|
||||
?: AppThemeMode.DEFAULT
|
||||
},
|
||||
isHidingEnabled = runBlocking {
|
||||
store.state.daggerGraphState
|
||||
.get { balanceHidingRepository }.getBalanceHidingSettings().isHidingEnabledInSettings
|
||||
store.inject(DaggerGraphState::balanceHidingRepository)
|
||||
.getBalanceHidingSettings().isHidingEnabledInSettings
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.feature.qrscanning.SourceType
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.walletconnect.BnbHelper
|
||||
|
|
@ -47,9 +48,9 @@ import timber.log.Timber
|
|||
class WalletConnectMiddleware {
|
||||
private var walletConnectManager = WalletConnectManager()
|
||||
private val walletConnectInteractor: WalletConnectInteractor
|
||||
get() = store.state.daggerGraphState.get(DaggerGraphState::walletConnectInteractor)
|
||||
get() = store.inject(DaggerGraphState::walletConnectInteractor)
|
||||
private val walletConnectRepository: WalletConnectRepository
|
||||
get() = store.state.daggerGraphState.get(DaggerGraphState::walletConnectRepository)
|
||||
get() = store.inject(DaggerGraphState::walletConnectRepository)
|
||||
|
||||
val walletConnectMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||
{ next ->
|
||||
|
|
@ -387,8 +388,7 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
|
||||
private suspend fun getWalletManagers(): List<WalletManager> {
|
||||
val walletManagerFacade = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManagerFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList()
|
||||
|
||||
return walletManagerFacade.getStoredWalletManagers(userWallet.walletId)
|
||||
|
|
@ -407,7 +407,7 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
|
||||
private suspend fun getAvailableEvmBlockchains(userWalletId: UserWalletId): List<Blockchain> {
|
||||
val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository)
|
||||
val currenciesRepository = store.inject(DaggerGraphState::currenciesRepository)
|
||||
|
||||
return currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
|
||||
.asSequence()
|
||||
|
|
@ -496,8 +496,7 @@ class WalletConnectMiddleware {
|
|||
style = userWallet.scanResponse.derivationStyleProvider.getDerivationStyle(),
|
||||
)?.rawPath
|
||||
|
||||
val walletManagerFacade = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManagerFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
|
||||
return walletManagerFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWallet.walletId,
|
||||
|
|
@ -511,8 +510,7 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
|
||||
private suspend fun getAccountsForWc(wcInteractor: WalletConnectInteractor, userWallet: UserWallet): List<Account> {
|
||||
val walletManagerFacade = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManagerFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
return walletManagerFacade.getStoredWalletManagers(userWallet.walletId).mapNotNull {
|
||||
val wallet = it.wallet
|
||||
val chainId = wcInteractor.blockchainHelper.networkIdToChainIdOrNull(
|
||||
|
|
|
|||
|
|
@ -262,7 +262,8 @@ private class DetailsScreenStateProvider : CollectionPreviewParameterProvider<De
|
|||
SettingsItem.LinkMoreCards({}).let(::add)
|
||||
SettingsItem.CardSettings({}).let(::add)
|
||||
SettingsItem.AppSettings({}).let(::add)
|
||||
SettingsItem.Chat({}).let(::add)
|
||||
// removed chat in task [REDACTED_TASK_KEY]
|
||||
// SettingsItem.Chat({}).let(::add)
|
||||
SettingsItem.SendFeedback({}).let(::add)
|
||||
SettingsItem.ReferralProgram({}).let(::add)
|
||||
SettingsItem.TermsOfService({}).let(::add)
|
||||
|
|
@ -279,7 +280,8 @@ private class DetailsScreenStateProvider : CollectionPreviewParameterProvider<De
|
|||
SettingsItem.AddWallet(showProgress = true, {}).let(::add)
|
||||
SettingsItem.CardSettings({}).let(::add)
|
||||
SettingsItem.AppSettings({}).let(::add)
|
||||
SettingsItem.Chat({}).let(::add)
|
||||
// removed chat in task [REDACTED_TASK_KEY]
|
||||
// SettingsItem.Chat({}).let(::add)
|
||||
SettingsItem.SendFeedback({}).let(::add)
|
||||
SettingsItem.TermsOfService({}).let(::add)
|
||||
}.toImmutableList(),
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ internal sealed class SettingsItem(
|
|||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_comment,
|
||||
title = resourceReference(R.string.details_row_title_send_feedback),
|
||||
title = resourceReference(R.string.details_row_title_contact_to_support),
|
||||
)
|
||||
|
||||
data class ReferralProgram(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import com.tangem.tap.common.extensions.addContext
|
|||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.feedback.FeedbackEmail
|
||||
import com.tangem.tap.common.feedback.SupportInfo
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
|
|
@ -89,8 +88,9 @@ internal class DetailsViewModel(
|
|||
SettingsItem.AppSettings(::navigateToAppSettings)
|
||||
.let(::add)
|
||||
|
||||
SettingsItem.Chat(::navigateToChat)
|
||||
.let(::add)
|
||||
// removed chat in task [REDACTED_TASK_KEY]
|
||||
// SettingsItem.Chat(::navigateToChat)
|
||||
// .let(::add)
|
||||
|
||||
SettingsItem.SendFeedback(::sendFeedback)
|
||||
.let(::add)
|
||||
|
|
@ -141,11 +141,6 @@ internal class DetailsViewModel(
|
|||
store.dispatchOnMain(GlobalAction.SendEmail(FeedbackEmail()))
|
||||
}
|
||||
|
||||
private fun navigateToChat() {
|
||||
Analytics.send(Settings.ButtonChat())
|
||||
store.dispatchOnMain(GlobalAction.OpenChat(SupportInfo()))
|
||||
}
|
||||
|
||||
private fun navigateToAppSettings() {
|
||||
Analytics.send(Settings.ButtonAppSettings())
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.AppSettings))
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import android.net.Uri
|
|||
interface Disclaimer {
|
||||
fun type(): DisclaimerType
|
||||
fun getUri(): Uri
|
||||
fun accept()
|
||||
fun isAccepted(): Boolean
|
||||
suspend fun accept()
|
||||
suspend fun isAccepted(): Boolean
|
||||
}
|
||||
|
||||
abstract class BaseDisclaimer(
|
||||
|
|
@ -18,32 +18,28 @@ abstract class BaseDisclaimer(
|
|||
|
||||
val baseUrl = "https://tangem.com"
|
||||
|
||||
override fun accept() {
|
||||
dataProvider.storage().accept(getPreferenceKey())
|
||||
override suspend fun accept() {
|
||||
dataProvider.accept()
|
||||
}
|
||||
|
||||
override fun isAccepted(): Boolean = dataProvider.storage().isAccepted(getPreferenceKey())
|
||||
|
||||
protected open fun getPreferenceKey(): String = type().name
|
||||
override suspend fun isAccepted(): Boolean = dataProvider.isAccepted()
|
||||
}
|
||||
|
||||
class DummyDisclaimer : Disclaimer {
|
||||
override fun type(): DisclaimerType = DisclaimerType.Tangem
|
||||
override fun getUri(): Uri = Uri.parse("https://tangem.com/tangem_tos.html")
|
||||
override fun accept() {}
|
||||
override fun isAccepted(): Boolean = false
|
||||
override suspend fun accept() {}
|
||||
override suspend fun isAccepted(): Boolean = false
|
||||
}
|
||||
|
||||
class TangemDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) {
|
||||
override fun type(): DisclaimerType = DisclaimerType.Tangem
|
||||
override fun getUri(): Uri = Uri.parse("$baseUrl/tangem_tos.html")
|
||||
override fun getPreferenceKey(): String = "tangem_tos_accepted"
|
||||
}
|
||||
|
||||
class Start2CoinDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) {
|
||||
override fun type(): DisclaimerType = DisclaimerType.Start2Coin
|
||||
override fun getUri(): Uri = Uri.parse("$baseUrl/" + filename(dataProvider.getLanguage(), getRegion()))
|
||||
override fun getPreferenceKey(): String = "start2Coin_tos_accepted_${getRegion()}"
|
||||
|
||||
@Suppress("ComplexMethod")
|
||||
private fun filename(languageCode: String, regionCode: String?): String {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
package com.tangem.tap.features.disclaimer
|
||||
|
||||
import com.tangem.data.source.preferences.storage.DisclaimerPrefStorage
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface DisclaimerDataProvider {
|
||||
fun getLanguage(): String
|
||||
fun getCardId(): String
|
||||
fun storage(): DisclaimerPrefStorage
|
||||
suspend fun accept()
|
||||
suspend fun isAccepted(): Boolean
|
||||
}
|
||||
|
|
@ -2,8 +2,9 @@ package com.tangem.tap.features.disclaimer
|
|||
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.data.source.preferences.storage.DisclaimerPrefStorage
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
|
|
@ -25,7 +26,7 @@ enum class DisclaimerType {
|
|||
}
|
||||
|
||||
fun DisclaimerType.createDisclaimer(cardDTO: CardDTO): Disclaimer {
|
||||
val dataProvider = provideDisclaimerDataProvider(cardDTO.cardId)
|
||||
val dataProvider = provideDisclaimerDataProvider(cardDTO.cardId, this)
|
||||
return when (this) {
|
||||
DisclaimerType.Tangem -> TangemDisclaimer(dataProvider)
|
||||
DisclaimerType.Start2Coin -> Start2CoinDisclaimer(dataProvider)
|
||||
|
|
@ -34,10 +35,24 @@ fun DisclaimerType.createDisclaimer(cardDTO: CardDTO): Disclaimer {
|
|||
|
||||
fun CardDTO.createDisclaimer(): Disclaimer = DisclaimerType.get(this).createDisclaimer(this)
|
||||
|
||||
private fun provideDisclaimerDataProvider(cardId: String): DisclaimerDataProvider {
|
||||
private fun provideDisclaimerDataProvider(cardId: String, disclaimerType: DisclaimerType): DisclaimerDataProvider {
|
||||
val cardRepository = store.inject(DaggerGraphState::cardRepository)
|
||||
return object : DisclaimerDataProvider {
|
||||
override fun getLanguage(): String = Locale.getDefault().language
|
||||
override fun getCardId(): String = cardId
|
||||
override fun storage(): DisclaimerPrefStorage = preferencesStorage.disclaimerPrefStorage
|
||||
|
||||
override suspend fun accept() {
|
||||
when (disclaimerType) {
|
||||
DisclaimerType.Tangem -> cardRepository.acceptTangemTOS()
|
||||
DisclaimerType.Start2Coin -> cardRepository.acceptStart2CoinTOS(cardId)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isAccepted(): Boolean {
|
||||
return when (disclaimerType) {
|
||||
DisclaimerType.Tangem -> cardRepository.isTangemTOSAccepted()
|
||||
DisclaimerType.Start2Coin -> cardRepository.isStart2CoinTOSAccepted(cardId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@ package com.tangem.tap.features.disclaimer.redux
|
|||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
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
|
||||
|
||||
|
|
@ -26,9 +28,11 @@ private fun handleDisclaimerMiddleware(action: Action, appState: AppState) {
|
|||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
}
|
||||
is DisclaimerAction.AcceptDisclaimer -> {
|
||||
state.disclaimer.accept()
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
state.callback?.onAccept?.invoke()
|
||||
mainScope.launch {
|
||||
state.disclaimer.accept()
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
state.callback?.onAccept?.invoke()
|
||||
}
|
||||
}
|
||||
is DisclaimerAction.OnBackPressed -> {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ 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.navigation.AppScreen
|
||||
|
|
@ -21,6 +22,7 @@ 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<DisclaimerState> {
|
||||
|
|
@ -92,10 +94,12 @@ class DisclaimerFragment : BaseFragment(R.layout.fragment_disclaimer), StoreSubs
|
|||
store.dispatch(DisclaimerAction.OnBackPressed)
|
||||
}
|
||||
|
||||
override fun newState(state: DisclaimerState) = with(binding) {
|
||||
if (activity == null || view == null) return
|
||||
override fun newState(state: DisclaimerState) {
|
||||
return with(binding) {
|
||||
if (activity == null || view == null) return
|
||||
|
||||
updateUiVisibility(state.disclaimer, state.progressState)
|
||||
updateUiVisibility(state.disclaimer, state.progressState)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUiVisibility(disclaimer: Disclaimer, progressState: ProgressState?) = with(binding) {
|
||||
|
|
@ -112,7 +116,9 @@ class DisclaimerFragment : BaseFragment(R.layout.fragment_disclaimer), StoreSubs
|
|||
groupError.hide()
|
||||
groupLoading.hide()
|
||||
webView.show()
|
||||
groupAccept.show(!disclaimer.isAccepted())
|
||||
lifecycleScope.launch {
|
||||
groupAccept.show(!disclaimer.isAccepted())
|
||||
}
|
||||
}
|
||||
ProgressState.Error -> {
|
||||
root.beginDelayedTransition()
|
||||
|
|
|
|||
|
|
@ -6,18 +6,15 @@ import com.tangem.common.doOnSuccess
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.common.extensions.eraseContext
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL
|
||||
|
|
@ -79,11 +76,11 @@ private fun handleHomeAction(action: Action) {
|
|||
}
|
||||
|
||||
private suspend fun readCard(analyticsEvent: AnalyticsEvent?) {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
store.inject(DaggerGraphState::scanCardProcessor).scan(
|
||||
analyticsEvent = analyticsEvent,
|
||||
onProgressStateChange = { showProgress ->
|
||||
if (showProgress) {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,7 @@ import com.tangem.domain.userwallets.UserWalletBuilder
|
|||
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.extensions.removeContext
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.features.saveWallet.redux.SaveWalletAction
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -29,26 +26,26 @@ import timber.log.Timber
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
object OnboardingHelper {
|
||||
fun isOnboardingCase(response: ScanResponse): Boolean {
|
||||
val cardInfoStorage = preferencesStorage.usedCardsPrefStorage
|
||||
suspend fun isOnboardingCase(response: ScanResponse): Boolean {
|
||||
val onboardingManager = store.state.globalState.onboardingState.onboardingManager
|
||||
val cardId = response.card.cardId
|
||||
return when {
|
||||
response.cardTypesResolver.isTangemTwins() -> {
|
||||
if (!response.twinsIsTwinned()) {
|
||||
true
|
||||
} else {
|
||||
cardInfoStorage.isActivationInProgress(cardId)
|
||||
onboardingManager?.isActivationInProgress(cardId) ?: false
|
||||
}
|
||||
}
|
||||
|
||||
response.cardTypesResolver.isWallet2() || response.cardTypesResolver.isShibaWallet() -> {
|
||||
val emptyWallets = response.card.wallets.isEmpty()
|
||||
val activationInProgress = cardInfoStorage.isActivationInProgress(cardId)
|
||||
val activationInProgress = onboardingManager?.isActivationInProgress(cardId)
|
||||
val backupNotActive = response.card.backupStatus?.isActive != true
|
||||
emptyWallets || activationInProgress || backupNotActive
|
||||
emptyWallets || activationInProgress == true || backupNotActive
|
||||
}
|
||||
|
||||
response.card.wallets.isNotEmpty() -> cardInfoStorage.isActivationInProgress(cardId)
|
||||
response.card.wallets.isNotEmpty() -> onboardingManager?.isActivationInProgress(cardId) ?: false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
|
@ -80,7 +77,7 @@ object OnboardingHelper {
|
|||
scope.launch {
|
||||
when {
|
||||
// When should save user wallets, then save card without navigate to save wallet screen
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
|
||||
store.inject(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
|
||||
proceedWithScanResponse(scanResponse, backupCardsIds)
|
||||
|
||||
store.dispatchOnMain(
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.data.source.preferences.storage.UsedCardsPrefStorage
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.operations.attestation.CardVerifyAndGetInfo
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.tap.common.entities.ProgressState
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.extensions.isPositive
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.domain.TapError
|
||||
|
|
@ -17,17 +18,17 @@ import com.tangem.tap.domain.extensions.getOrLoadCardArtworkUrl
|
|||
import com.tangem.tap.domain.model.Currency
|
||||
import com.tangem.tap.domain.model.hasPendingTransactions
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class OnboardingManager(
|
||||
var scanResponse: ScanResponse,
|
||||
private val usedCardsPrefStorage: UsedCardsPrefStorage,
|
||||
) {
|
||||
class OnboardingManager(var scanResponse: ScanResponse) {
|
||||
|
||||
private val cardRepository: CardRepository = store.inject(DaggerGraphState::cardRepository)
|
||||
private var cardInfo: Result<CardVerifyAndGetInfo.Response.Item>? = null
|
||||
|
||||
suspend fun loadArtworkUrl(): String {
|
||||
|
|
@ -76,17 +77,23 @@ class OnboardingManager(
|
|||
)
|
||||
}
|
||||
|
||||
fun activationStarted(cardId: String) {
|
||||
usedCardsPrefStorage.activationStarted(cardId)
|
||||
suspend fun startActivation(cardId: String) {
|
||||
cardRepository.startCardActivation(cardId)
|
||||
}
|
||||
|
||||
fun activationFinished(cardId: String) {
|
||||
usedCardsPrefStorage.activationFinished(cardId)
|
||||
suspend fun finishActivation(cardId: String) {
|
||||
cardRepository.finishCardActivation(cardId)
|
||||
}
|
||||
|
||||
fun isActivationStarted(cardId: String): Boolean {
|
||||
return usedCardsPrefStorage.isActivationStarted(cardId)
|
||||
suspend fun finishActivation(cardIds: List<String>) {
|
||||
cardRepository.finishCardsActivation(cardIds)
|
||||
}
|
||||
|
||||
suspend fun isActivationStarted(cardId: String): Boolean = cardRepository.isActivationStarted(cardId)
|
||||
|
||||
suspend fun isActivationFinished(cardId: String): Boolean = cardRepository.isActivationFinished(cardId)
|
||||
|
||||
suspend fun isActivationInProgress(cardId: String): Boolean = cardRepository.isActivationInProgress(cardId)
|
||||
}
|
||||
|
||||
data class OnboardingWalletBalance(
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ class OnboardingMenuProvider : MenuProvider {
|
|||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
|
||||
R.id.menu_item_chat_support -> {
|
||||
Analytics.send(Onboarding.ButtonChat())
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
// changed on email support [REDACTED_TASK_KEY]
|
||||
store.dispatch(GlobalAction.SendEmail(SupportInfo()))
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ 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
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
|
|
@ -57,8 +58,10 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
|
||||
when (action) {
|
||||
is OnboardingNoteAction.Init -> {
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
scope.launch {
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
}
|
||||
is OnboardingNoteAction.LoadCardArtwork -> {
|
||||
|
|
@ -86,8 +89,10 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
}
|
||||
OnboardingNoteStep.Done -> {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(DELAY_SDK_DIALOG_CLOSE) { store.dispatch(OnboardingNoteAction.Confetti.Show) }
|
||||
mainScope.launch {
|
||||
onboardingManager.finishActivation(card.cardId)
|
||||
postUi(DELAY_SDK_DIALOG_CLOSE) { store.dispatch(OnboardingNoteAction.Confetti.Show) }
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
|
@ -101,7 +106,7 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
val updatedResponse = scanResponse.copy(card = result.data.card)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
onboardingManager.activationStarted(updatedResponse.card.cardId)
|
||||
onboardingManager.startActivation(updatedResponse.card.cardId)
|
||||
store.dispatch(OnboardingNoteAction.SetStepOfScreen(OnboardingNoteStep.TopUpWallet))
|
||||
}
|
||||
is CompletionResult.Failure -> Unit
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.onboarding.OnboardingDialog
|
||||
import com.tangem.tap.features.onboarding.OnboardingHelper
|
||||
import com.tangem.tap.mainScope
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
|
|
@ -43,8 +44,10 @@ private fun handleOtherCardsAction(action: Action) {
|
|||
|
||||
when (action) {
|
||||
is OnboardingOtherCardsAction.Init -> {
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
scope.launch {
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
}
|
||||
is OnboardingOtherCardsAction.LoadCardArtwork -> {
|
||||
|
|
@ -67,8 +70,10 @@ private fun handleOtherCardsAction(action: Action) {
|
|||
}
|
||||
OnboardingOtherCardsStep.Done -> {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
|
||||
mainScope.launch {
|
||||
onboardingManager.finishActivation(card.cardId)
|
||||
postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
|
@ -88,7 +93,7 @@ private fun handleOtherCardsAction(action: Action) {
|
|||
)
|
||||
val updatedCard = updatedResponse.card
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
onboardingManager.activationStarted(updatedCard.cardId)
|
||||
onboardingManager.startActivation(updatedCard.cardId)
|
||||
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
store.dispatch(OnboardingOtherCardsAction.SetStepOfScreen(OnboardingOtherCardsStep.Done))
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ 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.preferencesStorage
|
||||
import com.tangem.tap.mainScope
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -75,44 +75,61 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
|
||||
fun startCardActivation(cardId: String) {
|
||||
if (twinCardsState.mode == CreateTwinWalletMode.CreateWallet) {
|
||||
onboardingManager?.activationStarted(cardId)
|
||||
scope.launch {
|
||||
onboardingManager?.startActivation(cardId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun finishCardActivation() {
|
||||
if (twinCardsState.mode == CreateTwinWalletMode.CreateWallet) {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
onboardingManager?.activationFinished(getScanResponse().card.cardId)
|
||||
twinCardsState.pairCardId?.let { onboardingManager?.activationFinished(it) }
|
||||
|
||||
val cardIds = listOfNotNull(getScanResponse().card.cardId, twinCardsState.pairCardId)
|
||||
|
||||
if (cardIds.isNotEmpty()) {
|
||||
mainScope.launch {
|
||||
onboardingManager?.finishActivation(cardIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (action) {
|
||||
is TwinCardsAction.Init -> {
|
||||
if (twinCardsState.currentStep is TwinCardsStep.WelcomeOnly) return
|
||||
mainScope.launch {
|
||||
if (twinCardsState.currentStep is TwinCardsStep.WelcomeOnly) return@launch
|
||||
|
||||
val scanResponse = getScanResponse()
|
||||
onboardingManager?.apply {
|
||||
if (!isActivationStarted(scanResponse.card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
|
||||
when (twinCardsState.mode) {
|
||||
CreateTwinWalletMode.CreateWallet -> {
|
||||
if (preferencesStorage.wasTwinsOnboardingShown()) {
|
||||
val step = when {
|
||||
!scanResponse.twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet
|
||||
twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done
|
||||
else -> TwinCardsStep.TopUpWallet
|
||||
}
|
||||
store.dispatch(TwinCardsAction.SetStepOfScreen(step))
|
||||
} else {
|
||||
store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.Welcome))
|
||||
val scanResponse = getScanResponse()
|
||||
onboardingManager?.apply {
|
||||
if (!isActivationStarted(scanResponse.card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
CreateTwinWalletMode.RecreateWallet -> {
|
||||
store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.Warning))
|
||||
|
||||
when (twinCardsState.mode) {
|
||||
CreateTwinWalletMode.CreateWallet -> {
|
||||
mainScope.launch {
|
||||
val wasTwinsOnboardingShown = store.inject(DaggerGraphState::wasTwinsOnboardingShownUseCase)
|
||||
.invokeSync()
|
||||
|
||||
val dispatchAction = if (wasTwinsOnboardingShown) {
|
||||
val step = when {
|
||||
!scanResponse.twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet
|
||||
twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done
|
||||
else -> TwinCardsStep.TopUpWallet
|
||||
}
|
||||
TwinCardsAction.SetStepOfScreen(step)
|
||||
} else {
|
||||
TwinCardsAction.SetStepOfScreen(TwinCardsStep.Welcome)
|
||||
}
|
||||
|
||||
store.dispatch(dispatchAction)
|
||||
}
|
||||
}
|
||||
CreateTwinWalletMode.RecreateWallet -> {
|
||||
store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.Warning))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -120,7 +137,10 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
when (action.step) {
|
||||
is TwinCardsStep.WelcomeOnly, TwinCardsStep.Welcome -> {
|
||||
Analytics.send(Onboarding.Twins.ScreenOpened())
|
||||
preferencesStorage.saveTwinsOnboardingShown()
|
||||
|
||||
scope.launch {
|
||||
store.inject(DaggerGraphState::saveTwinsOnboardingShownUseCase).invoke()
|
||||
}
|
||||
}
|
||||
is TwinCardsStep.CreateFirstWallet -> {
|
||||
Analytics.send(Onboarding.CreateWallet.ScreenOpened())
|
||||
|
|
@ -295,7 +315,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
CreateTwinWalletMode.RecreateWallet -> {
|
||||
scope.launch {
|
||||
val walletsRepository = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
|
||||
|
||||
if (walletsRepository.shouldSaveUserWalletsSync()) {
|
||||
OnboardingHelper.trySaveWalletAndNavigateToWalletScreen(scanResponse)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import com.tangem.tap.common.analytics.events.AnalyticsParam
|
|||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
|
|
@ -72,8 +74,10 @@ private fun handleWalletAction(action: Action) {
|
|||
when (action) {
|
||||
OnboardingWalletAction.Init -> {
|
||||
ifNotNull(onboardingManager, card) { manager, notNullCard ->
|
||||
if (!manager.isActivationStarted(notNullCard.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
mainScope.launch {
|
||||
if (!manager.isActivationStarted(notNullCard.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
}
|
||||
when {
|
||||
|
|
@ -144,8 +148,10 @@ private fun handleWalletAction(action: Action) {
|
|||
onboardingManager.scanResponse = updatedResponse
|
||||
|
||||
store.dispatch(GlobalAction.Onboarding.ShouldResetCardOnCreate(false))
|
||||
startCardActivation(updatedResponse)
|
||||
store.dispatch(OnboardingWalletAction.ResumeBackup)
|
||||
mainScope.launch {
|
||||
onboardingManager.startActivation(updatedResponse.card.cardId)
|
||||
store.dispatchWithMain(OnboardingWalletAction.ResumeBackup)
|
||||
}
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
if (result.error is TangemSdkError.WalletAlreadyCreated) {
|
||||
|
|
@ -398,8 +404,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
store.dispatchOnMain(BackupAction.AddBackupCard.ChangeButtonLoading(true))
|
||||
backupService.addBackupCard { result ->
|
||||
backupService.skipCompatibilityChecks = false
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||
.config.filter.cardIdFilter = null
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository).sdk.config.filter.cardIdFilter = null
|
||||
store.dispatchOnMain(BackupAction.AddBackupCard.ChangeButtonLoading(false))
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
|
|
@ -493,11 +498,13 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
backupService.discardSavedBackup()
|
||||
}
|
||||
is BackupAction.DiscardSavedBackup -> {
|
||||
backupService.primaryCardId?.let {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
finishCardsActivationForDiscardedUnfinishedBackup(it)
|
||||
mainScope.launch {
|
||||
backupService.primaryCardId?.let {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
store.state.globalState.onboardingState.onboardingManager?.finishActivation(it)
|
||||
}
|
||||
backupService.discardSavedBackup()
|
||||
}
|
||||
backupService.discardSavedBackup()
|
||||
}
|
||||
is BackupAction.CheckForUnfinishedBackup -> {
|
||||
if (backupService.hasIncompletedBackup) {
|
||||
|
|
@ -514,17 +521,21 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
}
|
||||
is BackupAction.SkipBackup -> {
|
||||
Analytics.send(Onboarding.Backup.Skipped())
|
||||
|
||||
Analytics.send(Onboarding.Finished())
|
||||
finishCardActivation(gatherCardIds(backupState, card))
|
||||
|
||||
scope.launch {
|
||||
store.state.globalState.onboardingState.onboardingManager?.finishActivation(
|
||||
cardIds = gatherCardIds(backupState, card),
|
||||
)
|
||||
}
|
||||
}
|
||||
is BackupAction.FinishBackup -> {
|
||||
if (action.withAnalytics) {
|
||||
Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber))
|
||||
}
|
||||
scope.launch {
|
||||
if (action.withAnalytics) {
|
||||
Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber))
|
||||
}
|
||||
|
||||
if (scanResponse != null) {
|
||||
scope.launch {
|
||||
if (scanResponse != null) {
|
||||
val userWallet = UserWalletBuilder(scanResponse)
|
||||
.backupCardsIds(backupState.backupCardIds.toSet())
|
||||
.build()
|
||||
|
|
@ -546,16 +557,22 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
)
|
||||
store.dispatchOnMain(GlobalAction.UpdateUserWalletsListManager(userWalletsListManager))
|
||||
}
|
||||
|
||||
val notActivatedCardIds = gatherCardIds(backupState, card).mapNotNull {
|
||||
if (store.state.globalState.onboardingState.onboardingManager?.isActivationFinished(it) == true) {
|
||||
null
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
// All cardIds may already be activated if the backup was skipped before.
|
||||
if (notActivatedCardIds.isEmpty()) return@launch
|
||||
|
||||
Analytics.send(Onboarding.Finished())
|
||||
|
||||
store.state.globalState.onboardingState.onboardingManager?.finishActivation(notActivatedCardIds)
|
||||
}
|
||||
|
||||
val notActivatedCardIds = gatherCardIds(backupState, card)
|
||||
.mapNotNull { if (cardActivationIsFinished(it)) null else it }
|
||||
|
||||
// All cardIds may already be activated if the backup was skipped before.
|
||||
if (notActivatedCardIds.isEmpty()) return
|
||||
|
||||
Analytics.send(Onboarding.Finished())
|
||||
finishCardActivation(notActivatedCardIds)
|
||||
}
|
||||
|
||||
is BackupAction.ResetBackupCard -> {
|
||||
|
|
@ -566,36 +583,12 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
}
|
||||
}
|
||||
|
||||
private fun cardActivationIsFinished(cardId: String): Boolean {
|
||||
return preferencesStorage.usedCardsPrefStorage.isActivationFinished(cardId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Wallet cards start activation at OnboardingWalletAction.CreateWallet
|
||||
*/
|
||||
private fun startCardActivation(scanResponse: ScanResponse) {
|
||||
preferencesStorage.usedCardsPrefStorage.activationStarted(scanResponse.card.cardId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Wallet cards finish activation at BackupAction.SkipBackup and BackupAction.FinishBackup
|
||||
*/
|
||||
internal fun finishCardActivation(cardIds: List<String>) {
|
||||
cardIds.forEach { cardId ->
|
||||
preferencesStorage.usedCardsPrefStorage.activationFinished(cardId)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun gatherCardIds(backupState: BackupState, card: CardDTO?): List<String> {
|
||||
return (listOf(backupState.primaryCardId, card?.cardId) + backupState.backupCardIds)
|
||||
.filterNotNull()
|
||||
.distinct()
|
||||
}
|
||||
|
||||
private fun finishCardsActivationForDiscardedUnfinishedBackup(cardId: String) {
|
||||
preferencesStorage.usedCardsPrefStorage.activationFinished(cardId)
|
||||
}
|
||||
|
||||
private fun handleOnBackPressed(state: OnboardingWalletState) {
|
||||
when (state.backupState.backupStep) {
|
||||
BackupStep.InitBackup, BackupStep.ScanOriginCard, BackupStep.AddBackupCards, BackupStep.EnterAccessCode,
|
||||
|
|
|
|||
|
|
@ -501,7 +501,8 @@ class OnboardingWalletFragment :
|
|||
private fun makeSeedPhraseRouter(): SeedPhraseRouter = SeedPhraseRouter(
|
||||
onBack = ::legacyOnBackHandler,
|
||||
onOpenChat = {
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
// changed on email support [REDACTED_TASK_KEY]
|
||||
store.dispatch(GlobalAction.SendEmail(SupportInfo()))
|
||||
},
|
||||
onOpenUriClick = { uri ->
|
||||
store.dispatchOpenUrl(uri.toString())
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ object WalletActivationErrorDialog {
|
|||
setTitle(context.getString(R.string.onboarding_activation_error_title))
|
||||
setMessage(context.getString(R.string.onboarding_activation_error_message))
|
||||
setPositiveButton(R.string.common_ok) { _, _ -> dialog.onConfirm() }
|
||||
setNegativeButton(R.string.chat_button_title) { _, _ ->
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
setNegativeButton(R.string.common_support) { _, _ ->
|
||||
// changed on email support [REDACTED_TASK_KEY]
|
||||
store.dispatch(GlobalAction.SendEmail(SupportInfo()))
|
||||
}
|
||||
setOnDismissListener { store.dispatchDialogHide() }
|
||||
setCancelable(false)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ internal sealed interface SaveWalletAction : Action {
|
|||
data class Error(val error: TangemError) : SaveWalletAction
|
||||
}
|
||||
|
||||
object AllowToUseBiometrics : SaveWalletAction
|
||||
|
||||
object Dismiss : SaveWalletAction
|
||||
|
||||
object CloseError : SaveWalletAction
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.tap.common.analytics.events.MainScreen
|
|||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
||||
|
|
@ -42,6 +43,7 @@ internal class SaveWalletMiddleware {
|
|||
private fun handleAction(action: SaveWalletAction, state: SaveWalletState) {
|
||||
when (action) {
|
||||
is SaveWalletAction.Save -> saveWalletIfBiometricsEnrolled(state)
|
||||
is SaveWalletAction.AllowToUseBiometrics -> allowToUseBiometrics(state)
|
||||
is SaveWalletAction.EnrollBiometrics.Enroll -> enrollBiometrics()
|
||||
is SaveWalletAction.SaveWalletWasShown -> saveWalletWasShown()
|
||||
is SaveWalletAction.Dismiss -> dismiss(state)
|
||||
|
|
@ -96,11 +98,16 @@ internal class SaveWalletMiddleware {
|
|||
.build()
|
||||
?: return@launch
|
||||
|
||||
provideLockableUserWalletsListManagerIfNot()
|
||||
val featureToggles = store.inject(DaggerGraphState::userWalletsListManagerFeatureToggles)
|
||||
if (featureToggles.isGeneralManagerEnabled) {
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
|
||||
} else {
|
||||
provideLockableUserWalletsListManagerIfNot()
|
||||
}
|
||||
|
||||
val isFirstSavedWallet = !userWalletsListManager.hasUserWallets
|
||||
|
||||
saveAccessCodeIfNeeded(state.backupInfo?.accessCode, userWallet.cardsInWallet)
|
||||
saveAccessCodeIfNeeded(accessCode = state.backupInfo?.accessCode, cardsInWallet = userWallet.cardsInWallet)
|
||||
.flatMap {
|
||||
// Save wallet only at first time (SaveWalletBottomSheet).
|
||||
// Otherwise (Example, add new wallet in Details) userWalletsListManager.wallets subscribers will
|
||||
|
|
@ -116,16 +123,14 @@ internal class SaveWalletMiddleware {
|
|||
store.dispatchWithMain(SaveWalletAction.Save.Error(error))
|
||||
}
|
||||
.doOnSuccess {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.saveShouldSaveUserWallets(item = true)
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
|
||||
|
||||
// Enable saving access codes only if this is the first time user save the wallet
|
||||
if (isFirstSavedWallet) {
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = userWallet.hasAccessCode,
|
||||
)
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = userWallet.hasAccessCode,
|
||||
)
|
||||
}
|
||||
|
||||
store.dispatchOnMain(SaveWalletAction.Save.Success)
|
||||
|
|
@ -141,6 +146,46 @@ internal class SaveWalletMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun allowToUseBiometrics(state: SaveWalletState) {
|
||||
val scanResponse = state.backupInfo?.scanResponse
|
||||
?: store.state.globalState.scanResponse
|
||||
?: return
|
||||
|
||||
if (state.backupInfo != null) {
|
||||
// TODO: Remove after onboarding refactoring
|
||||
Analytics.send(Onboarding.EnableBiometrics(AnalyticsParam.OnOffState.On))
|
||||
} else {
|
||||
Analytics.send(MainScreen.EnableBiometrics(AnalyticsParam.OnOffState.On))
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync
|
||||
?: UserWalletBuilder(scanResponse)
|
||||
.backupCardsIds(state.backupInfo?.backupCardsIds)
|
||||
.build()
|
||||
?: return@launch
|
||||
|
||||
store.inject(DaggerGraphState::walletsRepository).saveShouldSaveUserWallets(item = true)
|
||||
|
||||
saveAccessCodeIfNeeded(accessCode = state.backupInfo?.accessCode, cardsInWallet = userWallet.cardsInWallet)
|
||||
.flatMap {
|
||||
userWalletsListManager.save(userWallet, canOverride = true)
|
||||
}
|
||||
.doOnFailure { error ->
|
||||
store.dispatchWithMain(SaveWalletAction.Save.Error(error))
|
||||
}
|
||||
.doOnSuccess {
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = userWallet.hasAccessCode,
|
||||
)
|
||||
|
||||
store.dispatchOnMain(SaveWalletAction.Save.Success)
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun provideLockableUserWalletsListManagerIfNot() {
|
||||
if (store.state.globalState.userWalletsListManager?.isLockable == true) return
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ internal object SaveWalletReducer {
|
|||
backupCardsIds = action.backupCardsIds,
|
||||
),
|
||||
)
|
||||
is SaveWalletAction.Save -> state.copy(
|
||||
isSaveInProgress = true,
|
||||
)
|
||||
is SaveWalletAction.Save,
|
||||
is SaveWalletAction.AllowToUseBiometrics,
|
||||
-> state.copy(isSaveInProgress = true)
|
||||
is SaveWalletAction.Save.Error -> state.copy(
|
||||
error = action.error,
|
||||
isSaveInProgress = false,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.saveWallet.ui
|
|||
import androidx.lifecycle.ViewModel
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManagerFeatureToggles
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.features.details.ui.cardsettings.TextReference
|
||||
|
|
@ -19,6 +20,7 @@ import javax.inject.Inject
|
|||
|
||||
@HiltViewModel
|
||||
internal class SaveWalletViewModel @Inject constructor(
|
||||
private val userWalletsListManagerFeatureToggles: UserWalletsListManagerFeatureToggles,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : ViewModel(), StoreSubscriber<SaveWalletState> {
|
||||
private val stateInternal = MutableStateFlow(SaveWalletScreenState())
|
||||
|
|
@ -31,7 +33,12 @@ internal class SaveWalletViewModel @Inject constructor(
|
|||
|
||||
fun saveWallet() {
|
||||
analyticsEventHandler.send(WalletScreenAnalyticsEvent.MainScreen.EnableBiometrics(AnalyticsParam.OnOffState.On))
|
||||
store.dispatch(SaveWalletAction.Save)
|
||||
|
||||
if (userWalletsListManagerFeatureToggles.isGeneralManagerEnabled) {
|
||||
store.dispatch(SaveWalletAction.AllowToUseBiometrics)
|
||||
} else {
|
||||
store.dispatch(SaveWalletAction.Save)
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelOrClose() {
|
||||
|
|
|
|||
|
|
@ -24,10 +24,7 @@ import com.tangem.domain.models.scan.CardDTO
|
|||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.analytics.events.Token.Send.SelectedCurrency.CurrencyType
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -211,7 +208,7 @@ private fun sendTransaction(
|
|||
// return@launch
|
||||
// }
|
||||
|
||||
val tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||
val tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||
val linkedTerminalState = tangemSdk.config.linkedTerminal
|
||||
if (card.isStart2Coin) {
|
||||
tangemSdk.config.linkedTerminal = false
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ object RequestFeeErrorDialog {
|
|||
return AlertDialog.Builder(context).apply {
|
||||
setTitle(R.string.common_fee_error)
|
||||
setMessage(context.getString(R.string.alert_failed_to_send_transaction_message, errorMessage))
|
||||
setNegativeButton(R.string.alert_button_send_feedback) { _, _ ->
|
||||
setNegativeButton(R.string.details_row_title_contact_to_support) { _, _ ->
|
||||
store.dispatch(GlobalAction.SendEmail(SendTransactionFailedEmail(errorMessage)))
|
||||
}
|
||||
setPositiveButton(R.string.common_retry) { _, _ -> dialog.onRetry() }
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ object SendTransactionFailsDialog {
|
|||
return AlertDialog.Builder(context).apply {
|
||||
setTitle(R.string.alert_failed_to_send_transaction_title)
|
||||
setMessage(context.getString(R.string.alert_failed_to_send_transaction_message, errorMessage))
|
||||
setNeutralButton(R.string.alert_button_send_feedback) { _, _ ->
|
||||
setNeutralButton(R.string.details_row_title_contact_to_support) { _, _ ->
|
||||
store.dispatch(GlobalAction.SendEmail(SendTransactionFailedEmail(errorMessage)))
|
||||
}
|
||||
setPositiveButton(R.string.common_cancel) { _, _ -> }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
|
|
@ -49,7 +50,11 @@ internal class TokensListMigration(
|
|||
is Either.Right -> {
|
||||
currentUserWallet = selectedWalletEither.value
|
||||
|
||||
when (val currenciesEither = getCurrenciesUseCase(userWalletId = selectedWalletEither.value.walletId)) {
|
||||
when (
|
||||
val currenciesEither = getCurrenciesUseCase.getSync(
|
||||
userWalletId = selectedWalletEither.value.walletId,
|
||||
)
|
||||
) {
|
||||
is Either.Left -> {
|
||||
Timber.e(currenciesEither.value.toString())
|
||||
TokensListCryptoCurrencies(coins = emptyList(), tokens = emptyList())
|
||||
|
|
@ -136,8 +141,8 @@ internal class TokensListMigration(
|
|||
|
||||
private suspend fun removeCurrenciesIfNeeded(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
if (currencies.isEmpty()) return
|
||||
val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository)
|
||||
val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
|
||||
val currenciesRepository = store.inject(DaggerGraphState::currenciesRepository)
|
||||
val walletManagersFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
|
||||
currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = currencies)
|
||||
|
||||
|
|
|
|||
|
|
@ -47,9 +47,7 @@ object TradeCryptoMiddleware {
|
|||
}
|
||||
|
||||
private val isSendRedesignedEnabled: Boolean
|
||||
get() = store.state.daggerGraphState.get(
|
||||
getDependency = DaggerGraphState::sendFeatureToggles,
|
||||
).isRedesignedSendEnabled
|
||||
get() = store.inject(getDependency = DaggerGraphState::sendFeatureToggles).isRedesignedSendEnabled
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
private fun handle(state: () -> AppState?, action: TradeCryptoAction) {
|
||||
|
|
@ -106,8 +104,7 @@ object TradeCryptoMiddleware {
|
|||
|
||||
if (currency is CryptoCurrency.Token && currency.network.isTestnet) {
|
||||
scope.launch {
|
||||
val walletManager = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManager = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
.getOrCreateWalletManager(
|
||||
userWalletId = action.userWallet.walletId,
|
||||
blockchain = blockchain,
|
||||
|
|
@ -175,8 +172,7 @@ object TradeCryptoMiddleware {
|
|||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
|
||||
scope.launch {
|
||||
val walletManager = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManager = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
.getOrCreateWalletManager(
|
||||
userWalletId = action.userWallet.walletId,
|
||||
blockchain = blockchain,
|
||||
|
|
@ -234,8 +230,7 @@ object TradeCryptoMiddleware {
|
|||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
|
||||
scope.launch {
|
||||
val walletManager = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val walletManager = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
.getOrCreateWalletManager(
|
||||
userWalletId = action.userWallet.walletId,
|
||||
blockchain = blockchain,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.common.doOnSuccess
|
|||
import com.tangem.common.flatMap
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
|
|
@ -16,9 +17,9 @@ import com.tangem.domain.userwallets.UserWalletBuilder
|
|||
import com.tangem.domain.wallets.legacy.unlockIfLockable
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
|
||||
|
|
@ -169,10 +170,10 @@ internal class WelcomeMiddleware {
|
|||
}
|
||||
|
||||
private suspend inline fun scanCardInternal(crossinline onCardScanned: suspend (ScanResponse) -> Unit) {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
store.inject(DaggerGraphState::scanCardProcessor).scan(
|
||||
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.SignIn),
|
||||
onSuccess = { scanResponse ->
|
||||
scope.launch { onCardScanned(scanResponse) }
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -105,7 +106,7 @@ suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletMa
|
|||
|
||||
val signer = TangemSigner(
|
||||
card = card,
|
||||
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
initialMessage = Message(),
|
||||
) { signResponse ->
|
||||
store.dispatch(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.blockchain.externallinkprovider.TxExploreState
|
||||
import com.tangem.blockchain.network.ResultChecker
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
|
|
@ -117,7 +118,10 @@ class TransactionManagerImpl(
|
|||
|
||||
override fun getExplorerTransactionLink(networkId: String, txAddress: String): String {
|
||||
val blockchain = Blockchain.fromNetworkId(networkId) ?: error("blockchain not found")
|
||||
return blockchain.getExploreTxUrl(txAddress)
|
||||
return when (val txUrlState = blockchain.getExploreTxUrl(txAddress)) {
|
||||
TxExploreState.Unsupported -> ""
|
||||
is TxExploreState.Url -> txUrlState.url
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMemoExtras(networkId: String, memo: String?): TransactionExtras? {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,15 @@ import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
|||
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManagerFeatureToggles
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggles
|
||||
|
|
@ -55,11 +60,9 @@ data class DaggerGraphState(
|
|||
val currenciesRepository: CurrenciesRepository? = null,
|
||||
val blockchainDataStorage: BlockchainDataStorage? = null,
|
||||
val accountCreator: AccountCreator? = null,
|
||||
) : StateType {
|
||||
|
||||
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
||||
return requireNotNull(getDependency()) {
|
||||
"${T::class.simpleName} isn't initialized "
|
||||
}
|
||||
}
|
||||
}
|
||||
val userWalletsListManagerFeatureToggles: UserWalletsListManagerFeatureToggles? = null,
|
||||
val generalUserWalletsListManager: UserWalletsListManager? = null,
|
||||
val wasTwinsOnboardingShownUseCase: WasTwinsOnboardingShownUseCase? = null,
|
||||
val saveTwinsOnboardingShownUseCase: SaveTwinsOnboardingShownUseCase? = null,
|
||||
val cardRepository: CardRepository? = null,
|
||||
) : StateType
|
||||
Loading…
Add table
Add a link
Reference in a new issue