Updated on 2026-08-14
This commit is contained in:
commit
d21b90dc62
30 changed files with 179 additions and 71 deletions
|
|
@ -29,7 +29,7 @@ suspend fun WalletManager.safeUpdate(): Result<Wallet> = try {
|
|||
if (blockchain.isNoAccountError(exception) && amountToCreateAccount != null) {
|
||||
Result.Failure(TapError.WalletManagerUpdate.NoAccountError(amountToCreateAccount.toString()))
|
||||
} else {
|
||||
val message = exception.localizedMessage ?: "Unknown exception during WalletManager update"
|
||||
val message = exception.localizedMessage ?: "An error has occurred. Try later"
|
||||
Result.Failure(TapError.WalletManagerUpdate.InternalError(message))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class PicassoHelper {
|
|||
.downloader(OkHttp3Downloader(getOkHttpForPicasso(application)))
|
||||
.build()
|
||||
picasso.isLoggingEnabled = BuildConfig.DEBUG
|
||||
picasso.setIndicatorsEnabled(BuildConfig.DEBUG)
|
||||
Picasso.setSingletonInstance(picasso)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ sealed class TapError(
|
|||
sealed class WalletManagerUpdate {
|
||||
class NoAccountError(amountToCreateAccount: String): CustomError(amountToCreateAccount)
|
||||
class InternalError(message: String): CustomError(message)
|
||||
object BlockchainIsUnreachable: TapError(R.string.wallet_balance_blockchain_unreachable)
|
||||
object BlockchainIsUnreachableTryLater: TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
|
||||
}
|
||||
|
||||
data class ValidateTransactionErrors(
|
||||
|
|
|
|||
|
|
@ -10,19 +10,14 @@ import com.tangem.operations.attestation.OnlineCardVerifier
|
|||
import com.tangem.tap.common.extensions.isPositive
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.UrlBitmapLoader
|
||||
import com.tangem.tap.domain.extensions.getOrLoadCardArtworkUrl
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.tap.features.wallet.models.hasPendingTransactions
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import com.tangem.tap.features.wallet.redux.Currency
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.persistence.UsedCardsPrefStorage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -35,24 +30,31 @@ class OnboardingManager(
|
|||
var cardInfo: Result<CardVerifyAndGetInfo.Response.Item>? = null
|
||||
private set
|
||||
|
||||
suspend fun loadArtwork(): Artwork {
|
||||
cardInfo = OnlineCardVerifier().getCardInfo(scanResponse.card.cardId, scanResponse.card.cardPublicKey)
|
||||
return loadArtwork(scanResponse.card.getOrLoadCardArtworkUrl(cardInfo))
|
||||
suspend fun loadArtworkUrl(): String {
|
||||
val cardInfo = cardInfo
|
||||
?: OnlineCardVerifier().getCardInfo(scanResponse.card.cardId, scanResponse.card.cardPublicKey)
|
||||
this.cardInfo = cardInfo
|
||||
return scanResponse.card.getOrLoadCardArtworkUrl(cardInfo)
|
||||
}
|
||||
|
||||
suspend fun loadArtwork(url: String): Artwork {
|
||||
return withContext(Dispatchers.Main) {
|
||||
suspendCoroutine { continuation ->
|
||||
UrlBitmapLoader().loadBitmap(url) {
|
||||
val result = when (it) {
|
||||
is Result.Success -> Artwork(url, it.data)
|
||||
is Result.Failure -> Artwork(url, null)
|
||||
}
|
||||
continuation.resume(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// suspend fun loadArtwork(): Artwork {
|
||||
// cardInfo = OnlineCardVerifier().getCardInfo(scanResponse.card.cardId, scanResponse.card.cardPublicKey)
|
||||
// return loadArtwork(scanResponse.card.getOrLoadCardArtworkUrl(cardInfo))
|
||||
// }
|
||||
//
|
||||
// suspend fun loadArtwork(url: String): Artwork {
|
||||
// return withContext(Dispatchers.Main) {
|
||||
// suspendCoroutine { continuation ->
|
||||
// UrlBitmapLoader().loadBitmap(url) {
|
||||
// val result = when (it) {
|
||||
// is Result.Success -> Artwork(url, it.data)
|
||||
// is Result.Failure -> Artwork(url, null)
|
||||
// }
|
||||
// continuation.resume(result)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
suspend fun updateBalance(walletManager: WalletManager): OnboardingWalletBalance {
|
||||
val balance = when (val result = walletManager.safeUpdate()) {
|
||||
|
|
@ -76,7 +78,10 @@ class OnboardingManager(
|
|||
when (error) {
|
||||
is TapError.WalletManagerUpdate.NoAccountError -> OnboardingWalletBalance.error(error)
|
||||
// NoInternetConnection, WalletManagerUpdate.InternalError
|
||||
else -> OnboardingWalletBalance.criticalError(error)
|
||||
else -> {
|
||||
Timber.e(error.localizedMessage)
|
||||
OnboardingWalletBalance.criticalError(TapError.WalletManagerUpdate.BlockchainIsUnreachableTryLater)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.annotation.LayoutRes
|
|||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tangem_sdk_new.extensions.fadeIn
|
||||
import com.tangem.tangem_sdk_new.extensions.fadeOut
|
||||
|
|
@ -73,7 +74,12 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
override fun newState(state: OnboardingNoteState) {
|
||||
if (activity == null) return
|
||||
|
||||
state.cardArtwork?.let { imv_front_card.swapToBitmapDrawable(it.artwork) }
|
||||
Picasso.get()
|
||||
.load(state.cardArtworkUrl)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(imv_front_card)
|
||||
|
||||
pb_state.max = state.steps.size - 1
|
||||
pb_state.progress = state.progress
|
||||
|
||||
|
|
@ -91,9 +97,13 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
private fun setBalance(state: OnboardingNoteState) {
|
||||
if (state.walletBalance.currency.blockchain == Blockchain.Unknown) return
|
||||
|
||||
val balanceValue = state.walletBalance.value.stripZeroPlainString()
|
||||
val currency = state.walletBalance.currency.currencySymbol
|
||||
tv_balance_value.text = "$balanceValue $currency"
|
||||
if (state.balanceCriticalError == null) {
|
||||
val balanceValue = state.walletBalance.value.stripZeroPlainString()
|
||||
val currency = state.walletBalance.currency.currencySymbol
|
||||
tv_balance_value.text = "$balanceValue $currency"
|
||||
} else {
|
||||
tv_balance_value.text = "–"
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupNoneState(state: OnboardingNoteState) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.features.onboarding.products.note.redux
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.onboarding.OnboardingWalletBalance
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import org.rekotlin.Action
|
||||
|
||||
/**
|
||||
|
|
@ -17,7 +16,7 @@ sealed class OnboardingNoteAction : Action {
|
|||
object ShowAddressInfoDialog : OnboardingNoteAction()
|
||||
|
||||
// from redux
|
||||
class SetArtwork(val artwork: Artwork) : OnboardingNoteAction()
|
||||
class SetArtworkUrl(val artworkUrl: String) : OnboardingNoteAction()
|
||||
data class SetWalletManager(val walletManager: WalletManager) : OnboardingNoteAction()
|
||||
object DetermineStepOfScreen : OnboardingNoteAction()
|
||||
object Done : OnboardingNoteAction()
|
||||
|
|
@ -27,6 +26,7 @@ sealed class OnboardingNoteAction : Action {
|
|||
sealed class Balance {
|
||||
object Update : OnboardingNoteAction()
|
||||
data class Set(val balance: OnboardingWalletBalance) : OnboardingNoteAction()
|
||||
data class SetCriticalError(val error: TapError?) : OnboardingNoteAction()
|
||||
data class SetNonCriticalError(val error: TapError?) : OnboardingNoteAction()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.extensions.hasWallets
|
||||
import com.tangem.tap.domain.extensions.makePrimaryWalletManager
|
||||
|
|
@ -50,8 +51,8 @@ private fun handleNoteAction(action: Action, dispatch: DispatchFunction) {
|
|||
when (action) {
|
||||
is OnboardingNoteAction.LoadCardArtwork -> {
|
||||
scope.launch {
|
||||
val artwork = onboardingManager.loadArtwork()
|
||||
withMainContext { store.dispatch(OnboardingNoteAction.SetArtwork(artwork)) }
|
||||
val artworkUrl = onboardingManager.loadArtworkUrl()
|
||||
withMainContext { store.dispatch(OnboardingNoteAction.SetArtworkUrl(artworkUrl)) }
|
||||
}
|
||||
}
|
||||
is OnboardingNoteAction.DetermineStepOfScreen -> {
|
||||
|
|
@ -69,7 +70,7 @@ private fun handleNoteAction(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
OnboardingNoteStep.Done -> {
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(500) { store.dispatch(OnboardingNoteAction.Confetti.Show) }
|
||||
postUi(DELAY_SDK_DIALOG_CLOSE) { store.dispatch(OnboardingNoteAction.Confetti.Show) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -117,10 +118,11 @@ private fun handleNoteAction(action: Action, dispatch: DispatchFunction) {
|
|||
|
||||
scope.launch {
|
||||
val loadedBalance = onboardingManager.updateBalance(walletManager)
|
||||
loadedBalance.criticalError?.let { store.dispatchErrorNotification(it) }
|
||||
delay(if (isLoadedBefore) 0 else 300)
|
||||
loadedBalance.criticalError?.let { store.dispatchErrorNotification(it) }
|
||||
withMainContext {
|
||||
store.dispatch(OnboardingNoteAction.Balance.Set(loadedBalance))
|
||||
store.dispatch(OnboardingNoteAction.Balance.SetCriticalError(loadedBalance.criticalError))
|
||||
store.dispatch(OnboardingNoteAction.Balance.SetNonCriticalError(loadedBalance.error))
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +150,7 @@ private fun handleNoteAction(action: Action, dispatch: DispatchFunction) {
|
|||
store.dispatch(GlobalAction.Onboarding.Stop)
|
||||
scope.launch {
|
||||
store.onCardScanned(scanResponse)
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
withMainContext { store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingNoteSt
|
|||
is GlobalAction.Onboarding.Start -> {
|
||||
state = OnboardingNoteState()
|
||||
}
|
||||
is OnboardingNoteAction.SetArtwork -> {
|
||||
state = state.copy(cardArtwork = action.artwork)
|
||||
is OnboardingNoteAction.SetArtworkUrl -> {
|
||||
state = state.copy(cardArtworkUrl = action.artworkUrl)
|
||||
}
|
||||
is OnboardingNoteAction.SetWalletManager -> {
|
||||
state = state.copy(walletManager = action.walletManager)
|
||||
|
|
@ -26,6 +26,9 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingNoteSt
|
|||
is OnboardingNoteAction.Balance.Set -> {
|
||||
state = state.copy(walletBalance = action.balance)
|
||||
}
|
||||
is OnboardingNoteAction.Balance.SetCriticalError -> {
|
||||
state = state.copy(balanceCriticalError = action.error)
|
||||
}
|
||||
is OnboardingNoteAction.Balance.SetNonCriticalError -> {
|
||||
state = state.copy(balanceNonCriticalError = action.error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.features.onboarding.products.note.redux
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.onboarding.OnboardingWalletBalance
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import org.rekotlin.StateType
|
||||
|
||||
/**
|
||||
|
|
@ -12,9 +11,10 @@ import org.rekotlin.StateType
|
|||
data class OnboardingNoteState(
|
||||
val walletManager: WalletManager? = null,
|
||||
// UI
|
||||
val cardArtwork: Artwork? = null,
|
||||
val cardArtworkUrl: String? = null,
|
||||
val walletBalance: OnboardingWalletBalance = OnboardingWalletBalance.loading(),
|
||||
val balanceNonCriticalError: TapError? = null,
|
||||
val balanceCriticalError: TapError? = null,
|
||||
val currentStep: OnboardingNoteStep = OnboardingNoteStep.None,
|
||||
val steps: List<OnboardingNoteStep> = OnboardingNoteStep.values().toList(),
|
||||
val showConfetti: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ import androidx.annotation.LayoutRes
|
|||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.onboarding.products.BaseOnboardingFragment
|
||||
import com.tangem.tap.features.onboarding.products.note.swapToBitmapDrawable
|
||||
import com.tangem.tap.features.onboarding.products.otherCards.redux.OnboardingOtherCardsAction
|
||||
import com.tangem.tap.features.onboarding.products.otherCards.redux.OnboardingOtherCardsState
|
||||
import com.tangem.tap.features.onboarding.products.otherCards.redux.OnboardingOtherCardsStep
|
||||
|
|
@ -60,7 +60,12 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
if (activity == null) return
|
||||
if (state.currentStep == OnboardingOtherCardsStep.None) return
|
||||
|
||||
state.cardArtwork?.let { imv_front_card.swapToBitmapDrawable(it.artwork) }
|
||||
Picasso.get()
|
||||
.load(state.cardArtworkUrl)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(imv_front_card)
|
||||
|
||||
pb_state.max = state.steps.size - 1
|
||||
pb_state.progress = state.progress
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.features.onboarding.products.otherCards.redux
|
||||
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import org.rekotlin.Action
|
||||
|
||||
/**
|
||||
|
|
@ -12,7 +11,7 @@ sealed class OnboardingOtherCardsAction : Action {
|
|||
object CreateWallet : OnboardingOtherCardsAction()
|
||||
|
||||
// from redux
|
||||
class SetArtwork(val artwork: Artwork) : OnboardingOtherCardsAction()
|
||||
class SetArtworkUrl(val artworkUrl: String) : OnboardingOtherCardsAction()
|
||||
object DetermineStepOfScreen : OnboardingOtherCardsAction()
|
||||
object Done : OnboardingOtherCardsAction()
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
|
|||
when (action) {
|
||||
is OnboardingOtherCardsAction.LoadCardArtwork -> {
|
||||
scope.launch {
|
||||
val artwork = onboardingManager.loadArtwork()
|
||||
withMainContext { store.dispatch(OnboardingOtherCardsAction.SetArtwork(artwork)) }
|
||||
val artworkUrl = onboardingManager.loadArtworkUrl()
|
||||
withMainContext { store.dispatch(OnboardingOtherCardsAction.SetArtworkUrl(artworkUrl)) }
|
||||
}
|
||||
}
|
||||
is OnboardingOtherCardsAction.DetermineStepOfScreen -> {
|
||||
|
|
@ -58,7 +58,7 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
|
|||
is OnboardingOtherCardsAction.SetStepOfScreen -> {
|
||||
if (action.step == OnboardingOtherCardsStep.Done) {
|
||||
onboardingManager.activationFinished(card.cardId)
|
||||
postUi(500) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
|
||||
postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
|
||||
}
|
||||
}
|
||||
is OnboardingOtherCardsAction.CreateWallet -> {
|
||||
|
|
@ -85,7 +85,7 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
|
|||
store.dispatch(GlobalAction.Onboarding.Stop)
|
||||
scope.launch {
|
||||
store.onCardScanned(onboardingManager.scanResponse)
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
withMainContext { store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingOtherC
|
|||
is GlobalAction.Onboarding.Start -> {
|
||||
state = OnboardingOtherCardsState()
|
||||
}
|
||||
is OnboardingOtherCardsAction.SetArtwork -> {
|
||||
state = state.copy(cardArtwork = action.artwork)
|
||||
is OnboardingOtherCardsAction.SetArtworkUrl -> {
|
||||
state = state.copy(cardArtworkUrl = action.artworkUrl)
|
||||
}
|
||||
is OnboardingOtherCardsAction.SetStepOfScreen -> {
|
||||
if (action.step != state.currentStep && state.steps.contains(action.step)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.features.onboarding.products.otherCards.redux
|
||||
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import org.rekotlin.StateType
|
||||
|
||||
/**
|
||||
|
|
@ -8,7 +7,7 @@ import org.rekotlin.StateType
|
|||
*/
|
||||
data class OnboardingOtherCardsState(
|
||||
// UI
|
||||
val cardArtwork: Artwork? = null,
|
||||
val cardArtworkUrl: String? = null,
|
||||
val showConfetti: Boolean = false,
|
||||
val currentStep: OnboardingOtherCardsStep = OnboardingOtherCardsStep.None,
|
||||
val steps: List<OnboardingOtherCardsStep> = OnboardingOtherCardsStep.values().toList(),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.Message
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.tap.domain.twins.AssetReader
|
||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||
|
|
@ -55,6 +56,8 @@ sealed class TwinCardsAction : Action {
|
|||
sealed class Balance {
|
||||
object Update : TwinCardsAction()
|
||||
data class Set(val balance: OnboardingWalletBalance) : TwinCardsAction()
|
||||
data class SetCriticalError(val error: TapError?) : TwinCardsAction()
|
||||
data class SetNonCriticalError(val error: TapError?) : TwinCardsAction()
|
||||
}
|
||||
|
||||
sealed class Confetti {
|
||||
|
|
|
|||
|
|
@ -212,7 +212,11 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
val loadedBalance = onboardingManager?.updateBalance(walletManager) ?: return@launch
|
||||
loadedBalance.criticalError?.let { store.dispatchErrorNotification(it) }
|
||||
delay(if (isLoadedBefore) 0 else 300)
|
||||
withMainContext { store.dispatch(TwinCardsAction.Balance.Set(loadedBalance)) }
|
||||
withMainContext {
|
||||
store.dispatch(TwinCardsAction.Balance.Set(loadedBalance))
|
||||
store.dispatch(TwinCardsAction.Balance.SetCriticalError(loadedBalance.criticalError))
|
||||
store.dispatch(TwinCardsAction.Balance.SetNonCriticalError(loadedBalance.error))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,10 @@ private fun internalReduce(action: Action, state: AppState): TwinCardsState {
|
|||
}
|
||||
}
|
||||
is TwinCardsAction.SetMode -> {
|
||||
state = state.copy(mode = action.mode)
|
||||
state = state.copy(
|
||||
mode = action.mode,
|
||||
userWasUnderstandIfWalletRecreate = false,
|
||||
)
|
||||
}
|
||||
is TwinCardsAction.SetStepOfScreen -> {
|
||||
state = state.copy(currentStep = action.step)
|
||||
|
|
@ -52,6 +55,12 @@ private fun internalReduce(action: Action, state: AppState): TwinCardsState {
|
|||
is TwinCardsAction.Balance.Set -> {
|
||||
state = state.copy(walletBalance = action.balance)
|
||||
}
|
||||
is TwinCardsAction.Balance.SetCriticalError -> {
|
||||
state = state.copy(balanceCriticalError = action.error)
|
||||
}
|
||||
is TwinCardsAction.Balance.SetNonCriticalError -> {
|
||||
state = state.copy(balanceNonCriticalError = action.error)
|
||||
}
|
||||
is TwinCardsAction.Confetti.Show -> {
|
||||
state = state.copy(showConfetti = true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.features.onboarding.products.twins.redux
|
||||
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.twins.TwinCardNumber
|
||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||
import com.tangem.tap.features.onboarding.OnboardingWalletBalance
|
||||
|
|
@ -22,6 +23,8 @@ data class TwinCardsState(
|
|||
val pairCardId: String? = null, // available after create\recreate wallets
|
||||
val walletManager: WalletManager? = null,
|
||||
val walletBalance: OnboardingWalletBalance = OnboardingWalletBalance.loading(),
|
||||
val balanceNonCriticalError: TapError? = null,
|
||||
val balanceCriticalError: TapError? = null,
|
||||
val showConfetti: Boolean = false,
|
||||
) : StateType {
|
||||
|
||||
|
|
|
|||
|
|
@ -77,18 +77,20 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
addBackPressHandler(this)
|
||||
|
||||
reconfigureLayoutForTwins()
|
||||
twinsWidget = TwinsCardWidget(LeapfrogWidget(cards_container)) { 250f }
|
||||
twinsWidget = TwinsCardWidget(LeapfrogWidget(cards_container)) { 285f }
|
||||
btnRefreshBalanceWidget = RefreshBalanceWidget(onboarding_main_container)
|
||||
|
||||
toolbar.title = getText(R.string.twins_recreate_toolbar)
|
||||
|
||||
Picasso.get()
|
||||
.load(Artwork.TWIN_CARD_1)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(imv_twin_front_card)
|
||||
|
||||
Picasso.get()
|
||||
.load(Artwork.TWIN_CARD_2)
|
||||
.error(R.drawable.card_placeholder_white)
|
||||
.placeholder(R.drawable.card_placeholder_white)
|
||||
?.into(imv_twin_back_card)
|
||||
}
|
||||
|
|
@ -114,11 +116,6 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
override fun newState(state: TwinCardsState) {
|
||||
if (activity == null) return
|
||||
|
||||
// toolbar.title = when (state.mode) {
|
||||
// CreateTwinWalletMode.CreateWallet -> getText(R.string.wallet_button_create_wallet)
|
||||
// CreateTwinWalletMode.RecreateWallet -> getText(R.string.twins_recreate_toolbar)
|
||||
// }
|
||||
|
||||
pb_state.max = state.steps.size - 1
|
||||
pb_state.progress = state.progress
|
||||
|
||||
|
|
@ -141,9 +138,13 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
private fun setBalance(state: TwinCardsState) {
|
||||
if (state.walletBalance.currency.blockchain == Blockchain.Unknown) return
|
||||
|
||||
val balanceValue = state.walletBalance.value.stripZeroPlainString()
|
||||
val currency = state.walletBalance.currency.currencySymbol
|
||||
tv_balance_value.text = "$balanceValue $currency"
|
||||
if (state.balanceCriticalError == null) {
|
||||
val balanceValue = state.walletBalance.value.stripZeroPlainString()
|
||||
val currency = state.walletBalance.currency.currencySymbol
|
||||
tv_balance_value.text = "$balanceValue $currency"
|
||||
} else {
|
||||
tv_balance_value.text = "–"
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWelcomeOnlyState(state: TwinCardsState) {
|
||||
|
|
@ -287,6 +288,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
store.dispatch(TwinCardsAction.TopUp)
|
||||
}
|
||||
|
||||
btn_alternative_action.isVisible = true
|
||||
btn_alternative_action.setText(R.string.onboarding_top_up_button_show_wallet_address)
|
||||
btn_alternative_action.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.ShowAddressInfoDialog)
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class WalletMiddleware {
|
|||
WalletAction.LoadArtwork(action.card, response.data.artwork?.id),
|
||||
GlobalAction.SetIfCardVerifiedOnline(response.data.passed)
|
||||
)
|
||||
actionList.forEach { store.dispatch(it) }
|
||||
withMainContext { actionList.forEach { store.dispatch(it) } }
|
||||
}
|
||||
is Result.Failure -> {
|
||||
store.dispatchOnMain(GlobalAction.SetIfCardVerifiedOnline(false))
|
||||
|
|
|
|||
14
app/src/main/res/drawable/shape_circle_home_screen.xml
Normal file
14
app/src/main/res/drawable/shape_circle_home_screen.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<size
|
||||
android:width="40dp"
|
||||
android:height="40dp" />
|
||||
|
||||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="#47F8F8F8"
|
||||
android:startColor="#F4F4F4"
|
||||
android:type="linear" />
|
||||
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="502dp">
|
||||
|
||||
|
|
@ -68,10 +69,12 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:maxWidth="170dp"
|
||||
android:minWidth="120dp"
|
||||
android:singleLine="true"
|
||||
android:text="addlkasLNXDLKNnkjkjhnjkjnljnnlsenn" />
|
||||
android:textSize="15sp"
|
||||
tools:text="addlkasLNXDLKNnkjkjhnjkjnljnnlsenn" />
|
||||
|
||||
<View
|
||||
android:layout_width="16dp"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="64dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginTop="14dp"
|
||||
android:layout_marginEnd="64dp"
|
||||
android:minLines="3"
|
||||
app:layout_constraintBottom_toTopOf="@+id/fl_scan_card_container"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/onboarding_main_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false">
|
||||
|
||||
<include layout="@layout/view_bg_home" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/imv_back_card"
|
||||
|
|
|
|||
32
app/src/main/res/layout/view_bg_home.xml
Normal file
32
app/src/main/res/layout/view_bg_home.xml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:translationY="-50dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/bg_circle_large"
|
||||
android:layout_width="670dp"
|
||||
android:layout_height="670dp"
|
||||
android:src="@drawable/shape_circle_home_screen"
|
||||
android:translationX="160dp"
|
||||
android:translationY="-175dp" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/bg_circle_medium"
|
||||
android:layout_width="650dp"
|
||||
android:layout_height="650dp"
|
||||
android:src="@drawable/shape_circle"
|
||||
android:tint="@color/backgroundWhite"
|
||||
android:translationX="170dp"
|
||||
android:translationY="-165dp" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/bg_circle_small"
|
||||
android:layout_width="590dp"
|
||||
android:layout_height="590dp"
|
||||
android:src="@drawable/shape_circle_home_screen"
|
||||
android:translationX="192dp"
|
||||
android:translationY="-132dp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:progressBackgroundTint="#401ACE80"
|
||||
android:progressTint="@color/accent" />
|
||||
</merge>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
android:id="@+id/btn_refresh_balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
|
|
|
|||
|
|
@ -14,15 +14,21 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:elevation="0dp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:letterSpacing="0.036"
|
||||
android:text="@string/onboarding_balance_title"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="#ABABAB"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<View
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_balance_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="0.036"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="0.000 BTC" />
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<string name="twins_onboarding_title" translatable="false">Tangem Twin</string>
|
||||
<string name="twins_onboarding_subtitle" translatable="false">One wallet. Two cards.</string>
|
||||
<string name="twins_onboarding_description_format" translatable="false">This one that you are holding in your handsand the other one with number #%s.</string>
|
||||
<string name="twins_onboarding_description_format" translatable="false">This one that you are holding in your hands and the other one with number #%s.</string>
|
||||
|
||||
<string name="wallet_twins_chip_format" translatable="false">Card %s of 2</string>
|
||||
|
||||
|
|
@ -194,5 +194,7 @@
|
|||
<string name="onboarding_twins_interrupt_warning" translatable="false">If the process of re-creating the wallet gets interrupted in any way, you’ll have to start over.</string>
|
||||
|
||||
<string name="onboarding_error_create_primary_wallet" translatable="false">Internal error: can\'t create wallet manager</string>
|
||||
<string name="wallet_balance_blockchain_unreachable_try_later" translatable="false">Blockchain is unreachable. Try later</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -90,12 +90,14 @@
|
|||
<style name="TextViewOnboarding.Header">
|
||||
<item name="android:textColor">#060606</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
<item name="android:lineSpacingExtra">4sp</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
</style>
|
||||
|
||||
<style name="TextViewOnboarding.Body">
|
||||
<item name="android:textColor">#686868</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:lineSpacingExtra">4sp</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue