Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-25 12:08:04 +04:00
parent d050fa2654
commit bbb3c9d6bb
16 changed files with 112 additions and 115 deletions

View file

@ -7,10 +7,10 @@ import com.tangem.screens.AlreadyUsedWalletDialogPageObject.message
import com.tangem.screens.AlreadyUsedWalletDialogPageObject.requestSupportButton import com.tangem.screens.AlreadyUsedWalletDialogPageObject.requestSupportButton
import com.tangem.screens.AlreadyUsedWalletDialogPageObject.thisIsMyWalletButton import com.tangem.screens.AlreadyUsedWalletDialogPageObject.thisIsMyWalletButton
import com.tangem.screens.AlreadyUsedWalletDialogPageObject.title import com.tangem.screens.AlreadyUsedWalletDialogPageObject.title
import com.tangem.screens.ScanWarningDialogPageObject
import com.tangem.screens.onActionIsUnavailableDialog import com.tangem.screens.onActionIsUnavailableDialog
import com.tangem.screens.onDataNotLoadedDialog import com.tangem.screens.onDataNotLoadedDialog
import com.tangem.screens.onFailedTransactionDialog import com.tangem.screens.onFailedTransactionDialog
import com.tangem.screens.onScanWarningDialog
import io.qameta.allure.kotlin.Allure.step import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.checkFailedTransactionDialog() { fun BaseTestCase.checkFailedTransactionDialog() {
@ -31,21 +31,21 @@ fun BaseTestCase.checkFailedTransactionDialog() {
} }
} }
fun checkScanWarningDialog() { fun BaseTestCase.checkScanWarningDialog() {
step("Assert 'Scan warning' dialog title is displayed") { step("Assert 'Scan warning' dialog title is displayed") {
ScanWarningDialogPageObject { warningTitle.isDisplayed() } onScanWarningDialog { warningTitle.assertIsDisplayed() }
} }
step("Assert warning dialog message is displayed") { step("Assert warning dialog message is displayed") {
ScanWarningDialogPageObject { warningMessage.isDisplayed() } onScanWarningDialog { warningMessage.assertIsDisplayed() }
} }
step("Assert 'Cancel' button is displayed") { step("Assert 'Cancel' button is displayed") {
ScanWarningDialogPageObject { cancelButton.isDisplayed() } onScanWarningDialog { cancelButton.assertIsDisplayed() }
} }
step("Assert 'How to scan' button is displayed") { step("Assert 'How to scan' button is displayed") {
ScanWarningDialogPageObject { howToScanButton.isDisplayed() } onScanWarningDialog { howToScanButton.assertIsDisplayed() }
} }
step("Assert 'Request support' button is displayed") { step("Assert 'Request support' button is displayed") {
ScanWarningDialogPageObject { requestSupportButton.isDisplayed() } onScanWarningDialog { requestSupportButton.assertIsDisplayed() }
} }
} }

View file

@ -1,36 +1,42 @@
package com.tangem.screens package com.tangem.screens
import com.kaspersky.kaspresso.screens.KScreen import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.tap.features.scanfails.ui.ScanFailsDialogTestTags
import com.tangem.wallet.R import com.tangem.wallet.R
import io.github.kakaocup.kakao.text.KTextView import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.kakao.text.KButton import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
import io.github.kakaocup.compose.node.element.KNode
import io.github.kakaocup.kakao.common.utilities.getResourceString
object ScanWarningDialogPageObject : KScreen<ScanWarningDialogPageObject>() { class ScanWarningDialogPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<ScanWarningDialogPageObject>(semanticsProvider = semanticsProvider) {
override val layoutId: Int? = null val warningTitle: KNode = child {
override val viewClass: Class<*>? = null hasText(getResourceString(R.string.common_warning))
useUnmergedTree = true
val warningTitle = KTextView {
withText(R.string.common_warning)
} }
val warningMessage = KTextView { val warningMessage: KNode = child {
withText(R.string.alert_troubleshooting_scan_card_title) hasText(getResourceString(R.string.alert_troubleshooting_scan_card_title))
useUnmergedTree = true
} }
val tryAgainButton = KButton { val howToScanButton: KNode = child {
withId(R.id.try_again_button) hasTestTag(ScanFailsDialogTestTags.HOW_TO_SCAN_BUTTON)
useUnmergedTree = true
} }
val howToScanButton = KButton { val requestSupportButton: KNode = child {
withId(R.id.how_to_scan_button) hasTestTag(ScanFailsDialogTestTags.REQUEST_SUPPORT_BUTTON)
useUnmergedTree = true
} }
val requestSupportButton = KButton { val cancelButton: KNode = child {
withId(R.id.request_support_button) hasTestTag(ScanFailsDialogTestTags.CANCEL_BUTTON)
useUnmergedTree = true
} }
}
val cancelButton = KButton { internal fun BaseTestCase.onScanWarningDialog(function: ScanWarningDialogPageObject.() -> Unit) =
withId(R.id.cancel_button) onComposeScreen(composeTestRule, function)
}
}

View file

@ -7,13 +7,26 @@ import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
import com.tangem.common.core.TangemSdkError import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.clickAndWaitFor import com.tangem.common.extensions.clickAndWaitFor
import com.tangem.common.extensions.clickWithAssertion import com.tangem.common.extensions.clickWithAssertion
import com.tangem.domain.redux.StateDialog import com.tangem.domain.card.ScanFailsRequester
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import com.tangem.scenarios.checkFailedTransactionDialog import com.tangem.scenarios.checkFailedTransactionDialog
import com.tangem.scenarios.checkScanWarningDialog import com.tangem.scenarios.checkScanWarningDialog
import com.tangem.scenarios.openMainScreen import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses import com.tangem.scenarios.synchronizeAddresses
import com.tangem.screens.* import com.tangem.screens.ThirdPartyAppPageObject
import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.screens.onCreateWalletStartScreen
import com.tangem.screens.onDetailsScreen
import com.tangem.screens.onDisclaimerScreen
import com.tangem.screens.onFailedTransactionDialog
import com.tangem.screens.onMainScreen
import com.tangem.screens.onScanWarningDialog
import com.tangem.screens.onSendAddressScreen
import com.tangem.screens.onSendConfirmScreen
import com.tangem.screens.onSendScreen
import com.tangem.screens.onStoriesScreen
import com.tangem.screens.onTokenDetailsScreen
import com.tangem.screens.onTopBar
import com.tangem.tap.domain.sdk.mocks.MockProvider import com.tangem.tap.domain.sdk.mocks.MockProvider
import com.tangem.tap.store import com.tangem.tap.store
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
@ -164,8 +177,10 @@ class FeedbackTest : BaseTestCase() {
} }
step("Force show 'Scan warning' dialog"){ step("Force show 'Scan warning' dialog"){
runOnUiThread { runOnUiThread {
val scanFailsState = StateDialog.ScanFailsDialog(source = StateDialog.ScanFailsSource.MAIN) val requester = store.state.daggerGraphState.scanFailsRequester!!
store.dispatch(GlobalAction.ShowDialog(scanFailsState)) MainScope().launch {
requester.show(ScanFailsRequester.Source.MAIN)
}
} }
} }
step("Check 'Scan warning' dialog") { step("Check 'Scan warning' dialog") {
@ -173,7 +188,7 @@ class FeedbackTest : BaseTestCase() {
checkScanWarningDialog() checkScanWarningDialog()
} }
step("Click on 'Request support' button") { step("Click on 'Request support' button") {
ScanWarningDialogPageObject { requestSupportButton.click() } onScanWarningDialog { requestSupportButton.performClick() }
} }
step("Assert 'Gmail' app is open") { step("Assert 'Gmail' app is open") {
ThirdPartyAppPageObject { assertElementWithTextExists(gmailText) } ThirdPartyAppPageObject { assertElementWithTextExists(gmailText) }

View file

@ -28,6 +28,7 @@ import com.tangem.domain.apptheme.GetAppThemeModeUseCase
import com.tangem.domain.apptheme.repository.AppThemeModeRepository import com.tangem.domain.apptheme.repository.AppThemeModeRepository
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.ScanFailsRequester
import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
@ -151,4 +152,6 @@ interface ApplicationEntryPoint {
fun getAppsFlyerClientFactory(): AppsFlyerClient.Factory fun getAppsFlyerClientFactory(): AppsFlyerClient.Factory
fun getCustomerIoFeatureToggles(): CustomerIoFeatureToggles fun getCustomerIoFeatureToggles(): CustomerIoFeatureToggles
fun getScanFailsRequester(): ScanFailsRequester
} }

View file

@ -239,6 +239,9 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
private val customerIoFeatureToggles: CustomerIoFeatureToggles private val customerIoFeatureToggles: CustomerIoFeatureToggles
get() = entryPoint.getCustomerIoFeatureToggles() get() = entryPoint.getCustomerIoFeatureToggles()
private val scanFailsRequester
get() = entryPoint.getScanFailsRequester()
// endregion // endregion
private val appScope = MainScope() private val appScope = MainScope()
@ -368,6 +371,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
userWalletsListRepository = userWalletsListRepository, userWalletsListRepository = userWalletsListRepository,
tangemHotSdk = tangemHotSdk, tangemHotSdk = tangemHotSdk,
trackingContextProxy = trackingContextProxy, trackingContextProxy = trackingContextProxy,
scanFailsRequester = scanFailsRequester,
), ),
), ),
) )

