Updated on 2026-08-14

This commit is contained in:
Tangem 2022-07-12 14:27:49 +04:00
commit 005126d1bb
48 changed files with 854 additions and 554 deletions

View file

@ -38,7 +38,9 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState
StoriesScreen(
homeState,
onScanButtonClick = { store.dispatch(HomeAction.ReadCard) },
onShopButtonClick = { store.dispatch(HomeAction.GoToShop(getRegionProvider())) },
onShopButtonClick = {
store.dispatch(HomeAction.GoToShop(store.state.globalState.userCountryCode))
},
onSearchTokensClick = {
store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens))
store.dispatch(TokensAction.AllowToAddTokens(false))

View file

@ -44,5 +44,8 @@ class TelephonyManagerRegionProvider(context: Context) : RegionProvider {
}
class LocaleRegionProvider : RegionProvider {
override fun getRegion(): String? = Locale.current.region
}
override fun getRegion(): String = Locale.current.region
}
const val RUSSIA_COUNTRY_CODE = "ru"
const val BELARUS_COUNTRY_CODE = "by"

View file

@ -1,13 +1,12 @@
package com.tangem.tap.features.home.redux
import com.tangem.tap.common.entities.IndeterminateProgressButton
import com.tangem.tap.features.home.RegionProvider
import org.rekotlin.Action
sealed class HomeAction : Action {
// from ui
object ReadCard : HomeAction()
data class GoToShop(val regionProvider: RegionProvider) : HomeAction()
data class GoToShop(val userCountryCode: String?) : HomeAction()
// internal
data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction()

View file

@ -15,6 +15,8 @@ import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.FragmentShareTransition
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.home.BELARUS_COUNTRY_CODE
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.home.redux.HomeMiddleware.Companion.BUY_WALLET_URL
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
@ -30,19 +32,19 @@ class HomeMiddleware {
companion object {
val handler = homeMiddleware
const val CARD_SHOP_URI = "http://cards.tangem.com/"
const val BUY_WALLET_URL = "https://mv.tangem.com/"
const val BUY_WALLET_URL = "https://tangem.com/ru/resellers/"
}
}
private val homeMiddleware: Middleware<AppState> = { dispatch, state ->
private val homeMiddleware: Middleware<AppState> = { _, _ ->
{ next ->
{ action ->
when (action) {
is HomeAction.Init -> {
store.dispatch(GlobalAction.RestoreAppCurrency)
store.dispatch(GlobalAction.InitCurrencyExchangeManager)
store.dispatch(GlobalAction.ExchangeManager.Init)
store.dispatch(HomeAction.SetTermsOfUseState(preferencesStorage.wasDisclaimerAccepted()))
store.dispatch(GlobalAction.FetchUserCountry)
}
is HomeAction.ShouldScanCardOnResume -> {
if (action.shouldScanCard) {
@ -55,8 +57,9 @@ private val homeMiddleware: Middleware<AppState> = { dispatch, state ->
// store.dispatch(NavigationAction.NavigateTo(AppScreen.AddCustomTokens))
}
is HomeAction.GoToShop -> {
when (action.regionProvider.getRegion()?.toLowerCase()) {
"ru" -> store.dispatchOpenUrl(BUY_WALLET_URL)
when (action.userCountryCode) {
RUSSIA_COUNTRY_CODE, BELARUS_COUNTRY_CODE ->
store.dispatchOpenUrl(BUY_WALLET_URL)
else -> store.dispatch(NavigationAction.NavigateTo(AppScreen.Shop))
}
store.state.globalState.analyticsHandlers?.triggerEvent(

View file

@ -83,7 +83,7 @@ class OnboardingManager(
data class OnboardingWalletBalance(
val value: BigDecimal = BigDecimal.ZERO,
val currency: Currency.Blockchain = Currency.Blockchain(Blockchain.Unknown, null),
val currency: Currency = Currency.Blockchain(Blockchain.Unknown, null),
val hasIncomingTransaction: Boolean = false,
val state: ProgressState,
val error: TapError? = null,

View file

@ -2,7 +2,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.domain.extensions.buyIsAllowed
import com.tangem.tap.features.onboarding.OnboardingWalletBalance
import com.tangem.tap.store
import org.rekotlin.StateType
@ -26,8 +25,8 @@ data class OnboardingNoteState(
val progress: Int
get() = steps.indexOf(currentStep)
val isBuyAllowed: Boolean by ReadOnlyProperty<Any, Boolean> { thisRef, property ->
store.state.globalState.currencyExchangeManager?.buyIsAllowed(walletBalance.currency) ?: false
val isBuyAllowed: Boolean by ReadOnlyProperty<Any, Boolean> { _, _ ->
store.state.globalState.exchangeManager?.availableForBuy(walletBalance.currency) ?: false
}
}

View file

@ -3,7 +3,6 @@ package com.tangem.tap.features.onboarding.products.twins.redux
import com.tangem.blockchain.common.WalletManager
import com.tangem.domain.common.TwinCardNumber
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.extensions.buyIsAllowed
import com.tangem.tap.domain.twins.TwinCardsManager
import com.tangem.tap.features.onboarding.OnboardingWalletBalance
import com.tangem.tap.store
@ -56,8 +55,8 @@ data class TwinCardsState(
val showAlert: Boolean
get() = currentStep == TwinCardsStep.CreateSecondWallet || currentStep == TwinCardsStep.CreateThirdWallet
val isBuyAllowed: Boolean by ReadOnlyProperty<Any, Boolean> { thisRef, property ->
store.state.globalState.currencyExchangeManager?.buyIsAllowed(walletBalance.currency) ?: false
val isBuyAllowed: Boolean by ReadOnlyProperty<Any, Boolean> { _, _ ->
store.state.globalState.exchangeManager?.availableForBuy(walletBalance.currency) ?: false
}
}

View file

@ -154,6 +154,7 @@ sealed class WalletAction : Action {
object SignedHashesMultiWalletDialog : DialogAction()
object ChooseTradeActionDialog : DialogAction()
data class ChooseCurrency(val amounts: List<Amount>?) : DialogAction()
object RussianCardholdersWarningDialog : DialogAction()
object Hide : DialogAction()
}
@ -164,8 +165,10 @@ sealed class WalletAction : Action {
object EmptyWallet : WalletAction()
sealed class TradeCryptoAction : WalletAction() {
object Buy : TradeCryptoAction()
object Sell : TradeCryptoAction()
data class Buy(
val checkUserLocation: Boolean = true,
) : TradeCryptoAction()
data class FinishSelling(val transactionId: String) : TradeCryptoAction()
data class SendCrypto(
val currencyId: String,

View file

@ -6,6 +6,12 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.address.AddressType
import com.tangem.common.extensions.isZero
import com.tangem.domain.common.extensions.canHandleToken
@ -16,8 +22,6 @@ import com.tangem.tap.common.redux.StateDialog
import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.tap.common.toggleWidget.WidgetState
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.extensions.buyIsAllowed
import com.tangem.tap.domain.extensions.sellIsAllowed
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
import com.tangem.tap.features.wallet.models.Currency
@ -28,6 +32,14 @@ import com.tangem.tap.features.wallet.models.WalletWarning
import com.tangem.tap.features.wallet.models.hasPendingTransactions
import com.tangem.tap.features.wallet.models.hasSendableAmounts
import com.tangem.tap.features.wallet.models.isSendableAmount
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
import com.tangem.tap.features.wallet.models.PendingTransaction
import com.tangem.tap.features.wallet.models.TotalBalance
import com.tangem.tap.features.wallet.models.WalletRent
import com.tangem.tap.features.wallet.models.WalletWarning
import com.tangem.tap.features.wallet.models.hasPendingTransactions
import com.tangem.tap.features.wallet.models.hasSendableAmounts
import com.tangem.tap.features.wallet.models.isSendableAmount
import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount
import com.tangem.tap.features.wallet.redux.reducers.findProgressState
import com.tangem.tap.features.wallet.ui.BalanceStatus
@ -35,6 +47,7 @@ import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import com.tangem.tap.store
import java.math.BigDecimal
import org.rekotlin.StateType
import kotlin.properties.ReadOnlyProperty
import org.rekotlin.StateType
@ -71,7 +84,7 @@ data class WalletState(
val shouldShowDetails: Boolean =
primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain
primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain
val blockchains: List<Blockchain>
get() = wallets.mapNotNull { it.walletManager?.wallet?.blockchain }
@ -328,6 +341,7 @@ sealed interface WalletDialog : StateDialog {
val currenciesList: List<FiatCurrency>,
val currentAppCurrency: FiatCurrency,
) : WalletDialog
object RussianCardholdersWarningDialog : WalletDialog
}
enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error }
@ -372,18 +386,21 @@ data class Artwork(
}
data class TradeCryptoState(
val sellingAllowed: Boolean = false,
val buyingAllowed: Boolean = false,
val isAvailableToSell: () -> Boolean = { false },
val isAvailableToBuy: () -> Boolean = { false },
) {
companion object {
fun from(
exchangeManager: CurrencyExchangeManager?,
walletData: WalletData
): TradeCryptoState {
val status = exchangeManager ?: return walletData.tradeCryptoState
val exchanger = exchangeManager ?: return walletData.tradeCryptoState
val currency = walletData.currency
return TradeCryptoState(status.sellIsAllowed(currency), status.buyIsAllowed(currency))
return TradeCryptoState(
isAvailableToSell = { exchanger.availableForSell(currency) },
isAvailableToBuy = { exchanger.availableForBuy(currency) },
)
}
}
}

View file

@ -8,12 +8,13 @@ import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.send.redux.PrepareSendScreen
import com.tangem.tap.features.send.redux.SendAction
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import com.tangem.tap.network.exchangeServices.buyErc20Tokens
import com.tangem.tap.network.exchangeServices.buyErc20TestnetTokens
import com.tangem.tap.scope
import com.tangem.tap.store
import kotlinx.coroutines.launch
@ -24,51 +25,70 @@ class TradeCryptoMiddleware {
if (DemoHelper.tryHandle(state, action)) return
when (action) {
is WalletAction.TradeCryptoAction.Buy -> startExchange(action)
is WalletAction.TradeCryptoAction.Sell -> startExchange(action)
is WalletAction.TradeCryptoAction.Buy -> proceedBuyAction(state, action)
is WalletAction.TradeCryptoAction.Sell -> proceedSellAction()
is WalletAction.TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen(action)
is WalletAction.TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId)
}
}
private fun startExchange(action: WalletAction.TradeCryptoAction) {
val selectedWalletData = store.state.walletState.getSelectedWalletData()
val exchangeManager = store.state.globalState.currencyExchangeManager ?: return
val addresses = selectedWalletData?.walletAddresses ?: return
if (addresses.list.isEmpty()) return
val appCurrency = store.state.globalState.appCurrency
val defaultAddress = addresses.list[0].address
val currency = selectedWalletData.currency
val currencySymbol = selectedWalletData.currency.currencySymbol
val exchangeAction = if (action is WalletAction.TradeCryptoAction.Buy) {
CurrencyExchangeManager.Action.Buy
} else {
CurrencyExchangeManager.Action.Sell
private fun proceedBuyAction(
state: () -> AppState?,
action: WalletAction.TradeCryptoAction.Buy,
) {
if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) {
store.dispatchOnMain(
WalletAction.DialogAction.RussianCardholdersWarningDialog
)
return
}
if (exchangeAction == CurrencyExchangeManager.Action.Buy &&
currency is Currency.Token && currency.blockchain.isTestnet()
) {
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
val exchangeManager = store.state.globalState.exchangeManager ?: return
val appCurrency = store.state.globalState.appCurrency
val addresses = selectedWalletData.walletAddresses?.list.orEmpty()
if (addresses.isEmpty()) return
val currency = selectedWalletData.currency
if (currency is Currency.Token && currency.blockchain.isTestnet()) {
val walletManager = store.state.walletState.getWalletManager(currency)
if (walletManager !is EthereumWalletManager) {
store.dispatchDebugErrorNotification("Testnet tokens available only for the ETH")
store.dispatchDebugErrorNotification("Testnet tokens available only for the Ethereum")
return
}
scope.launch { exchangeManager.buyErc20Tokens(walletManager, currency.token) }
scope.launch { exchangeManager.buyErc20TestnetTokens(walletManager, currency.token) }
return
}
exchangeManager.getUrl(
action = exchangeAction,
action = CurrencyExchangeManager.Action.Buy,
blockchain = currency.blockchain,
cryptoCurrencyName = currencySymbol,
cryptoCurrencyName = currency.currencySymbol,
fiatCurrencyName = appCurrency.code,
walletAddress = defaultAddress
walletAddress = addresses[0].address
)?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) }
}
private fun proceedSellAction() {
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
val exchangeManager = store.state.globalState.exchangeManager ?: return
val appCurrency = store.state.globalState.appCurrency
val addresses = selectedWalletData.walletAddresses?.list.orEmpty()
if (addresses.isEmpty()) return
val currency = selectedWalletData.currency
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)) }
}
private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) {
@ -89,7 +109,7 @@ class TradeCryptoMiddleware {
}
private fun openReceiptUrl(transactionId: String) {
val exchangeManager = store.state.globalState.currencyExchangeManager ?: return
val exchangeManager = store.state.globalState.exchangeManager ?: return
store.dispatchOnMain(NavigationAction.PopBackTo())
exchangeManager.getSellCryptoReceiptUrl(CurrencyExchangeManager.Action.Sell, transactionId)?.let {

View file

@ -27,10 +27,13 @@ class WalletDialogsMiddleware {
is WalletAction.DialogAction.ChooseCurrency -> {
store.dispatchDialogShow(
WalletDialog.SelectAmountToSendDialog(
amounts = action.amounts
amounts = action.amounts
)
)
}
is WalletAction.DialogAction.RussianCardholdersWarningDialog -> {
store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog)
}
is WalletAction.DialogAction.Hide -> {
store.dispatchDialogHide()
}

View file

@ -38,7 +38,7 @@ class OnWalletLoadedReducer {
val walletData = walletState.getWalletData(blockchainNetwork) ?: return walletState
val fiatCurrency = store.state.globalState.appCurrency
val exchangeManager = store.state.globalState.currencyExchangeManager
val exchangeManager = store.state.globalState.exchangeManager
val coinAmountValue = wallet.amounts[AmountType.Coin]?.value
val formattedAmount = coinAmountValue?.toFormattedCurrencyString(
@ -118,7 +118,7 @@ class OnWalletLoadedReducer {
if (wallet.blockchain != walletState.primaryBlockchain) return walletState
val fiatCurrencyName = store.state.globalState.appCurrency.code
val exchangeManager = store.state.globalState.currencyExchangeManager
val exchangeManager = store.state.globalState.exchangeManager
val token = wallet.getFirstToken()
val tokenData = if (token != null) {

View file

@ -6,17 +6,14 @@ import com.tangem.blockchain.common.Wallet
import com.tangem.common.extensions.mapNotNullValues
import com.tangem.domain.common.TwinCardNumber
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.extensions.toFiatRateString
import com.tangem.tap.common.extensions.toFiatString
import com.tangem.tap.common.extensions.toFiatValue
import com.tangem.tap.common.extensions.toFormattedCurrencyString
import com.tangem.tap.common.extensions.toFormattedFiatValue
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.extensions.getArtworkUrl
import com.tangem.tap.domain.getFirstToken
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.wallet.models.WalletRent
import com.tangem.tap.features.wallet.redux.*
import com.tangem.tap.features.wallet.redux.AddressData
import com.tangem.tap.features.wallet.redux.Artwork
import com.tangem.tap.features.wallet.models.Currency
@ -32,8 +29,8 @@ import com.tangem.tap.features.wallet.redux.WalletStore
import com.tangem.tap.features.wallet.ui.BalanceStatus
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import com.tangem.tap.store
import java.math.BigDecimal
import org.rekotlin.Action
import java.math.BigDecimal
class WalletReducer {
companion object {
@ -49,7 +46,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
if (action !is WalletAction) return state.walletState
val exchangeManager = store.state.globalState.currencyExchangeManager
val exchangeManager = store.state.globalState.exchangeManager
var newState = state.walletState
when (action) {

View file

@ -92,7 +92,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
private fun setupButtons() = with(binding) {
rowButtons.onBuyClick = {
store.dispatch(WalletAction.TradeCryptoAction.Buy)
store.dispatch(WalletAction.TradeCryptoAction.Buy())
}
rowButtons.onSellClick = {
store.dispatch(WalletAction.TradeCryptoAction.Sell)
@ -184,8 +184,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
}
rowButtons.updateButtonsVisibility(
buyAllowed = selectedWallet.tradeCryptoState.buyingAllowed,
sellAllowed = selectedWallet.tradeCryptoState.sellingAllowed,
buyAllowed = selectedWallet.tradeCryptoState.isAvailableToBuy(),
sellAllowed = selectedWallet.tradeCryptoState.isAvailableToSell(),
sendAllowed = selectedWallet.mainButton.enabled,
)
}

View file

@ -27,12 +27,12 @@ class ChooseTradeActionBottomSheetDialog(context: Context) : BottomSheetDialog(c
}
binding!!.dialogBtnBuy.setOnClickListener {
store.dispatch(WalletAction.TradeCryptoAction.Buy)
dismiss()
store.dispatch(WalletAction.TradeCryptoAction.Buy())
}
binding!!.dialogBtnSell.setOnClickListener {
store.dispatch(WalletAction.TradeCryptoAction.Sell)
dismiss()
store.dispatch(WalletAction.TradeCryptoAction.Sell)
}
}
}

View file

@ -0,0 +1,44 @@
package com.tangem.tap.features.wallet.ui.dialogs
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tangem.tap.common.extensions.dispatchDialogHide
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.store
import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding
class RussianCardholdersWarningBottomSheetDialog(context: Context) : BottomSheetDialog(context) {
private var binding: DialogRussiansCardholdersWarningBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DialogRussiansCardholdersWarningBinding
.inflate(LayoutInflater.from(context))
.also { setContentView(it.root) }
}
override fun show() {
super.show()
setOnDismissListener {
binding = null
store.dispatchDialogHide()
}
binding?.btnYes?.setOnClickListener {
store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false))
dismiss()
}
binding?.btnNo?.setOnClickListener {
store.dispatch(NavigationAction.OpenUrl(INSTRUCTION_URL))
dismiss()
}
}
companion object {
private const val INSTRUCTION_URL = "https://tangem.com/howtobuy.html"
}
}

View file

@ -1,12 +1,9 @@
package com.tangem.tap.features.wallet.ui.images
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.utils.widget.ImageFilterView
import coil.imageLoader
import coil.load
import coil.request.ImageRequest
import coil.transform.RoundedCornersTransformation
import com.tangem.blockchain.common.Blockchain
@ -29,57 +26,112 @@ fun loadCurrencyIcon(
token: Token?,
blockchain: Blockchain,
) {
when {
token == null -> currencyImageView.loadIcon(
iconUrl = getIconUrl(blockchain.toNetworkId()),
placeholderRes = blockchain.getRoundIconRes(),
CurrencyIconLoader(
currencyImageView = currencyImageView,
currencyTextView = currencyTextView,
token = token,
blockchain = blockchain
)
.load()
}
private class CurrencyIconLoader(
private val currencyImageView: ImageFilterView,
private val currencyTextView: TextView,
private val token: Token?,
private val blockchain: Blockchain,
) {
fun load() {
when {
token == null && blockchain.isTestnet() -> loadTestnetBlockchainIcon()
token == null -> loadBlockchainIcon()
blockchain.isTestnet() -> loadTestnetTokenIcon()
else -> loadTokenIcon()
}
}
private fun loadBlockchainIcon() {
loadBlockchainIconBase(
onStart = {
if (blockchain.isTestnet()) {
currencyImageView.saturation = 0f
} else {
currencyImageView.colorFilter = null
}
currencyImageView.colorFilter = null
}
)
token.symbol == QCX -> currencyImageView.load(R.drawable.ic_qcx)
token.symbol == VOYR -> currencyImageView.load(R.drawable.ic_voyr)
else -> currencyImageView.loadIcon(
iconUrl = getTokenIconUrl(token, blockchain),
}
private fun loadTestnetBlockchainIcon() {
loadBlockchainIconBase(
onStart = {
currencyImageView.saturation = 0f
}
)
}
private fun loadTokenIcon() {
loadTokenIconBase(
onStart = {
currencyImageView.setColorFilter(it.getColor())
},
onSuccess = {
currencyImageView.colorFilter = null
}
)
}
private fun loadTestnetTokenIcon() {
loadTokenIconBase(
onStart = {
currencyImageView.saturation = 0f
}
)
}
private inline fun loadBlockchainIconBase(
crossinline onStart: (Blockchain) -> Unit = {},
crossinline onSuccess: (Blockchain) -> Unit = {},
crossinline onError: (Blockchain) -> Unit = {},
) {
currencyImageView.loadIcon(
data = getIconUrl(blockchain.toNetworkId()),
placeholderRes = blockchain.getRoundIconRes(),
onStart = { onStart(blockchain) },
onSuccess = { onSuccess(blockchain) },
onError = { onError(blockchain) },
)
}
private inline fun loadTokenIconBase(
crossinline onStart: (Token) -> Unit = {},
crossinline onSuccess: (Token) -> Unit = {},
crossinline onError: (Token) -> Unit = {},
) {
if (token == null) return
currencyImageView.loadIcon(
data = getTokenIcon(token, blockchain),
placeholderRes = R.drawable.shape_circle,
onStart = {
currencyTextView.text = token.symbol.take(1)
currencyTextView.setTextColor(token.getTextColor())
if (blockchain.isTestnet()) {
currencyImageView.saturation = 0f
}
},
onError = {
currencyImageView.colorFilter = PorterDuffColorFilter(
/* color = */
token.getColor(),
/* mode = */
PorterDuff.Mode.SRC_ATOP,
)
onStart(token)
},
onSuccess = {
if (!blockchain.isTestnet()) {
currencyImageView.colorFilter = null
}
}
currencyTextView.text = null
onSuccess(token)
},
onError = { onError(token) },
)
}
}
private inline fun ImageView.loadIcon(
iconUrl: String?,
data: Any?,
placeholderRes: Int,
crossinline onStart: () -> Unit = {},
crossinline onSuccess: () -> Unit = {},
crossinline onError: () -> Unit = {},
) {
ImageRequest.Builder(context)
.data(iconUrl)
.data(data)
.placeholder(placeholderRes)
.error(placeholderRes)
.fallback(placeholderRes)
@ -101,9 +153,15 @@ private inline fun ImageView.loadIcon(
.also(context.imageLoader::enqueue)
}
private fun getTokenIconUrl(token: Token, blockchain: Blockchain): String? {
return token.id?.let(::getIconUrl)
?: token.getCustomIconUrl()
?: IconsUtil.getTokenIconUri(blockchain, token)
?.toString()
private fun getTokenIcon(token: Token, blockchain: Blockchain): Any? {
return when (token.symbol) {
QCX -> R.drawable.ic_qcx
VOYR -> R.drawable.ic_voyr
else -> {
token.id?.let(::getIconUrl)
?: token.getCustomIconUrl()
?: IconsUtil.getTokenIconUri(blockchain, token)
?.toString()
}
}
}

View file

@ -118,9 +118,8 @@ class SingleWalletView : WalletView {
setupButtonsType(state, binding)
val btnConfirm = if (state.tradeCryptoState.sellingAllowed ||
state.tradeCryptoState.buyingAllowed
) {
val tradeState = state.tradeCryptoState
val btnConfirm = if (tradeState.isAvailableToSell() || tradeState.isAvailableToBuy()) {
lButtonsShort.btnConfirm
} else {
lButtonsLong.btnConfirmLong
@ -148,10 +147,10 @@ class SingleWalletView : WalletView {
}
private fun setupTradeButton(binding: FragmentWalletBinding, tradeCryptoState: TradeCryptoState) {
val allowedToBuy = tradeCryptoState.buyingAllowed
val allowedToSell = tradeCryptoState.sellingAllowed
val allowedToBuy = tradeCryptoState.isAvailableToBuy()
val allowedToSell = tradeCryptoState.isAvailableToSell()
val action = when {
allowedToBuy && !allowedToSell -> WalletAction.TradeCryptoAction.Buy
allowedToBuy && !allowedToSell -> WalletAction.TradeCryptoAction.Buy()
!allowedToBuy && allowedToSell -> WalletAction.TradeCryptoAction.Sell
allowedToBuy && allowedToSell -> WalletAction.DialogAction.ChooseTradeActionDialog
else -> null
@ -176,9 +175,7 @@ class SingleWalletView : WalletView {
}
private fun setupButtonsType(state: WalletData, binding: FragmentWalletBinding) = with(binding) {
if (state.tradeCryptoState.sellingAllowed ||
state.tradeCryptoState.buyingAllowed
) {
if (state.tradeCryptoState.isAvailableToSell() || state.tradeCryptoState.isAvailableToBuy()) {
lButtonsLong.root.hide()
lButtonsShort.root.show()
} else {