Updated on 2026-08-14
This commit is contained in:
commit
8843c047f8
105 changed files with 1749 additions and 1200 deletions
|
|
@ -3,8 +3,9 @@ package com.tangem.tap.features.details.redux
|
|||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.tap.common.analytics.AnalyticsAnOld
|
||||
import com.tangem.tap.common.analytics.AnalyticsParamAnOld
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -119,19 +120,16 @@ class DetailsMiddleware {
|
|||
val card = store.state.detailsState.cardSettingsState?.card ?: return
|
||||
scope.launch {
|
||||
val result = tangemSdkManager.resetToFactorySettings(card)
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
(result.error as? TangemSdkError)?.let { error ->
|
||||
store.state.globalState.analyticsHandler.handleCardSdkErrorEvent(
|
||||
error,
|
||||
AnalyticsAnOld.ActionToLog.PurgeWallet,
|
||||
card = store.state.detailsState.scanResponse?.card,
|
||||
)
|
||||
}
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Settings.CardSettings.FactoryResetFinished())
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
(result.error as? TangemSdkError)?.let { error ->
|
||||
Analytics.send(Settings.CardSettings.FactoryResetFinished(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,28 +154,20 @@ class DetailsMiddleware {
|
|||
SecurityOption.LongTap -> tangemSdkManager.setLongTap(cardId)
|
||||
SecurityOption.PassCode -> tangemSdkManager.setPasscode(cardId)
|
||||
SecurityOption.AccessCode -> tangemSdkManager.setAccessCode(cardId)
|
||||
else -> null
|
||||
else -> return@launch
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
val paramValue = AnalyticsParam.SecurityMode.from(selectedOption)
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
selectedOption?.let {
|
||||
store.dispatch(GlobalAction.UpdateSecurityOptions(it))
|
||||
}
|
||||
Analytics.send(Settings.CardSettings.SecurityModeChanged(paramValue))
|
||||
store.dispatch(GlobalAction.UpdateSecurityOptions(selectedOption))
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Success)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
(result.error as? TangemSdkError)?.let { error ->
|
||||
store.state.globalState.analyticsHandler.handleCardSdkErrorEvent(
|
||||
error = error,
|
||||
action = AnalyticsAnOld.ActionToLog.ChangeSecOptions,
|
||||
params = mapOf(
|
||||
AnalyticsParamAnOld.NEW_SECURITY_OPTION to
|
||||
(selectedOption?.name ?: ""),
|
||||
),
|
||||
card = store.state.detailsState.scanResponse?.card,
|
||||
)
|
||||
Analytics.send(Settings.CardSettings.SecurityModeChanged(paramValue, error))
|
||||
}
|
||||
store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Failure)
|
||||
}
|
||||
|
|
@ -190,7 +180,10 @@ class DetailsMiddleware {
|
|||
is DetailsAction.ManageSecurity.ChangeAccessCode -> {
|
||||
val card = store.state.detailsState.cardSettingsState?.card ?: return
|
||||
scope.launch {
|
||||
tangemSdkManager.setAccessCode(card.cardId)
|
||||
when (tangemSdkManager.setAccessCode(card.cardId)) {
|
||||
is CompletionResult.Success -> Analytics.send(Settings.CardSettings.UserCodeChanged())
|
||||
is CompletionResult.Failure -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> { /* no-op */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ package com.tangem.tap.features.details.ui.cardsettings
|
|||
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.common.getTwinCardIdForUser
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.details.redux.CardSettingsState
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
|
|
@ -59,12 +62,15 @@ class CardSettingsViewModel(private val store: Store<AppState>) {
|
|||
private fun handleClickingItem(item: CardInfo) {
|
||||
when (item) {
|
||||
is CardInfo.ChangeAccessCode -> {
|
||||
Analytics.send(Settings.CardSettings.ButtonChangeUserCode(AnalyticsParam.UserCode.AccessCode))
|
||||
store.dispatch(DetailsAction.ManageSecurity.ChangeAccessCode)
|
||||
}
|
||||
is CardInfo.ResetToFactorySettings -> {
|
||||
Analytics.send(Settings.CardSettings.ButtonFactoryReset())
|
||||
store.dispatch(DetailsAction.ResetToFactory.Start)
|
||||
}
|
||||
is CardInfo.SecurityMode -> {
|
||||
Analytics.send(Settings.CardSettings.ButtonChangeSecurityMode())
|
||||
store.dispatch(DetailsAction.ManageSecurity.OpenSecurity)
|
||||
}
|
||||
else -> {}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import androidx.compose.ui.platform.ComposeView
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -24,7 +26,7 @@ class DetailsFragment : Fragment(), StoreSubscriber<DetailsState> {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
Analytics.send(Settings.ScreenOpened())
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(android.R.transition.fade)
|
||||
exitTransition = inflater.inflateTransition(android.R.transition.fade)
|
||||
|
|
|
|||
|
|
@ -162,8 +162,8 @@ fun DetailsItem(
|
|||
|
||||
@Composable
|
||||
fun TangemSocialAccounts(
|
||||
links: List<TangemLink>,
|
||||
onSocialNetworkClick: (String) -> Unit,
|
||||
links: List<SocialNetworkLink>,
|
||||
onSocialNetworkClick: (SocialNetworkLink) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LazyRow(
|
||||
|
|
@ -171,11 +171,11 @@ fun TangemSocialAccounts(
|
|||
) {
|
||||
items(links) {
|
||||
Icon(
|
||||
painter = painterResource(id = it.iconRes),
|
||||
painter = painterResource(id = it.network.iconRes),
|
||||
contentDescription = "",
|
||||
modifier = modifier
|
||||
.padding(8.dp)
|
||||
.clickable { onSocialNetworkClick(it.url) },
|
||||
.clickable { onSocialNetworkClick(it) },
|
||||
tint = colorResource(id = R.color.icon_informative),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import com.tangem.wallet.R
|
|||
|
||||
data class DetailsScreenState(
|
||||
val elements: List<SettingsElement>,
|
||||
val tangemLinks: List<TangemLink>,
|
||||
val tangemLinks: List<SocialNetworkLink>,
|
||||
val tangemVersion: String,
|
||||
val appCurrency: String,
|
||||
val onItemsClick: (SettingsElement) -> Unit,
|
||||
val onSocialNetworkClick: (String) -> Unit,
|
||||
val onSocialNetworkClick: (SocialNetworkLink) -> Unit,
|
||||
) {
|
||||
val appNameRes: Int = R.string.app_name
|
||||
}
|
||||
|
|
@ -30,28 +30,38 @@ enum class SettingsElement(
|
|||
;
|
||||
}
|
||||
|
||||
data class TangemLink(
|
||||
val iconRes: Int,
|
||||
data class SocialNetworkLink(
|
||||
val network: SocialNetwork,
|
||||
val url: String,
|
||||
)
|
||||
|
||||
sealed class SocialNetwork(val id: String, val iconRes: Int) {
|
||||
object Telegram : SocialNetwork("Telegram", R.drawable.ic_telegram)
|
||||
object Twitter : SocialNetwork("Twitter", R.drawable.ic_twitter)
|
||||
object Facebook : SocialNetwork("Facebook", R.drawable.ic_facebook)
|
||||
object Instagram : SocialNetwork("Instagram", R.drawable.ic_instagram)
|
||||
object GitHub : SocialNetwork("GitHub", R.drawable.ic_github)
|
||||
object Youtube : SocialNetwork("Youtube", R.drawable.ic_youtube)
|
||||
object LinkedIn : SocialNetwork("LinkedIn", R.drawable.ic_linkedin)
|
||||
}
|
||||
|
||||
object TangemSocialAccounts {
|
||||
val accountsEn: List<TangemLink> = listOf(
|
||||
TangemLink(R.drawable.ic_telegram, "https://t.me/TangemCards"),
|
||||
TangemLink(R.drawable.ic_twitter, "https://twitter.com/tangem"),
|
||||
TangemLink(R.drawable.ic_facebook, "https://m.facebook.com/TangemCards/"),
|
||||
TangemLink(R.drawable.ic_instagram, "https://instagram.com/tangemcards"),
|
||||
TangemLink(R.drawable.ic_github, "https://github.com/tangem"),
|
||||
TangemLink(R.drawable.ic_youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"),
|
||||
TangemLink(R.drawable.ic_linkedin, "https://www.linkedin.com/company/tangem"),
|
||||
val accountsEn: List<SocialNetworkLink> = listOf(
|
||||
SocialNetworkLink(SocialNetwork.Telegram, "https://t.me/TangemCards"),
|
||||
SocialNetworkLink(SocialNetwork.Twitter, "https://twitter.com/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"),
|
||||
SocialNetworkLink(SocialNetwork.Instagram, "https://instagram.com/tangemcards"),
|
||||
SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"),
|
||||
SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"),
|
||||
)
|
||||
val accountsRu: List<TangemLink> = listOf(
|
||||
TangemLink(R.drawable.ic_telegram, "https://t.me/tangem_ru"),
|
||||
TangemLink(R.drawable.ic_twitter, "https://twitter.com/tangem"),
|
||||
TangemLink(R.drawable.ic_facebook, "https://m.facebook.com/TangemCards/"),
|
||||
TangemLink(R.drawable.ic_instagram, "https://instagram.com/tangemcards"),
|
||||
TangemLink(R.drawable.ic_github, "https://github.com/tangem"),
|
||||
TangemLink(R.drawable.ic_youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"),
|
||||
TangemLink(R.drawable.ic_linkedin, "https://www.linkedin.com/company/tangem"),
|
||||
val accountsRu: List<SocialNetworkLink> = listOf(
|
||||
SocialNetworkLink(SocialNetwork.Telegram, "https://t.me/tangem_ru"),
|
||||
SocialNetworkLink(SocialNetwork.Twitter, "https://twitter.com/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"),
|
||||
SocialNetworkLink(SocialNetwork.Instagram, "https://instagram.com/tangemcards"),
|
||||
SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"),
|
||||
SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"),
|
||||
)
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.tangem.tap.features.details.ui.details
|
|||
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.feedback.FeedbackEmail
|
||||
import com.tangem.tap.common.feedback.SupportInfo
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -51,8 +53,9 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
)
|
||||
}
|
||||
|
||||
private fun handleSocialNetworkClick(url: String) {
|
||||
store.dispatch(NavigationAction.OpenUrl(url))
|
||||
private fun handleSocialNetworkClick(link: SocialNetworkLink) {
|
||||
Analytics.send(Settings.ButtonSocialNetwork(link.network))
|
||||
store.dispatch(NavigationAction.OpenUrl(link.url))
|
||||
}
|
||||
|
||||
private fun handleClickingSettingsItem(item: SettingsElement) {
|
||||
|
|
@ -61,21 +64,26 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions))
|
||||
}
|
||||
SettingsElement.Chat -> {
|
||||
Analytics.send(Settings.ButtonChat())
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
}
|
||||
SettingsElement.SendFeedback -> {
|
||||
Analytics.send(Settings.ButtonSendFeedback())
|
||||
store.dispatch(GlobalAction.SendEmail(FeedbackEmail()))
|
||||
}
|
||||
SettingsElement.CardSettings -> {
|
||||
Analytics.send(Settings.ButtonCardSettings())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CardSettings))
|
||||
}
|
||||
SettingsElement.AppCurrency -> {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
}
|
||||
SettingsElement.AppSettings -> {
|
||||
Analytics.send(Settings.ButtonAppSettings())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.AppSettings)) //TODO: To be available later
|
||||
}
|
||||
SettingsElement.LinkMoreCards -> {
|
||||
Analytics.send(Settings.ButtonCreateBackup())
|
||||
store.dispatch(DetailsAction.CreateBackup)
|
||||
}
|
||||
SettingsElement.TermsOfService -> {
|
||||
|
|
@ -90,7 +98,7 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getSocialLinks(): List<TangemLink> {
|
||||
private fun getSocialLinks(): List<SocialNetworkLink> {
|
||||
val locale = LocaleRegionProvider().getRegion()
|
||||
return if (locale.lowercase() == RUSSIA_COUNTRY_CODE) {
|
||||
TangemSocialAccounts.accountsRu
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.compose.TangemTypography
|
||||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
|
||||
|
|
@ -53,7 +55,12 @@ fun WalletConnectScreen(
|
|||
},
|
||||
fab = {
|
||||
if (!state.isLoading) {
|
||||
AddSessionFab(onAddSession = { state.onAddSession(context.getFromClipboard()?.toString()) })
|
||||
AddSessionFab(
|
||||
onAddSession = {
|
||||
Analytics.send(Settings.ButtonStartWalletConnectSession())
|
||||
state.onAddSession(context.getFromClipboard()?.toString())
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
titleRes = R.string.wallet_connect_title,
|
||||
|
|
@ -147,7 +154,10 @@ private fun WalletConnectSessions(
|
|||
modifier = modifier.weight(1f),
|
||||
)
|
||||
IconButton(
|
||||
onClick = { state.onRemoveSession(session.sessionId) },
|
||||
onClick = {
|
||||
Analytics.send(Settings.ButtonStopWalletConnectSession())
|
||||
state.onRemoveSession(session.sessionId)
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_cross_rounded_24),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import androidx.compose.ui.platform.ComposeView
|
|||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.home.compose.StoriesScreen
|
||||
|
|
@ -28,6 +30,7 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Analytics.send(IntroductionProcess.ScreenOpened())
|
||||
store.dispatch(HomeAction.Init)
|
||||
}
|
||||
|
||||
|
|
@ -81,9 +84,16 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
|
|||
private fun ScreenContent() {
|
||||
StoriesScreen(
|
||||
homeState,
|
||||
onScanButtonClick = { store.dispatch(HomeAction.ReadCard) },
|
||||
onShopButtonClick = { store.dispatch(HomeAction.GoToShop(store.state.globalState.userCountryCode)) },
|
||||
onScanButtonClick = {
|
||||
Analytics.send(IntroductionProcess.ButtonScanCard())
|
||||
store.dispatch(HomeAction.ReadCard)
|
||||
},
|
||||
onShopButtonClick = {
|
||||
Analytics.send(IntroductionProcess.ButtonBuyCards())
|
||||
store.dispatch(HomeAction.GoToShop(store.state.globalState.userCountryCode))
|
||||
},
|
||||
onSearchTokensClick = {
|
||||
Analytics.send(IntroductionProcess.ButtonTokensList())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens))
|
||||
store.dispatch(TokensAction.AllowToAddTokens(false))
|
||||
store.dispatch(TokensAction.LoadCurrencies())
|
||||
|
|
|
|||
|
|
@ -9,10 +9,9 @@ import com.tangem.domain.common.extensions.withMainContext
|
|||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.backupService
|
||||
import com.tangem.tap.common.analytics.AnalyticsEventAnOld
|
||||
import com.tangem.tap.common.analytics.AnalyticsParamAnOld
|
||||
import com.tangem.tap.common.analytics.GetCardSourceParamsAnOld
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor
|
||||
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
|
|
@ -105,10 +104,6 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
|
|||
RUSSIA_COUNTRY_CODE, BELARUS_COUNTRY_CODE -> store.dispatchOpenUrl(BUY_WALLET_URL)
|
||||
else -> store.dispatch(NavigationAction.NavigateTo(AppScreen.Shop))
|
||||
}
|
||||
store.state.globalState.analyticsHandler.handleAnalyticsEvent(
|
||||
event = AnalyticsEventAnOld.GET_CARD,
|
||||
params = mapOf(AnalyticsParamAnOld.SOURCE.param to GetCardSourceParamsAnOld.WELCOME.param),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -158,11 +153,12 @@ private fun showDisclaimerIfNeed(scanResponse: ScanResponse, nextHandler: (ScanR
|
|||
}
|
||||
|
||||
private fun onScanSuccess(scanResponse: ScanResponse) {
|
||||
Analytics.send(IntroductionProcess.CardWasScanned())
|
||||
val globalState = store.state.globalState
|
||||
val tapWalletManager = globalState.tapWalletManager
|
||||
tapWalletManager.updateConfigManager(scanResponse)
|
||||
|
||||
globalState.analyticsHandler.attachToAllEvents(AnalyticsParam.BatchId, scanResponse.card.batchId)
|
||||
Analytics.addParamsInterceptor(BatchIdParamsInterceptor(scanResponse.card.batchId))
|
||||
|
||||
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
|
||||
|
||||
|
|
@ -178,7 +174,7 @@ private fun onScanSuccess(scanResponse: ScanResponse) {
|
|||
val isOnboardingCase = result.data
|
||||
if (isOnboardingCase) {
|
||||
store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false))
|
||||
store.dispatch(OnboardingSaltPayAction.Init.SetDependencies(manager, config))
|
||||
store.dispatch(OnboardingSaltPayAction.SetDependencies(manager, config))
|
||||
store.dispatch(OnboardingSaltPayAction.Update)
|
||||
navigateTo(AppScreen.OnboardingWallet)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.common.extensions.dispatchShare
|
||||
|
|
@ -21,7 +23,7 @@ import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding
|
|||
*/
|
||||
class AddressInfoBottomSheetDialog(
|
||||
private val stateDialog: AppDialog.AddressInfoDialog,
|
||||
context: Context
|
||||
context: Context,
|
||||
) : BottomSheetDialog(context) {
|
||||
|
||||
var binding: DialogOnboardingAddressInfoBinding? = null
|
||||
|
|
@ -40,6 +42,7 @@ class AddressInfoBottomSheetDialog(
|
|||
|
||||
override fun show() {
|
||||
super.show()
|
||||
Analytics.send(Token.Recieve.ScreenOpened())
|
||||
showData(data = stateDialog.addressData)
|
||||
}
|
||||
|
||||
|
|
@ -51,10 +54,12 @@ class AddressInfoBottomSheetDialog(
|
|||
imvQrCode.setImageBitmap(data.qrCode)
|
||||
tvAddress.text = data.address
|
||||
btnFlCopyAddress.setOnClickListener {
|
||||
Analytics.send(Token.Recieve.ButtonCopyAddress())
|
||||
context.copyToClipboard(data.address)
|
||||
store.dispatchToastNotification(R.string.copy_toast_msg)
|
||||
}
|
||||
btnFlShare.setOnClickListener {
|
||||
Analytics.send(Token.Recieve.ButtonShareAddress())
|
||||
store.dispatchShare(data.shareUrl)
|
||||
}
|
||||
tvReceiveMessage.text = getQRReceiveMessage(tvReceiveMessage.context, stateDialog.currency)
|
||||
|
|
@ -67,7 +72,7 @@ fun getQRReceiveMessage(context: Context, currency: Currency): String {
|
|||
context.getString(
|
||||
R.string.address_qr_code_message_format,
|
||||
currency.blockchain.fullName,
|
||||
currency.currencySymbol
|
||||
currency.currencySymbol,
|
||||
)
|
||||
}
|
||||
is Currency.Token -> {
|
||||
|
|
@ -75,7 +80,7 @@ fun getQRReceiveMessage(context: Context, currency: Currency): String {
|
|||
R.string.address_qr_code_message_token_format,
|
||||
currency.token.name,
|
||||
currency.currencySymbol,
|
||||
currency.blockchain.fullName
|
||||
currency.blockchain.fullName,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,15 +14,16 @@ class OnboardingHelper {
|
|||
|
||||
fun isOnboardingCase(response: ScanResponse): Boolean {
|
||||
val cardInfoStorage = preferencesStorage.usedCardsPrefStorage
|
||||
val cardId = response.card.cardId
|
||||
return when {
|
||||
response.isTangemTwins() -> {
|
||||
if (!response.twinsIsTwinned()) {
|
||||
true
|
||||
} else {
|
||||
cardInfoStorage.activationIsStarted(response.card.cardId)
|
||||
cardInfoStorage.isActivationInProgress(cardId)
|
||||
}
|
||||
}
|
||||
response.card.hasWallets() -> cardInfoStorage.activationIsStarted(response.card.cardId)
|
||||
response.card.hasWallets() -> cardInfoStorage.isActivationInProgress(cardId)
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,10 @@ class OnboardingManager(
|
|||
}
|
||||
}
|
||||
|
||||
return balance.copy(currency = Currency.Blockchain(
|
||||
walletManager.wallet.blockchain, walletManager.wallet.publicKey.derivationPath?.rawPath)
|
||||
return balance.copy(
|
||||
currency = Currency.Blockchain(
|
||||
walletManager.wallet.blockchain, walletManager.wallet.publicKey.derivationPath?.rawPath,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +81,14 @@ class OnboardingManager(
|
|||
fun activationFinished(cardId: String) {
|
||||
usedCardsPrefStorage.activationFinished(cardId)
|
||||
}
|
||||
|
||||
fun isActivationFinished(cardId: String): Boolean {
|
||||
return usedCardsPrefStorage.isActivationFinished(cardId)
|
||||
}
|
||||
|
||||
fun isActivationStarted(cardId: String): Boolean {
|
||||
return usedCardsPrefStorage.isActivationStarted(cardId)
|
||||
}
|
||||
}
|
||||
|
||||
data class OnboardingWalletBalance(
|
||||
|
|
@ -98,23 +108,23 @@ data class OnboardingWalletBalance(
|
|||
companion object {
|
||||
fun error(error: TapError): OnboardingWalletBalance = OnboardingWalletBalance(
|
||||
state = ProgressState.Error,
|
||||
error = error
|
||||
error = error,
|
||||
)
|
||||
|
||||
fun criticalError(error: TapError): OnboardingWalletBalance = OnboardingWalletBalance(
|
||||
state = ProgressState.Error,
|
||||
criticalError = error
|
||||
criticalError = error,
|
||||
)
|
||||
|
||||
fun loading(value: BigDecimal = BigDecimal.ZERO): OnboardingWalletBalance = OnboardingWalletBalance(
|
||||
value,
|
||||
state = ProgressState.Loading
|
||||
state = ProgressState.Loading,
|
||||
)
|
||||
|
||||
fun done(value: BigDecimal, hasTransactions: Boolean): OnboardingWalletBalance = OnboardingWalletBalance(
|
||||
value,
|
||||
hasIncomingTransaction = hasTransactions,
|
||||
state = ProgressState.Done
|
||||
state = ProgressState.Done,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import androidx.core.view.isVisible
|
|||
import androidx.transition.TransitionManager
|
||||
import coil.load
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
|
|
@ -41,6 +43,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
binding.toolbar.setTitle(R.string.onboarding_title)
|
||||
btnRefreshBalanceWidget = RefreshBalanceWidget(mainBinding.onboardingTopContainer.onboardingWalletContainer)
|
||||
|
||||
store.dispatch(OnboardingNoteAction.Init)
|
||||
store.dispatch(OnboardingNoteAction.LoadCardArtwork)
|
||||
store.dispatch(OnboardingNoteAction.DetermineStepOfScreen)
|
||||
}
|
||||
|
|
@ -108,7 +111,10 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
private fun setupCreateWalletState(state: OnboardingNoteState) =
|
||||
with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
|
||||
btnMainAction.setOnClickListener { store.dispatch(OnboardingNoteAction.CreateWallet) }
|
||||
btnMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(OnboardingNoteAction.CreateWallet)
|
||||
}
|
||||
btnAlternativeAction.setText(R.string.onboarding_button_what_does_it_mean)
|
||||
btnAlternativeAction.setOnClickListener { }
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import org.rekotlin.Action
|
|||
*/
|
||||
sealed class OnboardingNoteAction : Action {
|
||||
// from user, ui
|
||||
object Init : OnboardingNoteAction()
|
||||
object LoadCardArtwork : OnboardingNoteAction()
|
||||
object CreateWallet : OnboardingNoteAction()
|
||||
object TopUp : OnboardingNoteAction()
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.common.extensions.getAddressData
|
||||
import com.tangem.tap.common.extensions.getToUpUrl
|
||||
import com.tangem.tap.common.extensions.getTopUpUrl
|
||||
import com.tangem.tap.common.extensions.onCardScanned
|
||||
import com.tangem.tap.common.postUi
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
|
|
@ -25,6 +29,8 @@ import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
|||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
|
|
@ -61,6 +67,11 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
val noteState = store.state.onboardingNoteState
|
||||
|
||||
when (action) {
|
||||
is OnboardingNoteAction.Init -> {
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
is OnboardingNoteAction.LoadCardArtwork -> {
|
||||
scope.launch {
|
||||
val artworkUrl = onboardingManager.loadArtworkUrl()
|
||||
|
|
@ -77,10 +88,15 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
}
|
||||
is OnboardingNoteAction.SetStepOfScreen -> {
|
||||
when (action.step) {
|
||||
OnboardingNoteStep.CreateWallet -> {
|
||||
Analytics.send(Onboarding.CreateWallet.ScreenOpened())
|
||||
}
|
||||
OnboardingNoteStep.TopUpWallet -> {
|
||||
Analytics.send(Onboarding.Topup.ScreenOpened())
|
||||
store.dispatch(OnboardingNoteAction.Balance.Update)
|
||||
}
|
||||
OnboardingNoteStep.Done -> {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(DELAY_SDK_DIALOG_CLOSE) { store.dispatch(OnboardingNoteAction.Confetti.Show) }
|
||||
}
|
||||
|
|
@ -92,6 +108,7 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
withMainContext {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
val updatedResponse = scanResponse.copy(card = result.data.card)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
onboardingManager.activationStarted(updatedResponse.card.cardId)
|
||||
|
|
@ -150,15 +167,27 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
is OnboardingNoteAction.ShowAddressInfoDialog -> {
|
||||
val addressData = noteState.walletManager?.getAddressData() ?: return
|
||||
|
||||
Analytics.send(Onboarding.Topup.ButtonShowWalletAddress())
|
||||
val appDialog = AppDialog.AddressInfoDialog(noteState.walletBalance.currency, addressData)
|
||||
store.dispatchDialogShow(appDialog)
|
||||
}
|
||||
is OnboardingNoteAction.TopUp -> {
|
||||
val topUpUrl = noteState.walletManager?.getToUpUrl() ?: return
|
||||
if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) {
|
||||
store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(topUpUrl))
|
||||
val walletManager = noteState.walletManager.guard {
|
||||
store.dispatchDebugErrorNotification("NPE: WalletManager")
|
||||
return
|
||||
}
|
||||
|
||||
val topUpUrl = walletManager.getTopUpUrl() ?: return
|
||||
val blockchain = walletManager.wallet.blockchain
|
||||
if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) {
|
||||
val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl, blockchain)
|
||||
store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData))
|
||||
return
|
||||
}
|
||||
|
||||
val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain)
|
||||
Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType))
|
||||
|
||||
store.dispatchOpenUrl(topUpUrl)
|
||||
}
|
||||
OnboardingNoteAction.Done -> {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import androidx.constraintlayout.widget.ConstraintSet
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import coil.load
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||
|
|
@ -33,6 +35,7 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
mainBinding.onboardingTopContainer.imvFrontCard.transitionName = ShareElement.imvFrontCard
|
||||
|
||||
binding.toolbar.setTitle(R.string.onboarding_title)
|
||||
store.dispatch(OnboardingOtherCardsAction.Init)
|
||||
store.dispatch(OnboardingOtherCardsAction.LoadCardArtwork)
|
||||
store.dispatch(OnboardingOtherCardsAction.DetermineStepOfScreen)
|
||||
}
|
||||
|
|
@ -68,7 +71,10 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
|
||||
private fun setupCreateWalletState() = with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
|
||||
btnMainAction.setOnClickListener { store.dispatch(OnboardingOtherCardsAction.CreateWallet) }
|
||||
btnMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(OnboardingOtherCardsAction.CreateWallet)
|
||||
}
|
||||
btnAlternativeAction.setText(R.string.onboarding_button_what_does_it_mean)
|
||||
btnAlternativeAction.setOnClickListener { }
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.rekotlin.Action
|
|||
*/
|
||||
sealed class OnboardingOtherCardsAction : Action {
|
||||
// from user, ui
|
||||
object Init : OnboardingOtherCardsAction()
|
||||
object LoadCardArtwork : OnboardingOtherCardsAction()
|
||||
object CreateWallet : OnboardingOtherCardsAction()
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.onCardScanned
|
||||
import com.tangem.tap.common.postUi
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -45,6 +47,11 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
|
|||
val card = onboardingManager.scanResponse.card
|
||||
|
||||
when (action) {
|
||||
is OnboardingOtherCardsAction.Init -> {
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
is OnboardingOtherCardsAction.LoadCardArtwork -> {
|
||||
scope.launch {
|
||||
val artworkUrl = onboardingManager.loadArtworkUrl()
|
||||
|
|
@ -59,9 +66,15 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
|
|||
store.dispatch((OnboardingOtherCardsAction.SetStepOfScreen(step)))
|
||||
}
|
||||
is OnboardingOtherCardsAction.SetStepOfScreen -> {
|
||||
if (action.step == OnboardingOtherCardsStep.Done) {
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
|
||||
when (action.step) {
|
||||
OnboardingOtherCardsStep.CreateWallet -> {
|
||||
Analytics.send(Onboarding.CreateWallet.ScreenOpened())
|
||||
}
|
||||
OnboardingOtherCardsStep.Done -> {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
|
||||
}
|
||||
}
|
||||
}
|
||||
is OnboardingOtherCardsAction.CreateWallet -> {
|
||||
|
|
@ -70,8 +83,9 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
|
|||
withMainContext {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
val updatedResponse = onboardingManager.scanResponse.copy(
|
||||
card = result.data.card
|
||||
card = result.data.card,
|
||||
)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
onboardingManager.activationStarted(updatedResponse.card.cardId)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
package com.tangem.tap.features.onboarding.products.twins.redux
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.common.extensions.getAddressData
|
||||
import com.tangem.tap.common.extensions.getToUpUrl
|
||||
import com.tangem.tap.common.extensions.getTopUpUrl
|
||||
import com.tangem.tap.common.extensions.onCardScanned
|
||||
import com.tangem.tap.common.postUi
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
|
|
@ -76,6 +80,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
|
||||
fun finishCardActivation() {
|
||||
if (twinCardsState.mode == CreateTwinWalletMode.CreateWallet) {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
onboardingManager?.activationFinished(getScanResponse().card.cardId)
|
||||
twinCardsState.pairCardId?.let { onboardingManager?.activationFinished(it) }
|
||||
}
|
||||
|
|
@ -85,11 +90,21 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
is TwinCardsAction.Init -> {
|
||||
if (twinCardsState.currentStep == TwinCardsStep.WelcomeOnly) return
|
||||
|
||||
val scanResponse = getScanResponse()
|
||||
onboardingManager?.apply {
|
||||
if (!isActivationStarted(scanResponse.card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
|
||||
when (twinCardsState.mode) {
|
||||
CreateTwinWalletMode.CreateWallet -> {
|
||||
if (preferencesStorage.wasTwinsOnboardingShown()) {
|
||||
val step = when {
|
||||
!getScanResponse().twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet
|
||||
!scanResponse.twinsIsTwinned() -> {
|
||||
Analytics.send(Onboarding.CreateWallet.ScreenOpened())
|
||||
TwinCardsStep.CreateFirstWallet
|
||||
}
|
||||
twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done
|
||||
else -> TwinCardsStep.TopUpWallet
|
||||
}
|
||||
|
|
@ -105,8 +120,8 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
is TwinCardsAction.Wallet.HandleOnBackPressed -> {
|
||||
val shouldReturnCardBack = twinCardsState.mode == CreateTwinWalletMode.CreateWallet
|
||||
&& twinCardsState.currentStep != TwinCardsStep.TopUpWallet
|
||||
&& twinCardsState.currentStep != TwinCardsStep.Done
|
||||
&& twinCardsState.currentStep != TwinCardsStep.TopUpWallet
|
||||
&& twinCardsState.currentStep != TwinCardsStep.Done
|
||||
|
||||
if (twinCardsState.showAlert) {
|
||||
val onInterruptPrompt = {
|
||||
|
|
@ -126,8 +141,10 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
is TwinCardsAction.SetStepOfScreen -> {
|
||||
when (action.step) {
|
||||
TwinCardsStep.WelcomeOnly -> preferencesStorage.saveTwinsOnboardingShown()
|
||||
TwinCardsStep.Welcome -> preferencesStorage.saveTwinsOnboardingShown()
|
||||
TwinCardsStep.WelcomeOnly, TwinCardsStep.Welcome -> {
|
||||
Analytics.send(Onboarding.Twins.ScreenOpened())
|
||||
preferencesStorage.saveTwinsOnboardingShown()
|
||||
}
|
||||
TwinCardsStep.TopUpWallet -> store.dispatch(TwinCardsAction.Balance.Update)
|
||||
TwinCardsStep.Done -> {
|
||||
finishCardActivation()
|
||||
|
|
@ -136,16 +153,17 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
}
|
||||
is TwinCardsAction.Wallet.LaunchFirstStep -> {
|
||||
Analytics.send(Onboarding.Twins.SetupStarted())
|
||||
val manager = TwinCardsManager(
|
||||
card = getScanResponse().card,
|
||||
assetReader = action.reader,
|
||||
analyticsHandler = store.state.globalState.analyticsHandler
|
||||
)
|
||||
store.dispatch(TwinCardsAction.CardsManager.Set(manager))
|
||||
|
||||
scope.launch {
|
||||
when (val result = manager.createFirstWallet(action.initialMessage)) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
startCardActivation(result.data.cardId)
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
withMainContext {
|
||||
|
|
@ -164,7 +182,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
val result = manager.createSecondWallet(
|
||||
action.initialMessage,
|
||||
action.preparingMessage,
|
||||
action.creatingWalletMessage
|
||||
action.creatingWalletMessage,
|
||||
)
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
|
|
@ -186,6 +204,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
scope.launch {
|
||||
when (val result = manager.complete(action.message)) {
|
||||
is Result.Success -> {
|
||||
Analytics.send(Onboarding.Twins.SetupFinished())
|
||||
updateScanResponse(result.data)
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
withMainContext {
|
||||
|
|
@ -222,11 +241,11 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
val balanceIsLoading = twinCardsState.walletBalance.copy(
|
||||
currency = Currency.Blockchain(
|
||||
walletManager.wallet.blockchain,
|
||||
walletManager.wallet.publicKey.derivationPath?.rawPath
|
||||
walletManager.wallet.publicKey.derivationPath?.rawPath,
|
||||
),
|
||||
state = ProgressState.Loading,
|
||||
error = null,
|
||||
criticalError = null
|
||||
criticalError = null,
|
||||
)
|
||||
store.dispatch(TwinCardsAction.Balance.Set(balanceIsLoading))
|
||||
|
||||
|
|
@ -240,7 +259,6 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
store.dispatch(TwinCardsAction.Balance.SetNonCriticalError(loadedBalance.error))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
is TwinCardsAction.Balance.Set -> {
|
||||
if (action.balance.balanceIsToppedUp()) {
|
||||
|
|
@ -256,7 +274,11 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
store.dispatchDialogShow(appDialog)
|
||||
}
|
||||
is TwinCardsAction.TopUp -> {
|
||||
val topUpUrl = twinCardsState.walletManager?.getToUpUrl() ?: return
|
||||
val topUpUrl = twinCardsState.walletManager?.getTopUpUrl() ?: return
|
||||
|
||||
val currencyType = AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin)
|
||||
Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType))
|
||||
|
||||
store.dispatchOpenUrl(topUpUrl)
|
||||
}
|
||||
TwinCardsAction.Done -> {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import com.tangem.common.extensions.VoidCallback
|
|||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.tap.common.AndroidAssetReader
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
|
|
@ -238,6 +240,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
|
||||
btnMainAction.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
|
||||
btnMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(
|
||||
TwinCardsAction.Wallet.LaunchFirstStep(
|
||||
Message(getString(R.string.twins_recreate_title_format, twinIndexNumber)),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import org.rekotlin.Action
|
|||
|
||||
sealed class OnboardingWalletAction : Action {
|
||||
object Init : OnboardingWalletAction()
|
||||
object StartSaltPayCardActivation : OnboardingWalletAction()
|
||||
object GetToCreateWalletStep : OnboardingWalletAction()
|
||||
object GetToSaltPayStep : OnboardingWalletAction()
|
||||
object CreateWallet : OnboardingWalletAction()
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.extensions.ifNotNull
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.tap.backupService
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.primaryCardIsSaltPayVisa
|
||||
|
|
@ -61,6 +65,12 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
|
||||
when (action) {
|
||||
OnboardingWalletAction.Init -> {
|
||||
ifNotNull(onboardingManager, card) { manager, card ->
|
||||
if (!card.isSaltPay && !manager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
card == null -> {
|
||||
// it's possible when found unfinished backup for standard Wallet cards
|
||||
|
|
@ -84,16 +94,10 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
}
|
||||
else -> {
|
||||
store.dispatch(OnboardingWalletAction.GetToCreateWalletStep)
|
||||
Analytics.send(Onboarding.CreateWallet.ScreenOpened())
|
||||
}
|
||||
}
|
||||
}
|
||||
is OnboardingWalletAction.StartSaltPayCardActivation -> {
|
||||
// we need to do this because the standard activation happens in the OnboardingWalletAction.CreateWallet
|
||||
// step which is omitted for SaltPay cards
|
||||
if (onboardingWalletState.isSaltPay && scanResponse != null) {
|
||||
startCardActivation(scanResponse)
|
||||
}
|
||||
}
|
||||
is OnboardingWalletAction.LoadArtwork -> {
|
||||
scope.launch {
|
||||
val artwork = onboardingManager?.loadArtworkUrl()
|
||||
|
|
@ -112,6 +116,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
withMainContext {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||
//here we must use updated scanResponse after createWallet & derivation
|
||||
val updatedResponse = globalState.onboardingState.onboardingManager.scanResponse.copy(
|
||||
card = result.data.card,
|
||||
|
|
@ -148,9 +153,6 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
} else {
|
||||
val backupState = store.state.onboardingWalletState.backupState
|
||||
val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState)
|
||||
if (onboardingWalletState.isSaltPay) {
|
||||
finishCardActivation(backupState, scanResponse.card)
|
||||
}
|
||||
scope.launch { globalState.tapWalletManager.onCardScanned(updatedScanResponse) }
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
}
|
||||
|
|
@ -166,6 +168,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
if (onboardingWalletState.isSaltPay) {
|
||||
BackupAction.StartBackup
|
||||
} else {
|
||||
Analytics.send(Onboarding.Backup.ScreenOpened())
|
||||
BackupAction.IntroduceBackup
|
||||
}
|
||||
} else {
|
||||
|
|
@ -221,6 +224,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
|
||||
when (action) {
|
||||
is BackupAction.StartBackup -> {
|
||||
Analytics.send(Onboarding.Backup.Started())
|
||||
backupService.discardSavedBackup()
|
||||
val primaryCard = scanResponse?.primaryCard
|
||||
if (primaryCard != null) {
|
||||
|
|
@ -266,7 +270,11 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
store.dispatchOnMain(GlobalAction.ShowDialog(BackupDialog.AddMoreBackupCards))
|
||||
}
|
||||
}
|
||||
is BackupAction.ShowEnterAccessCodeScreen -> {
|
||||
Analytics.send(Onboarding.Backup.SettingAccessCodeStarted())
|
||||
}
|
||||
is BackupAction.CheckAccessCode -> {
|
||||
Analytics.send(Onboarding.Backup.AccessCodeEntered())
|
||||
if (action.accessCode.length < 4) {
|
||||
store.dispatch(BackupAction.SetAccessCodeError(AccessCodeError.CodeTooShort))
|
||||
} else {
|
||||
|
|
@ -275,6 +283,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
}
|
||||
}
|
||||
is BackupAction.SaveAccessCodeConfirmation -> {
|
||||
Analytics.send(Onboarding.Backup.AccessCodeReEntered())
|
||||
if (action.accessCodeConfirmation == backupState.accessCode) {
|
||||
store.dispatch(BackupAction.SetAccessCodeError(null))
|
||||
backupService.setAccessCode(action.accessCodeConfirmation)
|
||||
|
|
@ -312,7 +321,9 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
}
|
||||
}
|
||||
is BackupAction.FinishBackup -> {
|
||||
Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber))
|
||||
if (!onboardingWalletState.isSaltPay) {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
finishCardActivation(backupState, card)
|
||||
}
|
||||
}
|
||||
|
|
@ -320,7 +331,10 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
backupService.discardSavedBackup()
|
||||
}
|
||||
is BackupAction.DiscardSavedBackup -> {
|
||||
backupService.primaryCardId?.let { finishCardsActivationForDiscardedUnfinishedBackup(it) }
|
||||
backupService.primaryCardId?.let {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
finishCardsActivationForDiscardedUnfinishedBackup(it)
|
||||
}
|
||||
backupService.discardSavedBackup()
|
||||
}
|
||||
is BackupAction.CheckForUnfinishedBackup -> {
|
||||
|
|
@ -333,6 +347,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet))
|
||||
}
|
||||
is BackupAction.DismissBackup -> {
|
||||
Analytics.send(Onboarding.Backup.Skipped())
|
||||
if (onboardingWalletState.isSaltPay) throw UnsupportedOperationException()
|
||||
store.dispatch(BackupAction.FinishBackup)
|
||||
}
|
||||
|
|
@ -351,7 +366,7 @@ private fun startCardActivation(scanResponse: ScanResponse) {
|
|||
* Standard Wallet cards finish activation at BackupAction.FinishBackup
|
||||
* SaltPay cards finish activation at OnboardingWalletAction.FinishOnboarding
|
||||
*/
|
||||
private fun finishCardActivation(backupState: BackupState, card: Card?) {
|
||||
internal fun finishCardActivation(backupState: BackupState, card: Card?) {
|
||||
(listOf(backupState.primaryCardId, card?.cardId) + backupState.backupCardIds)
|
||||
.distinct().filterNotNull()
|
||||
.forEach { cardId ->
|
||||
|
|
@ -377,7 +392,7 @@ private fun initSaltPayOnBackupFinishedIfNeeded(
|
|||
if (scanResponse == null) throw IllegalArgumentException()
|
||||
|
||||
val (manager, config) = OnboardingSaltPayState.initDependency(scanResponse)
|
||||
store.dispatchOnMain(OnboardingSaltPayAction.Init.SetDependencies(manager, config))
|
||||
store.dispatchOnMain(OnboardingSaltPayAction.SetDependencies(manager, config))
|
||||
store.dispatchOnMain(OnboardingSaltPayAction.Update)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import java.math.BigDecimal
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
sealed class OnboardingSaltPayAction : Action {
|
||||
sealed class Init : OnboardingSaltPayAction() {
|
||||
data class SetDependencies(
|
||||
val registrationManager: SaltPayActivationManager,
|
||||
val saltPayConfig: SaltPayConfig,
|
||||
) : Init()
|
||||
}
|
||||
object Init : OnboardingSaltPayAction()
|
||||
|
||||
data class SetDependencies(
|
||||
val registrationManager: SaltPayActivationManager,
|
||||
val saltPayConfig: SaltPayConfig,
|
||||
) : OnboardingSaltPayAction()
|
||||
|
||||
data class SetInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction()
|
||||
data class SetClaimRefreshInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction()
|
||||
|
|
|
|||
|
|
@ -10,15 +10,18 @@ import com.tangem.domain.common.extensions.successOr
|
|||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.network.api.paymentology.KYCStatus
|
||||
import com.tangem.network.api.paymentology.RegistrationResponse
|
||||
import com.tangem.tap.common.analytics.GlobalAnalyticsEventHandler
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.isPositive
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TangemSigner
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.features.onboarding.OnboardingManager
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.finishCardActivation
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.AllSymbolsTheSameFilter
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler
|
||||
|
|
@ -58,10 +61,23 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
|
||||
fun getAppState(): AppState = appState()!!
|
||||
fun getOnboardingWalletState(): OnboardingWalletState = getAppState().onboardingWalletState
|
||||
fun getOnboardingManager(): OnboardingManager? = getAppState().globalState.onboardingState.onboardingManager
|
||||
fun getState(): OnboardingSaltPayState = getOnboardingWalletState().onboardingSaltPayState!!
|
||||
val analyticsHandler = getAppState().globalState.analyticsHandler
|
||||
|
||||
when (action) {
|
||||
is OnboardingSaltPayAction.Init -> {
|
||||
if (!getOnboardingWalletState().isSaltPay) return
|
||||
val onboardingManager = getOnboardingManager().guard {
|
||||
// onboardingManager may be null if it's started from standard Wallet unfinished backup
|
||||
return
|
||||
}
|
||||
|
||||
val card = onboardingManager.scanResponse.card
|
||||
if (!onboardingManager.isActivationStarted(card.cardId)) {
|
||||
Analytics.send(Onboarding.Started())
|
||||
onboardingManager.activationStarted(card.cardId)
|
||||
}
|
||||
}
|
||||
is OnboardingSaltPayAction.Update -> {
|
||||
handleInProgress = true
|
||||
|
||||
|
|
@ -77,8 +93,6 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
}
|
||||
is OnboardingSaltPayAction.RegisterCard -> {
|
||||
analyticsHandler.handleAnalyticsEvent(Onboarding.ButtonConnect())
|
||||
|
||||
handleInProgress = true
|
||||
val state = getState()
|
||||
|
||||
|
|
@ -151,7 +165,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
is OnboardingSaltPayAction.TrySetPin -> {
|
||||
try {
|
||||
assertPinValid(action.pin, getState().pinLength)
|
||||
analyticsHandler.handleAnalyticsEvent(Onboarding.PinCodeSet())
|
||||
Analytics.send(Onboarding.PinCodeSet())
|
||||
store.dispatch(OnboardingSaltPayAction.SetPin(action.pin))
|
||||
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.CardRegistration))
|
||||
} catch (error: SaltPayActivationError) {
|
||||
|
|
@ -159,7 +173,6 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
}
|
||||
is OnboardingSaltPayAction.Claim -> {
|
||||
analyticsHandler.handleAnalyticsEvent(Onboarding.ButtonClaim())
|
||||
val state = getState()
|
||||
handleInProgress = true
|
||||
|
||||
|
|
@ -192,7 +205,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
|
||||
handleInProgress = false
|
||||
analyticsHandler.handleAnalyticsEvent(Onboarding.ClaimWasSuccessfully())
|
||||
Analytics.send(Onboarding.ClaimWasSuccessfully())
|
||||
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimInProgress))
|
||||
dispatchOnMain(OnboardingSaltPayAction.RefreshClaim)
|
||||
}
|
||||
|
|
@ -233,23 +246,31 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
|
|||
}
|
||||
}
|
||||
}
|
||||
is OnboardingSaltPayAction.SetStep -> handleAnalytics(analyticsHandler, action.newStep)
|
||||
is OnboardingSaltPayAction.SetStep -> {
|
||||
when (action.newStep) {
|
||||
SaltPayActivationStep.KycStart -> Analytics.send(Onboarding.KYCStarted())
|
||||
SaltPayActivationStep.KycWaiting -> Analytics.send(Onboarding.KYCInProgress())
|
||||
SaltPayActivationStep.KycReject -> Analytics.send(Onboarding.KYCRejected())
|
||||
SaltPayActivationStep.Claim -> Analytics.send(Onboarding.ClaimScreenOpened())
|
||||
SaltPayActivationStep.ClaimSuccess, SaltPayActivationStep.Success -> {
|
||||
Analytics.send(Onboarding.Finished())
|
||||
val onboardingManager = getOnboardingManager().guard {
|
||||
// Null is possible if it is started from a standard pending backup and in this case
|
||||
// it is impossible to get here
|
||||
store.dispatchDebugErrorNotification("OnboardingManager can't be NULL")
|
||||
return
|
||||
}
|
||||
finishCardActivation(getOnboardingWalletState().backupState, onboardingManager.scanResponse.card)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
/* do nothing, only reduce */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAnalytics(analyticsHandler: GlobalAnalyticsEventHandler, step: SaltPayActivationStep) {
|
||||
when (step) {
|
||||
SaltPayActivationStep.KycStart -> analyticsHandler.handleAnalyticsEvent(Onboarding.KYCStarted())
|
||||
SaltPayActivationStep.KycWaiting -> analyticsHandler.handleAnalyticsEvent(Onboarding.KYCInProgress())
|
||||
SaltPayActivationStep.KycReject -> analyticsHandler.handleAnalyticsEvent(Onboarding.KYCRejected())
|
||||
SaltPayActivationStep.Claim -> analyticsHandler.handleAnalyticsEvent(Onboarding.ClaimScreenOpened())
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun SaltPayActivationManager.update(
|
||||
currentStep: SaltPayActivationStep,
|
||||
currentAmountToClaim: Amount?,
|
||||
|
|
@ -265,7 +286,7 @@ suspend fun SaltPayActivationManager.update(
|
|||
return Result.Failure(ex)
|
||||
}
|
||||
|
||||
checkGasIfNeeded(this, newStep).successOr { return it }
|
||||
// checkGasIfNeeded(this, newStep).successOr { return it }
|
||||
|
||||
Timber.d("update: success: %s", newStep)
|
||||
return Result.Success(newStep)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class OnboardingSaltPayReducer {
|
|||
private fun internalReduce(anyAction: Action, onboardingWalletState: OnboardingWalletState): OnboardingWalletState {
|
||||
val action = anyAction as? OnboardingSaltPayAction ?: return onboardingWalletState
|
||||
|
||||
if (onboardingWalletState.onboardingSaltPayState == null && action is OnboardingSaltPayAction.Init.SetDependencies) {
|
||||
if (onboardingWalletState.onboardingSaltPayState == null && action is OnboardingSaltPayAction.SetDependencies) {
|
||||
return onboardingWalletState.copy(
|
||||
onboardingSaltPayState = OnboardingSaltPayState(
|
||||
saltPayManager = action.registrationManager,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import coil.size.Scale
|
|||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.compose.PinCodeWidget
|
||||
import com.tangem.tap.common.extensions.configureSettings
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
|
|
@ -178,6 +180,7 @@ internal class OnboardingSaltPayView(
|
|||
showOnlyView(connectCard.root) {
|
||||
progressButton = SaltPayProgressButton(connectCard.root)
|
||||
connectCard.btnConnect.setOnClickListener {
|
||||
Analytics.send(Onboarding.ButtonConnect())
|
||||
store.dispatch(OnboardingSaltPayAction.RegisterCard)
|
||||
}
|
||||
}
|
||||
|
|
@ -286,6 +289,7 @@ internal class OnboardingSaltPayView(
|
|||
btnMain.text = getText(R.string.onboarding_button_claim)
|
||||
btnMain.isEnabled
|
||||
btnMain.setOnClickListener {
|
||||
Analytics.send(Onboarding.ButtonClaim())
|
||||
store.dispatch(OnboardingSaltPayAction.Claim)
|
||||
}
|
||||
progressButton = SaltPayProgressButton(actionContainer.root)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class WalletBackupAnimator(
|
|||
when (backupCardsCounts) {
|
||||
0 -> {
|
||||
when (currentStep) {
|
||||
STEP_CREATE_WALLET -> {
|
||||
UNDEFINED, STEP_CREATE_WALLET -> {
|
||||
cardsWidget.toFolded(false) { cardsWidget.toFan() }
|
||||
|
||||
FIRST_BACKUP.animateAlpha(0.6f, 0)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import com.tangem.common.CardIdFormatter
|
|||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.PropertyCalculator
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.inflate
|
||||
import com.tangem.tap.common.extensions.show
|
||||
|
|
@ -32,6 +34,7 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
|
|||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayView
|
||||
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -81,7 +84,7 @@ class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_walle
|
|||
addBackPressHandler(this)
|
||||
|
||||
store.dispatch(OnboardingWalletAction.Init)
|
||||
store.dispatch(OnboardingWalletAction.StartSaltPayCardActivation)
|
||||
store.dispatch(OnboardingSaltPayAction.Init)
|
||||
store.dispatch(OnboardingWalletAction.LoadArtwork)
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +173,10 @@ class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_walle
|
|||
|
||||
private fun setupCreateWalletState() = with(binding) {
|
||||
layoutButtonsCommon.btnWalletMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
|
||||
layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(OnboardingWalletAction.CreateWallet) }
|
||||
layoutButtonsCommon.btnWalletMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(OnboardingWalletAction.CreateWallet)
|
||||
}
|
||||
layoutButtonsCommon.btnWalletAlternativeAction.hide()
|
||||
|
||||
toolbar.title = getText(R.string.onboarding_getting_started)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ import com.tangem.common.services.Result
|
|||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.AnalyticsAnOld
|
||||
import com.tangem.tap.common.analytics.AnalyticsEventAnOld
|
||||
import com.tangem.tap.common.analytics.AnalyticsParamAnOld
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -219,13 +219,10 @@ private fun sendTransaction(
|
|||
dispatch(SendAction.ChangeSendButtonState(ButtonState.ENABLED))
|
||||
tangemSdk.config.linkedTerminal = isLinkedTerminal
|
||||
|
||||
val currencyType = AnalyticsParam.CurrencyType.Amount(amountToSend)
|
||||
when (sendResult) {
|
||||
is SimpleResult.Success -> {
|
||||
store.state.globalState.analyticsHandler?.handleAnalyticsEvent(
|
||||
event = AnalyticsEventAnOld.TRANSACTION_IS_SENT,
|
||||
card = card,
|
||||
blockchain = walletManager.wallet.blockchain.currency,
|
||||
)
|
||||
Analytics.send(Token.Send.TransactionSent(currencyType))
|
||||
dispatch(SendAction.SendSuccess)
|
||||
|
||||
if (externalTransactionData != null) {
|
||||
|
|
@ -250,15 +247,10 @@ private fun sendTransaction(
|
|||
feeAmount = feeAmount,
|
||||
destinationAddress = destinationAddress,
|
||||
)
|
||||
store.state.globalState.analyticsHandler?.handleBlockchainSdkErrorEvent(
|
||||
error = sendResult.error,
|
||||
action = AnalyticsAnOld.ActionToLog.SendTransaction,
|
||||
params = mapOf(AnalyticsParamAnOld.BLOCKCHAIN to walletManager.wallet.blockchain.currency),
|
||||
card = card,
|
||||
)
|
||||
|
||||
val error = (sendResult.error as? BlockchainSdkError) ?: return@withMainContext
|
||||
|
||||
Analytics.send(Token.Send.TransactionSent(currencyType, error))
|
||||
|
||||
when (error) {
|
||||
is BlockchainSdkError.WrappedTangemError -> {
|
||||
val tangemSdkError = (error.tangemError as? TangemSdkError) ?: return@withMainContext
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import com.google.android.material.textfield.TextInputEditText
|
|||
import com.tangem.Message
|
||||
import com.tangem.tangem_sdk_new.extensions.hideSoftKeyboard
|
||||
import com.tangem.tap.common.KeyboardObserver
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
import com.tangem.tap.common.extensions.setOnImeActionListener
|
||||
|
|
@ -28,10 +30,25 @@ import com.tangem.tap.common.toggleWidget.IndeterminateProgressButtonWidget
|
|||
import com.tangem.tap.common.toggleWidget.ViewStateWidget
|
||||
import com.tangem.tap.features.BaseStoreFragment
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi.*
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi.*
|
||||
import com.tangem.tap.features.send.redux.FeeActionUi.*
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi.CheckClipboard
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi.PasteAddressPayId
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi.SetTruncateHandler
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi.TruncateOrRestore
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi.CheckAmountToSend
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi.SetMainCurrency
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi.SetMaxAmount
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi.ToggleMainCurrency
|
||||
import com.tangem.tap.features.send.redux.FeeActionUi.ChangeIncludeFee
|
||||
import com.tangem.tap.features.send.redux.FeeActionUi.ChangeSelectedFee
|
||||
import com.tangem.tap.features.send.redux.FeeActionUi.ToggleControlsVisibility
|
||||
import com.tangem.tap.features.send.redux.ReceiptAction
|
||||
import com.tangem.tap.features.send.redux.ReleaseSendState
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.SendActionUi
|
||||
import com.tangem.tap.features.send.redux.TransactionExtrasAction
|
||||
import com.tangem.tap.features.send.redux.states.FeeType
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import com.tangem.tap.features.send.ui.stateSubscribers.SendStateSubscriber
|
||||
|
|
@ -43,7 +60,12 @@ import com.tangem.wallet.R
|
|||
import com.tangem.wallet.databinding.FragmentSendBinding
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import java.text.DecimalFormatSymbols
|
||||
|
||||
/**
|
||||
|
|
@ -61,6 +83,11 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
|
||||
val binding: FragmentSendBinding by viewBinding(FragmentSendBinding::bind)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Analytics.send(Token.Send.ScreenOpened())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
addBackPressHandler(this)
|
||||
|
|
@ -101,10 +128,12 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
.launchIn(mainScope)
|
||||
|
||||
imvPaste.setOnClickListener {
|
||||
Analytics.send(Token.Send.ButtonPaste())
|
||||
store.dispatch(PasteAddressPayId(requireContext().getFromClipboard()?.toString() ?: ""))
|
||||
store.dispatch(TruncateOrRestore(!etAddressOrPayId.isFocused))
|
||||
}
|
||||
imvQrCode.setOnClickListener {
|
||||
Analytics.send(Token.Send.ButtonQRCode())
|
||||
startActivityForResult(
|
||||
Intent(requireContext(), ScanQrCodeActivity::class.java),
|
||||
ScanQrCodeActivity.SCAN_QR_REQUEST_CODE
|
||||
|
|
@ -165,6 +194,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
store.dispatch(AmountAction.SetDecimalSeparator(decimalSeparator))
|
||||
|
||||
binding.lSendAmount.tvAmountCurrency.setOnClickListener {
|
||||
Analytics.send(Token.Send.ButtonSwapCurrency())
|
||||
store.dispatch(ToggleMainCurrency)
|
||||
store.dispatch(ReceiptAction.RefreshReceipt)
|
||||
store.dispatch(SendAction.ChangeSendButtonState(store.state.sendState.getButtonState()))
|
||||
|
|
|
|||
|
|
@ -119,13 +119,8 @@ private fun handle(action: Action) {
|
|||
|
||||
is ShopAction.FinishSuccessfulOrder -> {
|
||||
scope.launch {
|
||||
shopService.waitForCheckout(
|
||||
productType = shopState.selectedProduct,
|
||||
analyticsHandler = store.state.globalState.analyticsHandler
|
||||
)
|
||||
shopService.waitForCheckout(shopState.selectedProduct)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,8 @@ import androidx.activity.OnBackPressedCallback
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.tangem.tap.common.GlobalLayoutStateHandler
|
||||
import com.tangem.tap.common.KeyboardObserver
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.common.shop.data.ProductType
|
||||
|
|
@ -41,6 +43,8 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber<
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Analytics.send(Shop.ScreenOpened())
|
||||
|
||||
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import androidx.compose.ui.platform.ComposeView
|
|||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.domain.features.addCustomToken.redux.AddCustomTokenState
|
||||
import com.tangem.domain.redux.domainStore
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.compose.ClosePopupTrigger
|
||||
import com.tangem.tap.features.BaseStoreFragment
|
||||
import com.tangem.tap.features.FragmentOnBackPressedHandler
|
||||
|
|
@ -28,6 +30,11 @@ class AddCustomTokenFragment : BaseStoreFragment(R.layout.view_compose_fragment)
|
|||
|
||||
private var state: MutableState<AddCustomTokenState> = mutableStateOf(domainStore.state.addCustomTokensState)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Analytics.send(ManageTokens.CustomToken.ScreenOpened())
|
||||
}
|
||||
|
||||
override fun subscribeToStore() {
|
||||
domainStore.subscribe(this) { state ->
|
||||
state.skipRepeats { oldState, newState ->
|
||||
|
|
@ -45,30 +52,29 @@ class AddCustomTokenFragment : BaseStoreFragment(R.layout.view_compose_fragment)
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
view.findViewById<Toolbar>(R.id.toolbar)?.let {
|
||||
it.setTitle(R.string.add_custom_token_title)
|
||||
}
|
||||
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||
view.findViewById<Toolbar>(R.id.toolbar)?.setTitle(R.string.add_custom_token_title)
|
||||
|
||||
val closePopupTrigger = initClosingPopupTriggerEvent()
|
||||
view.findViewById<ComposeView>(R.id.view_compose)?.setContent {
|
||||
AppCompatTheme(requireContext()) {
|
||||
Box(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
AddCustomTokenScreen(state, closePopupTrigger)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun initClosingPopupTriggerEvent(): ClosePopupTrigger = ClosePopupTrigger().apply {
|
||||
onCloseComplete = ::handleOnBackPressed
|
||||
addBackPressHandler(object : FragmentOnBackPressedHandler {
|
||||
override fun handleOnBackPressed() = close()
|
||||
})
|
||||
addBackPressHandler(
|
||||
object : FragmentOnBackPressedHandler {
|
||||
override fun handleOnBackPressed() = close()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,8 @@ import com.tangem.domain.redux.domainStore
|
|||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.assetReader
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -51,6 +53,7 @@ class TokensMiddleware {
|
|||
handleAddingCustomToken(action)
|
||||
}
|
||||
is TokensAction.SetSearchInput -> {
|
||||
Analytics.send(ManageTokens.TokenSearched())
|
||||
handleLoadCurrencies(
|
||||
scanResponse = store.state.globalState.scanResponse,
|
||||
newSearchInput = action.searchInput
|
||||
|
|
@ -335,6 +338,7 @@ class TokensMiddleware {
|
|||
store.dispatchOnMain(NavigationAction.PopBackTo())
|
||||
}
|
||||
|
||||
Analytics.send(ManageTokens.CustomToken.TokenWasAdded(customCurrency))
|
||||
val currency = Currency.fromCustomCurrency(customCurrency)
|
||||
val isNeedToDerive = isNeedToDerive(scanResponse, currency)
|
||||
val currencyList = listOf(currency)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import androidx.transition.TransitionInflater
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
import com.tangem.tap.common.extensions.dispatchNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -48,12 +50,17 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(TokensAction.ResetState)
|
||||
}
|
||||
})
|
||||
Analytics.send(ManageTokens.ScreenOpened())
|
||||
|
||||
activity?.onBackPressedDispatcher?.addCallback(
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
store.dispatch(TokensAction.ResetState)
|
||||
}
|
||||
},
|
||||
)
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(R.transition.slide_right)
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
|
|
@ -80,6 +87,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
toolbar.setNavigationOnClickListener { activity?.onBackPressed() }
|
||||
|
||||
val onSaveChanges = { tokens: List<TokenWithBlockchain>, blockchains: List<Blockchain> ->
|
||||
Analytics.send(ManageTokens.ButtonSaveChanges())
|
||||
store.dispatch(TokensAction.SaveChanges(tokens, blockchains))
|
||||
}
|
||||
val onNetworkItemClicked = { contractAddress: ContractAddress ->
|
||||
|
|
@ -88,11 +96,11 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
}
|
||||
|
||||
val onLoadMore = {
|
||||
store.dispatch(
|
||||
TokensAction.LoadMore(
|
||||
scanResponse = store.state.globalState.scanResponse
|
||||
)
|
||||
)
|
||||
store.dispatch(
|
||||
TokensAction.LoadMore(
|
||||
scanResponse = store.state.globalState.scanResponse,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
cvCurrencies.setContent {
|
||||
|
|
@ -101,7 +109,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
tokensState = tokensState,
|
||||
onSaveChanges = onSaveChanges,
|
||||
onNetworkItemClicked = onNetworkItemClicked,
|
||||
onLoadMore = onLoadMore
|
||||
onLoadMore = onLoadMore,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -119,6 +127,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
return when (item.itemId) {
|
||||
R.id.menu_search -> true
|
||||
R.id.menu_navigate_add_custom_token -> {
|
||||
Analytics.send(ManageTokens.ButtonCustomToken())
|
||||
store.dispatch(TokensAction.PrepareAndNavigateToAddCustomToken)
|
||||
true
|
||||
}
|
||||
|
|
@ -154,15 +163,18 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
|
|||
}
|
||||
|
||||
fun SearchView.inputtedTextAsFlow(): Flow<String> = callbackFlow {
|
||||
val watcher = setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
return false
|
||||
}
|
||||
val watcher =
|
||||
setOnQueryTextListener(
|
||||
object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String?): Boolean {
|
||||
trySend(newText ?: "")
|
||||
return false
|
||||
}
|
||||
})
|
||||
override fun onQueryTextChange(newText: String?): Boolean {
|
||||
trySend(newText ?: "")
|
||||
return false
|
||||
}
|
||||
},
|
||||
)
|
||||
awaitClose { (watcher) }
|
||||
}
|
||||
|
|
@ -8,8 +8,16 @@ import androidx.compose.foundation.layout.Box
|
|||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.ExtendedFloatingActionButton
|
||||
import androidx.compose.material.FabPosition
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -20,6 +28,9 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.compose.Keyboard
|
||||
import com.tangem.tap.common.compose.extensions.addAndNotify
|
||||
import com.tangem.tap.common.compose.extensions.removeAndNotify
|
||||
|
|
@ -41,7 +52,7 @@ fun CurrenciesScreen(
|
|||
tokensState: MutableState<TokensState> = mutableStateOf(store.state.tokensState),
|
||||
onSaveChanges: (List<TokenWithBlockchain>, List<Blockchain>) -> Unit,
|
||||
onNetworkItemClicked: (ContractAddress) -> Unit,
|
||||
onLoadMore: () -> Unit
|
||||
onLoadMore: () -> Unit,
|
||||
) {
|
||||
val tokensAddedOnMainScreen = remember { tokensState.value.addedTokens }
|
||||
val blockchainsAddedOnMainScreen = remember { tokensState.value.addedBlockchains }
|
||||
|
|
@ -82,21 +93,21 @@ fun CurrenciesScreen(
|
|||
AnimatedVisibility(
|
||||
visible = tokensState.value.loadCoinsState == LoadCoinsState.LOADING,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut()
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
color = Color(0xFF1ACE80)
|
||||
color = Color(0xFF1ACE80),
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = tokensState.value.loadCoinsState == LoadCoinsState.LOADED,
|
||||
enter = fadeIn(animationSpec = tween(1000)),
|
||||
exit = fadeOut(animationSpec = tween(1000))
|
||||
exit = fadeOut(animationSpec = tween(1000)),
|
||||
) {
|
||||
Column {
|
||||
val showHeader = tokensState.value.scanResponse?.card?.useOldStyleDerivation == true
|
||||
|
|
@ -110,7 +121,7 @@ fun CurrenciesScreen(
|
|||
onAddCurrencyToggleClick(currency, token)
|
||||
},
|
||||
onNetworkItemClicked = onNetworkItemClicked,
|
||||
onLoadMore = onLoadMore
|
||||
onLoadMore = onLoadMore,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -122,29 +133,39 @@ private fun toggleBlockchain(
|
|||
blockchain: Blockchain,
|
||||
blockchainsAddedOnMainScreen: List<Blockchain>,
|
||||
addedBlockchainsState: MutableState<List<Blockchain>>,
|
||||
addedTokens: List<TokenWithBlockchain>
|
||||
addedTokens: List<TokenWithBlockchain>,
|
||||
) {
|
||||
val isTryingToRemove = addedBlockchainsState.value.contains(blockchain)
|
||||
val isAddedOnMainScreen = blockchainsAddedOnMainScreen.contains(blockchain)
|
||||
val isTokenWithSameBlockchainFound = addedTokens.any { it.blockchain == blockchain }
|
||||
val analyticsCurrencyTypeParam = AnalyticsParam.CurrencyType.Blockchain(blockchain)
|
||||
|
||||
if (isTryingToRemove) {
|
||||
if (isTokenWithSameBlockchainFound) {
|
||||
store.dispatchDialogShow(WalletDialog.TokensAreLinkedDialog(
|
||||
currencyTitle = blockchain.name,
|
||||
currencySymbol = blockchain.currency
|
||||
))
|
||||
store.dispatchDialogShow(
|
||||
WalletDialog.TokensAreLinkedDialog(
|
||||
currencyTitle = blockchain.name,
|
||||
currencySymbol = blockchain.currency,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
if (isAddedOnMainScreen) {
|
||||
store.dispatchDialogShow(WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = blockchain.name,
|
||||
onOk = { addedBlockchainsState.removeAndNotify(blockchain) }
|
||||
))
|
||||
store.dispatchDialogShow(
|
||||
WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = blockchain.name,
|
||||
onOk = {
|
||||
analyticsCurrencyTypeParam.sendOn()
|
||||
addedBlockchainsState.removeAndNotify(blockchain)
|
||||
},
|
||||
),
|
||||
)
|
||||
} else {
|
||||
analyticsCurrencyTypeParam.sendOff()
|
||||
addedBlockchainsState.removeAndNotify(blockchain)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
analyticsCurrencyTypeParam.sendOn()
|
||||
addedBlockchainsState.addAndNotify(blockchain)
|
||||
}
|
||||
}
|
||||
|
|
@ -158,28 +179,46 @@ private fun toggleToken(
|
|||
val isTryingToRemove = addedTokensState.value.contains(token)
|
||||
val isAddedOnMainScreen = tokensAddedOnMainScreen.contains(token)
|
||||
val isUnsupportedToken = !tokensState.canHandleToken(token)
|
||||
val analyticsCurrencyTypeParam = AnalyticsParam.CurrencyType.Token(token.token)
|
||||
|
||||
if (isTryingToRemove) {
|
||||
if (isAddedOnMainScreen) {
|
||||
store.dispatchDialogShow(WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = token.token.name,
|
||||
onOk = { addedTokensState.removeAndNotify(token) }
|
||||
))
|
||||
store.dispatchDialogShow(
|
||||
WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = token.token.name,
|
||||
onOk = {
|
||||
analyticsCurrencyTypeParam.sendOff()
|
||||
addedTokensState.removeAndNotify(token)
|
||||
},
|
||||
),
|
||||
)
|
||||
} else {
|
||||
analyticsCurrencyTypeParam.sendOff()
|
||||
addedTokensState.removeAndNotify(token)
|
||||
}
|
||||
} else {
|
||||
if (isUnsupportedToken) {
|
||||
store.dispatchDialogShow(AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.common_warning,
|
||||
messageId = R.string.alert_manage_tokens_unsupported_message,
|
||||
))
|
||||
store.dispatchDialogShow(
|
||||
AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.common_warning,
|
||||
messageId = R.string.alert_manage_tokens_unsupported_message,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
analyticsCurrencyTypeParam.sendOn()
|
||||
addedTokensState.addAndNotify(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AnalyticsParam.CurrencyType.sendOn() {
|
||||
Analytics.send(ManageTokens.TokenSwitcherChanged(this, AnalyticsParam.OnOffState.On))
|
||||
}
|
||||
|
||||
private fun AnalyticsParam.CurrencyType.sendOff() {
|
||||
Analytics.send(ManageTokens.TokenSwitcherChanged(this, AnalyticsParam.OnOffState.Off))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SaveChangesButton(keyboardState: Keyboard, onSaveChanges: () -> Unit) {
|
||||
|
||||
|
|
@ -198,6 +237,6 @@ fun SaveChangesButton(keyboardState: Keyboard, onSaveChanges: () -> Unit) {
|
|||
onClick = onSaveChanges,
|
||||
backgroundColor = colorResource(id = R.color.accent),
|
||||
contentColor = Color.White,
|
||||
modifier = Modifier.padding(bottom = padding.dp)
|
||||
modifier = Modifier.padding(bottom = padding.dp),
|
||||
)
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import com.tangem.tap.domain.TapError
|
|||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
import com.tangem.wallet.R
|
||||
import org.rekotlin.Action
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -154,7 +155,9 @@ sealed class WalletAction : Action {
|
|||
object SignedHashesMultiWalletDialog : DialogAction()
|
||||
object ChooseTradeActionDialog : DialogAction()
|
||||
data class ChooseCurrency(val amounts: List<Amount>?) : DialogAction()
|
||||
data class RussianCardholdersWarningDialog(val topUpUrl: String? = null) : DialogAction()
|
||||
data class RussianCardholdersWarningDialog(
|
||||
val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data? = null
|
||||
) : DialogAction()
|
||||
|
||||
object Hide : DialogAction()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package com.tangem.tap.features.wallet.redux.middlewares
|
|||
import com.tangem.common.services.Result
|
||||
import com.tangem.network.api.tangemTech.CurrenciesResponse
|
||||
import com.tangem.network.api.tangemTech.TangemTechService
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -61,6 +64,7 @@ class AppCurrencyMiddleware(
|
|||
}
|
||||
|
||||
private fun selectCurrency(action: WalletAction.AppCurrencyAction.SelectAppCurrency) {
|
||||
Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(action.fiatCurrency)))
|
||||
tapWalletManager.rates.clear()
|
||||
fiatCurrenciesPrefStorage.saveAppCurrency(action.fiatCurrency)
|
||||
store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ import com.tangem.blockchain.common.Token
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
|
|
@ -109,6 +112,7 @@ class MultiWalletMiddleware {
|
|||
WalletDialog.RemoveWalletDialog(
|
||||
currencyTitle = currency.currencyName,
|
||||
onOk = {
|
||||
Analytics.send(ButtonRemoveToken(AnalyticsParam.CurrencyType.Currency(currency)))
|
||||
store.dispatch(WalletAction.MultiWallet.RemoveWallet(currency))
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@ package com.tangem.tap.features.wallet.redux.middlewares
|
|||
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
|
|
@ -19,7 +23,6 @@ import com.tangem.tap.scope
|
|||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class TradeCryptoMiddleware {
|
||||
fun handle(state: () -> AppState?, action: WalletAction.TradeCryptoAction) {
|
||||
if (DemoHelper.tryHandle(state, action)) return
|
||||
|
|
@ -50,6 +53,7 @@ class TradeCryptoMiddleware {
|
|||
val exchangeManager = store.state.globalState.exchangeManager
|
||||
val appCurrency = store.state.globalState.appCurrency
|
||||
val currency = selectedWalletData.currency
|
||||
Analytics.send(Token.ButtonBuy(AnalyticsParam.CurrencyType.Currency(currency)))
|
||||
|
||||
if (currency is Currency.Token && currency.blockchain.isTestnet()) {
|
||||
val walletManager = store.state.walletState.getWalletManager(currency)
|
||||
|
|
@ -62,7 +66,7 @@ class TradeCryptoMiddleware {
|
|||
exchangeManager.buyErc20TestnetTokens(
|
||||
card = card,
|
||||
walletManager = walletManager,
|
||||
token = currency.token
|
||||
token = currency.token,
|
||||
)
|
||||
}
|
||||
return
|
||||
|
|
@ -73,8 +77,11 @@ class TradeCryptoMiddleware {
|
|||
blockchain = currency.blockchain,
|
||||
cryptoCurrencyName = currency.currencySymbol,
|
||||
fiatCurrencyName = appCurrency.code,
|
||||
walletAddress = addresses[0].address
|
||||
)?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) }
|
||||
walletAddress = addresses[0].address,
|
||||
)?.let {
|
||||
store.dispatchOpenUrl(it)
|
||||
Analytics.send(Token.Topup.ScreenOpened())
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedSellAction() {
|
||||
|
|
@ -85,29 +92,40 @@ class TradeCryptoMiddleware {
|
|||
if (addresses.isEmpty()) return
|
||||
|
||||
val currency = selectedWalletData.currency
|
||||
Analytics.send(Token.ButtonSell(AnalyticsParam.CurrencyType.Currency(currency)))
|
||||
|
||||
store.state.globalState.exchangeManager.getUrl(
|
||||
action = CurrencyExchangeManager.Action.Sell,
|
||||
blockchain = currency.blockchain,
|
||||
cryptoCurrencyName = currency.currencySymbol,
|
||||
fiatCurrencyName = appCurrency.code,
|
||||
walletAddress = addresses[0].address
|
||||
)?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) }
|
||||
walletAddress = addresses[0].address,
|
||||
)?.let {
|
||||
store.dispatchOpenUrl(it)
|
||||
Analytics.send(Token.Withdraw.ScreenOpened())
|
||||
}
|
||||
}
|
||||
|
||||
private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) {
|
||||
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
|
||||
|
||||
Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(selectedWalletData.currency)))
|
||||
|
||||
val walletManager = store.state.walletState.getWalletManager(selectedWalletData.currency)
|
||||
store.dispatchOnMain(PrepareSendScreen(
|
||||
coinAmount = walletManager?.wallet?.amounts?.get(AmountType.Coin),
|
||||
coinRate = selectedWalletData.fiatRate,
|
||||
walletManager = walletManager
|
||||
))
|
||||
store.dispatchOnMain(SendAction.SendSpecificTransaction(
|
||||
sendAmount = action.amount,
|
||||
destinationAddress = action.destinationAddress,
|
||||
transactionId = action.transactionId
|
||||
))
|
||||
store.dispatchOnMain(
|
||||
PrepareSendScreen(
|
||||
coinAmount = walletManager?.wallet?.amounts?.get(AmountType.Coin),
|
||||
coinRate = selectedWalletData.fiatRate,
|
||||
walletManager = walletManager,
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(
|
||||
SendAction.SendSpecificTransaction(
|
||||
sendAmount = action.amount,
|
||||
destinationAddress = action.destinationAddress,
|
||||
transactionId = action.transactionId,
|
||||
),
|
||||
)
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Send))
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +134,6 @@ class TradeCryptoMiddleware {
|
|||
store.state.globalState.exchangeManager.getSellCryptoReceiptUrl(
|
||||
action = CurrencyExchangeManager.Action.Sell,
|
||||
transactionId = transactionId,
|
||||
)?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) }
|
||||
)?.let { store.dispatchOpenUrl(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
package com.tangem.tap.features.wallet.redux.middlewares
|
||||
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
|
|
@ -14,6 +17,9 @@ class WalletDialogsMiddleware {
|
|||
store.dispatchDialogShow(WalletDialog.SignedHashesMultiWalletDialog)
|
||||
}
|
||||
is WalletAction.DialogAction.ChooseTradeActionDialog -> {
|
||||
store.state.walletState.getSelectedWalletData()?.let {
|
||||
Analytics.send(Token.ButtonExchange(AnalyticsParam.CurrencyType.Currency(it.currency)))
|
||||
}
|
||||
store.dispatchDialogShow(WalletDialog.ChooseTradeActionDialog)
|
||||
}
|
||||
is WalletAction.DialogAction.QrCode -> {
|
||||
|
|
@ -21,18 +27,18 @@ class WalletDialogsMiddleware {
|
|||
AppDialog.AddressInfoDialog(
|
||||
currency = action.currency,
|
||||
addressData = action.selectedAddress,
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletAction.DialogAction.ChooseCurrency -> {
|
||||
store.dispatchDialogShow(
|
||||
WalletDialog.SelectAmountToSendDialog(
|
||||
amounts = action.amounts
|
||||
)
|
||||
amounts = action.amounts,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletAction.DialogAction.RussianCardholdersWarningDialog -> {
|
||||
store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog(action.topUpUrl))
|
||||
store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog(action.dialogData))
|
||||
}
|
||||
is WalletAction.DialogAction.Hide -> {
|
||||
store.dispatchDialogHide()
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import com.tangem.blockchain.common.Amount
|
|||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.operations.attestation.Attestation
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.tap.common.analytics.AnalyticsAnOld
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
|
|
@ -189,15 +189,7 @@ class WalletMiddleware {
|
|||
globalState.scanResponse?.copy(card = result.data)
|
||||
scanNoteResponse?.let { store.onCardScanned(scanNoteResponse) }
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
(result.error as? TangemSdkError)?.let { error ->
|
||||
store.state.globalState.analyticsHandler.handleCardSdkErrorEvent(
|
||||
error,
|
||||
AnalyticsAnOld.ActionToLog.CreateWallet,
|
||||
card = store.state.detailsState.scanResponse?.card,
|
||||
)
|
||||
}
|
||||
}
|
||||
is CompletionResult.Failure -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -251,6 +243,7 @@ class WalletMiddleware {
|
|||
action.context.shareText(action.address)
|
||||
}
|
||||
is WalletAction.ExploreAddress -> {
|
||||
Analytics.send(Token.ButtonExplore())
|
||||
store.dispatchOpenUrl(action.exploreUrl)
|
||||
}
|
||||
is WalletAction.Send -> {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.tangem.common.card.Card
|
|||
import com.tangem.common.card.FirmwareVersion
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.tap.common.analytics.AnalyticsEventAnOld
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.isGreaterThan
|
||||
import com.tangem.tap.common.redux.global.GlobalState
|
||||
|
|
@ -54,14 +53,10 @@ class WarningsMiddleware {
|
|||
if (action.remainingSignatures != null &&
|
||||
action.remainingSignatures <= WarningMessagesManager.REMAINING_SIGNATURES_WARNING
|
||||
) {
|
||||
store.state.globalState.warningManager
|
||||
?.removeWarnings(
|
||||
messageRes = R.string.warning_low_signatures_format
|
||||
)
|
||||
store.state.globalState.warningManager?.removeWarnings(R.string.warning_low_signatures_format)
|
||||
addWarningMessage(
|
||||
warning =
|
||||
WarningMessagesManager.remainingSignaturesNotEnough(action.remainingSignatures),
|
||||
autoUpdate = true
|
||||
warning = WarningMessagesManager.remainingSignaturesNotEnough(action.remainingSignatures),
|
||||
autoUpdate = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +64,8 @@ class WarningsMiddleware {
|
|||
is WalletAction.Warnings.CheckHashesCount,
|
||||
is WalletAction.Warnings.CheckHashesCount.ConfirmHashesCount,
|
||||
is WalletAction.Warnings.CheckHashesCount.NeedToCheckHashesCountOnline,
|
||||
is WalletAction.Warnings.Set -> Unit
|
||||
is WalletAction.Warnings.Set,
|
||||
-> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +77,6 @@ class WarningsMiddleware {
|
|||
preferencesStorage.appRatingLaunchObserver.foundWalletWithFunds()
|
||||
}
|
||||
if (preferencesStorage.appRatingLaunchObserver.isReadyToShow()) {
|
||||
store.state.globalState.analyticsHandler?.handleAnalyticsEvent(AnalyticsEventAnOld.APP_RATING_DISPLAYED)
|
||||
addWarningMessage(WarningMessagesManager.appRatingWarning(), true)
|
||||
}
|
||||
}
|
||||
|
|
@ -118,11 +113,7 @@ class WarningsMiddleware {
|
|||
if (remainingSignatures != null &&
|
||||
remainingSignatures <= WarningMessagesManager.REMAINING_SIGNATURES_WARNING
|
||||
) {
|
||||
addWarningMessage(
|
||||
WarningMessagesManager.remainingSignaturesNotEnough(
|
||||
remainingSignatures
|
||||
)
|
||||
)
|
||||
addWarningMessage(WarningMessagesManager.remainingSignaturesNotEnough(remainingSignatures))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,15 +169,9 @@ class WarningsMiddleware {
|
|||
}
|
||||
is SimpleResult.Failure ->
|
||||
if (result.error is BlockchainSdkError.SignatureCountNotMatched) {
|
||||
addWarningMessage(
|
||||
WarningMessagesManager.alreadySignedHashesWarning(),
|
||||
true
|
||||
)
|
||||
addWarningMessage(WarningMessagesManager.alreadySignedHashesWarning(), true)
|
||||
} else if (signedHashes > 0) {
|
||||
addWarningMessage(
|
||||
WarningMessagesManager.alreadySignedHashesWarning(),
|
||||
true
|
||||
)
|
||||
addWarningMessage(WarningMessagesManager.alreadySignedHashesWarning(), true)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
|
|
@ -207,7 +192,7 @@ class WarningsMiddleware {
|
|||
val warningManager = store.state.globalState.warningManager ?: return emptyList()
|
||||
return warningManager.getWarnings(
|
||||
WarningMessage.Location.MainScreen,
|
||||
store.state.walletState.blockchains
|
||||
store.state.walletState.blockchains,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.features.wallet.redux.models
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -31,5 +32,7 @@ sealed interface WalletDialog : StateDialog {
|
|||
val titleRes: Int = R.string.token_details_unable_hide_alert_title
|
||||
}
|
||||
|
||||
data class RussianCardholdersWarningDialog(val topUpUrl: String?) : WalletDialog
|
||||
data class RussianCardholdersWarningDialog(val data: Data?) : WalletDialog {
|
||||
data class Data(val topUpUrl: String, val blockchain: Blockchain)
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,12 @@ fun List<WalletData>.calculateTotalFiatAmount(): BigDecimal {
|
|||
.reduce(BigDecimal::plus)
|
||||
}
|
||||
|
||||
fun List<WalletData>.calculateTotalCryptoAmount(): BigDecimal {
|
||||
return this
|
||||
.map { it.currencyData.amount ?: BigDecimal.ZERO }
|
||||
.reduce(BigDecimal::plus)
|
||||
}
|
||||
|
||||
private fun List<WalletData>.mapToProgressState(): List<ProgressState> {
|
||||
return this.map { wallet ->
|
||||
if (wallet.fiatRate == null) ProgressState.Error
|
||||
|
|
@ -25,12 +31,15 @@ private fun List<WalletData>.mapToProgressState(): List<ProgressState> {
|
|||
BalanceStatus.VerifiedOnline,
|
||||
BalanceStatus.SameCurrencyTransactionInProgress,
|
||||
BalanceStatus.TransactionInProgress,
|
||||
BalanceStatus.NoAccount -> ProgressState.Done
|
||||
BalanceStatus.NoAccount,
|
||||
-> ProgressState.Done
|
||||
BalanceStatus.Unreachable,
|
||||
BalanceStatus.EmptyCard,
|
||||
BalanceStatus.UnknownBlockchain -> ProgressState.Error
|
||||
BalanceStatus.UnknownBlockchain,
|
||||
-> ProgressState.Error
|
||||
BalanceStatus.Loading,
|
||||
null -> ProgressState.Loading
|
||||
null,
|
||||
-> ProgressState.Loading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,20 +50,24 @@ private infix fun ProgressState.or(newState: ProgressState): ProgressState {
|
|||
ProgressState.Loading,
|
||||
ProgressState.Refreshing,
|
||||
ProgressState.Error,
|
||||
ProgressState.Done -> this
|
||||
ProgressState.Done,
|
||||
-> this
|
||||
}
|
||||
ProgressState.Done,
|
||||
ProgressState.Error -> when (newState) {
|
||||
ProgressState.Error,
|
||||
-> when (newState) {
|
||||
ProgressState.Loading,
|
||||
ProgressState.Refreshing,
|
||||
ProgressState.Error -> newState
|
||||
ProgressState.Error,
|
||||
-> newState
|
||||
ProgressState.Done -> this
|
||||
}
|
||||
ProgressState.Refreshing -> when (newState) {
|
||||
ProgressState.Loading -> this
|
||||
ProgressState.Refreshing,
|
||||
ProgressState.Error,
|
||||
ProgressState.Done -> newState
|
||||
ProgressState.Done,
|
||||
-> newState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,9 @@ import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
|||
import com.tangem.tangem_sdk_new.extensions.dpToPx
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import com.tangem.tap.common.TestActions
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.DetailsScreen
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.appendIfNotNull
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.fitChipsByGroupWidth
|
||||
|
|
@ -59,12 +62,17 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(WalletAction.MultiWallet.SelectWallet(null))
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
})
|
||||
|
||||
Analytics.send(DetailsScreen.ScreenOpened())
|
||||
activity?.onBackPressedDispatcher?.addCallback(
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(WalletAction.MultiWallet.SelectWallet(null))
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
},
|
||||
)
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(R.transition.slide_right)
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
|
|
@ -125,7 +133,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
view?.findViewById<View>(R.id.l_balance)?.let { view ->
|
||||
TestActions.initFor(
|
||||
view = view,
|
||||
actions = TestWallet.solanaRentExemptWarning()
|
||||
actions = TestWallet.solanaRentExemptWarning(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -149,13 +157,15 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
|
||||
binding.srlWalletDetails.setOnRefreshListener {
|
||||
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
|
||||
store.dispatch(WalletAction.LoadWallet(
|
||||
blockchain = BlockchainNetwork(
|
||||
selectedWallet.currency.blockchain,
|
||||
selectedWallet.currency.derivationPath,
|
||||
emptyList()
|
||||
)
|
||||
)
|
||||
Analytics.send(Token.Refreshed())
|
||||
store.dispatch(
|
||||
WalletAction.LoadWallet(
|
||||
blockchain = BlockchainNetwork(
|
||||
selectedWallet.currency.blockchain,
|
||||
selectedWallet.currency.derivationPath,
|
||||
emptyList(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +193,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
tvCurrencyTitle.text = currencyData.currency
|
||||
tvCurrencySubtitle.text = tvCurrencySubtitle.getString(
|
||||
R.string.wallet_currency_subtitle,
|
||||
currency.blockchain.fullName
|
||||
currency.blockchain.fullName,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -225,7 +235,6 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
private fun showPendingTransactionsIfPresent(pendingTransactions: List<PendingTransaction>) {
|
||||
pendingTransactionAdapter.submitList(pendingTransactions)
|
||||
binding.rvPendingTransaction.show(pendingTransactions.isNotEmpty())
|
||||
|
|
@ -256,8 +265,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
store.dispatch(
|
||||
WalletAction.ExploreAddress(
|
||||
state.walletAddresses.selectedAddress.exploreUrl,
|
||||
requireContext()
|
||||
)
|
||||
requireContext(),
|
||||
),
|
||||
)
|
||||
}
|
||||
ivQrCode.setImageBitmap(state.walletAddresses.selectedAddress.shareUrl.toQrCode())
|
||||
|
|
@ -272,7 +281,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
binding.srlWalletDetails.isRefreshing = false
|
||||
(activity as? SnackbarHandler)?.showSnackbar(
|
||||
text = R.string.wallet_notification_no_internet,
|
||||
buttonTitle = R.string.common_retry
|
||||
buttonTitle = R.string.common_retry,
|
||||
) { store.dispatch(WalletAction.LoadData) }
|
||||
}
|
||||
} else {
|
||||
|
|
@ -292,7 +301,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
||||
}
|
||||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress,
|
||||
BalanceStatus.TransactionInProgress -> {
|
||||
BalanceStatus.TransactionInProgress,
|
||||
-> {
|
||||
lBalanceError.root.hide()
|
||||
lBalance.root.show()
|
||||
lBalance.groupBalance.show()
|
||||
|
|
@ -315,7 +325,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
lBalance.tvError.show()
|
||||
lBalance.tvError.setWarningStatus(
|
||||
R.string.wallet_balance_blockchain_unreachable,
|
||||
data.errorMessage
|
||||
data.errorMessage,
|
||||
)
|
||||
}
|
||||
BalanceStatus.NoAccount -> {
|
||||
|
|
@ -325,7 +335,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
lBalanceError.tvErrorDescriptions.text =
|
||||
getString(
|
||||
R.string.wallet_error_no_account_subtitle_format,
|
||||
data.amountToCreateAccount, data.currencySymbol
|
||||
data.amountToCreateAccount, data.currencySymbol,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -364,7 +374,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
private fun TextView.setStatus(
|
||||
text: String,
|
||||
@ColorRes color: Int,
|
||||
@DrawableRes drawable: Int?
|
||||
@DrawableRes drawable: Int?,
|
||||
) {
|
||||
this.text = text
|
||||
setTextColor(getColor(color))
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ import coil.load
|
|||
import coil.size.Scale
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.converters.BasicSignInEventConverter
|
||||
import com.tangem.tap.common.analytics.converters.BasicTopUpEventConverter
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Portfolio
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -52,6 +57,8 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
Analytics.send(MainScreen.ScreenOpened())
|
||||
activity?.onBackPressedDispatcher?.addCallback(
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
|
|
@ -71,8 +78,6 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
state.select { it.walletState }
|
||||
}
|
||||
walletView.setFragment(this, binding)
|
||||
// store.dispatch(WalletAction.UpdateWallet(force = false))
|
||||
// store.dispatch(WalletAction.LoadWallet())
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
|
@ -86,6 +91,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
(activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar)
|
||||
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
Analytics.send(MainScreen.ButtonScanCard())
|
||||
store.dispatch(WalletAction.Scan)
|
||||
}
|
||||
setupWarningsRecyclerView()
|
||||
|
|
@ -115,6 +121,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
override fun newState(state: WalletState) {
|
||||
if (activity == null || view == null) return
|
||||
|
||||
handleBasicAnalyticsEvent(state)
|
||||
val isSaltPay = store.state.globalState.scanResponse?.card?.isSaltPay == true
|
||||
|
||||
when {
|
||||
|
|
@ -152,6 +159,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
if (state.state != ProgressState.Loading ||
|
||||
state.state != ProgressState.Refreshing
|
||||
) {
|
||||
Analytics.send(Portfolio.Refreshed())
|
||||
store.dispatch(WalletAction.LoadData.Refresh)
|
||||
}
|
||||
}
|
||||
|
|
@ -221,4 +229,11 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
if (store.state.walletState.shouldShowDetails) inflater.inflate(R.menu.menu_wallet, menu)
|
||||
}
|
||||
|
||||
private fun handleBasicAnalyticsEvent(state: WalletState) {
|
||||
val scanResponse = store.state.globalState.scanResponse ?: return
|
||||
|
||||
BasicSignInEventConverter(scanResponse).convert(state)?.let { Analytics.send(it) }
|
||||
BasicTopUpEventConverter(scanResponse).convert(state)?.let { Analytics.send(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Portfolio
|
||||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
|
|
@ -20,8 +22,7 @@ import com.tangem.tap.store
|
|||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.ItemCurrencyWalletBinding
|
||||
|
||||
class WalletAdapter
|
||||
: ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(DiffUtilCallback) {
|
||||
class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(DiffUtilCallback) {
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return currentList[position].currencyData.currencySymbol?.hashCode()?.toLong() ?: 0
|
||||
|
|
@ -30,7 +31,7 @@ class WalletAdapter
|
|||
fun submitList(
|
||||
list: List<WalletData>,
|
||||
primaryBlockchain: Blockchain?,
|
||||
primaryToken: Token? = null
|
||||
primaryToken: Token? = null,
|
||||
) {
|
||||
// We used this method to sort the list of currencies. Sorting is disabled for now.
|
||||
super.submitList(list)
|
||||
|
|
@ -38,7 +39,7 @@ class WalletAdapter
|
|||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletsViewHolder {
|
||||
val layout = ItemCurrencyWalletBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
LayoutInflater.from(parent.context), parent, false,
|
||||
)
|
||||
return WalletsViewHolder(layout)
|
||||
}
|
||||
|
|
@ -49,11 +50,11 @@ class WalletAdapter
|
|||
|
||||
object DiffUtilCallback : DiffUtil.ItemCallback<WalletData>() {
|
||||
override fun areContentsTheSame(
|
||||
oldItem: WalletData, newItem: WalletData
|
||||
oldItem: WalletData, newItem: WalletData,
|
||||
) = oldItem == newItem
|
||||
|
||||
override fun areItemsTheSame(
|
||||
oldItem: WalletData, newItem: WalletData
|
||||
oldItem: WalletData, newItem: WalletData,
|
||||
) = oldItem == newItem
|
||||
}
|
||||
|
||||
|
|
@ -112,6 +113,7 @@ class WalletAdapter
|
|||
|
||||
if (wallet.walletAddresses != null) {
|
||||
cardWallet.setOnClickListener {
|
||||
Analytics.send(Portfolio.TokenTapped())
|
||||
store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet))
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.play.core.review.ReviewManagerFactory
|
||||
import com.tangem.tap.common.analytics.AnalyticsEventAnOld
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.extensions.getActivity
|
||||
import com.tangem.tap.common.extensions.getColor
|
||||
import com.tangem.tap.common.extensions.getString
|
||||
|
|
@ -26,7 +28,7 @@ class WarningMessagesAdapter : ListAdapter<WarningMessage, WarningMessageVH>(Dif
|
|||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WarningMessageVH {
|
||||
val binding = LayoutWarningCardActionBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
LayoutInflater.from(parent.context), parent, false,
|
||||
)
|
||||
return WarningMessageVH(binding)
|
||||
}
|
||||
|
|
@ -60,7 +62,7 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
|
|||
tvMessage.text = getString(
|
||||
resId = warning.messageResId,
|
||||
default = warning.message,
|
||||
formatArgs = warning.messageFormatArg
|
||||
formatArgs = warning.messageFormatArg,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +100,7 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
|
|||
}
|
||||
}
|
||||
val buttonTitle = binding.root.getString(
|
||||
warning.buttonTextId ?: R.string.how_to_got_it_button
|
||||
warning.buttonTextId ?: R.string.how_to_got_it_button,
|
||||
)
|
||||
binding.btnGotIt.setOnClickListener(buttonAction)
|
||||
binding.btnGotIt.text = buttonTitle
|
||||
|
|
@ -107,14 +109,13 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
|
|||
binding.groupControlsTemporary.hide()
|
||||
binding.groupControlsRating.show()
|
||||
binding.btnClose.show()
|
||||
val analyticsHandler = store.state.globalState.analyticsHandler
|
||||
binding.btnClose.setOnClickListener {
|
||||
analyticsHandler?.handleAnalyticsEvent(AnalyticsEventAnOld.APP_RATING_DISMISS)
|
||||
Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Closed))
|
||||
store.dispatch(GlobalAction.HideWarningMessage(warning))
|
||||
store.dispatch(WalletAction.Warnings.AppRating.RemindLater)
|
||||
}
|
||||
binding.btnCanBeBetter.setOnClickListener {
|
||||
analyticsHandler?.handleAnalyticsEvent(AnalyticsEventAnOld.APP_RATING_NEGATIVE)
|
||||
Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Disliked))
|
||||
store.dispatch(WalletAction.Warnings.AppRating.SetNeverToShow)
|
||||
store.dispatch(GlobalAction.HideWarningMessage(warning))
|
||||
store.dispatch(GlobalAction.SendEmail(RateCanBeBetterEmail()))
|
||||
|
|
@ -122,7 +123,7 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
|
|||
binding.btnReallyCool.setOnClickListener {
|
||||
val activity = binding.root.context.getActivity() ?: return@setOnClickListener
|
||||
|
||||
analyticsHandler?.handleAnalyticsEvent(AnalyticsEventAnOld.APP_RATING_POSITIVE)
|
||||
Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Liked))
|
||||
store.dispatch(WalletAction.Warnings.AppRating.SetNeverToShow)
|
||||
val reviewManager = ReviewManagerFactory.create(activity)
|
||||
val task = reviewManager.requestReviewFlow()
|
||||
|
|
|
|||
|
|
@ -4,15 +4,21 @@ import android.content.Context
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding
|
||||
|
||||
class RussianCardholdersWarningBottomSheetDialog(
|
||||
context: Context, private val topUpUrl: String?,
|
||||
context: Context,
|
||||
private val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data?,
|
||||
) : BottomSheetDialog
|
||||
(context) {
|
||||
|
||||
|
|
@ -20,6 +26,7 @@ class RussianCardholdersWarningBottomSheetDialog(
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Analytics.send(Token.Topup.P2PScreenOpened())
|
||||
binding = DialogRussiansCardholdersWarningBinding
|
||||
.inflate(LayoutInflater.from(context))
|
||||
.also { setContentView(it.root) }
|
||||
|
|
@ -33,8 +40,10 @@ class RussianCardholdersWarningBottomSheetDialog(
|
|||
}
|
||||
|
||||
binding?.btnYes?.setOnClickListener {
|
||||
if (topUpUrl != null) {
|
||||
store.dispatchOpenUrl(topUpUrl)
|
||||
if (dialogData != null) {
|
||||
val currencyType = AnalyticsParam.CurrencyType.Blockchain(dialogData.blockchain)
|
||||
Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType))
|
||||
store.dispatchOpenUrl(dialogData.topUpUrl)
|
||||
} else {
|
||||
store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.tangem.tap.features.wallet.ui.dialogs
|
|||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.common.feedback.ScanFailsEmail
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -19,6 +21,7 @@ class ScanFailsDialog {
|
|||
setTitle(context.getString(R.string.common_warning))
|
||||
setMessage(R.string.alert_troubleshooting_scan_card_title)
|
||||
setPositiveButton(R.string.alert_button_request_support) { _, _ ->
|
||||
Analytics.send(IntroductionProcess.ButtonRequestSupport())
|
||||
store.dispatch(GlobalAction.SendEmail(ScanFailsEmail()))
|
||||
}
|
||||
setNeutralButton(R.string.alert_troubleshooting_scan_card_ok) { _, _ -> }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import com.tangem.common.card.Card
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Portfolio
|
||||
import com.tangem.tap.common.extensions.animateVisibility
|
||||
import com.tangem.tap.common.extensions.formatAmountAsSpannedString
|
||||
import com.tangem.tap.common.extensions.getQuantityString
|
||||
|
|
@ -85,6 +88,7 @@ class MultiWalletView : WalletView() {
|
|||
|
||||
binding.btnAddToken.setOnClickListener {
|
||||
val card = store.state.globalState.scanResponse!!.card
|
||||
Analytics.send(Portfolio.ButtonManageTokens())
|
||||
store.dispatch(
|
||||
TokensAction.LoadCurrencies(
|
||||
supportedBlockchains = CurrenciesRepository.getBlockchains(
|
||||
|
|
@ -112,6 +116,7 @@ class MultiWalletView : WalletView() {
|
|||
) = with(binding.lWalletBackupWarning) {
|
||||
root.isVisible = showBackupWarning
|
||||
root.setOnClickListener {
|
||||
Analytics.send(MainScreen.NoticeBackupYourWalletTapped())
|
||||
store.dispatch(WalletAction.MultiWallet.BackupWallet)
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +127,7 @@ class MultiWalletView : WalletView() {
|
|||
) = with(binding.lWalletRescanWarning) {
|
||||
root.isVisible = showRescanWarning
|
||||
root.setOnClickListener {
|
||||
Analytics.send(MainScreen.NoticeScanYourCardTapped())
|
||||
store.dispatch(WalletAction.MultiWallet.ScanToGetDerivations)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue