Updated on 2026-08-14
This commit is contained in:
commit
754cc96cc3
38 changed files with 160 additions and 169 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) { _, _ -> }
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 ->
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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) { _, _ -> }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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) }
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue