Updated on 2026-08-14

This commit is contained in:
Tangem 2022-07-26 18:34:38 +03:00
commit e2d1147b5c
45 changed files with 600 additions and 232 deletions

View file

@ -109,7 +109,7 @@ class DemoConfig {
testDemoCardIds).distinct()
}
private val releaseDemoCardIds = mutableListOf<String>(
private val releaseDemoCardIds = mutableListOf(
// Tangem Wallet:
"AC01000000041100",
"AC01000000042462",
@ -284,7 +284,10 @@ class DemoTransactionSender(
override suspend fun send(transactionData: TransactionData, signer: TransactionSigner): SimpleResult {
val dataToSign = randomString(32).toByteArray()
val signerResponse = signer.sign(dataToSign, walletManager.wallet.cardId, walletManager.wallet.publicKey)
val signerResponse = signer.sign(
hash = dataToSign,
publicKey = walletManager.wallet.publicKey
)
return when (signerResponse) {
is CompletionResult.Success -> SimpleResult.Failure(Exception(ID))
is CompletionResult.Failure -> SimpleResult.fromTangemSdkError(signerResponse.error)

View file

@ -1,10 +1,10 @@
package com.tangem.tap.features.demo
import com.tangem.blockchain.common.WalletManager
import com.tangem.common.card.Card
import com.tangem.domain.common.ScanResponse
/**
[REDACTED_AUTHOR]
*/
fun ScanResponse.isDemoCard(): Boolean = DemoHelper.isDemoCardId(card.cardId)
fun WalletManager.isDemoWallet(): Boolean = DemoHelper.isDemoCardId(wallet.cardId)
fun Card.isDemoCard(): Boolean = DemoHelper.isDemoCardId(cardId)

View file

@ -1,6 +1,7 @@
package com.tangem.tap.features.details.redux.walletconnect
import android.app.Activity
import com.tangem.blockchain.common.Blockchain
import com.tangem.domain.common.ScanResponse
import com.tangem.tap.common.redux.NotificationAction
import com.tangem.wallet.R
@ -47,6 +48,16 @@ sealed class WalletConnectAction : Action {
data class Success(val session: WalletConnectSession) : WalletConnectAction()
}
data class SwitchBlockchain(
val blockchain: Blockchain?,
val session: WalletConnectSession
) : WalletConnectAction()
data class UpdateBlockchain(
val updatedSession: WalletConnectSession
) : WalletConnectAction()
data class FailureEstablishingSession(val session: WCSession?) : WalletConnectAction()
data class SetSessionsRestored(val sessions: List<WalletConnectSession>) :

View file

@ -1,10 +1,8 @@
package com.tangem.tap.features.details.redux.walletconnect
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.WalletManager
import com.tangem.common.extensions.guard
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.TapWorkarounds.isTestCard
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.getFromClipboard
@ -14,11 +12,10 @@ import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.currenciesRepository
import com.tangem.tap.domain.extensions.isMultiwalletAllowed
import com.tangem.tap.domain.extensions.makeWalletManagerForApp
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.domain.walletconnect.BnbHelper
import com.tangem.tap.domain.walletconnect.WalletConnectManager
import com.tangem.tap.domain.walletconnect.WalletConnectNetworkUtils
import com.tangem.tap.domain.walletconnect.WcWalletManagerFactory
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.scope
import com.tangem.tap.store
@ -159,6 +156,45 @@ class WalletConnectMiddleware {
action.id, action.data, action.sessionData
)
}
is WalletConnectAction.SwitchBlockchain -> {
val blockchain = action.blockchain.guard {
store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork))
return
}
val factory = WcWalletManagerFactory(
factory = store.state.globalState.tapWalletManager.walletManagerFactory,
currenciesRepository = currenciesRepository
)
val walletState = store.state.walletState
scope.launch {
val walletManager = factory.getWalletManager(
wallet = action.session.wallet,
blockchain = blockchain,
walletState = walletState
).guard {
store.dispatchOnMain(
GlobalAction.ShowDialog(
WalletConnectDialog.AddNetwork(blockchain.fullName)
)
)
return@launch
}
val updatedWallet = action.session.wallet.copy(
walletPublicKey = walletManager.wallet.publicKey.seedKey,
derivedPublicKey = walletManager.wallet.publicKey.derivedKey,
derivationPath = walletManager.wallet.publicKey.derivationPath,
blockchain = action.blockchain
)
val updatedSession = action.session.copy(wallet = updatedWallet)
store.dispatchOnMain(WalletConnectAction.UpdateBlockchain(updatedSession))
}
}
is WalletConnectAction.UpdateBlockchain -> {
walletConnectManager.updateBlockchain(action.updatedSession)
}
}
}
@ -189,8 +225,13 @@ class WalletConnectMiddleware {
return
}
val factory = WcWalletManagerFactory(
factory = store.state.globalState.tapWalletManager.walletManagerFactory,
currenciesRepository = currenciesRepository
)
val walletState = store.state.walletState
scope.launch {
val walletManager = getWalletManager(scanResponse, blockchain).guard {
val walletManager = factory.getWalletManager(scanResponse, blockchain, walletState).guard {
store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(session.session))
store.dispatchOnMain(
GlobalAction.ShowDialog(
@ -232,37 +273,4 @@ class WalletConnectMiddleware {
}
}
private suspend fun getWalletManager(
scanResponse: ScanResponse, blockchain: Blockchain
): WalletManager? {
val card = scanResponse.card
val factory = store.state.globalState.tapWalletManager.walletManagerFactory
val blockchainToMake = if (blockchain == Blockchain.Ethereum && card.isTestCard) {
Blockchain.EthereumTestnet
} else {
blockchain
}
val blockchainNetwork = BlockchainNetwork(
blockchain = blockchainToMake,
card = card
)
return if (store.state.globalState.scanResponse?.card?.cardId == card.cardId) {
store.state.walletState.getWalletManager(blockchainNetwork)
} else {
if (currenciesRepository
.loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed)
.contains(blockchainNetwork)
) {
factory.makeWalletManagerForApp(
scanResponse = scanResponse,
blockchainNetwork = blockchainNetwork
)
} else {
null
}
}
}
}

View file

@ -34,6 +34,11 @@ class WalletConnectReducer {
is WalletConnectAction.RefuseOpeningSession -> state.copy(loading = false)
is WalletConnectAction.OpeningSessionTimeout -> state.copy(loading = false)
is WalletConnectAction.FailureEstablishingSession -> state.copy(loading = false)
is WalletConnectAction.UpdateBlockchain -> state.copy(
sessions = state.sessions
.filterNot { it.peerId == action.updatedSession.peerId }
+ action.updatedSession
)
else -> state
}

View file

@ -82,6 +82,7 @@ data class WalletForSession(
sealed class WalletConnectDialog : StateDialog {
data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog()
object UnsupportedCard : WalletConnectDialog()
object UnsupportedNetwork : WalletConnectDialog()
data class AddNetwork(val network: String) : WalletConnectDialog()
object OpeningSessionRejected : WalletConnectDialog()
object SessionTimeout : WalletConnectDialog()

View file

@ -1,10 +1,14 @@
package com.tangem.tap.features.home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
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.redux.navigation.AppScreen
@ -15,12 +19,12 @@ import com.tangem.tap.features.home.redux.HomeState
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
import com.tangem.tap.features.tokens.redux.TokensAction
import com.tangem.tap.store
import com.tangem.wallet.R
import org.rekotlin.StoreSubscriber
class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState> {
class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
var homeState: MutableState<HomeState> = mutableStateOf(store.state.homeState)
private var homeState: MutableState<HomeState> = mutableStateOf(store.state.homeState)
private var composeView: ComposeView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -29,6 +33,13 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
val context = container?.context ?: return null
store.dispatch(BackupAction.CheckForUnfinishedBackup)
getView()?.findViewById<ComposeView>(R.id.cv_stories)?.setContent {
AppCompatTheme {
@ -46,16 +57,16 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState
store.dispatch(TokensAction.LoadCurrencies())
}
)
composeView = ComposeView(context).apply {
setContent {
AppCompatTheme {
ScreenContent()
}
}
}
}
private fun getRegionProvider(): RegionProvider = RegionService(
listOf(
// TelephonyManagerRegionProvider(requireContext()),
LocaleRegionProvider()
)
)
return composeView
}
override fun onStart() {
super.onStart()
@ -71,6 +82,11 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState
store.unsubscribe(this)
}
override fun onDestroyView() {
super.onDestroyView()
rollbackStatusBarIconsColor()
composeView = null
}
override fun newState(state: HomeState) {
if (activity == null || view == null) return
@ -78,4 +94,32 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber<HomeState
homeState.value = state
}
@Composable
private fun ScreenContent() {
StoriesScreen(
homeState,
onScanButtonClick = { store.dispatch(HomeAction.ReadCard) },
onShopButtonClick = {
store.dispatch(
HomeAction.GoToShop(store.state.globalState.userCountryCode)
)
},
onSearchTokensClick = {
store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens))
store.dispatch(TokensAction.AllowToAddTokens(false))
store.dispatch(TokensAction.LoadCurrencies())
}
)
}
/*
* !!! Workaround !!!
* Used to roll back the color of icons in the status bar after the stories screen
* */
private fun rollbackStatusBarIconsColor() {
WindowInsetsControllerCompat(
activity?.window ?: return,
view ?: return,
).isAppearanceLightStatusBars = true
}
}

View file

@ -3,12 +3,25 @@ package com.tangem.tap.features.home.compose
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@ -25,8 +38,13 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.tangem.tap.common.compose.SpacerS24
import com.tangem.tap.features.home.compose.content.*
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.tap.features.home.compose.content.FirstStoriesContent
import com.tangem.tap.features.home.compose.content.StoriesCurrencies
import com.tangem.tap.features.home.compose.content.StoriesRevolutionaryWallet
import com.tangem.tap.features.home.compose.content.StoriesUltraSecureBackup
import com.tangem.tap.features.home.compose.content.StoriesWalletForEveryone
import com.tangem.tap.features.home.compose.content.StoriesWeb3
import com.tangem.tap.features.home.compose.views.HomeButtons
import com.tangem.tap.features.home.compose.views.StoriesProgressBar
import com.tangem.tap.features.home.redux.HomeState
@ -43,6 +61,7 @@ fun StoriesScreen(
) {
val steps = 6
val currentStep = remember { mutableStateOf(1) }
val systemUiController = rememberSystemUiController()
val isDarkBackground = currentStep.value !in 3..5
@ -58,13 +77,20 @@ fun StoriesScreen(
val hideContent = remember { mutableStateOf(true) }
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = false,
)
}
Box(
Modifier
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF090E13))
) {
Row(
Modifier.fillMaxSize()
modifier = Modifier.fillMaxSize()
) {
Box(
Modifier
@ -105,19 +131,23 @@ fun StoriesScreen(
}
if (!isDarkBackground) {
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(id = R.drawable.ic_overlay),
contentDescription = null,
modifier = Modifier
.fillMaxSize(),
contentScale = ContentScale.FillBounds
)
}
val insets = WindowInsets.systemBars
.union(WindowInsets(top = 32.dp))
Column(
modifier = Modifier
.windowInsetsPadding(insets)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
) {
SpacerS24()
StoriesProgressBar(
steps = steps,
currentStep = currentStep.value,

View file

@ -7,7 +7,7 @@ import com.tangem.blockchain.extensions.Result
import com.tangem.common.extensions.isZero
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.demo.DemoTransactionSender
import com.tangem.tap.features.demo.isDemoWallet
import com.tangem.tap.features.demo.isDemoCard
import com.tangem.tap.features.send.redux.AmountActionUi
import com.tangem.tap.features.send.redux.FeeAction
import com.tangem.tap.features.send.redux.ReceiptAction
@ -28,6 +28,7 @@ class RequestFeeMiddleware {
fun handle(appState: AppState?, dispatch: DispatchFunction) {
val sendState = appState?.sendState ?: return
val walletManager = sendState.walletManager ?: return
val scanResponse = appState.globalState.scanResponse ?: return
if (!SendState.isReadyToRequestFee()) {
dispatch(FeeAction.FeeCalculation.SetFeeError(FeeAction.Error.ADDRESS_OR_AMOUNT_IS_EMPTY))
@ -40,7 +41,7 @@ class RequestFeeMiddleware {
val destinationAddress = sendState.addressPayIdState.destinationWalletAddress!!
val destinationAmount = Amount(typedAmount, sendState.amountState.amountToSendCrypto)
val txSender = if (walletManager.isDemoWallet()) {
val txSender = if (scanResponse.isDemoCard()) {
DemoTransactionSender(walletManager)
} else {
walletManager as TransactionSender

View file

@ -4,7 +4,11 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.BlockchainSdkError
import com.tangem.blockchain.common.TransactionError
import com.tangem.blockchain.common.TransactionSender
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.extensions.SimpleResult
import com.tangem.common.card.Card
import com.tangem.common.core.TangemSdkError
@ -15,7 +19,11 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.AnalyticsEvent
import com.tangem.tap.common.analytics.AnalyticsParam
import com.tangem.tap.common.extensions.*
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.safeUpdate
import com.tangem.tap.common.extensions.stripZeroPlainString
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
@ -26,9 +34,15 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.extensions.minimalAmount
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.demo.DemoTransactionSender
import com.tangem.tap.features.demo.isDemoWallet
import com.tangem.tap.features.send.redux.*
import com.tangem.tap.features.demo.isDemoCard
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
import com.tangem.tap.features.send.redux.AmountAction
import com.tangem.tap.features.send.redux.AmountActionUi
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
import com.tangem.tap.features.send.redux.PrepareSendScreen
import com.tangem.tap.features.send.redux.SendAction
import com.tangem.tap.features.send.redux.SendActionUi
import com.tangem.tap.features.send.redux.states.ButtonState
import com.tangem.tap.features.send.redux.states.ExternalTransactionData
import com.tangem.tap.features.send.redux.states.MainCurrencyType
@ -38,6 +52,7 @@ import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdk
import com.tangem.wallet.R
import java.util.EnumSet
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@ -45,7 +60,6 @@ import kotlinx.coroutines.withContext
import org.rekotlin.Action
import org.rekotlin.Middleware
import timber.log.Timber
import java.util.*
/**
[REDACTED_AUTHOR]
@ -161,7 +175,11 @@ private fun sendTransaction(
tangemSdk.config.linkedTerminal = false
}
val signer = TangemSigner(tangemSdk, action.messageForSigner) { signResponse ->
val signer = TangemSigner(
card = card,
tangemSdk = tangemSdk,
initialMessage = action.messageForSigner
) { signResponse ->
store.dispatch(
GlobalAction.UpdateWalletSignedHashes(
walletSignedHashes = signResponse.totalSignedHashes,
@ -171,7 +189,7 @@ private fun sendTransaction(
)
}
val sendResult = try {
if (walletManager.isDemoWallet()) {
if (card.isDemoCard()) {
DemoTransactionSender(walletManager).send(txData, signer)
} else {
(walletManager as TransactionSender).send(txData, signer)
@ -340,5 +358,4 @@ private fun updateWarnings(dispatch: (Action) -> Unit) {
val warnings = warningsManager.getWarnings(WarningMessage.Location.SendScreen, listOf(blockchain))
dispatch(SendAction.Warnings.Set(warnings))
}
}

View file

@ -73,6 +73,9 @@ data class WalletState(
val walletManagers: List<WalletManager>
get() = wallets.mapNotNull { it.walletManager }
val cardId: String?
get() = wallets.firstOrNull()?.walletManager?.wallet?.cardId
fun getWalletManager(currency: Currency?): WalletManager? {
if (currency?.blockchain == null) return null
return getWalletStore(currency)?.walletManager

View file

@ -45,6 +45,7 @@ class TradeCryptoMiddleware {
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
val exchangeManager = store.state.globalState.exchangeManager ?: return
val card = store.state.globalState.scanResponse?.card ?: return
val appCurrency = store.state.globalState.appCurrency
val addresses = selectedWalletData.walletAddresses?.list.orEmpty()
@ -59,7 +60,13 @@ class TradeCryptoMiddleware {
return
}
scope.launch { exchangeManager.buyErc20TestnetTokens(walletManager, currency.token) }
scope.launch {
exchangeManager.buyErc20TestnetTokens(
card = card,
walletManager = walletManager,
token = currency.token
)
}
return
}

View file

@ -1,8 +1,5 @@
package com.tangem.tap.features.wallet.redux.middlewares
import android.content.Intent
import android.net.Uri
import androidx.core.content.ContextCompat
import com.tangem.blockchain.blockchains.solana.RentProvider
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.AmountType
@ -15,12 +12,7 @@ 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.Analytics
import com.tangem.tap.common.extensions.copyToClipboard
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.onCardScanned
import com.tangem.tap.common.extensions.shareText
import com.tangem.tap.common.extensions.stripZeroPlainString
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
@ -233,9 +225,7 @@ class WalletMiddleware {
action.context.shareText(action.address)
}
is WalletAction.ExploreAddress -> {
val uri = Uri.parse(action.exploreUrl)
val intent = Intent(Intent.ACTION_VIEW, uri)
ContextCompat.startActivity(action.context, intent, null)
store.dispatchOpenUrl(action.exploreUrl)
}
is WalletAction.Send -> {
val newAction = prepareSendAction(action.amount, store.state.walletState)

View file

@ -5,7 +5,6 @@ import android.widget.TextView
import androidx.constraintlayout.utils.widget.ImageFilterView
import coil.imageLoader
import coil.request.ImageRequest
import coil.transform.RoundedCornersTransformation
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.IconsUtil
import com.tangem.blockchain.common.Token
@ -21,13 +20,13 @@ private const val QCX = "QCX"
private const val VOYR = "VOYRME"
fun loadCurrencyIcon(
currencyImageView: ImageFilterView,
currencyImageView: CurrencyIconView,
currencyTextView: TextView,
token: Token?,
blockchain: Blockchain,
) {
CurrencyIconLoader(
currencyImageView = currencyImageView,
currencyImageView = currencyImageView.imageView,
currencyTextView = currencyTextView,
token = token,
blockchain = blockchain
@ -135,14 +134,6 @@ private inline fun ImageView.loadIcon(
.placeholder(placeholderRes)
.error(placeholderRes)
.fallback(placeholderRes)
.transformations(
RoundedCornersTransformation(
topLeft = 32f,
topRight = 32f,
bottomLeft = 32f,
bottomRight = 32f
)
)
.listener(
onStart = { onStart() },
onSuccess = { _, _ -> onSuccess() },

View file

@ -0,0 +1,30 @@
package com.tangem.tap.features.wallet.ui.images
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.utils.widget.ImageFilterView
import com.google.android.material.card.MaterialCardView
import com.tangem.tangem_sdk_new.extensions.dpToPx
import com.tangem.wallet.databinding.ViewCurrencyIconBinding
class CurrencyIconView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : MaterialCardView(context, attrs, defStyleAttr) {
private val binding = ViewCurrencyIconBinding.inflate(
LayoutInflater.from(context),
this
)
val imageView: ImageFilterView
get() = binding.iv
init {
elevation = 0f
cardElevation = 0f
radius = dpToPx(8f)
background = null
}
}