Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-21 15:05:17 +04:00
parent 9a8ff1830d
commit a0798cfef2
252 changed files with 247 additions and 5857 deletions

View file

@ -23,7 +23,7 @@ import com.tangem.wallet.R
*/
abstract class BaseFragment(layoutId: Int) : Fragment(layoutId), FragmentOnBackPressedHandler {
protected lateinit var mainView: View
private lateinit var mainView: View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View file

@ -23,9 +23,9 @@ import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.model.Currency
import com.tangem.tap.features.customtoken.impl.domain.models.FoundToken
import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager

View file

@ -615,10 +615,6 @@ internal class AddCustomTokenViewModel @Inject constructor(
}
}
private fun DerivationPath?.isSameDerivationPath(rawDerivationPath: String?): Boolean {
return this == rawDerivationPath?.let { DerivationPath(it) }
}
private fun handleContractAddressErrorValidation(type: AddCustomTokenError) {
when {
isNetworkSelected() && type == AddCustomTokenError.InvalidContractAddress -> {

View file

@ -6,8 +6,8 @@ import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.common.entities.ProgressState
import com.tangem.tap.domain.model.Currency
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.scope
import com.tangem.tap.store
import kotlinx.coroutines.launch

View file

@ -74,8 +74,6 @@ sealed class WalletConnectAction : Action {
) :
WalletConnectAction()
data class SetDataToSend(val transactionData: WcTransactionData) : WalletConnectAction()
data class HandlePersonalSignRequest(
val message: WCEthereumSignMessage,
val session: WalletConnectSession,

View file

@ -73,9 +73,7 @@ data class WalletForSession(
} else if (other.derivedPublicKey != null) return false
if (derivationPath != other.derivationPath) return false
if (isTestNet != other.isTestNet) return false
if (blockchain != other.blockchain) return false
return true
return blockchain == other.blockchain
}
override fun hashCode(): Int {

View file

@ -122,7 +122,6 @@ internal data class SocialNetworkLink(
internal sealed class EventError {
object Empty : EventError()
data class DemoReferralNotAvailable(val onErrorShow: () -> Unit) : EventError()
}
sealed class SocialNetwork(val id: String, val iconRes: Int) {

View file

@ -1,10 +1,6 @@
package com.tangem.tap.features.home
import android.content.Context
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.PHONE_TYPE_CDMA
import androidx.compose.ui.text.intl.Locale
import java.lang.ref.WeakReference
/**
[REDACTED_AUTHOR]
@ -13,39 +9,8 @@ interface RegionProvider {
fun getRegion(): String?
}
class RegionService(
private val providers: List<RegionProvider>,
) : RegionProvider {
override fun getRegion(): String? {
for (provider in providers) {
val region = provider.getRegion()
if (region != null) return region
}
return null
}
}
class TelephonyManagerRegionProvider(context: Context) : RegionProvider {
private val wContext: WeakReference<Context> = WeakReference(context)
override fun getRegion(): String? {
val tm = wContext.get()?.getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager ?: return null
val region = when (tm.phoneType) {
PHONE_TYPE_CDMA -> {
// Result may be unreliable
tm.networkCountryIso
}
else -> tm.networkCountryIso
}
return region.ifEmpty { return null }
}
}
class LocaleRegionProvider : RegionProvider {
override fun getRegion(): String = Locale.current.region
}
const val RUSSIA_COUNTRY_CODE = "ru"
const val BELARUS_COUNTRY_CODE = "by"
const val RUSSIA_COUNTRY_CODE = "ru"

View file

@ -37,7 +37,6 @@ import timber.log.Timber
object HomeMiddleware {
val handler = homeMiddleware
const val BUY_WALLET_URL = "https://tangem.com/ru/resellers/"
const val NEW_BUY_WALLET_URL = "https://buy.tangem.com/"
}

View file

@ -3,7 +3,6 @@ package com.tangem.tap.features.home.redux
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import com.tangem.tap.common.entities.IndeterminateProgressButton
import com.tangem.tap.common.entities.ProgressState
import com.tangem.tap.features.send.redux.states.ButtonState
import org.rekotlin.StateType
import java.util.Locale
@ -17,9 +16,6 @@ data class HomeState(
val firstStory: Stories
get() = stories[0]
val btnScanStateInProgress: Boolean
get() = btnScanState.progressState == ProgressState.Loading
fun stepOf(story: Stories): Int = stories.indexOf(story)
fun onCountryCodeUpdate(homeState: HomeState, countryCode: String) {

View file

@ -15,15 +15,11 @@ class IntentProcessor {
intentHandlers.add(handler)
}
fun removeIntentHandler(handler: IntentHandler) {
intentHandlers.remove(handler)
}
fun removeAll() {
intentHandlers.clear()
}
suspend fun handleIntent(intent: Intent?) {
fun handleIntent(intent: Intent?) {
intentHandlers.forEach {
it.handleIntent(intent)
}

View file

@ -14,9 +14,9 @@ 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.extensions.getOrLoadCardArtworkUrl
import com.tangem.tap.domain.model.Currency
import com.tangem.tap.domain.model.hasPendingTransactions
import com.tangem.tap.features.demo.isDemoCard
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.features.wallet.models.hasPendingTransactions
import timber.log.Timber
import java.math.BigDecimal
@ -25,11 +25,10 @@ import java.math.BigDecimal
*/
class OnboardingManager(
var scanResponse: ScanResponse,
val usedCardsPrefStorage: UsedCardsPrefStorage,
private val usedCardsPrefStorage: UsedCardsPrefStorage,
) {
var cardInfo: Result<CardVerifyAndGetInfo.Response.Item>? = null
private set
private var cardInfo: Result<CardVerifyAndGetInfo.Response.Item>? = null
suspend fun loadArtworkUrl(): String {
val cardInfo = cardInfo
@ -85,10 +84,6 @@ class OnboardingManager(
usedCardsPrefStorage.activationFinished(cardId)
}
fun isActivationFinished(cardId: String): Boolean {
return usedCardsPrefStorage.isActivationFinished(cardId)
}
fun isActivationStarted(cardId: String): Boolean {
return usedCardsPrefStorage.isActivationStarted(cardId)
}

View file

@ -96,69 +96,69 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
}
private fun setupNoneState() = with(mainBinding.onboardingActionContainer) {
btnMainAction.isVisible = false
btnAlternativeAction.isVisible = false
btnMainAction?.isVisible = false
btnAlternativeAction?.isVisible = false
btnRefreshBalanceWidget.show(false)
tvHeader.isVisible = false
tvBody.isVisible = false
tvBody?.isVisible = false
btnMainAction.text = ""
btnMainAction.icon = null
btnAlternativeAction.text = ""
btnAlternativeAction.icon = null
btnMainAction?.text = ""
btnMainAction?.icon = null
btnAlternativeAction?.text = ""
btnAlternativeAction?.icon = null
tvHeader.text = ""
tvBody.text = ""
tvBody?.text = ""
}
private fun setupCreateWalletState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.onboarding_create_wallet_button_create_wallet)
btnMainAction?.setIconResource(R.drawable.ic_tangem_24)
btnMainAction?.setOnClickListener {
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
store.dispatch(OnboardingNoteAction.CreateWallet)
}
btnAlternativeAction.setText(R.string.onboarding_button_what_does_it_mean)
btnAlternativeAction.setOnClickListener { }
btnAlternativeAction?.setText(R.string.onboarding_button_what_does_it_mean)
btnAlternativeAction?.setOnClickListener { }
btnRefreshBalanceWidget.mainView.setOnClickListener(null)
tvHeader.setText(R.string.onboarding_create_wallet_header)
tvBody.setText(R.string.onboarding_create_wallet_body)
tvBody?.setText(R.string.onboarding_create_wallet_body)
mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable(
requireContext().getDrawableCompat(R.drawable.shape_circle),
)
updateConstraints(state.currentStep, R.layout.lp_onboarding_create_wallet)
btnAlternativeAction.isVisible = false // temporary
btnAlternativeAction?.isVisible = false // temporary
}
private fun setupTopUpWalletState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
if (state.isBuyAllowed) {
btnMainAction.setText(R.string.onboarding_top_up_button_but_crypto)
btnMainAction.icon = null
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.onboarding_top_up_button_but_crypto)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener {
store.dispatch(OnboardingNoteAction.TopUp)
}
btnAlternativeAction.isVisible = true
btnAlternativeAction.setText(R.string.onboarding_top_up_button_show_wallet_address)
btnAlternativeAction.setOnClickListener {
btnAlternativeAction?.isVisible = true
btnAlternativeAction?.setText(R.string.onboarding_top_up_button_show_wallet_address)
btnAlternativeAction?.setOnClickListener {
store.dispatch(OnboardingNoteAction.ShowAddressInfoDialog)
}
} else {
btnMainAction.setText(R.string.onboarding_button_receive_crypto)
btnMainAction.icon = null
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.onboarding_button_receive_crypto)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener {
store.dispatch(OnboardingNoteAction.ShowAddressInfoDialog)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction?.isVisible = false
}
tvHeader.setText(R.string.onboarding_topup_title)
if (state.balanceNonCriticalError == null) {
tvBody.setText(R.string.onboarding_top_up_body)
tvBody?.setText(R.string.onboarding_top_up_body)
} else {
state.walletBalance.amountToCreateAccount?.let { amount ->
val tvBodyMessage = getString(
@ -166,7 +166,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
amount,
state.walletBalance.currency.currencySymbol,
)
tvBody.text = tvBodyMessage
tvBody?.text = tvBodyMessage
}
}
@ -183,20 +183,20 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
}
private fun setupDoneState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.common_continue)
btnMainAction.icon = null
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.common_continue)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener {
showConfetti(false)
store.dispatch(OnboardingNoteAction.Done)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction.text = ""
btnAlternativeAction.setOnClickListener { }
btnAlternativeAction?.isVisible = false
btnAlternativeAction?.text = ""
btnAlternativeAction?.setOnClickListener { }
btnRefreshBalanceWidget.mainView.setOnClickListener(null)
tvHeader.setText(R.string.onboarding_done_header)
tvBody.setText(R.string.onboarding_done_body)
tvBody?.setText(R.string.onboarding_done_body)
mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable(
requireContext().getDrawableCompat(R.drawable.shape_rectangle_rounded_8),

View file

@ -15,11 +15,11 @@ import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.model.Currency
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager

View file

@ -71,19 +71,19 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
}
private fun setupCreateWalletState() = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.onboarding_create_wallet_button_create_wallet)
btnMainAction?.setIconResource(R.drawable.ic_tangem_24)
btnMainAction?.setOnClickListener {
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
store.dispatch(OnboardingOtherCardsAction.CreateWallet)
}
btnAlternativeAction.setText(R.string.onboarding_button_what_does_it_mean)
btnAlternativeAction.setOnClickListener { }
btnAlternativeAction?.setText(R.string.onboarding_button_what_does_it_mean)
btnAlternativeAction?.setOnClickListener { }
tvHeader.setText(R.string.onboarding_create_wallet_header)
tvBody.setText(R.string.onboarding_create_wallet_body)
tvBody?.setText(R.string.onboarding_create_wallet_body)
btnAlternativeAction.isVisible = false // temporary
btnAlternativeAction?.isVisible = false // temporary
mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable(
requireContext().getDrawableCompat(R.drawable.shape_circle),
@ -92,19 +92,19 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
}
private fun setupDoneState() = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.common_continue)
btnMainAction.icon = null
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.common_continue)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener {
showConfetti(false)
store.dispatch(OnboardingOtherCardsAction.Done)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction.text = ""
btnAlternativeAction.setOnClickListener { }
btnAlternativeAction?.isVisible = false
btnAlternativeAction?.text = ""
btnAlternativeAction?.setOnClickListener { }
tvHeader.setText(R.string.onboarding_done_header)
tvBody.setText(R.string.onboarding_done_body)
tvBody?.setText(R.string.onboarding_done_body)
mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable(
requireContext().getDrawableCompat(R.drawable.shape_rectangle_rounded_8),

View file

@ -21,11 +21,11 @@ import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.model.Currency
import com.tangem.tap.domain.twins.TwinCardsManager
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.preferencesStorage
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope

View file

@ -187,14 +187,14 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
pbBinding.pbState.hide()
tvHeader.setText(R.string.twins_onboarding_subtitle)
tvBody.text = getString(
tvBody?.text = getString(
R.string.twins_onboarding_description_format,
state.cardNumber?.pairIndexNumber(),
)
btnMainAction.setText(R.string.common_continue)
btnMainAction.icon = null
btnMainAction.setOnClickListener { onMainButtonClick() }
btnMainAction?.setText(R.string.common_continue)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener { onMainButtonClick() }
}
private fun setupWarningState(state: TwinCardsState) = with(mainBinding.onboardingActionContainer) {
@ -202,18 +202,18 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
mainBinding.onboardingTopContainer.onboardingTwinsWelcomeBg.root.hide()
pbBinding.pbState.hide()
chbUnderstand.show()
chbUnderstand?.show()
tvHeader.setText(R.string.common_warning)
tvBody.setText(R.string.twins_recreate_warning)
tvBody?.setText(R.string.twins_recreate_warning)
chbUnderstand.setOnCheckedChangeListener { buttonView, isChecked ->
chbUnderstand?.setOnCheckedChangeListener { buttonView, isChecked ->
store.dispatch(TwinCardsAction.SetUserUnderstand(isChecked))
}
btnMainAction.isEnabled = state.userWasUnderstandIfWalletRecreate
btnMainAction.setText(R.string.common_continue)
btnMainAction.icon = null
btnMainAction.setOnClickListener {
btnMainAction?.isEnabled = state.userWasUnderstandIfWalletRecreate
btnMainAction?.setText(R.string.common_continue)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener {
store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.CreateFirstWallet))
}
}
@ -223,7 +223,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
mainBinding.onboardingTopContainer.onboardingTwinsWelcomeBg.bgCircleLarge.hide()
mainBinding.onboardingTopContainer.onboardingTwinsWelcomeBg.bgCircleMedium.hide()
mainBinding.onboardingTopContainer.onboardingTwinsWelcomeBg.bgCircleMin.hide()
chbUnderstand.hide()
chbUnderstand?.hide()
pbBinding.pbState.show()
mainBinding.onboardingTopContainer.onboardingWalletContainer.beginDelayedTransition()
@ -251,11 +251,11 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
val twinIndexNumber = state.cardNumber?.indexNumber()
tvHeader.text = getString(R.string.twins_recreate_title_format, twinIndexNumber)
tvBody.setText(R.string.onboarding_twins_interrupt_warning)
tvBody?.setText(R.string.onboarding_twins_interrupt_warning)
btnMainAction.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
btnMainAction.setOnClickListener {
btnMainAction?.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
btnMainAction?.setIconResource(R.drawable.ic_tangem_24)
btnMainAction?.setOnClickListener {
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
store.dispatch(
TwinCardsAction.Wallet.LaunchFirstStep(
@ -265,8 +265,8 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction.isClickable = false
btnAlternativeAction?.isVisible = false
btnAlternativeAction?.isClickable = false
}
private fun setupCreateSecondWalletState(state: TwinCardsState) = with(mainBinding.onboardingActionContainer) {
@ -274,12 +274,12 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
val twinPairIndexNumber = state.cardNumber?.pairIndexNumber()
tvHeader.text = getString(R.string.twins_recreate_title_format, twinPairIndexNumber)
tvBody.setText(R.string.onboarding_twins_interrupt_warning)
tvBody?.setText(R.string.onboarding_twins_interrupt_warning)
btnMainAction.text =
btnMainAction?.text =
getString(R.string.twins_recreate_button_format, twinPairIndexNumber)
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
btnMainAction.setOnClickListener {
btnMainAction?.setIconResource(R.drawable.ic_tangem_24)
btnMainAction?.setOnClickListener {
store.dispatch(
TwinCardsAction.Wallet.LaunchSecondStep(
Message(
@ -300,11 +300,11 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
val twinIndexNumber = state.cardNumber?.indexNumber()
tvHeader.text = getString(R.string.twins_recreate_title_format, twinIndexNumber)
tvBody.setText(R.string.onboarding_twins_interrupt_warning)
tvBody?.setText(R.string.onboarding_twins_interrupt_warning)
btnMainAction.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
btnMainAction.setOnClickListener {
btnMainAction?.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
btnMainAction?.setIconResource(R.drawable.ic_tangem_24)
btnMainAction?.setOnClickListener {
store.dispatch(
TwinCardsAction.Wallet.LaunchThirdStep(
Message(getString(R.string.twins_recreate_title_format, twinIndexNumber)),
@ -337,27 +337,27 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
}
if (state.isBuyAllowed) {
btnMainAction.setText(R.string.onboarding_top_up_button_but_crypto)
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.onboarding_top_up_button_but_crypto)
btnMainAction?.setOnClickListener {
store.dispatch(TwinCardsAction.TopUp)
}
btnAlternativeAction.isVisible = true
btnAlternativeAction.setText(R.string.onboarding_top_up_button_show_wallet_address)
btnAlternativeAction.setOnClickListener {
btnAlternativeAction?.isVisible = true
btnAlternativeAction?.setText(R.string.onboarding_top_up_button_show_wallet_address)
btnAlternativeAction?.setOnClickListener {
store.dispatch(TwinCardsAction.ShowAddressInfoDialog)
}
} else {
btnMainAction.setText(R.string.onboarding_button_receive_crypto)
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.onboarding_button_receive_crypto)
btnMainAction?.setOnClickListener {
store.dispatch(TwinCardsAction.ShowAddressInfoDialog)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction?.isVisible = false
}
tvHeader.setText(R.string.onboarding_topup_title)
tvBody.setText(R.string.onboarding_top_up_body)
btnMainAction.icon = null
tvBody?.setText(R.string.onboarding_top_up_body)
btnMainAction?.icon = null
btnRefreshBalanceWidget.changeState(state.walletBalance.state)
if (btnRefreshBalanceWidget.isShowing != true) {
@ -375,18 +375,18 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
}
private fun setupDoneState(state: TwinCardsState) = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.common_continue)
btnMainAction.icon = null
btnMainAction.setOnClickListener {
btnMainAction?.setText(R.string.common_continue)
btnMainAction?.icon = null
btnMainAction?.setOnClickListener {
store.dispatch(TwinCardsAction.Confetti.Hide)
store.dispatch(TwinCardsAction.Done)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction.isClickable = false
btnAlternativeAction?.isVisible = false
btnAlternativeAction?.isClickable = false
tvHeader.setText(R.string.onboarding_done_header)
tvBody.setText(R.string.onboarding_done_body)
tvBody?.setText(R.string.onboarding_done_body)
val layout = when (state.mode) {
CreateTwinWalletMode.CreateWallet -> R.layout.lp_onboarding_done_activation_twins

View file

@ -250,7 +250,7 @@ class TestBackupAnimation(
}
@Suppress("MagicNumber")
fun setStep(step: Int, onStepUpdate: (Int) -> Unit = {}) {
private fun setStep(step: Int, onStepUpdate: (Int) -> Unit = {}) {
steps = step
when (steps) {
0 -> setupCreateWalletState()

View file

@ -140,7 +140,7 @@ class OnboardingWalletFragment :
}
private fun initCardsWidget(leapfrogWidget: LeapfrogWidget, deviceScaleFactor: Float, isTest: Boolean = false) {
cardsWidget = WalletCardsWidget(leapfrogWidget, deviceScaleFactor) { 200f * deviceScaleFactor }
cardsWidget = WalletCardsWidget(leapfrogWidget, deviceScaleFactor)
animator = if (isTest) {
TestBackupAnimation(WalletBackupAnimator(cardsWidget), binding)
} else {

View file

@ -7,19 +7,16 @@ import android.view.View
import android.widget.ImageView
import androidx.core.animation.doOnEnd
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapView
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapViewState
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapfrogWidget
class WalletCardsWidget(
val leapfrogWidget: LeapfrogWidget,
private val deviceScaleFactor: Float = 1f,
val getTopOfAnchorViewForActivateState: () -> Float,
) {
private val animDuration: Long = 400
var currentState: WidgetState? = null
private set
private var currentState: WidgetState? = null
fun toWelcome(animate: Boolean = true, onEnd: () -> Unit = {}) {
if (currentState == WidgetState.WELCOME) return
@ -239,15 +236,5 @@ private data class CardProperties(
)
}
companion object {
fun from(leapViewState: LeapViewState): CardProperties {
val leapViewProperties = leapViewState.properties
return CardProperties(
yTranslation = leapViewProperties.yTranslation,
elevation = leapViewProperties.elevationEnd,
scale = leapViewProperties.scale,
)
}
}
companion object
}

View file

@ -86,19 +86,9 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
binding.groupControlsTemporary.show()
binding.btnClose.hide()
val buttonAction =
when (warning.titleResId) {
// R.string.warning_important_security_info -> {
// View.OnClickListener {
// store.dispatch(WalletAction.DialogAction.SignedHashesMultiWalletDialog)
// }
// }
else -> {
View.OnClickListener {
store.dispatch(GlobalAction.HideWarningMessage(warning))
}
}
}
val buttonAction = View.OnClickListener {
store.dispatch(GlobalAction.HideWarningMessage(warning))
}
val buttonTitle = binding.root.getString(
warning.buttonTextId ?: R.string.how_to_got_it_button,
)
@ -107,18 +97,11 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
}
WarningMessage.Type.AppRating -> {
binding.groupControlsTemporary.hide()
binding.groupControlsRating.show()
binding.btnClose.show()
binding.btnClose.setOnClickListener {
Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Closed))
store.dispatch(GlobalAction.HideWarningMessage(warning))
}
// binding.btnCanBeBetter.setOnClickListener {
// Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Disliked))
// store.dispatch(WalletAction.Warnings.AppRating.SetNeverToShow)
// store.dispatch(GlobalAction.HideWarningMessage(warning))
// store.dispatch(GlobalAction.SendEmail(RateCanBeBetterEmail()))
// }
binding.btnReallyCool.setOnClickListener {
val activity = binding.root.context.getActivity() ?: return@setOnClickListener
@ -126,16 +109,7 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi
val reviewManager = ReviewManagerFactory.create(activity)
val task = reviewManager.requestReviewFlow()
task.addOnCompleteListener {
if (it.isSuccessful) {
val reviewFlow = reviewManager.launchReviewFlow(activity, it.result)
reviewFlow.addOnCompleteListener {
if (it.isSuccessful) {
// send review was succeed
} else {
// send fails
}
}
} else {
if (!it.isSuccessful) {
Timber.e(task.exception)
}
}.addOnFailureListener {

View file

@ -1,131 +0,0 @@
package com.tangem.tap.features.wallet.models
import com.tangem.blockchain.common.derivation.DerivationStyle
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.BlockchainNetwork
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.toCoinId
import com.tangem.domain.features.addCustomToken.CustomCurrency
import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.blockchain.common.Blockchain as SdkBlockchain
import com.tangem.blockchain.common.Token as SdkToken
sealed interface Currency {
val coinId: String?
get() = when (this) {
is Blockchain -> blockchain.toCoinId()
is Token -> token.id
}
val blockchain: SdkBlockchain
val currencySymbol: CryptoCurrencyName
val derivationPath: String?
val currencyName: String
get() = when (this) {
is Blockchain -> blockchain.fullName
is Token -> token.name
}
val decimals
get() = when (this) {
is Blockchain -> blockchain.decimals()
is Token -> token.decimals
}
data class Token(
val token: SdkToken,
override val blockchain: SdkBlockchain,
override val derivationPath: String?,
) : Currency {
override val currencySymbol = token.symbol
}
data class Blockchain(
override val blockchain: SdkBlockchain,
override val derivationPath: String?,
) : Currency {
override val currencySymbol: CryptoCurrencyName = blockchain.currency
}
fun isCustomCurrency(derivationStyle: DerivationStyle?): Boolean {
if (this is Token && this.token.id == null) return true
if (derivationPath == null || derivationStyle == null) return false
return derivationPath != blockchain.derivationPath(derivationStyle)?.rawPath
}
fun isBlockchain(): Boolean = this is Blockchain
fun isToken(): Boolean = this is Token
companion object {
fun fromBlockchainNetwork(blockchainNetwork: BlockchainNetwork, token: SdkToken? = null): Currency {
return if (token != null) {
Token(
token = token,
blockchain = blockchainNetwork.blockchain,
derivationPath = blockchainNetwork.derivationPath,
)
} else {
Blockchain(
blockchain = blockchainNetwork.blockchain,
derivationPath = blockchainNetwork.derivationPath,
)
}
}
fun fromCustomCurrency(customCurrency: CustomCurrency): Currency {
return when (customCurrency) {
is CustomCurrency.CustomBlockchain -> Blockchain(
blockchain = customCurrency.network,
derivationPath = customCurrency.derivationPath?.rawPath,
)
is CustomCurrency.CustomToken -> Token(
token = customCurrency.token,
blockchain = customCurrency.network,
derivationPath = customCurrency.derivationPath?.rawPath,
)
}
}
fun fromTokenResponse(tokenBody: UserTokensResponse.Token): Currency? {
val blockchain = com.tangem.blockchain.common.Blockchain.fromNetworkId(tokenBody.networkId)
?: return null
return when {
tokenBody.contractAddress != null -> Token(
token = SdkToken(
name = tokenBody.name,
symbol = tokenBody.symbol,
contractAddress = tokenBody.contractAddress!!,
decimals = tokenBody.decimals,
id = tokenBody.id,
),
blockchain = blockchain,
derivationPath = tokenBody.derivationPath,
)
else -> Blockchain(
blockchain = blockchain,
derivationPath = tokenBody.derivationPath,
)
}
}
}
}
fun BlockchainNetwork.toCurrencies(): List<Currency> {
val blockchain = Currency.fromBlockchainNetwork(this)
val tokens = this.tokens.map { Currency.fromBlockchainNetwork(this, it) }
return listOf(blockchain) + tokens
}
fun List<BlockchainNetwork>.toCurrencies(): List<Currency> {
return flatMap { it.toCurrencies() }
}
fun List<Currency>.toBlockchainNetworks(): List<BlockchainNetwork> {
return this.filter { it.isBlockchain() }.map { BlockchainNetwork(it.blockchain, it.derivationPath, getTokens(it)) }
}
fun List<Currency>.getTokens(currency: Currency): List<SdkToken> {
return this
.filter { it.isToken() && it.blockchain == currency.blockchain && it.derivationPath == currency.derivationPath }
.mapNotNull { if (it is Currency.Token) it.token else null }
}

View file

@ -1,86 +0,0 @@
package com.tangem.tap.features.wallet.models
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.TransactionStatus
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.extensions.isAboveZero
import com.tangem.tap.common.extensions.toFormattedString
import java.math.BigDecimal
data class PendingTransaction(
val transactionData: TransactionData,
val type: PendingTransactionType,
) {
val address: String? = when (type) {
PendingTransactionType.Incoming -> nullIfUnknown(transactionData.sourceAddress)
PendingTransactionType.Outgoing -> nullIfUnknown(transactionData.destinationAddress)
PendingTransactionType.Unknown -> null
}
val amountValue: BigDecimal? = transactionData.amount.value
val amountValueUi: String? = amountValue?.toFormattedString(transactionData.amount.decimals)
val currency: String = transactionData.amount.currencySymbol
private fun nullIfUnknown(address: String): String? = if (address == "unknown") null else address
}
enum class PendingTransactionType { Incoming, Outgoing, Unknown }
fun TransactionData.toPendingTransaction(walletAddress: String): PendingTransaction? {
if (this.status == TransactionStatus.Confirmed) return null
val type: PendingTransactionType = when {
this.sourceAddress == walletAddress -> PendingTransactionType.Outgoing
this.destinationAddress == walletAddress -> PendingTransactionType.Incoming
else -> PendingTransactionType.Unknown
}
return PendingTransaction(this, type)
}
fun List<TransactionData>.toPendingTransactions(walletAddress: String): List<PendingTransaction> {
return this.mapNotNull { it.toPendingTransaction(walletAddress) }
}
fun List<PendingTransaction>.filterByCoin(): List<PendingTransaction> {
return this.filter { it.transactionData.amount.type == AmountType.Coin }
}
fun TransactionData.toPendingTransactionForToken(token: Token, walletAddress: String): PendingTransaction? {
if (this.amount.currencySymbol != token.symbol) return null
return this.toPendingTransaction(walletAddress)
}
fun Wallet.getPendingTransactions(type: PendingTransactionType? = null): List<PendingTransaction> {
val txs = recentTransactions.toPendingTransactions(address)
return when (type) {
null -> txs
else -> txs.filter { it.type == type }
}
}
fun Wallet.getPendingTransactions(token: Token): List<PendingTransaction> {
return recentTransactions.mapNotNull { it.toPendingTransactionForToken(token, address) }
}
fun Wallet.hasPendingTransactions(): Boolean {
return getPendingTransactions().isNotEmpty()
}
fun Wallet.getSendableAmounts(): List<Amount> {
return amounts.values
.filter { it.type != AmountType.Reserve }
.filter { it.isAboveZero() }
}
fun Wallet.hasSendableAmounts(): Boolean {
return getSendableAmounts().isNotEmpty()
}
fun Wallet.isSendableAmount(type: AmountType): Boolean {
return amounts[type]?.isAboveZero() == true
}