Updated on 2026-08-14

This commit is contained in:
Tangem 2020-09-22 12:29:03 +03:00
parent 9a14c11e33
commit c55e5745e9
11 changed files with 90 additions and 86 deletions

View file

@ -1,6 +1,7 @@
package com.tangem.tap
import android.app.Application
import com.tangem.tap.common.images.PicassoHelper
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.appReducer
import com.tangem.tap.network.NetworkConnectivity
@ -24,5 +25,6 @@ class TapApplication : Application() {
}
NetworkConnectivity.createInstance(store, this)
preferencesStorage = PreferencesStorage(this)
PicassoHelper.initPicassoWithCaching(this)
}
}

View file

@ -0,0 +1,39 @@
package com.tangem.tap.common.images
import android.app.Application
import com.squareup.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
import okhttp3.Cache
import okhttp3.CacheControl
import okhttp3.OkHttpClient
import java.io.File
import java.util.concurrent.TimeUnit
class PicassoHelper {
companion object {
private const val KEEP_CACHE_MAX_DAYS = 7
fun initPicassoWithCaching(application: Application) {
val picasso = Picasso.Builder(application)
.downloader(OkHttp3Downloader(getOkHttpForPicasso(application)))
.build()
Picasso.setSingletonInstance(picasso)
}
private fun getOkHttpForPicasso(application: Application): OkHttpClient {
val okHttpBuilder = OkHttpClient.Builder()
okHttpBuilder.cache(Cache(File(application.filesDir, "artworks"), Long.MAX_VALUE))
okHttpBuilder.addInterceptor { chain ->
val cacheControl = CacheControl.Builder()
.maxStale(KEEP_CACHE_MAX_DAYS, TimeUnit.DAYS)
.build()
val origRequest = chain.request()
val neverExpireRequest = origRequest.newBuilder()
.cacheControl(cacheControl)
.build()
chain.proceed(neverExpireRequest)
}
return okHttpBuilder.build()
}
}
}

View file

@ -2,17 +2,14 @@ package com.tangem.tap.domain
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.commands.Card
import com.tangem.commands.CardStatus
import com.tangem.commands.common.network.Result
import com.tangem.commands.common.network.TangemService
import com.tangem.common.extensions.toHexString
import com.tangem.tap.TapConfig
import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.features.wallet.redux.Artwork
import com.tangem.tap.features.wallet.redux.PayIdState
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.network.NetworkConnectivity
@ -26,7 +23,6 @@ import java.math.BigDecimal
class TapWalletManager {
private val payIdManager = PayIdManager()
private val coinMarketCapService = CoinMarketCapService()
private val tangemService = TangemService()
suspend fun loadWalletData() {
val walletManager = store.state.globalState.scanNoteResponse?.walletManager
@ -37,21 +33,6 @@ class TapWalletManager {
updateWallet(walletManager)
}
suspend fun loadArtwork(card: Card, artworkId: String) {
val result =
tangemService.getArtwork(card.cardId, card.cardPublicKey!!.toHexString(), artworkId)
withContext(Dispatchers.Main) {
when (result) {
is Result.Success -> {
store.dispatch(WalletAction.LoadArtwork.Success(
Artwork(artworkId, result.data.byteStream().readBytes())
))
}
is Result.Failure -> store.dispatch(WalletAction.LoadArtwork.Failure)
}
}
}
suspend fun loadPayId() {
val result = loadPayIdIfNeeded()
result?.let { handlePayIdResult(it) }

View file

@ -19,7 +19,6 @@ import com.tangem.tap.network.NetworkStateChanged
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
import com.tangem.wallet.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -46,21 +45,6 @@ val walletMiddleware: Middleware<AppState> = { dispatch, state ->
store.state.globalState.tapWalletManager.loadFiatRate(store.state.globalState.appCurrency)
}
}
is WalletAction.LoadArtwork -> {
if (action.artworkId != null) {
scope.launch {
store.state.globalState.tapWalletManager.loadArtwork(
action.card, action.artworkId
)
}
} else {
val artworkRes = R.drawable.card_default
store.dispatch(WalletAction.LoadArtwork.Success(Artwork(
artworkId = artworkRes.toString(), artworkResId = artworkRes
)))
}
}
is WalletAction.CreateWallet -> {
scope.launch {
val result = tangemSdkManager.createWallet(

View file

@ -2,6 +2,7 @@ package com.tangem.tap.features.wallet.redux
import com.tangem.blockchain.common.AmountType
import com.tangem.common.extensions.isZero
import com.tangem.common.extensions.toHexString
import com.tangem.tap.common.extensions.toFiatString
import com.tangem.tap.common.extensions.toFormattedCurrencyString
import com.tangem.tap.common.extensions.toFormattedString
@ -12,6 +13,8 @@ import com.tangem.tap.features.wallet.models.toPendingTransactions
import com.tangem.tap.features.wallet.ui.BalanceStatus
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import com.tangem.tap.features.wallet.ui.TokenData
import com.tangem.tap.store
import com.tangem.wallet.R
import org.rekotlin.Action
class WalletReducer {
@ -165,8 +168,18 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
token = newState.currencyData.token?.copy(fiatAmount = tokenFiatAmount)
))
}
is WalletAction.LoadArtwork.Success -> {
newState = newState.copy(cardImage = action.artwork)
is WalletAction.LoadArtwork -> {
// TODO: form URL in Card SDK
var artworkAddress = "https://verify.tangem.com/card/artwork"
artworkAddress += "?artworkId=${action.artworkId}"
artworkAddress += "&CID=${store.state.globalState.scanNoteResponse?.card?.cardId}"
artworkAddress += "&publicKey=${store.state.globalState.scanNoteResponse?.card?.cardPublicKey?.toHexString()}"
val artwork = if (action.artworkId != null) {
Artwork(artworkId = artworkAddress)
} else {
Artwork(artworkResId = R.drawable.card_default)
}
newState = newState.copy(cardImage = artwork)
}
is WalletAction.ShowQrCode -> {
newState = newState.copy(

View file

@ -62,7 +62,7 @@ data class AddressData(
)
data class Artwork(
val artworkId: String,
val artworkId: String? = null,
val artwork: Bitmap? = null,
val artworkResId: Int? = null
) {

View file

@ -85,6 +85,7 @@ class BalanceWidget(
fragment.tv_status_error_message.text = data.errorMessage
showStatus(R.id.group_error)
fragment.tv_status_error_message.show(!data.errorMessage.isNullOrBlank())
}
BalanceStatus.EmptyCard -> {
fragment.l_balance.hide()

View file

@ -35,7 +35,6 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
private var dialog: Dialog? = null
private var snackbar: Snackbar? = null
private var artworkId: String? = null
private lateinit var viewAdapter: PendingTransactionsAdapter
@ -187,25 +186,15 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
}
private fun setupCardImage(cardImage: Artwork?) {
if (cardImage?.artwork != null) {
if (cardImage.artworkId != this.artworkId) {
prepareShowingCardImage(cardImage.artworkId)
iv_card.setImageBitmap(cardImage.artwork)
}
} else if (cardImage?.artworkResId != null) {
if (cardImage.artworkId != this.artworkId) {
prepareShowingCardImage(cardImage.artworkId)
iv_card.setImageDrawable(getDrawable(cardImage.artworkResId))
}
val address = cardImage?.artworkId ?: cardImage?.artworkResId
val picassoRequest = when (address) {
is String -> Picasso.get().load(address)
is Int -> Picasso.get().load(address)
else -> null
}
}
private fun prepareShowingCardImage(artworkId: String) {
this.artworkId = artworkId
val fadeInAnimation: Animation = AlphaAnimation(0.0f, 1.0f)
fadeInAnimation.duration = 400
iv_card.startAnimation(fadeInAnimation)
iv_card_tangem_logo.hide()
picassoRequest?.placeholder(R.drawable.card_placeholder)
?.error(R.drawable.card_placeholder)
?.into(iv_card)
}
private fun handleDialogs(walletDialog: WalletDialog?) {