View file

@ -4,9 +4,8 @@ import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError import com.tangem.common.core.TangemSdkError
import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.card.ScanFailsRequester
import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.StateDialog
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.AppState
@ -54,12 +53,14 @@ private fun handleFailureChooseBehaviour(
store.dispatch(GlobalAction.ScanFailsCounter.Increment) store.dispatch(GlobalAction.ScanFailsCounter.Increment)
if (store.state.globalState.scanCardFailsCounter >= 2) { if (store.state.globalState.scanCardFailsCounter >= 2) {
val scanFailsSource = when (analyticsSource) { val scanFailsSource = when (analyticsSource) {
is AnalyticsParam.ScreensSources.SignIn -> StateDialog.ScanFailsSource.SIGN_IN is AnalyticsParam.ScreensSources.SignIn -> ScanFailsRequester.Source.SIGN_IN
is AnalyticsParam.ScreensSources.Settings -> StateDialog.ScanFailsSource.SETTINGS is AnalyticsParam.ScreensSources.Settings -> ScanFailsRequester.Source.SETTINGS
is AnalyticsParam.ScreensSources.Intro -> StateDialog.ScanFailsSource.INTRO is AnalyticsParam.ScreensSources.Intro -> ScanFailsRequester.Source.INTRO
else -> StateDialog.ScanFailsSource.MAIN else -> ScanFailsRequester.Source.MAIN
}
scope.launch {
store.inject(DaggerGraphState::scanFailsRequester).show(scanFailsSource)
} }
store.dispatchDialogShow(StateDialog.ScanFailsDialog(scanFailsSource))
} }
} else { } else {
store.dispatch(GlobalAction.ScanFailsCounter.Reset) store.dispatch(GlobalAction.ScanFailsCounter.Reset)

View file

@ -1,6 +1,5 @@
package com.tangem.tap.domain.model package com.tangem.tap.domain.model
import com.tangem.domain.features.addCustomToken.CustomCurrency
import com.tangem.tap.common.redux.global.CryptoCurrencyName import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.blockchain.common.Blockchain as SdkBlockchain import com.tangem.blockchain.common.Blockchain as SdkBlockchain
import com.tangem.blockchain.common.Token as SdkToken import com.tangem.blockchain.common.Token as SdkToken
@ -29,20 +28,4 @@ sealed interface Currency {
) : Currency { ) : Currency {
override val currencySymbol: CryptoCurrencyName = blockchain.currency override val currencySymbol: CryptoCurrencyName = blockchain.currency
} }
companion object {
fun fromCustomCurrency(customCurrency: CustomCurrency): Currency {
return when (customCurrency) {
is CustomCurrency.CustomBlockchain -> Blockchain(
blockchain = customCurrency.network,
derivationPath = customCurrency.derivationPath?.rawPath,
)
is CustomCurrency.CustomToken -> Token(
token = customCurrency.token,
blockchain = customCurrency.network,
derivationPath = customCurrency.derivationPath?.rawPath,
)
}
}
}
} }

View file

@ -9,18 +9,19 @@ import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
import com.tangem.domain.card.ScanCardException import com.tangem.domain.card.ScanCardException
import com.tangem.domain.card.ScanFailsRequester
import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.StateDialog
import com.tangem.tap.common.analytics.events.TangemSdkErrorEvent import com.tangem.tap.common.analytics.events.TangemSdkErrorEvent
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchNavigationAction import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.extensions.inject
import com.tangem.tap.domain.scanCard.chains.* import com.tangem.tap.domain.scanCard.chains.*
import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter
import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
import com.tangem.tap.store import com.tangem.tap.store
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
internal object UseCaseScanProcessor { internal object UseCaseScanProcessor {
private val scanCardExceptionConverter = ScanCardExceptionConverter() private val scanCardExceptionConverter = ScanCardExceptionConverter()
@ -57,7 +58,7 @@ internal object UseCaseScanProcessor {
val chains = buildList { val chains = buildList {
add( add(
FailedScansCounterChain( FailedScansCounterChain(
{ showMaxUnsuccessfulScansReachedDialog(analyticsSource) }, { showScanFailsDialog(analyticsSource) },
), ),
) )
add(AnalyticsChain(Basic.CardWasScanned(analyticsSource))) add(AnalyticsChain(Basic.CardWasScanned(analyticsSource)))
@ -71,14 +72,16 @@ internal object UseCaseScanProcessor {
) )
} }
private fun showMaxUnsuccessfulScansReachedDialog(source: AnalyticsParam.ScreensSources) { private fun showScanFailsDialog(source: AnalyticsParam.ScreensSources) {
val scanFailsSource = when (source) { val scanFailsSource = when (source) {
is AnalyticsParam.ScreensSources.SignIn -> StateDialog.ScanFailsSource.SIGN_IN is AnalyticsParam.ScreensSources.SignIn -> ScanFailsRequester.Source.SIGN_IN
is AnalyticsParam.ScreensSources.Settings -> StateDialog.ScanFailsSource.SETTINGS is AnalyticsParam.ScreensSources.Settings -> ScanFailsRequester.Source.SETTINGS
is AnalyticsParam.ScreensSources.Intro -> StateDialog.ScanFailsSource.INTRO is AnalyticsParam.ScreensSources.Intro -> ScanFailsRequester.Source.INTRO
else -> StateDialog.ScanFailsSource.MAIN else -> ScanFailsRequester.Source.MAIN
}
scope.launch {
store.inject(DaggerGraphState::scanFailsRequester).show(scanFailsSource)
} }
store.dispatchDialogShow(StateDialog.ScanFailsDialog(scanFailsSource))
} }
private suspend fun proceedWithException( private suspend fun proceedWithException(

View file

@ -13,11 +13,7 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.tap.common.analytics.events.ScanFailsDialogAnalytics import com.tangem.tap.common.analytics.events.ScanFailsDialogAnalytics
import com.tangem.tap.features.scanfails.ui.ScanFailsUM import com.tangem.tap.features.scanfails.ui.ScanFailsUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject

View file

@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -61,34 +62,43 @@ internal fun ScanFailsDialogContent(state: ScanFailsUM) {
text = stringResourceSafe(R.string.alert_button_how_to_scan), text = stringResourceSafe(R.string.alert_button_how_to_scan),
onClick = state.onHowToScan, onClick = state.onHowToScan,
color = TangemTheme.colors.text.accent, color = TangemTheme.colors.text.accent,
modifier = Modifier.testTag(ScanFailsDialogTestTags.HOW_TO_SCAN_BUTTON),
) )
DialogTextButton( DialogTextButton(
text = stringResourceSafe(R.string.alert_button_request_support), text = stringResourceSafe(R.string.alert_button_request_support),
onClick = state.onRequestSupport, onClick = state.onRequestSupport,
color = TangemTheme.colors.text.accent, color = TangemTheme.colors.text.accent,
modifier = Modifier.testTag(ScanFailsDialogTestTags.REQUEST_SUPPORT_BUTTON),
) )
DialogTextButton( DialogTextButton(
text = stringResourceSafe(R.string.common_cancel), text = stringResourceSafe(R.string.common_cancel),
onClick = state.onDismiss, onClick = state.onDismiss,
color = TangemTheme.colors.text.warning, color = TangemTheme.colors.text.warning,
modifier = Modifier.testTag(ScanFailsDialogTestTags.CANCEL_BUTTON),
) )
} }
} }
} }
@Composable @Composable
private fun DialogTextButton(text: String, onClick: () -> Unit, color: Color) { private fun DialogTextButton(text: String, onClick: () -> Unit, color: Color, modifier: Modifier = Modifier) {
Text( Text(
text = text.uppercase(), text = text.uppercase(),
color = color, color = color,
style = TangemTheme.typography.button, style = TangemTheme.typography.button,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.clickable(onClick = onClick), modifier = modifier.clickable(onClick = onClick),
) )
} }
object ScanFailsDialogTestTags {
const val HOW_TO_SCAN_BUTTON = "scan_fails_how_to_scan_button"
const val REQUEST_SUPPORT_BUTTON = "scan_fails_request_support_button"
const val CANCEL_BUTTON = "scan_fails_cancel_button"
}
// region Preview // region Preview
@Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)

View file

@ -18,6 +18,7 @@ import com.tangem.domain.apptheme.repository.AppThemeModeRepository
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.ScanCardUseCase
import com.tangem.domain.card.ScanFailsRequester
import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
@ -73,4 +74,5 @@ data class DaggerGraphState(
val userWalletsListRepository: UserWalletsListRepository? = null, val userWalletsListRepository: UserWalletsListRepository? = null,
val tangemHotSdk: TangemHotSdk? = null, val tangemHotSdk: TangemHotSdk? = null,
val trackingContextProxy: TrackingContextProxy? = null, val trackingContextProxy: TrackingContextProxy? = null,
val scanFailsRequester: ScanFailsRequester? = null,
) : StateType ) : StateType

View file

@ -52,6 +52,7 @@ internal fun RootContent(
wcContent: @Composable (modifier: Modifier) -> Unit, wcContent: @Composable (modifier: Modifier) -> Unit,
hotAccessCodeContent: @Composable (modifier: Modifier) -> Unit, hotAccessCodeContent: @Composable (modifier: Modifier) -> Unit,
rootDetectedWarningContent: @Composable (modifier: Modifier) -> Unit, rootDetectedWarningContent: @Composable (modifier: Modifier) -> Unit,
scanFailsContent: @Composable (modifier: Modifier) -> Unit,
) { ) {
val context = LocalContext.current val context = LocalContext.current
@ -89,6 +90,8 @@ internal fun RootContent(
rootDetectedWarningContent(Modifier.fillMaxSize()) rootDetectedWarningContent(Modifier.fillMaxSize())
scanFailsContent(Modifier.fillMaxSize())
TangemSnackbarHost( TangemSnackbarHost(
modifier = Modifier modifier = Modifier
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter)

View file

@ -40,6 +40,8 @@ import com.tangem.hot.sdk.android.create
import com.tangem.sdk.api.BackupServiceHolder import com.tangem.sdk.api.BackupServiceHolder
import com.tangem.tap.common.SnackbarHandler import com.tangem.tap.common.SnackbarHandler
import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.features.scanfails.ScanFailsComponent
import com.tangem.tap.features.scanfails.ScanFailsRequesterProxy
import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.hot.TangemHotSDKProxy import com.tangem.tap.features.hot.TangemHotSDKProxy
import com.tangem.tap.features.root.RootDetectedWarningComponent import com.tangem.tap.features.root.RootDetectedWarningComponent
@ -75,6 +77,8 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
private val cardRepository: CardRepository, private val cardRepository: CardRepository,
private val onboardingRepository: OnboardingRepository, private val onboardingRepository: OnboardingRepository,
private val trackingContextProxy: TrackingContextProxy, private val trackingContextProxy: TrackingContextProxy,
private val scanFailsComponentFactory: ScanFailsComponent.Factory,
private val scanFailsRequesterProxy: ScanFailsRequesterProxy,
private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsEventHandler: AnalyticsEventHandler,
private val analyticsExceptionHandler: AnalyticsExceptionHandler, private val analyticsExceptionHandler: AnalyticsExceptionHandler,
private val backupServiceHolder: BackupServiceHolder, private val backupServiceHolder: BackupServiceHolder,
@ -97,6 +101,11 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
.create(child("rootDetectedWarningComponent"), Unit) .create(child("rootDetectedWarningComponent"), Unit)
} }
private val scanFailsComponent: ScanFailsComponent by lazy {
scanFailsComponentFactory
.create(child("scanFailsComponent"), Unit)
}
private val navigation = navigationProvider.getOrCreateTyped<AppRoute>() private val navigation = navigationProvider.getOrCreateTyped<AppRoute>()
private val stack: Value<ChildStack<AppRoute, Child>> = childStack( private val stack: Value<ChildStack<AppRoute, Child>> = childStack(
@ -197,6 +206,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
wcContent = { wcRoutingComponent.Content(it) }, wcContent = { wcRoutingComponent.Content(it) },
hotAccessCodeContent = { hotAccessCodeRequestComponent.Content(it) }, hotAccessCodeContent = { hotAccessCodeRequestComponent.Content(it) },
rootDetectedWarningContent = { rootDetectedWarningComponent.Content(it) }, rootDetectedWarningContent = { rootDetectedWarningComponent.Content(it) },
scanFailsContent = { scanFailsComponent.Content(it) },
) )
} }
@ -240,10 +250,12 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
onCreate = { onCreate = {
tangemHotSDKProxy.sdkState.value = TangemHotSdk.create(activity) tangemHotSDKProxy.sdkState.value = TangemHotSdk.create(activity)
hotAccessCodeRequesterProxy.componentRequester.value = hotAccessCodeRequestComponent hotAccessCodeRequesterProxy.componentRequester.value = hotAccessCodeRequestComponent
scanFailsRequesterProxy.componentRequester.value = scanFailsComponent
}, },
onDestroy = { onDestroy = {
tangemHotSDKProxy.sdkState.value = null tangemHotSDKProxy.sdkState.value = null
hotAccessCodeRequesterProxy.componentRequester.value = null hotAccessCodeRequesterProxy.componentRequester.value = null
scanFailsRequesterProxy.componentRequester.value = null
}, },
) )
} }

View file

@ -1,27 +0,0 @@
package com.tangem.domain.features.addCustomToken
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.crypto.hdWallet.DerivationPath
/**
[REDACTED_AUTHOR]
*/
sealed class CustomCurrency(
val network: Blockchain,
val derivationPath: DerivationPath?,
) {
@Deprecated("It will be removed in next releases")
class CustomBlockchain(
network: Blockchain,
derivationPath: DerivationPath?,
) : CustomCurrency(network, derivationPath)
@Deprecated("It will be removed in next releases")
class CustomToken(
val token: Token,
network: Blockchain,
derivationPath: DerivationPath?,
) : CustomCurrency(network, derivationPath)
}

View file

@ -1,7 +0,0 @@
package com.tangem.domain.redux
import org.rekotlin.Action
sealed class OnboardingManageTokensAction : Action {
data object CurrenciesSaved : OnboardingManageTokensAction()
}

View file

@ -13,8 +13,6 @@ import com.tangem.core.ui.event.triggeredEvent
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.message.SnackbarMessage import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.domain.redux.OnboardingManageTokensAction
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.features.managetokens.analytics.ManageTokensAnalyticEvent import com.tangem.features.managetokens.analytics.ManageTokensAnalyticEvent
import com.tangem.features.managetokens.component.ManageTokensMode import com.tangem.features.managetokens.component.ManageTokensMode
import com.tangem.features.managetokens.component.ManageTokensSource import com.tangem.features.managetokens.component.ManageTokensSource
@ -41,7 +39,6 @@ import javax.inject.Inject
internal class OnboardingManageTokensModel @Inject constructor( internal class OnboardingManageTokensModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider, override val dispatchers: CoroutineDispatcherProvider,
private val messageSender: UiMessageSender, private val messageSender: UiMessageSender,
private val reduxStateHolder: ReduxStateHolder,
private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsEventHandler: AnalyticsEventHandler,
manageTokensListManagerFactory: ManageTokensListManager.Factory, manageTokensListManagerFactory: ManageTokensListManager.Factory,
manageTokensUseCasesFacadeFactory: ManageTokensUseCasesFacade.Factory, manageTokensUseCasesFacadeFactory: ManageTokensUseCasesFacade.Factory,
@ -294,10 +291,6 @@ internal class OnboardingManageTokensModel @Inject constructor(
} }
private fun returnToParentComponent() { private fun returnToParentComponent() {
// old onboarding
reduxStateHolder.dispatch(OnboardingManageTokensAction.CurrenciesSaved)
// new one
modelScope.launch { modelScope.launch {
returnToParentComponentFlow.emit(Unit) returnToParentComponentFlow.emit(Unit)
} }