diff --git a/.gitignore b/.gitignore index 0fde302b00..13b2127afa 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ # Local configuration file (sdk path, etc) local.properties +# Google services + + # Gradle generated files .gradle diff --git a/app/build.gradle b/app/build.gradle index 6674f33d44..823fe723d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -75,9 +75,9 @@ dependencies { implementation 'com.google.android.play:core-ktx:1.8.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' - implementation 'com.tangem:blockchain:develop-5' - implementation 'com.tangem:core:develop-10' - implementation 'com.tangem:sdk:develop-10' + implementation 'com.tangem:blockchain:develop-8' + implementation 'com.tangem:core:develop-14' + implementation 'com.tangem:sdk:develop-14' // WebView implementation "androidx.browser:browser:1.3.0" diff --git a/app/src/main/assets/erc20_tokens.json b/app/src/main/assets/erc20_tokens.json index 9b29c198bb..5f2bfeb629 100644 --- a/app/src/main/assets/erc20_tokens.json +++ b/app/src/main/assets/erc20_tokens.json @@ -629,6 +629,13 @@ "name" : "QASH", "contractAddress" : "0x618e75ac90b12c6049ba3b27f5d5f8651b0037f6" }, + { + "decimalCount" : 8, + "symbol" : "QCX", + "name" : "QuickX Protocol", + "contractAddress" : "0xf9e5af7b42d31d51677c75bbbd37c1986ec79aee", + "customIcon": "qcx" + }, { "decimalCount" : 8, "symbol" : "QRL", diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Picasso.kt b/app/src/main/java/com/tangem/tap/common/extensions/Picasso.kt new file mode 100644 index 0000000000..97a952841e --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/extensions/Picasso.kt @@ -0,0 +1,86 @@ +package com.tangem.tap.common.extensions + +import android.widget.ImageView +import android.widget.TextView +import com.squareup.picasso.Callback +import com.squareup.picasso.Picasso +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.IconsUtil +import com.tangem.blockchain.common.Token +import com.tangem.wallet.R + +fun Picasso.loadCurrenciesIcon( + imageView: ImageView, + textView: TextView, + token: Token? = null, + blockchain: Blockchain?, +) { + val blockchain = blockchain ?: Blockchain.Ethereum + + val url = if (token != null) { + IconsUtil.getTokenIconUri(blockchain, token) + } else { + IconsUtil.getBlockchainIconUri(blockchain) + } + + imageView.setImageDrawable(null) + imageView.colorFilter = null + textView.text = null + + when { + url != null -> { + this.load(url) + .placeholder(R.drawable.shape_circle) + ?.into(imageView, + object : Callback { + override fun onError(e: Exception?) { + setOfflineCurrencyImage(imageView, textView, token, blockchain) + } + + override fun onSuccess() { + } + }) + } + token?.symbol == QCX -> { + this.load(R.drawable.ic_qcx)?.into(imageView) + } + else -> { + setOfflineCurrencyImage(imageView, textView, token, blockchain) + } + } +} + +private const val QCX = "QCX" + +private fun setOfflineCurrencyImage( + imageView: ImageView, + textView: TextView, + token: Token?, + blockchain: Blockchain, +) { + if (token != null) { + setTokenImage(imageView, textView, token) + } else { + setBlockchainImage(imageView, textView, blockchain) + } +} + +private fun setBlockchainImage( + imageView: ImageView, + textView: TextView, + blockchain: Blockchain +) { + imageView.setImageResource(blockchain.getIconRes()) + imageView.colorFilter = null + textView.text = null +} + +private fun setTokenImage( + imageView: ImageView, + textView: TextView, + token: Token +) { + imageView.setImageResource(R.drawable.shape_circle) + imageView.setColorFilter(token.getColor()) + textView.text = token.symbol.take(1) +} diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index a699f2ee45..4156e2449f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -84,6 +84,7 @@ private fun handleEraseWallet(action: DetailsAction.EraseWallet, state: DetailsS return when (action) { DetailsAction.EraseWallet.Check -> { val notAllowedByCard = state.card?.settingsMask?.contains(Settings.ProhibitPurgeWallet) == true + || state.card?.settingsMask?.contains(Settings.IsReusable) == false val notEmpty = state.wallets.any { !it.recentTransactions.isNullOrEmpty() || it.amounts.toSendableAmounts().isNotEmpty() } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt index 9fe1ba05bd..0047481627 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt @@ -7,7 +7,10 @@ import androidx.annotation.StringRes import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import com.squareup.picasso.Callback +import com.squareup.picasso.Picasso import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.IconsUtil import com.tangem.blockchain.common.Token import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.CryptoCurrencyName @@ -16,6 +19,7 @@ import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.item_currency_subtitle.view.* import kotlinx.android.synthetic.main.item_popular_token.view.* +import java.lang.Exception import java.util.* class CurrenciesAdapter : ListAdapter(DiffUtilCallback) { @@ -104,9 +108,11 @@ class CurrenciesAdapter : ListAdapter view.btn_add_token.show(!isAdded) view.btn_token_added.show(isAdded) - view.iv_currency.setImageResource(currency.blockchain.getIconRes()) - view.iv_currency.colorFilter = null - view.tv_token_letter.text = null + Picasso.get().loadCurrenciesIcon( + imageView = view.iv_currency, + textView = view.tv_token_letter, + blockchain = blockchain, token = null + ) view.btn_add_token.setOnClickListener { store.dispatch(WalletAction.MultiWallet.AddBlockchain(blockchain)) @@ -123,10 +129,11 @@ class CurrenciesAdapter : ListAdapter view.btn_add_token.show(!isAdded) view.btn_token_added.show(isAdded) - view.iv_currency.setImageResource(R.drawable.shape_circle) - view.iv_currency.setColorFilter(token.getColor()) - view.tv_token_letter.text = token.symbol.take(1) - + Picasso.get().loadCurrenciesIcon( + imageView = view.iv_currency, + textView = view.tv_token_letter, + token = token, blockchain = Blockchain.Ethereum + ) view.btn_add_token.setOnClickListener { store.dispatch(WalletAction.MultiWallet.AddToken(token)) view.btn_add_token.hide() @@ -152,7 +159,10 @@ sealed class CurrencyListItem { data class TitleListItem(@StringRes val titleResId: Int) : CurrencyListItem() companion object { - fun createListOfCurrencies(blockchains: List, tokens: List): List { + fun createListOfCurrencies( + blockchains: List, + tokens: List + ): List { val blockchainsTitle = R.string.add_tokens_subtitle_blockchains val tokensTitle = R.string.add_tokens_subtitle_tokens return listOf(TitleListItem(blockchainsTitle)) + diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 6d7bc13229..62de9a0a68 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -81,6 +81,9 @@ data class WalletState( && (walletData.token == null || walletData.token != store.state.walletState.primaryToken)) { val walletManager = getWalletManager(walletData.currencyData.currencySymbol) ?: return true + + if (walletData.token == null && walletManager.presetTokens.isNotEmpty()) return false + val wallet = walletManager.wallet if (walletData.blockchain != null) { return wallet.recentTransactions.toPendingTransactions(wallet.address).isEmpty() && diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index d68d7863f2..da28809df6 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -39,10 +39,10 @@ class MultiWalletMiddleware { globalState?.scanNoteResponse?.card?.cardId?.let { currenciesRepository.saveAddedToken(it, action.token) } - addToken(action.token, walletState) + addToken(action.token, walletState, globalState) } is WalletAction.MultiWallet.AddTokens -> { - action.tokens.map { addToken(it, walletState) } + action.tokens.map { addToken(it, walletState, globalState) } } is WalletAction.MultiWallet.AddBlockchain -> { globalState?.scanNoteResponse?.card?.let { card -> @@ -62,6 +62,8 @@ class MultiWalletMiddleware { is WalletAction.MultiWallet.RemoveWallet -> { val cardId = globalState?.scanNoteResponse?.card?.cardId if (action.walletData.token != null) { + walletState?.getWalletManagerForToken(action.walletData.token.symbol) + ?.removeToken(action.walletData.token) cardId?.let { currenciesRepository.removeToken(it, action.walletData.token) } } else if (action.walletData.blockchain != null) { cardId?.let { currenciesRepository.removeBlockchain(it, action.walletData.blockchain) } @@ -120,8 +122,15 @@ class MultiWalletMiddleware { } } - private fun addToken(token: Token, walletState: WalletState?) { - val walletManager = walletState?.getWalletManager(token.symbol) + private fun addToken(token: Token, walletState: WalletState?, globalState: GlobalState?) { + val card = globalState?.scanNoteResponse?.card ?: return + val walletManager = walletState?.getWalletManager(token.symbol) ?: + globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp( + card = card, + blockchain = Blockchain.Ethereum + )?.also { walletManager -> + store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) + } scope.launch { val result = walletManager?.addToken(token) withContext(Dispatchers.Main) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index c14d364abf..c82c47f25f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -6,10 +6,14 @@ import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import com.squareup.picasso.Callback +import com.squareup.picasso.Picasso import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.IconsUtil import com.tangem.blockchain.common.Token import com.tangem.tap.common.extensions.getColor import com.tangem.tap.common.extensions.getIconRes +import com.tangem.tap.common.extensions.loadCurrenciesIcon import com.tangem.tap.common.extensions.show import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletData @@ -17,6 +21,11 @@ import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.item_currency_wallet.view.* +import kotlinx.android.synthetic.main.item_currency_wallet.view.iv_currency +import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_currency_symbol +import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_token_letter +import kotlinx.android.synthetic.main.item_popular_token.view.* +import java.lang.Exception import java.math.BigDecimal class WalletAdapter @@ -89,16 +98,15 @@ class WalletAdapter view.card_wallet.setOnClickListener { store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet)) } - val blockchain = wallet.currencyData.currencySymbol?.let { Blockchain.fromCurrency(it) } - if (blockchain != null && blockchain != Blockchain.Unknown) { - view.tv_token_letter.text = null - view.iv_currency.colorFilter = null - view.iv_currency.setImageResource(blockchain.getIconRes()) - } else { - view.tv_token_letter.text = wallet.currencyData.currencySymbol?.take(1) - wallet.token?.getColor()?.let { view.iv_currency.setColorFilter(it) } - view.iv_currency.setImageResource(R.drawable.shape_circle) - } + val blockchain = wallet.blockchain + val token = wallet.token + + Picasso.get().loadCurrenciesIcon( + imageView = view.iv_currency, + textView = view.tv_token_letter, + token = token, blockchain = blockchain + ) + when (wallet.currencyData.status) { BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> hideWarning() BalanceStatus.Loading -> { diff --git a/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt b/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt index 05c2b6a6bd..00c2f87e19 100644 --- a/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt +++ b/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt @@ -44,6 +44,7 @@ class NetworkConnectivity( (capabilities != null) && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) } else { diff --git a/app/src/main/res/drawable-ldpi/ic_qcx.png b/app/src/main/res/drawable-ldpi/ic_qcx.png new file mode 100644 index 0000000000..68f2ded287 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_qcx.png differ diff --git a/dependencies.gradle b/dependencies.gradle index f74991aa26..22dc84c906 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,4 +1,4 @@ ext.versions = [ - kotlin : '1.4.31', - build_gradle: '4.1.3', + kotlin : '1.5.0', + build_gradle: '4.2.0', ] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 385ee4fcc0..c6dab66ff6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip