From c76d1de3cfc19a09ffd70e80d9958a56c80440aa Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 26 Mar 2026 16:28:00 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../kotlin/com/tangem/tests/FeedbackTest.kt | 4 +- .../tap/common/redux/global/GlobalAction.kt | 12 -- .../common/redux/global/GlobalMiddleware.kt | 36 ----- .../tap/common/redux/global/GlobalReducer.kt | 6 - .../tap/common/redux/global/GlobalState.kt | 1 - .../scanCard/DefaultScanFailsCounter.kt | 37 +++++ .../domain/scanCard/LegacyScanProcessor.kt | 10 +- .../domain/scanCard/UseCaseScanProcessor.kt | 9 +- .../features/scanfails/ScanFailsComponent.kt | 3 +- .../tap/features/scanfails/ScanFailsModel.kt | 14 +- .../scanfails/ScanFailsRequesterProxy.kt | 3 +- .../features/scanfails/di/ScanFailsModule.kt | 6 + .../scanCard/DefaultScanFailsCounterTest.kt | 138 ++++++++++++++++++ .../tangem/domain/card/ScanFailsCounter.kt | 10 ++ .../tangem/domain/card/ScanFailsRequester.kt | 6 +- 15 files changed, 211 insertions(+), 84 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanFailsCounter.kt create mode 100644 app/src/test/kotlin/com/tangem/tap/domain/scanCard/DefaultScanFailsCounterTest.kt create mode 100644 domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsCounter.kt diff --git a/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt index 1009e83a52..6232f3caf0 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt @@ -7,7 +7,7 @@ import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.clickAndWaitFor import com.tangem.common.extensions.clickWithAssertion -import com.tangem.domain.card.ScanFailsRequester +import com.tangem.core.analytics.models.AnalyticsParam import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import com.tangem.scenarios.checkFailedTransactionDialog @@ -179,7 +179,7 @@ class FeedbackTest : BaseTestCase() { runOnUiThread { val requester = store.state.daggerGraphState.scanFailsRequester!! MainScope().launch { - requester.show(ScanFailsRequester.Source.MAIN) + requester.show(AnalyticsParam.ScreensSources.Main) } } } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index 315fe98387..a36bd807b6 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -1,23 +1,11 @@ package com.tangem.tap.common.redux.global -import com.tangem.common.CompletionResult -import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.scan.ScanResponse import org.rekotlin.Action sealed class GlobalAction : Action { - object ScanFailsCounter { - data class ChooseBehavior( - val result: CompletionResult, - val analyticsSource: AnalyticsParam.ScreensSources, - ) : GlobalAction() - - object Reset : GlobalAction() - object Increment : GlobalAction() - } - data class SaveScanResponse(val scanResponse: ScanResponse) : GlobalAction() data class ChangeAppCurrency(val appCurrency: AppCurrency) : GlobalAction() diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index 5bf0f5559a..f2df3df6e9 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -1,11 +1,6 @@ package com.tangem.tap.common.redux.global -import com.tangem.common.CompletionResult -import com.tangem.common.core.TangemSdkError -import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.card.ScanFailsRequester -import com.tangem.domain.models.scan.ScanResponse import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.redux.AppState @@ -30,43 +25,12 @@ private val globalMiddlewareHandler: Middleware = { _, _ -> } } -@Suppress("LongMethod", "ComplexMethod") private fun handleAction(action: Action) { when (action) { - is GlobalAction.ScanFailsCounter.ChooseBehavior -> { - when (action.result) { - is CompletionResult.Success -> store.dispatch(GlobalAction.ScanFailsCounter.Reset) - is CompletionResult.Failure -> { - handleFailureChooseBehaviour(action.result, action.analyticsSource) - } - } - } is GlobalAction.RestoreAppCurrency -> restoreAppCurrency() } } -private fun handleFailureChooseBehaviour( - result: CompletionResult.Failure, - analyticsSource: AnalyticsParam.ScreensSources, -) { - if (result.error is TangemSdkError.UserCancelled) { - store.dispatch(GlobalAction.ScanFailsCounter.Increment) - if (store.state.globalState.scanCardFailsCounter >= 2) { - val scanFailsSource = when (analyticsSource) { - is AnalyticsParam.ScreensSources.SignIn -> ScanFailsRequester.Source.SIGN_IN - is AnalyticsParam.ScreensSources.Settings -> ScanFailsRequester.Source.SETTINGS - is AnalyticsParam.ScreensSources.Intro -> ScanFailsRequester.Source.INTRO - else -> ScanFailsRequester.Source.MAIN - } - scope.launch { - store.inject(DaggerGraphState::scanFailsRequester).show(scanFailsSource) - } - } - } else { - store.dispatch(GlobalAction.ScanFailsCounter.Reset) - } -} - private fun restoreAppCurrency() { scope.launch { val currency = store.inject(DaggerGraphState::appCurrencyRepository) diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index b381df3054..e46630172e 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -10,12 +10,6 @@ fun globalReducer(action: Action, state: AppState): GlobalState { val globalState = state.globalState return when (action) { - is GlobalAction.ScanFailsCounter.Increment -> { - globalState.copy(scanCardFailsCounter = globalState.scanCardFailsCounter + 1) - } - is GlobalAction.ScanFailsCounter.Reset -> { - globalState.copy(scanCardFailsCounter = 0) - } is GlobalAction.SaveScanResponse -> { globalState.copy(scanResponse = action.scanResponse) } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 3c7906a1e5..01782e2e9a 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -10,7 +10,6 @@ data class GlobalState( val scanResponse: ScanResponse? = null, val tapWalletManager: TapWalletManager = TapWalletManager(), val appCurrency: AppCurrency = AppCurrency.Default, - val scanCardFailsCounter: Int = 0, val isLastSignWithRing: Boolean = false, ) : StateType diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanFailsCounter.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanFailsCounter.kt new file mode 100644 index 0000000000..cc7df51451 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanFailsCounter.kt @@ -0,0 +1,37 @@ +package com.tangem.tap.domain.scanCard + +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.domain.card.ScanFailsCounter +import com.tangem.domain.card.ScanFailsRequester +import com.tangem.utils.coroutines.AppCoroutineScope +import kotlinx.coroutines.launch +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +internal class DefaultScanFailsCounter @Inject constructor( + private val scanFailsRequester: ScanFailsRequester, + private val appScope: AppCoroutineScope, +) : ScanFailsCounter { + + private var counter: Int = 0 + + override fun reset() { + counter = 0 + } + + override fun onScanFailure(isUserCancelled: Boolean, source: AnalyticsParam.ScreensSources) { + if (isUserCancelled) { + counter++ + if (counter >= THRESHOLD) { + appScope.launch { scanFailsRequester.show(source) } + } + } else { + counter = 0 + } + } + + private companion object { + const val THRESHOLD = 2 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt index fd2e386a76..3c0b311ca7 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt @@ -19,6 +19,7 @@ import com.tangem.core.ui.R import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.toWrappedList import com.tangem.core.ui.message.dialog.Dialogs +import com.tangem.domain.card.ScanFailsCounter import com.tangem.domain.card.common.util.twinsIsTwinned import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.feedback.models.FeedbackEmailType @@ -26,9 +27,7 @@ import com.tangem.domain.models.scan.ScanResponse import com.tangem.sdk.extensions.localizedDescriptionRes import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.inject -import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.disclaimer.createDisclaimer import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.mainScope @@ -49,6 +48,7 @@ internal class LegacyScanProcessor @Inject constructor( @GlobalUiMessageSender private val uiMessageSender: UiMessageSender, private val analyticsEventHandler: AnalyticsEventHandler, private val trackingContextProxy: TrackingContextProxy, + private val scanFailsCounter: ScanFailsCounter, ) { suspend fun scan( @@ -89,10 +89,13 @@ internal class LegacyScanProcessor @Inject constructor( ) val analyticsEvent = Basic.CardWasScanned(analyticsSource) - store.dispatchOnMain(GlobalAction.ScanFailsCounter.ChooseBehavior(result, analyticsSource)) result .doOnFailure { error -> + scanFailsCounter.onScanFailure( + isUserCancelled = error is TangemSdkError.UserCancelled, + source = analyticsSource, + ) onScanFailure( analyticsSource = analyticsSource, error = error, @@ -106,6 +109,7 @@ internal class LegacyScanProcessor @Inject constructor( ) } .doOnSuccess { scanResponse -> + scanFailsCounter.reset() tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse) sendAnalytics(analyticsEvent, scanResponse) diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt index f82939019e..d9bbaccdb4 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/UseCaseScanProcessor.kt @@ -9,7 +9,6 @@ import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.domain.card.ScanCardException -import com.tangem.domain.card.ScanFailsRequester import com.tangem.domain.models.scan.ScanResponse import com.tangem.tap.common.analytics.events.TangemSdkErrorEvent import com.tangem.tap.common.extensions.dispatchNavigationAction @@ -73,14 +72,8 @@ internal object UseCaseScanProcessor { } private fun showScanFailsDialog(source: AnalyticsParam.ScreensSources) { - val scanFailsSource = when (source) { - is AnalyticsParam.ScreensSources.SignIn -> ScanFailsRequester.Source.SIGN_IN - is AnalyticsParam.ScreensSources.Settings -> ScanFailsRequester.Source.SETTINGS - is AnalyticsParam.ScreensSources.Intro -> ScanFailsRequester.Source.INTRO - else -> ScanFailsRequester.Source.MAIN - } scope.launch { - store.inject(DaggerGraphState::scanFailsRequester).show(scanFailsSource) + store.inject(DaggerGraphState::scanFailsRequester).show(source) } } diff --git a/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsComponent.kt b/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsComponent.kt index ffb2163692..41452daa3c 100644 --- a/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsComponent.kt +++ b/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsComponent.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.decompose.model.getOrCreateModel @@ -21,7 +22,7 @@ internal class ScanFailsComponent @AssistedInject constructor( private val model: ScanFailsModel = getOrCreateModel(params) - override suspend fun show(source: ScanFailsRequester.Source): ScanFailsRequester.Result { + override suspend fun show(source: AnalyticsParam.ScreensSources): ScanFailsRequester.Result { model.show(source) return model.waitResult() } diff --git a/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsModel.kt b/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsModel.kt index bbd95fded5..43804e0c66 100644 --- a/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsModel.kt +++ b/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsModel.kt @@ -30,14 +30,13 @@ internal class ScanFailsModel @Inject constructor( val uiState: StateFlow field = MutableStateFlow(ScanFailsUM(onDismiss = ::dismiss)) - fun show(source: ScanFailsRequester.Source) { - val analyticsSource = source.toAnalyticsSource() + fun show(source: AnalyticsParam.ScreensSources) { result.value = null uiState.update { ScanFailsUM( isShown = true, - onHowToScan = { onHowToScan(analyticsSource) }, - onRequestSupport = { onRequestSupport(analyticsSource) }, + onHowToScan = { onHowToScan(source) }, + onRequestSupport = { onRequestSupport(source) }, onDismiss = ::dismiss, ) } @@ -70,11 +69,4 @@ internal class ScanFailsModel @Inject constructor( sendFeedbackEmailUseCase(type = FeedbackEmailType.ScanningProblem) } } - - private fun ScanFailsRequester.Source.toAnalyticsSource(): AnalyticsParam.ScreensSources = when (this) { - ScanFailsRequester.Source.MAIN -> AnalyticsParam.ScreensSources.Main - ScanFailsRequester.Source.SIGN_IN -> AnalyticsParam.ScreensSources.SignIn - ScanFailsRequester.Source.SETTINGS -> AnalyticsParam.ScreensSources.Settings - ScanFailsRequester.Source.INTRO -> AnalyticsParam.ScreensSources.Intro - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsRequesterProxy.kt b/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsRequesterProxy.kt index 806d511714..5c4851d54e 100644 --- a/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsRequesterProxy.kt +++ b/app/src/main/java/com/tangem/tap/features/scanfails/ScanFailsRequesterProxy.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.scanfails +import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.domain.card.ScanFailsRequester import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filterNotNull @@ -13,7 +14,7 @@ class ScanFailsRequesterProxy @Inject constructor() : ScanFailsRequester { val componentRequester = MutableStateFlow(null) - override suspend fun show(source: ScanFailsRequester.Source): ScanFailsRequester.Result { + override suspend fun show(source: AnalyticsParam.ScreensSources): ScanFailsRequester.Result { return withTimeout(timeMillis = 1000) { componentRequester.filterNotNull().first() }.show(source) diff --git a/app/src/main/java/com/tangem/tap/features/scanfails/di/ScanFailsModule.kt b/app/src/main/java/com/tangem/tap/features/scanfails/di/ScanFailsModule.kt index 6d637e7594..3785c1dccf 100644 --- a/app/src/main/java/com/tangem/tap/features/scanfails/di/ScanFailsModule.kt +++ b/app/src/main/java/com/tangem/tap/features/scanfails/di/ScanFailsModule.kt @@ -2,7 +2,9 @@ package com.tangem.tap.features.scanfails.di import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.decompose.model.Model +import com.tangem.domain.card.ScanFailsCounter import com.tangem.domain.card.ScanFailsRequester +import com.tangem.tap.domain.scanCard.DefaultScanFailsCounter import com.tangem.tap.features.scanfails.ScanFailsComponent import com.tangem.tap.features.scanfails.ScanFailsModel import com.tangem.tap.features.scanfails.ScanFailsRequesterProxy @@ -29,4 +31,8 @@ internal interface ScanFailsModule { @Binds @Singleton fun bindRequester(impl: ScanFailsRequesterProxy): ScanFailsRequester + + @Binds + @Singleton + fun bindScanFailsCounter(impl: DefaultScanFailsCounter): ScanFailsCounter } \ No newline at end of file diff --git a/app/src/test/kotlin/com/tangem/tap/domain/scanCard/DefaultScanFailsCounterTest.kt b/app/src/test/kotlin/com/tangem/tap/domain/scanCard/DefaultScanFailsCounterTest.kt new file mode 100644 index 0000000000..5f80e2dc56 --- /dev/null +++ b/app/src/test/kotlin/com/tangem/tap/domain/scanCard/DefaultScanFailsCounterTest.kt @@ -0,0 +1,138 @@ +package com.tangem.tap.domain.scanCard + +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.domain.card.ScanFailsRequester +import com.tangem.utils.coroutines.AppCoroutineScope +import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider +import io.mockk.clearMocks +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +internal class DefaultScanFailsCounterTest { + + private val scanFailsRequester = mockk() + private val dispatchers = TestingCoroutineDispatcherProvider() + private val appScope = object : AppCoroutineScope { + override val coroutineContext = dispatchers.main + } + + private lateinit var counter: DefaultScanFailsCounter + + @BeforeEach + fun setup() { + clearMocks(scanFailsRequester) + counter = DefaultScanFailsCounter( + scanFailsRequester = scanFailsRequester, + appScope = appScope, + ) + } + + @Test + fun `single user cancellation does not show dialog`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.Main + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 0) { scanFailsRequester.show(source) } + } + + @Test + fun `two consecutive user cancellations show dialog`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.Main + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 1) { scanFailsRequester.show(source) } + } + + @Test + fun `non-cancelled failure resets counter`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.Main + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = false, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 0) { scanFailsRequester.show(source) } + } + + @Test + fun `reset clears counter`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.Main + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + counter.reset() + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 0) { scanFailsRequester.show(source) } + } + + @Test + fun `after reset two new cancellations show dialog again`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.SignIn + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + counter.reset() + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 2) { scanFailsRequester.show(source) } + } + + @Test + fun `dialog receives correct source`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.Settings + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 1) { scanFailsRequester.show(source) } + } + + @Test + fun `third consecutive cancellation also triggers dialog`() = runTest { + // Arrange + val source = AnalyticsParam.ScreensSources.Intro + coEvery { scanFailsRequester.show(source) } returns ScanFailsRequester.Result.Dismissed + + // Act + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + counter.onScanFailure(isUserCancelled = true, source = source) + + // Assert + coVerify(exactly = 2) { scanFailsRequester.show(source) } + } +} \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsCounter.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsCounter.kt new file mode 100644 index 0000000000..6d1816cc9f --- /dev/null +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsCounter.kt @@ -0,0 +1,10 @@ +package com.tangem.domain.card + +import com.tangem.core.analytics.models.AnalyticsParam + +interface ScanFailsCounter { + + fun reset() + + fun onScanFailure(isUserCancelled: Boolean, source: AnalyticsParam.ScreensSources) +} \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsRequester.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsRequester.kt index 19fbb925c4..f85ebc13d5 100644 --- a/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsRequester.kt +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/ScanFailsRequester.kt @@ -1,10 +1,10 @@ package com.tangem.domain.card +import com.tangem.core.analytics.models.AnalyticsParam + interface ScanFailsRequester { - suspend fun show(source: Source): Result - - enum class Source { MAIN, SIGN_IN, SETTINGS, INTRO } + suspend fun show(source: AnalyticsParam.ScreensSources): Result sealed class Result { data object Dismissed : Result()