Updated on 2026-08-14

This commit is contained in:
Tangem 2024-03-29 19:12:02 +05:00
commit 754cc96cc3
38 changed files with 160 additions and 169 deletions

View file

@ -46,7 +46,7 @@ class DialogManager : StoreSubscriber<GlobalState> {
dialog = when (state.dialog) {
is AppDialog.SimpleOkDialogRes -> SimpleOkDialog.create(state.dialog, context)
is StateDialog.ScanFailsDialog -> ScanFailsDialog.create(context)
is StateDialog.ScanFailsDialog -> ScanFailsDialog.create(context, state.dialog.source)
is AppDialog.AddressInfoDialog -> AddressInfoBottomSheetDialog(state.dialog, context)
is AppDialog.TestActionsDialog -> TestActionsBottomSheetDialog(state.dialog, context)
is AppDialog.RussianCardholdersWarningDialog -> RussianCardholdersWarningBottomSheetDialog(

View file

@ -13,7 +13,6 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWallet
import com.tangem.tap.features.saveWallet.redux.SaveWalletReducer
import com.tangem.tap.features.send.redux.reducers.SendScreenReducer
import com.tangem.tap.features.shop.redux.ShopReducer
import com.tangem.tap.features.signin.redux.SignInReducer
import com.tangem.tap.features.tokens.legacy.redux.TokensReducer
import com.tangem.tap.features.welcome.redux.WelcomeReducer
import com.tangem.tap.proxy.AppStateHolder
@ -40,7 +39,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder)
shopState = ShopReducer.reduce(action, state.shopState),
welcomeState = WelcomeReducer.reduce(action, state),
saveWalletState = SaveWalletReducer.reduce(action, state),
signInState = SignInReducer.reduce(action, state),
daggerGraphState = DaggerGraphReducer.reduce(action, state),
)
}

View file

@ -31,8 +31,6 @@ import com.tangem.tap.features.send.redux.middlewares.SendMiddleware
import com.tangem.tap.features.send.redux.states.SendState
import com.tangem.tap.features.shop.redux.ShopMiddleware
import com.tangem.tap.features.shop.redux.ShopState
import com.tangem.tap.features.signin.redux.SignInMiddleware
import com.tangem.tap.features.signin.redux.SignInState
import com.tangem.tap.features.tokens.legacy.redux.TokensState
import com.tangem.tap.features.wallet.redux.middlewares.TradeCryptoMiddleware
import com.tangem.tap.features.welcome.redux.WelcomeMiddleware
@ -59,7 +57,6 @@ data class AppState(
val shopState: ShopState = ShopState(),
val welcomeState: WelcomeState = WelcomeState(),
val saveWalletState: SaveWalletState = SaveWalletState(),
val signInState: SignInState = SignInState(),
val daggerGraphState: DaggerGraphState = DaggerGraphState(),
) : StateType {
@ -97,7 +94,6 @@ data class AppState(
SaveWalletMiddleware().middleware,
LockUserWalletsTimerMiddleware().middleware,
AccessCodeRequestPolicyMiddleware().middleware,
SignInMiddleware.middleware,
DaggerGraphMiddleware.daggerGraphMiddleware,
LegacyMiddleware.legacyMiddleware,
TradeCryptoMiddleware.middleware,

View file

@ -2,6 +2,7 @@ package com.tangem.tap.common.redux.global
import com.tangem.blockchain.common.WalletManager
import com.tangem.common.CompletionResult
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.navigation.StateDialog
import com.tangem.datasource.config.ConfigManager
import com.tangem.datasource.config.models.ChatConfig
@ -51,7 +52,11 @@ sealed class GlobalAction : Action {
}
object ScanFailsCounter {
data class ChooseBehavior(val result: CompletionResult<ScanResponse>) : GlobalAction()
data class ChooseBehavior(
val result: CompletionResult<ScanResponse>,
val analyticsSource: AnalyticsParam.ScreensSources,
) : GlobalAction()
object Reset : GlobalAction()
object Increment : GlobalAction()
}

View file

@ -4,6 +4,7 @@ import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
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.StateDialog
import com.tangem.datasource.config.models.Config
@ -54,14 +55,7 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
when (action.result) {
is CompletionResult.Success -> store.dispatch(GlobalAction.ScanFailsCounter.Reset)
is CompletionResult.Failure -> {
if (action.result.error is TangemSdkError.UserCancelled) {
store.dispatch(GlobalAction.ScanFailsCounter.Increment)
if (store.state.globalState.scanCardFailsCounter >= 2) {
store.dispatchDialogShow(StateDialog.ScanFailsDialog)
}
} else {
store.dispatch(GlobalAction.ScanFailsCounter.Reset)
}
handleFailureChooseBehaviour(action.result, action.analyticsSource)
}
}
}
@ -184,6 +178,26 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
}
}
private fun handleFailureChooseBehaviour(
result: CompletionResult.Failure<ScanResponse>,
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 -> StateDialog.ScanFailsSource.SIGN_IN
is AnalyticsParam.ScreensSources.Settings -> StateDialog.ScanFailsSource.SETTINGS
is AnalyticsParam.ScreensSources.Intro -> StateDialog.ScanFailsSource.INTRO
else -> StateDialog.ScanFailsSource.MAIN
}
store.dispatchDialogShow(StateDialog.ScanFailsDialog(scanFailsSource))
}
} else {
store.dispatch(GlobalAction.ScanFailsCounter.Reset)
}
}
private fun restoreAppCurrency() {
scope.launch {
val currency = store.inject(DaggerGraphState::appCurrencyRepository)

View file

@ -4,7 +4,9 @@ import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
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.StateDialog
import com.tangem.tap.common.extensions.dispatchDialogHide
import com.tangem.tap.common.feedback.ScanFailsEmail
import com.tangem.tap.common.redux.global.GlobalAction
@ -15,12 +17,18 @@ import com.tangem.wallet.R
[REDACTED_AUTHOR]
*/
object ScanFailsDialog {
fun create(context: Context): AlertDialog {
fun create(context: Context, source: StateDialog.ScanFailsSource): AlertDialog {
return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
setTitle(context.getString(R.string.common_warning))
setMessage(R.string.alert_troubleshooting_scan_card_title)
setPositiveButton(R.string.alert_button_request_support) { _, _ ->
Analytics.send(Basic.ButtonSupport())
val sourceAnalytics = when (source) {
StateDialog.ScanFailsSource.MAIN -> AnalyticsParam.ScreensSources.Main
StateDialog.ScanFailsSource.SIGN_IN -> AnalyticsParam.ScreensSources.SignIn
StateDialog.ScanFailsSource.SETTINGS -> AnalyticsParam.ScreensSources.Settings
StateDialog.ScanFailsSource.INTRO -> AnalyticsParam.ScreensSources.Intro
}
Analytics.send(Basic.ButtonSupport(sourceAnalytics))
store.dispatch(GlobalAction.SendEmail(ScanFailsEmail()))
}
setNeutralButton(R.string.common_cancel) { _, _ -> }

View file

@ -2,7 +2,7 @@ package com.tangem.tap.domain.scanCard
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemError
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.common.extensions.inject
@ -27,7 +27,7 @@ internal class DefaultScanCardProcessor : ScanCardProcessor {
@Suppress("LongParameterList")
override suspend fun scan(
analyticsEvent: AnalyticsEvent?,
analyticsSource: AnalyticsParam.ScreensSources,
cardId: String?,
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
@ -38,7 +38,7 @@ internal class DefaultScanCardProcessor : ScanCardProcessor {
) {
if (isNewCardScanningEnabled) {
UseCaseScanProcessor.scan(
analyticsEvent,
analyticsSource,
cardId,
onProgressStateChange,
onScanStateChange,
@ -49,7 +49,7 @@ internal class DefaultScanCardProcessor : ScanCardProcessor {
)
} else {
LegacyScanProcessor.scan(
analyticsEvent,
analyticsSource,
cardId,
onProgressStateChange,
onScanStateChange,

View file

@ -7,6 +7,8 @@ import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsEvent
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.TapWorkarounds.canSkipBackup
@ -45,7 +47,7 @@ internal object LegacyScanProcessor {
@Suppress("LongParameterList")
suspend fun scan(
analyticsEvent: AnalyticsEvent?,
analyticsSource: AnalyticsParam.ScreensSources,
cardId: String?,
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
@ -61,7 +63,8 @@ internal object LegacyScanProcessor {
val result = tangemSdkManager.scanProduct(cardId)
store.dispatchOnMain(GlobalAction.ScanFailsCounter.ChooseBehavior(result))
val analyticsEvent = Basic.CardWasScanned(analyticsSource)
store.dispatchOnMain(GlobalAction.ScanFailsCounter.ChooseBehavior(result, analyticsSource))
result
.doOnFailure { error ->

View file

@ -3,7 +3,8 @@ package com.tangem.tap.domain.scanCard
import arrow.fx.coroutines.resourceScope
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemError
import com.tangem.core.analytics.models.AnalyticsEvent
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.card.ScanCardException
@ -34,7 +35,7 @@ internal object UseCaseScanProcessor {
@Suppress("LongParameterList")
suspend fun scan(
analyticsEvent: AnalyticsEvent?,
analyticsSource: AnalyticsParam.ScreensSources,
cardId: String?,
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
@ -48,9 +49,7 @@ internal object UseCaseScanProcessor {
val scanCardUseCase = store.inject(DaggerGraphState::scanCardUseCase)
val chains = buildList {
add(ScanningFinishedChain { onScanStateChange(false) })
if (analyticsEvent != null) {
add(AnalyticsChain(analyticsEvent))
}
add(AnalyticsChain(Basic.CardWasScanned(analyticsSource)))
add(DisclaimerChain(store, disclaimerWillShow))
add(CheckForOnboardingChain(store, store.state.globalState.tapWalletManager))
}

View file

@ -13,6 +13,7 @@ import com.tangem.tap.features.details.redux.walletconnect.WalletForSession
import com.trustwallet.walletconnect.models.WCPeerMeta
import com.trustwallet.walletconnect.models.session.WCSession
import timber.log.Timber
import java.io.FileNotFoundException
import java.nio.charset.Charset
class WalletConnectRepository(val context: Application) {
@ -35,6 +36,8 @@ class WalletConnectRepository(val context: Application) {
val json = context.readFileText(FILE_NAME_PREFIX_SESSIONS)
.hexToUtf8()
walletConnectAdapter.fromJson(json)!!.map { it.toSession() }
} catch (e: FileNotFoundException) {
emptyList()
} catch (exception: Exception) {
Timber.w(exception)
emptyList()

View file

@ -14,12 +14,9 @@ import com.walletconnect.android.CoreClient
import com.walletconnect.android.relay.ConnectionType
import com.walletconnect.web3.wallet.client.Wallet
import com.walletconnect.web3.wallet.client.Web3Wallet
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@ -192,8 +189,8 @@ class WalletConnectRepositoryImpl @Inject constructor(
if (sessionDelete is Wallet.Model.SessionDelete.Success) {
scope.launch {
_events.emit(WalletConnectEvents.SessionDeleted(sessionDelete.topic))
updateSessionsInternal().join()
}
updateSessions()
}
Timber.d("onSessionDelete: $sessionDelete")
}
@ -209,21 +206,21 @@ class WalletConnectRepositoryImpl @Inject constructor(
accounts = userNamespaces?.flatMap { it.value } ?: emptyList(),
),
)
updateSessionsInternal().join()
}
updateSessions()
}
}
override fun onSessionUpdateResponse(sessionUpdateResponse: Wallet.Model.SessionUpdateResponse) {
// Triggered when wallet receives the session update response from Dapp
Timber.d("onSessionUpdateResponse: $sessionUpdateResponse")
updateSessions()
updateSessionsInternal()
}
override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) {
// Triggered whenever the connection state is changed
Timber.d("onConnectionStateChange: $state")
if (state.isAvailable) updateSessions()
if (state.isAvailable) updateSessionsInternal()
}
override fun onError(error: Wallet.Model.Error) {
@ -416,7 +413,7 @@ class WalletConnectRepositoryImpl @Inject constructor(
dAppUrl = session?.url ?: "",
),
)
updateSessions()
updateSessionsInternal()
Timber.d("Disconnected successfully: $it")
},
onError = {
@ -440,20 +437,22 @@ class WalletConnectRepositoryImpl @Inject constructor(
}
override fun updateSessions() {
scope.launch {
val availableSessions = Web3Wallet.getListOfActiveSessions()
.map {
WalletConnectSession(
topic = it.topic,
icon = it.metaData?.icons?.firstOrNull(),
name = it.metaData?.name,
url = it.metaData?.url,
)
}
Timber.d("Available sessions: $availableSessions")
currentSessions = availableSessions
_activeSessions.emit(availableSessions)
}
updateSessionsInternal()
}
private fun updateSessionsInternal(): Job = scope.launch {
val availableSessions = Web3Wallet.getListOfActiveSessions()
.map {
WalletConnectSession(
topic = it.topic,
icon = it.metaData?.icons?.firstOrNull(),
name = it.metaData?.name,
url = it.metaData?.url,
)
}
Timber.d("Available sessions: $availableSessions")
currentSessions = availableSessions
_activeSessions.emit(availableSessions)
}
private fun findMissingNetworks(

View file

@ -37,10 +37,12 @@ class WalletConnectInteractor(
suspend fun startListening(userWalletId: String, cardId: String?) {
this.userWalletId = userWalletId
this.cardId = cardId
walletConnectRepository.updateSessions()
coroutineScope {
launch { subscribeToEvents() }
launch { subscribeToSessions() }
walletConnectRepository.updateSessions()
}
}
@ -88,11 +90,12 @@ class WalletConnectInteractor(
is WalletConnectEvents.SessionApprovalSuccess -> {
sessionsRepository.saveSession(
userWallet = userWalletId,
session = Session.fromAccounts(
session = Session(
accounts = wcEvent.accounts,
topic = wcEvent.topic,
),
)
walletConnectRepository.updateSessions()
handler.onSessionEstablished()
}
is WalletConnectEvents.SessionDeleted -> {

View file

@ -3,13 +3,4 @@ package com.tangem.tap.domain.walletconnect2.domain.models
data class Session(
val topic: String,
val accounts: List<Account>,
) {
companion object {
fun fromAccounts(accounts: List<Account>, topic: String): Session {
return Session(
topic = topic,
accounts = accounts,
)
}
}
}
)

View file

@ -7,7 +7,6 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.core.UserCodeRequestPolicy
import com.tangem.common.extensions.guard
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.extensions.TextReference
@ -580,7 +579,7 @@ class DetailsMiddleware {
)
store.inject(DaggerGraphState::scanCardProcessor).scan(
analyticsEvent = Basic.CardWasScanned(CoreAnalyticsParam.ScannedFrom.MyWallets),
analyticsSource = CoreAnalyticsParam.ScreensSources.Settings,
onWalletNotCreated = {
// No need to rollback policy, continue with the policy set before the card scan
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)

View file

@ -59,8 +59,7 @@ sealed class WalletConnectAction : Action {
) : WalletConnectAction()
data class FailureEstablishingSession(val session: WCSession?, val error: TapError? = null) : WalletConnectAction()
data class SetSessionsRestored(val sessions: List<WalletConnectSession>) :
WalletConnectAction()
data class SetSessionsRestored(val sessions: List<WalletConnectSession>) : WalletConnectAction()
data class DisconnectSession(val topic: String, val session: WCSession?) : WalletConnectAction()

View file

@ -20,8 +20,9 @@ object WalletConnectReducer {
is WalletConnectAction.SetNewSessionData -> {
state.copy(newSessionData = action.newSession)
}
is WalletConnectAction.SetSessionsRestored ->
WalletConnectState(sessions = action.sessions)
is WalletConnectAction.SetSessionsRestored -> state.copy(
sessions = action.sessions,
)
is WalletConnectAction.RemoveSession -> {
val sessions =
state.sessions.filterNot { it.session.toUri() == action.session.toUri() }

View file

@ -4,6 +4,7 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import com.tangem.common.extensions.guard
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
@ -138,7 +139,7 @@ internal class DetailsViewModel(
}
private fun sendFeedback() {
Analytics.send(Basic.ButtonSupport())
Analytics.send(Basic.ButtonSupport(AnalyticsParam.ScreensSources.Settings))
store.dispatchOnMain(GlobalAction.SendEmail(FeedbackEmail()))
}

View file

@ -1,8 +1,5 @@
package com.tangem.tap.features.home.redux
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.entities.IndeterminateProgressButton
import kotlinx.coroutines.CoroutineScope
import org.rekotlin.Action
@ -17,11 +14,9 @@ sealed class HomeAction : Action {
/**
* Action for scanning card
*
* @property analyticsEvent analytics event
* @property scope lifecycle scope. It will be canceled when lifecycle-aware component is destroyed
*/
data class ReadCard(
val analyticsEvent: AnalyticsEvent? = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Introduction),
val scope: CoroutineScope,
) : HomeAction()

View file

@ -5,12 +5,14 @@ import com.tangem.common.doOnResult
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.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
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.userwallets.UserWalletBuilder
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.analytics.events.Shop
import com.tangem.tap.common.entities.IndeterminateProgressButton
@ -19,7 +21,6 @@ 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
import com.tangem.tap.features.send.redux.states.ButtonState
import com.tangem.tap.features.signin.redux.SignInAction
import com.tangem.tap.preferencesStorage
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
@ -59,7 +60,7 @@ private fun handleHomeAction(action: Action) {
}
is HomeAction.ReadCard -> {
action.scope.launch {
readCard(action.analyticsEvent)
readCard()
}
}
is HomeAction.GoToShop -> {
@ -75,13 +76,13 @@ private fun handleHomeAction(action: Action) {
}
}
private suspend fun readCard(analyticsEvent: AnalyticsEvent?) {
private suspend fun readCard() {
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
)
store.inject(DaggerGraphState::scanCardProcessor).scan(
analyticsEvent = analyticsEvent,
analyticsSource = AnalyticsParam.ScreensSources.Intro,
onProgressStateChange = { showProgress ->
if (showProgress) {
changeButtonState(ButtonState.PROGRESS)
@ -113,14 +114,32 @@ private fun proceedWithScanResponse(scanResponse: ScanResponse) = scope.launch {
Timber.e(error, "Unable to save user wallet")
}
.doOnSuccess {
sendSignedInCardAnalyticsEvent(scanResponse)
scope.launch { store.onUserWalletSelected(userWallet = userWallet) }
}
.doOnResult {
store.dispatchOnMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card))
navigateTo(AppScreen.Wallet)
}
}
private fun sendSignedInCardAnalyticsEvent(scanResponse: ScanResponse) {
val currency = ParamCardCurrencyConverter().convert(
value = scanResponse.cardTypesResolver,
)
if (currency != null) {
Analytics.send(
event = Basic.SignedIn(
currency = currency,
batch = scanResponse.card.batchId,
signInType = Basic.SignedIn.SignInType.Card,
walletsCount = userWalletsListManager.walletsCount.toString(),
hasBackup = scanResponse.card.backupStatus?.isActive,
),
)
}
}
private suspend fun navigateTo(appScreen: AppScreen) {
store.dispatchOnMain(NavigationAction.NavigateTo(appScreen))
delay(timeMillis = 200)

View file

@ -5,6 +5,7 @@ import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.view.MenuProvider
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.feedback.SupportInfo
import com.tangem.tap.common.redux.global.GlobalAction
@ -21,7 +22,7 @@ class OnboardingMenuProvider : MenuProvider {
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
R.id.menu_item_chat_support -> {
Analytics.send(Basic.ButtonSupport())
Analytics.send(Basic.ButtonSupport(AnalyticsParam.ScreensSources.Intro))
// changed on email support [REDACTED_TASK_KEY]
store.dispatch(GlobalAction.SendEmail(SupportInfo()))
true

View file

@ -22,6 +22,7 @@ import com.tangem.common.CardIdFormatter
import com.tangem.common.CompletionResult
import com.tangem.common.core.CardIdDisplayFormat
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.ui.extensions.setStatusBarColor
import com.tangem.domain.common.util.cardTypesResolver
@ -502,7 +503,7 @@ class OnboardingWalletFragment :
private fun makeSeedPhraseRouter(): SeedPhraseRouter = SeedPhraseRouter(
onBack = ::legacyOnBackHandler,
onOpenChat = {
Analytics.send(Basic.ButtonSupport())
Analytics.send(Basic.ButtonSupport(AnalyticsParam.ScreensSources.Intro))
// changed on email support [REDACTED_TASK_KEY]
store.dispatch(GlobalAction.SendEmail(SupportInfo()))
},

View file

@ -4,6 +4,7 @@ import android.app.Dialog
import android.content.Context
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.extensions.dispatchDialogHide
import com.tangem.tap.common.feedback.SupportInfo
@ -21,7 +22,7 @@ object WalletActivationErrorDialog {
setPositiveButton(R.string.common_ok) { _, _ -> dialog.onConfirm() }
setNegativeButton(R.string.common_support) { _, _ ->
// changed on email support [REDACTED_TASK_KEY]
Analytics.send(Basic.ButtonSupport())
Analytics.send(Basic.ButtonSupport(AnalyticsParam.ScreensSources.Intro))
store.dispatch(GlobalAction.SendEmail(SupportInfo()))
}
setOnDismissListener { store.dispatchDialogHide() }

View file

@ -3,6 +3,7 @@ package com.tangem.tap.features.send.ui.dialogs
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.feedback.SendTransactionFailedEmail
import com.tangem.tap.common.redux.global.GlobalAction
@ -21,7 +22,7 @@ object RequestFeeErrorDialog {
setTitle(R.string.common_fee_error)
setMessage(context.getString(R.string.alert_failed_to_send_transaction_message, errorMessage))
setNegativeButton(R.string.details_row_title_contact_to_support) { _, _ ->
Analytics.send(Basic.ButtonSupport())
Analytics.send(Basic.ButtonSupport(AnalyticsParam.ScreensSources.Send))
store.dispatch(GlobalAction.SendEmail(SendTransactionFailedEmail(errorMessage)))
}
setPositiveButton(R.string.common_retry) { _, _ -> dialog.onRetry() }

View file

@ -6,6 +6,7 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.BlockchainSdkError
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.sdk.extensions.localizedDescription
import com.tangem.tap.common.extensions.stripZeroPlainString
@ -33,7 +34,7 @@ object SendTransactionFailsDialog {
setTitle(R.string.alert_failed_to_send_transaction_title)
setMessage(context.getString(R.string.alert_failed_to_send_transaction_message, errorMessage))
setNeutralButton(R.string.details_row_title_contact_to_support) { _, _ ->
Analytics.send(Basic.ButtonSupport())
Analytics.send(Basic.ButtonSupport(AnalyticsParam.ScreensSources.Send))
store.dispatch(GlobalAction.SendEmail(SendTransactionFailedEmail(errorMessage)))
}
setPositiveButton(R.string.common_cancel) { _, _ -> }

View file

@ -1,12 +0,0 @@
package com.tangem.tap.features.signin.redux
import com.tangem.core.analytics.models.Basic
import org.rekotlin.Action
/**
[REDACTED_AUTHOR]
*/
sealed interface SignInAction : Action {
data class SetSignInType(val type: Basic.SignedIn.SignInType) : SignInAction
}

View file

@ -1,15 +0,0 @@
package com.tangem.tap.features.signin.redux
import com.tangem.tap.common.redux.AppState
import org.rekotlin.Middleware
/**
[REDACTED_AUTHOR]
*/
object SignInMiddleware {
val middleware: Middleware<AppState> = { _, _ ->
{ next ->
{ action -> next(action) }
}
}
}

View file

@ -1,17 +0,0 @@
package com.tangem.tap.features.signin.redux
import com.tangem.tap.common.redux.AppState
import org.rekotlin.Action
/**
[REDACTED_AUTHOR]
*/
object SignInReducer {
fun reduce(action: Action, state: AppState): SignInState {
if (action !is SignInAction) return state.signInState
return when (action) {
is SignInAction.SetSignInType -> state.signInState.copy(type = action.type)
}
}
}

View file

@ -1,8 +0,0 @@
package com.tangem.tap.features.signin.redux
import com.tangem.core.analytics.models.Basic
/**
[REDACTED_AUTHOR]
*/
data class SignInState(val type: Basic.SignedIn.SignInType? = null)

View file

@ -25,7 +25,6 @@ import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
import com.tangem.tap.features.signin.redux.SignInAction
import com.tangem.tap.proxy.redux.DaggerGraphState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -98,7 +97,6 @@ internal class WelcomeMiddleware {
signInType = Basic.SignedIn.SignInType.Biometric,
)
store.dispatchWithMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Biometric))
store.dispatchWithMain(NavigationAction.NavigateTo(AppScreen.Wallet))
store.dispatchWithMain(WelcomeAction.ProceedWithBiometrics.Success)
store.onUserWalletSelected(userWallet = selectedUserWallet)
@ -128,7 +126,6 @@ internal class WelcomeMiddleware {
.doOnSuccess {
sendSignedInAnalyticsEvent(scanResponse = scanResponse, signInType = Basic.SignedIn.SignInType.Card)
store.dispatchWithMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card))
store.dispatchWithMain(NavigationAction.NavigateTo(AppScreen.Wallet))
store.dispatchWithMain(WelcomeAction.ProceedWithCard.Success)
store.onUserWalletSelected(userWallet = userWallet)
@ -175,7 +172,7 @@ internal class WelcomeMiddleware {
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
)
store.inject(DaggerGraphState::scanCardProcessor).scan(
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.SignIn),
analyticsSource = AnalyticsParam.ScreensSources.SignIn,
onSuccess = { scanResponse ->
scope.launch { onCardScanned(scanResponse) }
},