diff --git a/app/build.gradle b/app/build.gradle index 48f34abcb7..abf8cda691 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -93,7 +93,7 @@ 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-88' + implementation 'com.tangem:blockchain:develop-93' // implementation 'com.tangem:blockchain:0.0.1' implementation 'com.tangem.tangem-sdk-kotlin:core:develop-154' implementation 'com.tangem.tangem-sdk-kotlin:android:develop-154' @@ -118,8 +118,9 @@ dependencies { // Camera implementation 'com.otaliastudios:cameraview:2.6.3' - // Image Loading - Picasso - implementation 'com.squareup.picasso:picasso:2.71828' + // Image Loading + implementation 'io.coil-kt:coil:2.1.0' + implementation 'io.coil-kt:coil-compose:2.1.0' // Firebase implementation platform('com.google.firebase:firebase-bom:26.0.0') @@ -172,9 +173,6 @@ dependencies { implementation "com.github.skydoves:androidveil:1.1.2" - implementation("io.coil-kt:coil:2.0.0-rc01") - implementation("io.coil-kt:coil-compose:2.0.0-rc01") - implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.6' testImplementation 'junit:junit:4.13.2' diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index b58485ab88..2e6c7b534b 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -1,6 +1,8 @@ package com.tangem.tap import android.app.Application +import coil.ImageLoader +import coil.ImageLoaderFactory import com.appsflyer.AppsFlyerLib import com.google.firebase.ktx.Firebase import com.google.firebase.remoteconfig.ktx.remoteConfig @@ -10,7 +12,7 @@ import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.domain.DomainLayer import com.tangem.network.common.MoshiConverter import com.tangem.tap.common.analytics.GlobalAnalyticsHandler -import com.tangem.tap.common.images.PicassoHelper +import com.tangem.tap.common.images.createCoilImageLoader import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.appReducer import com.tangem.tap.common.redux.global.GlobalAction @@ -43,7 +45,7 @@ lateinit var currenciesRepository: CurrenciesRepository lateinit var walletConnectRepository: WalletConnectRepository lateinit var shopService: TangemShopService -class TapApplication : Application() { +class TapApplication : Application(), ImageLoaderFactory { override fun onCreate() { super.onCreate() @@ -61,7 +63,6 @@ class TapApplication : Application() { NetworkConnectivity.createInstance(store, this) preferencesStorage = PreferencesStorage(this) - PicassoHelper.initPicassoWithCaching(this) currenciesRepository = CurrenciesRepository( this, store.state.domainNetworks.tangemTechService ) @@ -75,6 +76,10 @@ class TapApplication : Application() { initAppsFlyer() } + override fun newImageLoader(): ImageLoader { + return createCoilImageLoader(context = this) + } + private fun loadConfigs() { val moshi = MoshiConverter.defaultMoshi() val localLoader = FeaturesLocalLoader(this, moshi) @@ -108,11 +113,6 @@ class TapApplication : Application() { } data class LogConfig( - // disables both [internal, http] - val picasso: Boolean = BuildConfig.DEBUG, - val picassoInternal: Boolean = true, - val picassoHttp: Boolean = true, - + val coil: Boolean = BuildConfig.DEBUG, val storeAction: Boolean = BuildConfig.DEBUG, - ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 8af2818c0a..342e29a83e 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -4,13 +4,10 @@ import android.app.Dialog import android.content.Context import com.tangem.tap.common.redux.AppDialog import com.tangem.tap.common.redux.global.GlobalState +import com.tangem.tap.common.ui.SimpleAlertDialog +import com.tangem.tap.common.ui.SimpleCancelableAlertDialog import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog -import com.tangem.tap.features.details.ui.walletconnect.dialogs.ApproveWcSessionDialog -import com.tangem.tap.features.details.ui.walletconnect.dialogs.BnbTransactionDialog -import com.tangem.tap.features.details.ui.walletconnect.dialogs.ClipboardOrScanQrDialog -import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialog -import com.tangem.tap.features.details.ui.walletconnect.dialogs.SimpleAlertDialog -import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionDialog +import com.tangem.tap.features.details.ui.walletconnect.dialogs.* import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.onboarding.products.twins.ui.dialog.CreateWalletInterruptDialog @@ -19,12 +16,8 @@ import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AddMoreBack import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.BackupInProgressDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.ConfirmDiscardingBackupDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.UnfinishedBackupFoundDialog -import com.tangem.tap.features.wallet.redux.WalletDialog -import com.tangem.tap.features.wallet.ui.dialogs.AmountToSendBottomSheetDialog -import com.tangem.tap.features.wallet.ui.dialogs.ChooseTradeActionBottomSheetDialog -import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog -import com.tangem.tap.features.wallet.ui.dialogs.SignedHashesWarningDialog -import com.tangem.tap.features.wallet.ui.dialogs.SimpleOkDialog +import com.tangem.tap.features.wallet.redux.models.WalletDialog +import com.tangem.tap.features.wallet.ui.dialogs.* import com.tangem.tap.features.wallet.ui.wallet.CurrencySelectionDialog import com.tangem.tap.store import com.tangem.wallet.R @@ -72,6 +65,15 @@ class DialogManager : StoreSubscriber { messageRes = R.string.wallet_connect_scanner_error_no_ethereum_wallet, context = context ) + is WalletConnectDialog.AddNetwork -> + SimpleAlertDialog.create( + titleRes = R.string.wallet_connect, + message = context.getString( + R.string.wallet_connect_network_not_found_format, + state.dialog.network + ), + context = context + ) is WalletConnectDialog.OpeningSessionRejected -> { SimpleAlertDialog.create( titleRes = R.string.wallet_connect, @@ -115,6 +117,20 @@ class DialogManager : StoreSubscriber { AmountToSendBottomSheetDialog(context, state.dialog) is WalletDialog.SignedHashesMultiWalletDialog -> SignedHashesWarningDialog.create(context) + is WalletDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create( + title = context.getString(state.dialog.titleRes, state.dialog.currencySymbol), + message = context.getString( + state.dialog.messageRes, state.dialog.currencySymbol, state.dialog.currencyTitle + ), + context = context, + ) + is WalletDialog.RemoveWalletDialog -> SimpleCancelableAlertDialog.create( + title = context.getString(state.dialog.titleRes, state.dialog.currencyTitle), + messageRes = state.dialog.messageRes, + context = context, + primaryButtonRes = state.dialog.primaryButtonRes, + primaryButtonAction = state.dialog.action + ) else -> null } dialog?.show() diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt index 5cf9b2d3ad..3cb5aa96c8 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt @@ -62,6 +62,7 @@ fun Blockchain.getNetworkName(): String { Blockchain.Ethereum, Blockchain.EthereumTestnet -> "ERC20" Blockchain.BSC, Blockchain.BSCTestnet -> "BEP20" Blockchain.Binance, Blockchain.BinanceTestnet -> "BEP2" + Blockchain.Tron, Blockchain.TronTestnet -> "TRC20" else -> "" } } 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 deleted file mode 100644 index dbeefadbe8..0000000000 --- a/app/src/main/java/com/tangem/tap/common/extensions/Picasso.kt +++ /dev/null @@ -1,135 +0,0 @@ -package com.tangem.tap.common.extensions - -import android.graphics.* -import android.widget.TextView -import androidx.constraintlayout.utils.widget.ImageFilterView -import com.squareup.picasso.Callback -import com.squareup.picasso.Picasso -import com.squareup.picasso.Transformation -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.IconsUtil -import com.tangem.blockchain.common.Token -import com.tangem.domain.common.extensions.toNetworkId -import com.tangem.tap.domain.extensions.getCustomIconUrl -import com.tangem.tap.domain.tokens.getIconUrl -import com.tangem.wallet.R - -fun Picasso.loadCurrenciesIcon( - imageView: ImageFilterView, - textView: TextView, - token: Token? = null, - blockchain: Blockchain, -) { - - val url: String? = if (token != null) { - token.id?.let { getIconUrl(it) } ?: token.getCustomIconUrl() - ?: IconsUtil.getTokenIconUri(blockchain, token)?.toString() - } else { - getIconUrl(blockchain.toNetworkId()) - } - - imageView.setImageDrawable(null) - imageView.colorFilter = null - textView.text = null - - when { - token?.symbol == QCX -> { - this.load(R.drawable.ic_qcx)?.into(imageView) - } - token?.symbol == VOYR -> { - this.load(R.drawable.ic_voyr)?.into(imageView) - } - url != null -> { - if (token != null) { - setTokenImage(imageView, textView, token, blockchain) - } - this.load(url) - .transform(RoundedCornersTransform()) - .noPlaceholder() - ?.into(imageView, - object : Callback { - override fun onError(e: Exception?) { - setOfflineCurrencyImage(imageView, textView, token, blockchain) - } - - override fun onSuccess() { - if (token != null) { - imageView.colorFilter = null - textView.text = null - } - if (blockchain.isTestnet()) imageView.saturation = 0f - } - }) - } - else -> { - setOfflineCurrencyImage(imageView, textView, token, blockchain) - } - } -} - -private const val QCX = "QCX" -private const val VOYR = "VOYRME" - -private fun setOfflineCurrencyImage( - imageView: ImageFilterView, - textView: TextView, - token: Token?, - blockchain: Blockchain, -) { - when (token) { - null -> setBlockchainImage(imageView, textView, blockchain) - else -> setTokenImage(imageView, textView, token, blockchain) - } -} - -private fun setBlockchainImage( - imageView: ImageFilterView, - textView: TextView, - blockchain: Blockchain, -) { - imageView.setImageResource(blockchain.getRoundIconRes()) - imageView.colorFilter = null - if (blockchain.isTestnet()) imageView.saturation = 0f - textView.text = null -} - -private fun setTokenImage( - imageView: ImageFilterView, - textView: TextView, - token: Token, - tokenBlockchain: Blockchain -) { - imageView.setImageResource(R.drawable.shape_circle) - if (tokenBlockchain.isTestnet()) { - imageView.saturation = 0f - } else { - imageView.setColorFilter(token.getColor()) - } - textView.text = token.symbol.take(1) -} - -private class RoundedCornersTransform : Transformation { - - override fun transform(source: Bitmap): Bitmap { - val size = source.width.coerceAtMost(source.height) - val x = (source.width - size) / 2 - val y = (source.height - size) / 2 - val squaredBitmap = Bitmap.createBitmap(source, x, y, size, size) - if (squaredBitmap != source) source.recycle() - - val paint = Paint().apply { - shader = BitmapShader(squaredBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) - isAntiAlias = true - } - - val rectF = RectF(0f, 0f, source.width.toFloat(), source.height.toFloat()) - val radius = size / 8f - val bitmap = Bitmap.createBitmap(size, size, source.config) - Canvas(bitmap).drawRoundRect(rectF, radius, radius, paint) - squaredBitmap.recycle() - - return bitmap - } - - override fun key(): String = "rounded_corners" -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt index b431b780ad..219e9339da 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt @@ -53,8 +53,7 @@ fun BigDecimal.toFiatString( fiatCurrencyName: String, formatWithSpaces: Boolean = false ): String { - var fiatValue = rateValue.multiply(this) - fiatValue = fiatValue.setScale(2, RoundingMode.HALF_UP) + val fiatValue = rateValue.multiply(this) return fiatValue.toFormattedFiatValue(fiatCurrencyName, formatWithSpaces) } @@ -67,7 +66,8 @@ fun BigDecimal.toFormattedFiatValue( fiatCurrencyName: String, formatWithSpaces: Boolean = false ): String { - val fiatValue = if (formatWithSpaces) this.formatWithSpaces() else this + val fiatValue = this.setScale(2, RoundingMode.HALF_UP) + .let { if (formatWithSpaces) it.formatWithSpaces() else it } return " ${fiatValue}  $fiatCurrencyName" } diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Token.kt b/app/src/main/java/com/tangem/tap/common/extensions/Token.kt index fdfb83ef77..10897bc069 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Token.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Token.kt @@ -1,6 +1,8 @@ package com.tangem.tap.common.extensions +import android.graphics.Color import androidx.annotation.ColorInt +import androidx.core.graphics.luminance import androidx.core.graphics.toColorInt import com.tangem.blockchain.common.Token import com.tangem.wallet.R @@ -9,8 +11,13 @@ import com.tangem.wallet.R fun Token.getColor(): Int { return try { ("#" + this.contractAddress.subSequence(2..7).toString()) - .toColorInt() + .toColorInt() } catch (exception: Exception) { R.color.lightGray4 } +} + +@ColorInt +fun Token.getTextColor(): Int { + return if (this.getColor().luminance > 0.5) Color.BLACK else Color.WHITE } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/images/Coil.kt b/app/src/main/java/com/tangem/tap/common/images/Coil.kt new file mode 100644 index 0000000000..64b7b76734 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/images/Coil.kt @@ -0,0 +1,50 @@ +package com.tangem.tap.common.images + +import android.content.Context +import android.util.Log +import coil.ImageLoader +import coil.util.Logger +import com.tangem.tap.logConfig +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import timber.log.Timber + +private const val COIL_LOG_TAG = "COIL" + +fun createCoilImageLoader( + context: Context +): ImageLoader { + return ImageLoader.Builder(context) + .apply { + if (!logConfig.coil) return@apply + + logger(CoilTimberLogger()) + okHttpClient { + OkHttpClient.Builder() + .addNetworkInterceptor( + HttpLoggingInterceptor { message -> + Timber.tag(COIL_LOG_TAG).d(message) + } + .apply { + level = HttpLoggingInterceptor.Level.BODY + } + ) + .build() + + } + } + .build() +} + + +private class CoilTimberLogger : Logger { + + override var level: Int = Log.DEBUG + + override fun log(tag: String, priority: Int, message: String?, throwable: Throwable?) { + with(Timber.tag(COIL_LOG_TAG)) { + throwable?.let { e -> e(e, message) } + message?.let { msg -> d(msg) } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/images/Picasso.kt b/app/src/main/java/com/tangem/tap/common/images/Picasso.kt deleted file mode 100644 index 81c52ca693..0000000000 --- a/app/src/main/java/com/tangem/tap/common/images/Picasso.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.tangem.tap.common.images - -import android.app.Application -import com.squareup.picasso.OkHttp3Downloader -import com.squareup.picasso.Picasso -import com.tangem.tap.logConfig -import com.tangem.wallet.BuildConfig -import okhttp3.Cache -import okhttp3.CacheControl -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import timber.log.Timber -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.isLoggingEnabled = logIsEnabled() - picasso.setIndicatorsEnabled(BuildConfig.DEBUG) - Picasso.setSingletonInstance(picasso) - } - - private fun getOkHttpForPicasso(application: Application): OkHttpClient { - return OkHttpClient.Builder().apply { - cache(Cache(File(application.filesDir, "artworks"), Long.MAX_VALUE)) - callTimeout(15000, TimeUnit.MILLISECONDS) - - if (logIsEnabled()) { - addDebugInterceptors(this) - } - - 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) - } - }.build() - - } - - private fun addDebugInterceptors(okHttpBuilder: OkHttpClient.Builder) { - val picassoInterceptor = HttpLoggingInterceptor(PicassoOkHttpLogger()).apply { - level = HttpLoggingInterceptor.Level.BODY - } - okHttpBuilder.addInterceptor(picassoInterceptor) - } - - private fun logIsEnabled(): Boolean = BuildConfig.DEBUG && logConfig.picasso - - } -} - -private class PicassoOkHttpLogger : HttpLoggingInterceptor.Logger { - override fun log(message: String) { - Timber.d(message) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt index 591a20e896..89d609b32c 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt @@ -2,8 +2,8 @@ package com.tangem.tap.common.redux import com.tangem.common.extensions.VoidCallback import com.tangem.tap.common.TestAction +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.AddressData -import com.tangem.tap.features.wallet.redux.Currency /** [REDACTED_AUTHOR] diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt index 3da94dc568..f5281cc796 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt @@ -5,6 +5,7 @@ import android.content.Intent import com.google.android.gms.wallet.PaymentData import com.shopify.buy3.Storefront import com.tangem.tap.common.analytics.AnalyticsHandler +import com.tangem.tap.common.extensions.filterNotNull import com.tangem.tap.common.shop.data.ProductType import com.tangem.tap.common.shop.data.TangemProduct import com.tangem.tap.common.shop.data.TotalSum @@ -21,7 +22,6 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { private val shopifyService = ShopifyService(application, shopifyShop) - private lateinit var product: Storefront.Product private val checkouts = mutableMapOf() private val variants = mutableMapOf() @@ -31,22 +31,19 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { suspend fun getProducts(): Result> { val result = shopifyService.getProducts() - result.onSuccess { - product = it.first { - val variantsSku = it.variants.edges.map { it.node.sku } - variantsSku.contains(ProductType.WALLET_2_CARDS.sku) && variantsSku.contains( - ProductType.WALLET_3_CARDS.sku - ) - } - product.variants.edges.map { it.node } - .forEach { variant -> - if (variant.sku == ProductType.WALLET_2_CARDS.sku) { - variants[ProductType.WALLET_2_CARDS] = variant - } else if (variant.sku == ProductType.WALLET_3_CARDS.sku) { - variants[ProductType.WALLET_3_CARDS] = variant - } - } + return result.mapCatching { product -> + val availableVariants = product + .flatMap { it.variants.edges.map { it.node } } + .filter { SKUS_TO_DISPLAY.contains(it.sku) } + .associateBy { ProductType.fromSku(it.sku) } + .filterNotNull() + variants.putAll(availableVariants) + if (variants.size < SKUS_TO_DISPLAY.size) { + return Result.failure(Exception( + "Shopify: products are missing, " + + "\nproducts available: ${variants.keys.map { it.sku }}")) + } val twoCardsProduct = TangemProduct( type = ProductType.WALLET_2_CARDS, @@ -65,7 +62,6 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { createCheckouts() return Result.success(listOf(twoCardsProduct, threeCardsProduct)) } - return Result.failure(result.exceptionOrNull()!!) } private suspend fun createCheckouts() { @@ -214,6 +210,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { companion object { const val TANGEM_WALLET_2_CARDS_SKU = "TG115x2" const val TANGEM_WALLET_3_CARDS_SKU = "TG115x3" + val SKUS_TO_DISPLAY = listOf(TANGEM_WALLET_2_CARDS_SKU, TANGEM_WALLET_3_CARDS_SKU) } } diff --git a/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt b/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt index 89116f8096..d8db451147 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt @@ -4,5 +4,15 @@ import com.tangem.tap.common.shop.TangemShopService enum class ProductType(val sku: String) { WALLET_2_CARDS(TangemShopService.TANGEM_WALLET_2_CARDS_SKU), - WALLET_3_CARDS(TangemShopService.TANGEM_WALLET_3_CARDS_SKU) + WALLET_3_CARDS(TangemShopService.TANGEM_WALLET_3_CARDS_SKU); + + companion object { + fun fromSku(sku: String): ProductType? { + return when (sku) { + WALLET_2_CARDS.sku -> WALLET_2_CARDS + WALLET_3_CARDS.sku -> WALLET_3_CARDS + else -> null + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt new file mode 100644 index 0000000000..8cd6e7e5ba --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt @@ -0,0 +1,59 @@ +package com.tangem.tap.common.ui + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import com.tangem.tap.common.redux.global.GlobalAction +import com.tangem.tap.store +import com.tangem.wallet.R + +class SimpleAlertDialog { + companion object { + fun create( + titleRes: Int? = null, + messageRes: Int? = null, + title: String? = null, + message: String? = null, + primaryButtonRes: Int = R.string.common_ok, + context: Context, + ): AlertDialog { + return SimpleCancelableAlertDialog.create( + titleRes = titleRes, + messageRes = messageRes, + title = title, + message = message, + primaryButtonRes = primaryButtonRes, + secondaryButtonRes = null, + context = context + ) + } + } +} + +class SimpleCancelableAlertDialog { + companion object { + fun create( + titleRes: Int? = null, + messageRes: Int? = null, + title: String? = null, + message: String? = null, + primaryButtonRes: Int = R.string.common_ok, + secondaryButtonRes: Int? = R.string.common_cancel, + primaryButtonAction: () -> Unit = {}, + secondaryButtonAction: () -> Unit = {}, + context: Context, + ): AlertDialog { + + return AlertDialog.Builder(context).apply { + setTitle(titleRes?.let { context.getString(it) } ?: title ) + setMessage(messageRes?.let { context.getString(it) } ?: message) + setPositiveButton(context.getText(primaryButtonRes)) { _, _ -> primaryButtonAction() } + if (secondaryButtonRes != null) { + setNegativeButton(context.getText(secondaryButtonRes)) { _, _ -> secondaryButtonAction()} + } + setOnDismissListener { + store.dispatch(GlobalAction.HideDialog) + } + }.create() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt b/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt index 4c9cafbdee..51252c819c 100644 --- a/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt @@ -3,7 +3,7 @@ package com.tangem.tap.domain import com.tangem.common.services.Result import com.tangem.domain.common.ThrottlerWithValues import com.tangem.network.api.tangemTech.TangemTechService -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.store import java.math.BigDecimal diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index cce3a27c15..123c26f691 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -26,7 +26,7 @@ import kotlinx.coroutines.withContext class TapWalletManager { val walletManagerFactory: WalletManagerFactory - by lazy { WalletManagerFactory(blockchainSdkConfig) } + by lazy { WalletManagerFactory(blockchainSdkConfig) } val rates: RatesRepository = RatesRepository() @@ -34,10 +34,10 @@ class TapWalletManager { store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig() } - private val walletManagersThrottler = ThrottlerWithValues>(10000) + private val walletManagersThrottler = + ThrottlerWithValues>(10000) suspend fun loadWalletData(walletManager: WalletManager) { - val blockchain = walletManager.wallet.blockchain val blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager) val result = if (walletManagersThrottler.isStillThrottled(blockchainNetwork)) { walletManagersThrottler.geValue(blockchainNetwork)!! @@ -54,17 +54,21 @@ class TapWalletManager { is Result.Failure -> { when (result.error) { is TapError.WalletManager.NoAccountError -> { - dispatchOnMain(WalletAction.LoadWallet.NoAccount( - walletManager.wallet, - blockchainNetwork, - (result.error as TapError.WalletManager.NoAccountError).customMessage - )) + dispatchOnMain( + WalletAction.LoadWallet.NoAccount( + walletManager.wallet, + blockchainNetwork, + (result.error as TapError.WalletManager.NoAccountError).customMessage + ) + ) } else -> { - dispatchOnMain(WalletAction.LoadWallet.Failure( - walletManager.wallet, - result.error.localizedMessage - )) + dispatchOnMain( + WalletAction.LoadWallet.Failure( + walletManager.wallet, + result.error.localizedMessage + ) + ) } } } @@ -109,6 +113,37 @@ class TapWalletManager { return } + if (data.card.isMultiwalletAllowed) { + loadMultiWalletData(data) + } else { + loadSingleWalletData(data) + } + + dispatchOnMain(WalletAction.LoadWallet()) + dispatchOnMain(WalletAction.LoadFiatRate()) + } + + private suspend fun loadMultiWalletData( + scanResponse: ScanResponse + ) { + val savedCurrencies = currenciesRepository.loadSavedCurrencies( + scanResponse.card.cardId, scanResponse.card.settings.isHDWalletAllowed + ) + if (savedCurrencies.isEmpty()) return + + val walletManagers = + walletManagerFactory.makeWalletManagersForApp(scanResponse, savedCurrencies) + dispatchOnMain( + WalletAction.MultiWallet.AddBlockchains(savedCurrencies, walletManagers), + ) + savedCurrencies.map { + if (it.tokens.isNotEmpty()) { + dispatchOnMain(WalletAction.MultiWallet.AddTokens(it.tokens, it)) + } + } + } + + private suspend fun loadSingleWalletData(data: ScanResponse) { val blockchain = data.getBlockchain() val primaryWalletManager = walletManagerFactory.makePrimaryWalletManager(data) @@ -120,87 +155,12 @@ class TapWalletManager { primaryWalletManager.addToken(primaryToken) dispatchOnMain(WalletAction.MultiWallet.SetPrimaryToken(primaryToken)) } - if (data.card.isMultiwalletAllowed) { - loadMultiWalletData(data, blockchain, primaryWalletManager) - } else { - dispatchOnMain(WalletAction.MultiWallet.AddBlockchains( + dispatchOnMain( + WalletAction.MultiWallet.AddBlockchains( listOf(BlockchainNetwork.fromWalletManager(primaryWalletManager)), listOf(primaryWalletManager) - )) - } - } else { - if (data.card.isMultiwalletAllowed) { - loadMultiWalletData(data, blockchain, null) - } - } - dispatchOnMain(WalletAction.LoadWallet()) - dispatchOnMain(WalletAction.LoadFiatRate()) - } - - private suspend fun loadMultiWalletData( - scanResponse: ScanResponse, - primaryBlockchain: Blockchain?, - primaryWalletManager: WalletManager? - ) { - val primaryTokens = primaryWalletManager?.cardTokens?.toList() ?: emptyList() - val savedCurrencies = currenciesRepository.loadSavedCurrencies( - scanResponse.card.cardId, scanResponse.card.settings.isHDWalletAllowed - ) - - if (savedCurrencies.isEmpty()) { - if (primaryBlockchain != null && primaryWalletManager != null) { - val blockchainNetwork = BlockchainNetwork.fromWalletManager(primaryWalletManager) - dispatchOnMain( - WalletAction.MultiWallet.SaveCurrencies(listOf(blockchainNetwork)), - WalletAction.MultiWallet.AddBlockchains( - listOf(blockchainNetwork), - listOf(primaryWalletManager) - ), - WalletAction.MultiWallet.AddTokens(primaryTokens.toList(), blockchainNetwork) ) - - } else { - val blockchainNetworks = listOf( - BlockchainNetwork(Blockchain.Bitcoin, scanResponse.card), - BlockchainNetwork(Blockchain.Ethereum, scanResponse.card) - ) - - val walletManagers = walletManagerFactory.makeWalletManagersForApp( - scanResponse, - blockchainNetworks - ) - - dispatchOnMain( - WalletAction.MultiWallet.SaveCurrencies(blockchainNetworks), - WalletAction.MultiWallet.AddBlockchains(blockchainNetworks, walletManagers), - ) - } -// dispatchOnMain( -// WalletAction.MultiWallet.FindBlockchainsInUse, -// WalletAction.MultiWallet.FindTokensInUse, -// ) - } else { - val walletManagers = if ( - primaryTokens.isNotEmpty() && - primaryWalletManager != null && - primaryBlockchain != null && primaryBlockchain != Blockchain.Unknown - ) { - val blockchainsWithoutPrimary = savedCurrencies.filterNot { it.blockchain == primaryBlockchain } - walletManagerFactory.makeWalletManagersForApp( - scanResponse, - blockchainsWithoutPrimary - ).plus(primaryWalletManager) - } else { - walletManagerFactory.makeWalletManagersForApp(scanResponse, savedCurrencies) - } - dispatchOnMain( - WalletAction.MultiWallet.AddBlockchains(savedCurrencies, walletManagers), ) - savedCurrencies.map { - if (it.tokens.isNotEmpty()) { - dispatchOnMain(WalletAction.MultiWallet.AddTokens(it.tokens, it)) - } - } } } diff --git a/app/src/main/java/com/tangem/tap/domain/UrlBitmapLoader.kt b/app/src/main/java/com/tangem/tap/domain/UrlBitmapLoader.kt deleted file mode 100644 index c06d9b0001..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/UrlBitmapLoader.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.tangem.tap.domain - -import android.graphics.Bitmap -import android.graphics.drawable.Drawable -import android.os.Handler -import android.os.Looper -import com.squareup.picasso.Picasso -import com.squareup.picasso.Target -import com.tangem.common.services.Result - -/** -[REDACTED_AUTHOR] - */ -class UrlBitmapLoader { - private val mainHandler = Handler(Looper.getMainLooper()) - - fun loadBitmap(url: String, callback: (Result) -> Unit) { - val target = DownloadTarget(callback) - protectedFromGarbageCollectorTargets.add(target) - mainHandler.post { Picasso.get().load(url).into(target) } - } - - fun loadBitmap(url: String, target: DownloadTarget) { - protectedFromGarbageCollectorTargets.add(target) - Picasso.get().load(url).into(target) - } - -} - -private val protectedFromGarbageCollectorTargets = mutableListOf() - -// It adds the ability to trigger multiple downloads with a unique callback. -open class DownloadTarget( - val callback: (Result) -> Unit, -) : Target { - - override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) { - callback(Result.Success(bitmap)) - protectedFromGarbageCollectorTargets.remove(this) - } - - override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) { - callback.invoke(Result.Failure(e ?: Exception("Unknown exception"))) - protectedFromGarbageCollectorTargets.remove(this) - } - - override fun onPrepareLoad(placeHolderDrawable: Drawable?) { - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/domain/extensions/CurrencyExchangeManager.kt index 23be9f4aaf..ca04907f47 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/CurrencyExchangeManager.kt @@ -2,7 +2,7 @@ package com.tangem.tap.domain.extensions import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Blockchain.Arbitrum -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.network.exchangeServices.CurrencyExchangeStatus import com.tangem.tap.store diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt b/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt index bff4c0c3b7..e636c4fa07 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt @@ -11,7 +11,7 @@ import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency fun WalletManagerFactory.makeWalletManagerForApp( scanResponse: ScanResponse, diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index 06afdcbd3c..982ed86857 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -112,31 +112,44 @@ private class CreateWalletTangemWallet : ProductCommandProcessor when (result) { is CompletionResult.Success -> { - val createWalletResponses = result.data.createWalletResponses - when { - card.settings.isBackupAllowed -> { - linkPrimaryCard(createWalletResponses, session, callback) - } - card.settings.isHDWalletAllowed -> { - deriveKeys(createWalletResponses, session, callback) - } - else -> { - callback( - CompletionResult.Success( - CreateProductWalletTaskResponse(card = session.environment.card!!) - ) - ) - } - } + proceedWithCreatedWallets(result.data.createWalletResponses, session, callback) } is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) } } } + private fun proceedWithCreatedWallets( + createWalletResponses: List, + session: CardSession, + callback: (result: CompletionResult) -> Unit, + ) { + when { + card.settings.isBackupAllowed -> { + linkPrimaryCard(createWalletResponses, session, callback) + } + card.settings.isHDWalletAllowed -> { + deriveKeys(createWalletResponses, session, callback) + } + else -> { + callback( + CompletionResult.Success( + CreateProductWalletTaskResponse(card = session.environment.card!!) + ) + ) + } + } + } + private fun linkPrimaryCard( createWalletResponse: List, session: CardSession, diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index 6888b7f648..2dafa32075 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -185,8 +185,9 @@ class CurrenciesRepository( tokens.map { async { tangemNetworkService.getTokens( - it.contractAddress, - it.blockchainDao.toBlockchain().toNetworkId() + contractAddress = it.contractAddress, + networkId = it.blockchainDao.toBlockchain().toNetworkId(), + active = true, ) } }.map { it.await() } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt b/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt index a0be7dc18a..5b806beecc 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/LoadAvailableCoinsService.kt @@ -53,6 +53,7 @@ class LoadAvailableCoinsService( val networkIds = supportedBlockchains.toSet().map { it.toNetworkId() } return networkService.getListOfCoins( networkIds = networkIds, + active = true, offset = offset, limit = LOAD_PER_PAGE, searchText = searchInput diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt index 8180023cb9..543640ad2f 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectRepository.kt @@ -5,11 +5,15 @@ import android.content.Context import com.squareup.moshi.JsonAdapter import com.squareup.moshi.JsonClass import com.squareup.moshi.Types +import com.tangem.common.extensions.hexToBytes +import com.tangem.common.extensions.toHexString import com.tangem.network.common.MoshiConverter import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession import com.tangem.tap.features.details.redux.walletconnect.WalletForSession import com.trustwallet.walletconnect.models.WCPeerMeta import com.trustwallet.walletconnect.models.session.WCSession +import timber.log.Timber +import java.nio.charset.Charset class WalletConnectRepository(val context: Application) { private val moshi = MoshiConverter.defaultMoshi() @@ -35,17 +39,29 @@ class WalletConnectRepository(val context: Application) { fun loadSavedSessions(): List { return try { val json = context.readFileText(FILE_NAME_PREFIX_SESSIONS) + .hexToUtf8() walletConnectAdapter.fromJson(json)!!.map { it.toSession() } } catch (exception: Exception) { + Timber.e(exception) emptyList() } } private fun saveSessions(sessions: List) { val json = walletConnectAdapter.toJson(sessions.map { SessionDao.fromSession(it) }) + .utf8ToHex() // convert to hex to solve problems with saving text with emojis + Timber.e("WC sessions, saving following json: $json") context.rewriteFile(json, FILE_NAME_PREFIX_SESSIONS) } + private fun String.utf8ToHex(): String { + return this.toByteArray().toHexString() + } + + private fun String.hexToUtf8(): String { + return this.hexToBytes().toString(Charset.defaultCharset()) + } + private fun Context.readFileText(fileName: String): String = this.openFileInput(fileName).bufferedReader().readText() diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt index 92551d6411..87af003060 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt @@ -5,7 +5,7 @@ import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.scope import com.tangem.tap.store diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index 8dbaafc988..25c5d373b4 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -1,12 +1,11 @@ package com.tangem.tap.features.details.redux.walletconnect import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.DerivationParams import com.tangem.blockchain.common.WalletManager import com.tangem.common.extensions.guard import com.tangem.domain.common.ScanResponse -import com.tangem.domain.common.TapWorkarounds.derivationStyle 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 import com.tangem.tap.common.redux.AppState @@ -21,8 +20,6 @@ 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.features.demo.DemoHelper -import com.tangem.tap.features.wallet.redux.Currency -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.wallet.R @@ -192,40 +189,51 @@ class WalletConnectMiddleware { return } - val walletManager = getWalletManager(scanResponse, blockchain).guard { - store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(null)) - return + scope.launch { + val walletManager = getWalletManager(scanResponse, blockchain).guard { + store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(session.session)) + store.dispatchOnMain( + GlobalAction.ShowDialog( + WalletConnectDialog.AddNetwork(blockchain.fullName) + ) + ) + return@launch + } + + val wallet = walletManager.wallet + val derivedKey = + if (wallet.publicKey.blockchainKey.contentEquals(wallet.publicKey.seedKey)) { + null + } else { + walletManager.wallet.publicKey.blockchainKey + } + val walletForSession = WalletForSession( + cardId = scanResponse.card.cardId, + walletPublicKey = wallet.publicKey.seedKey, + derivedPublicKey = derivedKey, + derivationPath = wallet.publicKey.derivationPath, + blockchain = wallet.blockchain + ) + + withMainContext { + val updatedSession = session.copy(wallet = walletForSession) + walletConnectManager.updateSession(updatedSession) + + store.dispatch(WalletConnectAction.AddScanResponse(scanResponse)) + + store.dispatch( + GlobalAction.ShowDialog( + WalletConnectDialog.ApproveWcSession( + updatedSession + ) + ) + ) + } } - val wallet = walletManager.wallet - val derivedKey = - if (wallet.publicKey.blockchainKey.contentEquals(wallet.publicKey.seedKey)) { - null - } else { - walletManager.wallet.publicKey.blockchainKey - } - val walletForSession = WalletForSession( - cardId = scanResponse.card.cardId, - walletPublicKey = wallet.publicKey.seedKey, - derivedPublicKey = derivedKey, - derivationPath = wallet.publicKey.derivationPath, - blockchain = wallet.blockchain - ) - val updatedSession = session.copy(wallet = walletForSession) - walletConnectManager.updateSession(updatedSession) - - store.dispatchOnMain(WalletConnectAction.AddScanResponse(scanResponse)) - - store.dispatchOnMain( - GlobalAction.ShowDialog( - WalletConnectDialog.ApproveWcSession( - updatedSession - ) - ) - ) } - private fun getWalletManager( + private suspend fun getWalletManager( scanResponse: ScanResponse, blockchain: Blockchain ): WalletManager? { val card = scanResponse.card @@ -236,42 +244,25 @@ class WalletConnectMiddleware { blockchain } + val blockchainNetwork = BlockchainNetwork( + blockchain = blockchainToMake, + card = card + ) + return if (store.state.globalState.scanResponse?.card?.cardId == card.cardId) { - val derivationPath = blockchainToMake.derivationPath(card.derivationStyle)?.rawPath - store.state.walletState.getWalletManager( - Currency.Blockchain(blockchainToMake, derivationPath) - ) - ?: factory.makeWalletManagerForApp( - scanResponse, - blockchainToMake, - card.derivationStyle?.let { DerivationParams.Default(it) } - ) - ?.also { walletManager -> - store.dispatch( - WalletAction.MultiWallet.AddBlockchain( - BlockchainNetwork.fromWalletManager(walletManager), walletManager - ) - ) - } + store.state.walletState.getWalletManager(blockchainNetwork) } else { - val walletManager = factory.makeWalletManagerForApp( - scanResponse, - blockchainToMake, - card.derivationStyle?.let { DerivationParams.Default(it) } - ) - scope.launch { - if (currenciesRepository.loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed) - .find { it.blockchain == blockchainToMake } != null - ) { - walletManager?.let { - currenciesRepository.saveUpdatedCurrency( - card.cardId, - BlockchainNetwork.fromWalletManager(walletManager) - ) - } - } + if (currenciesRepository + .loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed) + .contains(blockchainNetwork) + ) { + factory.makeWalletManagerForApp( + scanResponse = scanResponse, + blockchainNetwork = blockchainNetwork + ) + } else { + null } - return walletManager } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt index 0039e247ee..4f5861c67b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt @@ -82,6 +82,7 @@ data class WalletForSession( sealed class WalletConnectDialog : StateDialog { data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog() object UnsupportedCard : WalletConnectDialog() + data class AddNetwork(val network: String) : WalletConnectDialog() object OpeningSessionRejected : WalletConnectDialog() object SessionTimeout : WalletConnectDialog() data class ApproveWcSession(val session: WalletConnectSession) : WalletConnectDialog() diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt index e8f3b56a62..2789b0069d 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt @@ -67,7 +67,7 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber } - setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) - } - }.create() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt index e9f47acef9..50faf24376 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt @@ -10,8 +10,8 @@ import com.tangem.tap.common.extensions.dispatchDialogHide import com.tangem.tap.common.extensions.dispatchShare import com.tangem.tap.common.extensions.dispatchToastNotification import com.tangem.tap.common.redux.AppDialog +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.AddressData -import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt index f0873595ff..26d719d0c6 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt @@ -12,8 +12,8 @@ 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.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.hasPendingTransactions -import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.persistence.UsedCardsPrefStorage import timber.log.Timber diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt index 3125784ba9..b31dd02832 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt @@ -10,7 +10,7 @@ import androidx.annotation.LayoutRes import androidx.constraintlayout.widget.ConstraintSet import androidx.core.view.isVisible import androidx.transition.TransitionManager -import com.squareup.picasso.Picasso +import coil.load import com.tangem.blockchain.common.Blockchain import com.tangem.tangem_sdk_new.extensions.fadeIn import com.tangem.tangem_sdk_new.extensions.fadeOut @@ -67,11 +67,11 @@ class OnboardingNoteFragment : BaseOnboardingFragment() { override fun newState(state: OnboardingNoteState) { if (activity == null || view == null) return - Picasso.get() - .load(state.cardArtworkUrl) - .error(R.drawable.card_placeholder_black) - .placeholder(R.drawable.card_placeholder_black) - ?.into(binding.onboardingTopContainer.imvFrontCard) + binding.onboardingTopContainer.imvFrontCard.load(state.cardArtworkUrl) { + placeholder(R.drawable.card_placeholder_black) + error(R.drawable.card_placeholder_black) + fallback(R.drawable.card_placeholder_black) + } pbBinding.pbState.max = state.steps.size - 1 pbBinding.pbState.progress = state.progress diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index 2c854ab5a0..34c0d381b2 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -15,7 +15,7 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.hasWallets import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.scope import com.tangem.tap.store diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/OnboardingOtherCardsFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/OnboardingOtherCardsFragment.kt index 996fdd67fe..e2b1e015c4 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/OnboardingOtherCardsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/OnboardingOtherCardsFragment.kt @@ -7,7 +7,7 @@ import androidx.annotation.LayoutRes import androidx.constraintlayout.widget.ConstraintSet import androidx.core.view.isVisible import androidx.transition.TransitionManager -import com.squareup.picasso.Picasso +import coil.load import com.tangem.tap.common.extensions.getDrawableCompat import com.tangem.tap.common.redux.navigation.ShareElement import com.tangem.tap.common.transitions.InternalNoteLayoutTransition @@ -54,11 +54,11 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment() { resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true) val deviceScaleFactorForWelcomeState = typedValue.float - twinsWidget = TwinsCardWidget(LeapfrogWidget(binding.onboardingTopContainer.cardsContainer), deviceScaleFactorForWelcomeState) { + twinsWidget = TwinsCardWidget( + LeapfrogWidget(binding.onboardingTopContainer.cardsContainer), + deviceScaleFactorForWelcomeState + ) { 285f * deviceScaleFactorForWelcomeState } - btnRefreshBalanceWidget = RefreshBalanceWidget(binding.onboardingTopContainer.onboardingMainContainer) + btnRefreshBalanceWidget = + RefreshBalanceWidget(binding.onboardingTopContainer.onboardingMainContainer) binding.toolbar.title = getText(R.string.twins_recreate_toolbar) - Picasso.get() - .load(Artwork.TWIN_CARD_1) - .error(R.drawable.card_placeholder_black) - .placeholder(R.drawable.card_placeholder_black) - ?.into(binding.onboardingTopContainer.imvTwinFrontCard) + binding.onboardingTopContainer.imvTwinFrontCard.load(Artwork.TWIN_CARD_1) { + placeholder(R.drawable.card_placeholder_black) + error(R.drawable.card_placeholder_black) + fallback(R.drawable.card_placeholder_black) + } - Picasso.get() - .load(Artwork.TWIN_CARD_2) - .error(R.drawable.card_placeholder_white) - .placeholder(R.drawable.card_placeholder_white) - ?.into(binding.onboardingTopContainer.imvTwinBackCard) + binding.onboardingTopContainer.imvTwinBackCard.load(Artwork.TWIN_CARD_2) { + placeholder(R.drawable.card_placeholder_white) + error(R.drawable.card_placeholder_white) + fallback(R.drawable.card_placeholder_white) + } } private fun reconfigureLayoutForTwins(containerBinding: LayoutOnboardingContainerTopBinding) = diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index c880488141..88121813ad 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.onboarding.products.wallet.redux +import com.tangem.blockchain.common.Blockchain import com.tangem.common.CompletionResult import com.tangem.common.card.Card import com.tangem.domain.common.ScanResponse @@ -12,9 +13,11 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.hasWallets +import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.wallet.redux.Artwork +import com.tangem.tap.features.wallet.redux.WalletAction import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.Middleware @@ -84,6 +87,11 @@ private fun handleWalletAction(action: Action) { primaryCard = result.data.primaryCard ) onboardingManager.scanResponse = updatedResponse + val blockchainNetworks = listOf( + BlockchainNetwork(Blockchain.Bitcoin, result.data.card), + BlockchainNetwork(Blockchain.Ethereum, result.data.card) + ) + store.dispatchOnMain(WalletAction.MultiWallet.SaveCurrencies(blockchainNetworks)) onboardingManager.activationStarted(updatedResponse.card.cardId) store.dispatch(OnboardingWalletAction.ProceedBackup) } @@ -260,6 +268,11 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) backupService.proceedBackup { result -> when (result) { is CompletionResult.Success -> { + val blockchainNetworks = listOf( + BlockchainNetwork(Blockchain.Bitcoin, result.data), + BlockchainNetwork(Blockchain.Ethereum, result.data) + ) + store.dispatchOnMain(WalletAction.MultiWallet.SaveCurrencies(blockchainNetworks)) if (backupService.currentState == BackupService.State.Finished) { store.dispatchOnMain(BackupAction.FinishBackup) } else { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index b9691488c5..056d5a28bb 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -11,9 +11,9 @@ import androidx.fragment.app.Fragment import androidx.transition.TransitionInflater import androidx.transition.TransitionManager import by.kirich1409.viewbindingdelegate.viewBinding +import coil.load import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.tabs.TabLayoutMediator -import com.squareup.picasso.Picasso import com.tangem.common.CardIdFormatter import com.tangem.common.core.CardIdDisplayFormat import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget @@ -22,7 +22,12 @@ import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show import com.tangem.tap.features.FragmentOnBackPressedHandler import com.tangem.tap.features.addBackPressHandler -import com.tangem.tap.features.onboarding.products.wallet.redux.* +import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction +import com.tangem.tap.features.onboarding.products.wallet.redux.BackupState +import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep +import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction +import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState +import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog import com.tangem.tap.store import com.tangem.wallet.R @@ -124,11 +129,11 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), } private fun loadImageIntoImageView(url: String?, view: ImageView) { - Picasso.get() - .load(url) - .error(R.drawable.card_placeholder_black) - .placeholder(R.drawable.card_placeholder_black) - ?.into(view) + view.load(url) { + placeholder(R.drawable.card_placeholder_black) + error(R.drawable.card_placeholder_black) + fallback(R.drawable.card_placeholder_black) + } } private fun setupCreateWalletState() = with(binding) { diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt index 65a909ce1c..edb435953f 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt @@ -106,7 +106,7 @@ class FeeReducer : SendInternalReducer { private fun getFeePrecision(sendState: SendState): FeePrecision { val blockchain = sendState.walletManager?.wallet?.blockchain - return if (blockchain?.fullNameWithoutTestnet == Blockchain.Tron.fullName && + return if ((blockchain?.fullNameWithoutTestnet == Blockchain.Arbitrum.fullName || blockchain?.fullNameWithoutTestnet == Blockchain.Tron.fullName) && sendState.amountState.typeOfAmount is AmountType.Token) { FeePrecision.CAN_BE_LOWER } else { diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt index 28a7f06b08..c15813fdaa 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt @@ -7,6 +7,7 @@ import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt import com.tangem.tap.features.send.redux.SendScreenAction import com.tangem.tap.features.send.redux.states.* +import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.store import java.math.BigDecimal @@ -15,10 +16,6 @@ import java.math.BigDecimal */ class ReceiptReducer : SendInternalReducer { - companion object { - const val EMPTY = "-" - } - private lateinit var sendState: SendState private lateinit var amountState: AmountState private lateinit var feeState: FeeState @@ -137,9 +134,9 @@ class ReceiptReducer : SendInternalReducer { ) } else { ReceiptTokenFiat( - amountFiat = EMPTY, - feeFiat = EMPTY, - totalFiat = EMPTY, + amountFiat = UNKNOWN_AMOUNT_SIGN, + feeFiat = UNKNOWN_AMOUNT_SIGN, + totalFiat = UNKNOWN_AMOUNT_SIGN, willSentToken = tokensToSend.stripZeroPlainString(), willSentFeeCoin = feeCoin.stripZeroPlainString(), symbols = symbols @@ -169,7 +166,7 @@ class ReceiptReducer : SendInternalReducer { ReceiptTokenCrypto( amountToken = tokensToSend.stripZeroPlainString(), feeCoin = feeCoin.stripZeroPlainString().addPrecisionSign(), - totalFiat = EMPTY, + totalFiat = UNKNOWN_AMOUNT_SIGN, symbols = symbols ) } @@ -206,7 +203,7 @@ class ReceiptReducer : SendInternalReducer { return when { !isToken && sendState.coinIsConvertible() -> sendState.coinConverter!!.toFiatWithPrecision(value).stripZeroPlainString() isToken && sendState.tokenIsConvertible() -> sendState.tokenConverter!!.toFiatWithPrecision(value).stripZeroPlainString() - else -> EMPTY + else -> UNKNOWN_AMOUNT_SIGN } } diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 3c49da49fb..2b71c1ba31 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -17,12 +17,13 @@ import com.tangem.tap.features.BaseStoreFragment import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error import com.tangem.tap.features.send.redux.FeeAction import com.tangem.tap.features.send.redux.SendAction -import com.tangem.tap.features.send.redux.reducers.ReceiptReducer import com.tangem.tap.features.send.redux.states.* import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog +import com.tangem.tap.features.wallet.redux.WalletState.Companion.ROUGH_SIGN +import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter import com.tangem.tap.store import com.tangem.wallet.R @@ -257,12 +258,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : val mainLayout = clReceiptContainer as ViewGroup val totalLayout = llTotalContainer.llTotal as ViewGroup val totalTokenLayout = llTotalContainer.flTotalTokenCrypto as ViewGroup - fun getString(id: Int, vararg formatStrings: String): String = - mainLayout.context.getString(id, *formatStrings) - val rough = getString(R.string.sign_rough) - fun roughOrEmpty(value: String): String = - if (value == ReceiptReducer.EMPTY) value else "$rough $value" + fun getString(id: Int, vararg formatStrings: String): String = mainLayout.getString(id, *formatStrings) + + fun roughOrEmpty(value: String): String { + return if (value == UNKNOWN_AMOUNT_SIGN) value else "$ROUGH_SIGN $value" + } when (state.visibleTypeOfReceipt) { ReceiptLayoutType.FIAT -> { diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopAction.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopAction.kt index 500cc39285..27a4a5b9e5 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopAction.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopAction.kt @@ -1,15 +1,20 @@ package com.tangem.tap.features.shop.redux import android.content.Intent +import com.tangem.tap.common.redux.NotificationAction import com.tangem.tap.common.shop.GooglePayService import com.tangem.tap.common.shop.data.ProductType import com.tangem.tap.common.shop.data.TangemProduct +import com.tangem.wallet.R import org.rekotlin.Action sealed class ShopAction : Action { object LoadProducts : ShopAction() { data class Success(val products: List) : ShopAction() + object Failure : ShopAction(), NotificationAction { + override val messageResource = R.string.common_server_unavailable + } } data class ApplyPromoCode(val promoCode: String) : ShopAction() { diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt index 464a99de96..f3734950da 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt @@ -11,6 +11,7 @@ import com.tangem.tap.store import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.Middleware +import timber.log.Timber class ShopMiddleware { @@ -88,10 +89,13 @@ private fun handle(action: Action) { } ShopAction.LoadProducts -> { scope.launch { - val result = shopService.getProducts() - result.onSuccess { - store.dispatchOnMain(ShopAction.LoadProducts.Success(it)) - } + shopService.getProducts().fold( + onSuccess = { store.dispatchOnMain(ShopAction.LoadProducts.Success(it)) }, + onFailure = { + Timber.e(it) + store.dispatchOnMain(ShopAction.LoadProducts.Failure) + } + ) } } is ShopAction.CheckIfGooglePayAvailable -> { diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopReducer.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopReducer.kt index ee12f53109..001c48a46f 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopReducer.kt @@ -65,5 +65,6 @@ private fun internalReduce(action: Action, state: ShopState): ShopState { } ShopAction.FinishSuccessfulOrder -> state ShopAction.ResetState -> ShopState() + ShopAction.LoadProducts.Failure -> state } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index aab99a3d58..dd40f7074e 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -30,7 +30,7 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.tokens.LoadAvailableCoinsService import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.WalletAction import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -309,7 +309,10 @@ class TokensMiddleware { if (currencies.isNotEmpty()) { currencies.forEach { currency -> store.state.walletState.getWalletData(currency)?.let { - store.dispatch(WalletAction.MultiWallet.RemoveWallet(it)) + store.dispatch(WalletAction.MultiWallet.RemoveWallet( + walletData = it, + fromWalletDetails = false + )) } } } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt index 1c60655d24..5fcc7510f2 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt @@ -34,18 +34,18 @@ data class TokensState( typealias ContractAddress = String fun List.toTokensContractAddresses(): List { - return mapNotNull { (it.currency as? com.tangem.tap.features.wallet.redux.Currency.Token)?.token?.contractAddress }.distinct() + return mapNotNull { (it.currency as? com.tangem.tap.features.wallet.models.Currency.Token)?.token?.contractAddress }.distinct() } fun List.toNonCustomTokens(derivationStyle: DerivationStyle?): List { return filter { !it.currency.isCustomCurrency(derivationStyle) } - .mapNotNull { (it.currency as? com.tangem.tap.features.wallet.redux.Currency.Token)?.token } + .mapNotNull { (it.currency as? com.tangem.tap.features.wallet.models.Currency.Token)?.token } .distinct() } fun List.toNonCustomTokensWithBlockchains(derivationStyle: DerivationStyle?): List { return mapNotNull { - if (it.currency !is com.tangem.tap.features.wallet.redux.Currency.Token) return@mapNotNull null + if (it.currency !is com.tangem.tap.features.wallet.models.Currency.Token) return@mapNotNull null if (it.currency.isCustomCurrency(derivationStyle)) return@mapNotNull null TokenWithBlockchain(it.currency.token, it.currency.blockchain) }.distinct() @@ -56,7 +56,7 @@ fun List.toNonCustomBlockchains(derivationStyle: DerivationStyle?): if (it.currency.isCustomCurrency(derivationStyle)) { null } else { - (it.currency as? com.tangem.tap.features.wallet.redux.Currency.Blockchain)?.blockchain + (it.currency as? com.tangem.tap.features.wallet.models.Currency.Blockchain)?.blockchain } }.distinct() } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt new file mode 100644 index 0000000000..76945c588f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/Currency.kt @@ -0,0 +1,97 @@ +package com.tangem.tap.features.wallet.models + +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.DerivationStyle +import com.tangem.blockchain.common.Token +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.tap.domain.tokens.models.BlockchainNetwork +import com.tangem.tap.features.tokens.redux.TokenWithBlockchain + +sealed interface Currency { + + val coinId: String? + get() = when (this) { + is Blockchain -> blockchain.toCoinId() + is Token -> token.id + } + val blockchain: com.tangem.blockchain.common.Blockchain + val currencySymbol: CryptoCurrencyName + val derivationPath: String? + + val currencyName: String + get() = when (this) { + is Blockchain -> blockchain.fullName + is Token -> token.name + } + + data class Token( + val token: com.tangem.blockchain.common.Token, + override val blockchain: com.tangem.blockchain.common.Blockchain, + override val derivationPath: String? + ) : Currency { + override val currencySymbol = token.symbol + } + + data class Blockchain( + override val blockchain: com.tangem.blockchain.common.Blockchain, + 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: com.tangem.blockchain.common.Token? = 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 fromTokenWithBlockchain(tokenWithBlockchain: TokenWithBlockchain): Token { + return Token( + token = tokenWithBlockchain.token, + blockchain = tokenWithBlockchain.blockchain, + derivationPath = null + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 769d28a8cd..eefae0bcf6 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -14,6 +14,7 @@ import com.tangem.tap.common.redux.NotificationAction import com.tangem.tap.domain.TapError import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.tokens.models.BlockchainNetwork +import com.tangem.tap.features.wallet.models.Currency import com.tangem.wallet.R import java.math.BigDecimal import org.rekotlin.Action @@ -74,7 +75,8 @@ sealed class WalletAction : Action { ) : MultiWallet() data class SelectWallet(val walletData: WalletData?) : MultiWallet() - data class RemoveWallet(val walletData: WalletData) : MultiWallet() + data class RemoveWallet(val walletData: WalletData, val fromWalletDetails: Boolean = true) : MultiWallet() + data class TryToRemoveWallet(val walletData: WalletData) : MultiWallet() data class SetPrimaryBlockchain(val blockchain: Blockchain) : MultiWallet() data class SetPrimaryToken(val token: Token) : MultiWallet() } 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 b906784269..ce660968f6 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 @@ -1,17 +1,10 @@ package com.tangem.tap.features.wallet.redux import android.graphics.Bitmap -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.* import com.tangem.blockchain.common.address.AddressType import com.tangem.common.extensions.isZero import com.tangem.domain.common.extensions.canHandleToken -import com.tangem.domain.common.extensions.toCoinId -import com.tangem.domain.features.addCustomToken.CustomCurrency import com.tangem.tap.common.entities.Button import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.extensions.toQrCode @@ -23,22 +16,15 @@ 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.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.models.* 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 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 java.math.BigDecimal import kotlin.properties.ReadOnlyProperty data class WalletState( @@ -315,6 +301,11 @@ data class WalletState( ) } else this } + + companion object { + const val UNKNOWN_AMOUNT_SIGN = "—" + const val ROUGH_SIGN = "≈" + } } sealed interface WalletDialog : StateDialog { @@ -439,87 +430,6 @@ data class WalletData( private fun tokenAmountIsEmpty(): Boolean = currencyData.amount?.isZero() == true } -sealed interface Currency { - - val coinId: String? - get() = when (this) { - is Blockchain -> blockchain.toCoinId() - is Token -> token.id - } - val blockchain: com.tangem.blockchain.common.Blockchain - val currencySymbol: CryptoCurrencyName - val derivationPath: String? - - data class Token( - val token: com.tangem.blockchain.common.Token, - override val blockchain: com.tangem.blockchain.common.Blockchain, - override val derivationPath: String? - ) : Currency { - override val currencySymbol = token.symbol - } - - data class Blockchain( - override val blockchain: com.tangem.blockchain.common.Blockchain, - 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: com.tangem.blockchain.common.Token? = 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 fromTokenWithBlockchain(tokenWithBlockchain: TokenWithBlockchain): Token { - return Token( - token = tokenWithBlockchain.token, - blockchain = tokenWithBlockchain.blockchain, - derivationPath = null - ) - } - } -} - data class WalletStore( val walletManager: WalletManager?, val blockchainNetwork: BlockchainNetwork, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt index d339e49202..f1fb6371cc 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt @@ -9,7 +9,7 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TapWalletManager import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletDialog +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.persistence.FiatCurrenciesPrefStorage import com.tangem.tap.scope import com.tangem.tap.store 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 ace70c1988..97a35f59c2 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 @@ -3,6 +3,8 @@ package com.tangem.tap.features.wallet.redux.middlewares import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.WalletManager +import com.tangem.common.extensions.guard +import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.redux.global.GlobalState import com.tangem.tap.common.redux.navigation.AppScreen @@ -12,9 +14,10 @@ import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.demo.isDemoCard -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.scope import com.tangem.tap.store import kotlinx.coroutines.Dispatchers @@ -55,23 +58,55 @@ class MultiWalletMiddleware { blockchainNetwork = action.blockchain ) } - store.dispatch(WalletAction.LoadFiatRate( - coinsList = listOf( - Currency.Blockchain( - action.blockchain.blockchain, - action.blockchain.derivationPath + store.dispatch( + WalletAction.LoadFiatRate( + coinsList = listOf( + Currency.Blockchain( + action.blockchain.blockchain, + action.blockchain.derivationPath + ) ) ) - )) - store.dispatch(WalletAction.LoadWallet( - action.blockchain, action.walletManager - )) + ) + store.dispatch( + WalletAction.LoadWallet( + action.blockchain, action.walletManager + ) + ) } is WalletAction.MultiWallet.SaveCurrencies -> { globalState.scanResponse?.card?.cardId?.let { currenciesRepository.saveCurrencies(it, action.blockchainNetworks) } } + is WalletAction.MultiWallet.TryToRemoveWallet -> { + val walletState = store.state.walletState + val currency = action.walletData.currency + val walletCanBeRemoved = store.state.walletState.canBeRemoved( + store.state.walletState.getSelectedWalletData() + ) + if (walletCanBeRemoved) { + store.dispatch(WalletAction.MultiWallet.RemoveWallet(action.walletData)) + return + } + + val walletManager = walletState.getWalletManager(currency).guard { + store.dispatch(WalletAction.MultiWallet.RemoveWallet(action.walletData)) + return + } + + val dialog = when { + currency is Currency.Blockchain && + walletManager.cardTokens.isNotEmpty() -> + WalletDialog.TokensAreLinkedDialog( + currency.currencyName, currency.currencySymbol + ) + + else -> + WalletDialog.RemoveWalletDialog(currency.currencyName, action.walletData) + } + store.dispatchDialogShow(dialog) + } is WalletAction.MultiWallet.RemoveWallet -> { val cardId = globalState.scanResponse?.card?.cardId when (val currency = action.walletData.currency) { @@ -94,12 +129,18 @@ class MultiWalletMiddleware { currenciesRepository.removeToken( cardId = it, token = currency.token, - blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager) + blockchainNetwork = BlockchainNetwork.fromWalletManager( + walletManager + ) ) } } } } + if (action.fromWalletDetails) { + store.dispatch(WalletAction.MultiWallet.SelectWallet(null)) + store.dispatch(NavigationAction.PopBackTo()) + } } // is WalletAction.MultiWallet.FindBlockchainsInUse -> { // val scanResponse = globalState.scanResponse ?: return diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 3e4210fe42..9590452975 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -10,7 +10,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.send.redux.SendAction -import com.tangem.tap.features.wallet.redux.Currency +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 diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt index e495c55c94..9ae3127317 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt @@ -4,7 +4,7 @@ import com.tangem.tap.common.extensions.dispatchDialogHide import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.redux.AppDialog import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletDialog +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.store class WalletDialogsMiddleware { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index e4f7b6f659..7a4ac13ea5 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -31,9 +31,10 @@ import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.wallet.models.PendingTransactionType +import com.tangem.tap.features.wallet.models.filterByCoin import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.getSendableAmounts -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletData import com.tangem.tap.features.wallet.redux.WalletState @@ -332,7 +333,10 @@ class WalletMiddleware { } val balance = walletManager.wallet.fundsAvailable(AmountType.Coin) - val outgoingTxs = walletManager.wallet.getPendingTransactions(PendingTransactionType.Outgoing) + val outgoingTxs = walletManager.wallet.getPendingTransactions( + PendingTransactionType.Outgoing + ).filterByCoin() + val rentExempt = result.data val show = if (outgoingTxs.isEmpty()) { isNeedToShowWarning(balance, rentExempt) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt new file mode 100644 index 0000000000..5e2458c15d --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt @@ -0,0 +1,39 @@ +package com.tangem.tap.features.wallet.redux.models + +import com.tangem.blockchain.common.Amount +import com.tangem.tap.common.entities.FiatCurrency +import com.tangem.tap.common.redux.StateDialog +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.store +import com.tangem.wallet.R + +sealed interface WalletDialog : StateDialog { + data class SelectAmountToSendDialog(val amounts: List?) : WalletDialog + object SignedHashesMultiWalletDialog : WalletDialog + object ChooseTradeActionDialog : WalletDialog + data class CurrencySelectionDialog( + val currenciesList: List, + val currentAppCurrency: FiatCurrency, + ) : WalletDialog + + data class RemoveWalletDialog( + val currencyTitle: String, + private val walletData: WalletData + ): WalletDialog { + val messageRes: Int = R.string.token_details_hide_alert_message + val titleRes: Int = R.string.token_details_hide_alert_title + val primaryButtonRes: Int = R.string.token_details_hide_alert_hide + val action = { store.dispatch(WalletAction.MultiWallet.RemoveWallet(walletData)) } + } + + data class TokensAreLinkedDialog( + val currencyTitle: String, + val currencySymbol: String + ): WalletDialog { + val messageRes: Int = R.string.token_details_unable_hide_alert_message + val titleRes: Int = R.string.token_details_unable_hide_alert_title + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index 850f6b3b3b..648479c03a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -7,10 +7,13 @@ import com.tangem.tap.common.extensions.toFiatString import com.tangem.tap.common.extensions.toFormattedCurrencyString import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork +import com.tangem.tap.features.wallet.models.Currency +import com.tangem.tap.features.wallet.models.WalletRent import com.tangem.tap.features.wallet.models.filterByToken import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.removeUnknownTransactions import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.features.wallet.ui.TokenData @@ -102,10 +105,10 @@ class MultiWalletReducer { } is WalletAction.MultiWallet.TokenLoaded -> { val currency = Currency.fromBlockchainNetwork(action.blockchain, action.token) - val wallet = state.getWalletManager(currency)?.wallet.guard { - throw NullPointerException("MultiWallet.TokenLoaded: WalletManager must be no NULL") + val walletManager = state.getWalletManager(currency).guard { + throw NullPointerException("MultiWallet.TokenLoaded: WalletManager must be not NULL") } - + val wallet = walletManager.wallet val pendingTransactions = wallet.getPendingTransactions() val tokenPendingTransactions = pendingTransactions.filterByToken(action.token) val tokenBalanceStatus = when { @@ -125,9 +128,8 @@ class MultiWalletReducer { action.amount.decimals, action.amount.currencySymbol ), fiatAmountFormatted = tokenWalletData.fiatRate?.let { - action.amount.value - ?.toFiatString(it, store.state.globalState.appCurrency.symbol) - }, + action.amount.value?.toFiatString(it, store.state.globalState.appCurrency.symbol) + } ?: UNKNOWN_AMOUNT_SIGN, blockchainAmount = wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), @@ -136,7 +138,8 @@ class MultiWalletReducer { token = action.token, blockchain = action.blockchain.blockchain, derivationPath = action.blockchain.derivationPath - ) + ), + walletRent = findWalletRent(state.getWalletStore(walletManager.wallet)) ) state.updateWalletData(newTokenWalletData) } @@ -157,8 +160,15 @@ class MultiWalletReducer { // is WalletAction.MultiWallet.FindTokensInUse -> state // is WalletAction.MultiWallet.FindBlockchainsInUse -> state is WalletAction.MultiWallet.SaveCurrencies -> state + is WalletAction.MultiWallet.TryToRemoveWallet -> state } } + + private fun findWalletRent(walletStore: WalletStore?): WalletRent? { + return walletStore?.walletsData?.firstOrNull { + it.walletRent != null + }?.walletRent + } } private fun addTokens( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt index ac3ede0818..c3219215ff 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt @@ -9,15 +9,16 @@ import com.tangem.tap.common.extensions.toFormattedCurrencyString import com.tangem.tap.common.extensions.toFormattedFiatValue import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.filterByToken import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.removeUnknownTransactions import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN 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 java.math.RoundingMode class OnWalletLoadedReducer { @@ -54,6 +55,8 @@ class OnWalletLoadedReducer { } val fiatAmount = walletData.fiatRate?.let { coinAmountValue?.toFiatValue(it) } + val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) ?: UNKNOWN_AMOUNT_SIGN + val newWalletData = walletData.copy( currencyData = walletData.currencyData.copy( status = balanceStatus, @@ -63,7 +66,7 @@ class OnWalletLoadedReducer { amount = coinAmountValue, amountFormatted = formattedAmount, fiatAmount = fiatAmount, - fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) + fiatAmountFormatted = fiatAmountFormatted, ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(isCoinSendButtonEnabled), @@ -81,8 +84,9 @@ class OnWalletLoadedReducer { else -> BalanceStatus.VerifiedOnline } val tokenAmountValue = wallet.getTokenAmount(token)?.value - val tokenFiatAmount = - tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate) } + val tokenFiatAmount = tokenWalletData?.fiatRate?.let { tokenAmountValue?.toFiatValue(it) } + val tokenFiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) + ?: UNKNOWN_AMOUNT_SIGN val isTokenSendButtonEnabled = newWalletData.shouldEnableTokenSendButton() && pendingTransactions.isEmpty() @@ -96,7 +100,7 @@ class OnWalletLoadedReducer { token.symbol ), fiatAmount = tokenFiatAmount, - fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) + fiatAmountFormatted = tokenFiatAmountFormatted, ), pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled), @@ -140,9 +144,8 @@ class OnWalletLoadedReducer { wallet.blockchain.decimals(), wallet.blockchain.currency ) - val fiatRate = walletState.primaryWallet?.fiatRate - val fiatAmountRaw = fiatRate?.multiply(amount)?.setScale(2, RoundingMode.DOWN) - val fiatAmount = fiatRate?.let { amount?.toFiatString(it, fiatCurrencyName) } + val fiatAmount = walletState.primaryWallet?.fiatRate?.let { amount?.toFiatValue(it) } + val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencyName) ?: UNKNOWN_AMOUNT_SIGN val pendingTransactions = wallet.getPendingTransactions() val sendButtonEnabled = amount?.isZero() == false && pendingTransactions.isEmpty() @@ -159,8 +162,8 @@ class OnWalletLoadedReducer { blockchainAmount = amount, amount = amount, amountFormatted = formattedAmount, - fiatAmountFormatted = fiatAmount, - fiatAmount = fiatAmountRaw + fiatAmount = fiatAmount, + fiatAmountFormatted = fiatAmountFormatted ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(sendButtonEnabled), diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index fe7213d361..3ab2f769c4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -19,7 +19,7 @@ import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.WalletRent import com.tangem.tap.features.wallet.redux.AddressData import com.tangem.tap.features.wallet.redux.Artwork -import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ErrorType import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.TradeCryptoState @@ -217,8 +217,8 @@ private fun internalReduce(action: Action, state: AppState): WalletState { currency = walletBlockchain.currency, ), fiatAmount = fiatAmount, - fiatAmountFormatted = fiatAmount.toFiatRateString( - fiatCurrencyName = store.state.globalState.appCurrency.symbol + fiatAmountFormatted = fiatAmount.toFormattedFiatValue( + fiatCurrencyName = state.globalState.appCurrency.symbol ), amountToCreateAccount = action.amountToCreateAccount, ) @@ -439,7 +439,7 @@ private fun setMultiWalletFiatRate( wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate) } if (currencyData.status == BalanceStatus.NoAccount && fiatAmount == null) { - fiatAmount = BigDecimal.ZERO + fiatAmount = BigDecimal.ZERO.setScale(2) } val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(appCurrency.symbol) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt index 2be2f19145..c627aa2e32 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt @@ -26,8 +26,8 @@ data class BalanceWidgetData( val blockchainAmount: BigDecimal? = BigDecimal.ZERO, val amount: BigDecimal? = null, val amountFormatted: String? = null, - val fiatAmountFormatted: String? = null, val fiatAmount: BigDecimal? = null, + val fiatAmountFormatted: String? = null, val token: TokenData? = null, val amountToCreateAccount: String? = null, val errorMessage: String? = null diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 77ed03ebfa..d86030b5e7 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -1,11 +1,7 @@ package com.tangem.tap.features.wallet.ui import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup +import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback import androidx.annotation.ColorRes @@ -15,31 +11,21 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.transition.TransitionInflater import by.kirich1409.viewbindingdelegate.viewBinding -import com.squareup.picasso.Picasso +import com.tangem.tangem_sdk_new.extensions.dpToPx import com.tangem.tap.common.SnackbarHandler import com.tangem.tap.common.TestActions -import com.tangem.tap.common.extensions.appendIfNotNull -import com.tangem.tap.common.extensions.beginDelayedTransition -import com.tangem.tap.common.extensions.fitChipsByGroupWidth -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.common.extensions.getString -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.loadCurrenciesIcon -import com.tangem.tap.common.extensions.show -import com.tangem.tap.common.extensions.toQrCode +import com.tangem.tap.common.extensions.* import com.tangem.tap.common.recyclerView.SpaceItemDecoration import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.onboarding.getQRReceiveMessage +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.redux.Currency -import com.tangem.tap.features.wallet.redux.ErrorType -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletData -import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter +import com.tangem.tap.features.wallet.ui.images.loadCurrencyIcon import com.tangem.tap.features.wallet.ui.test.TestWalletDetails import com.tangem.tap.store import com.tangem.wallet.R @@ -143,16 +129,18 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), handleCurrencyIcon(selectedWallet) handleWarnings(selectedWallet) + updateViewMeasurements() binding.srlWalletDetails.setOnRefreshListener { if (selectedWallet.currencyData.status != BalanceStatus.Loading) { store.dispatch(WalletAction.LoadWallet( - blockchain = BlockchainNetwork( - selectedWallet.currency.blockchain, - selectedWallet.currency.derivationPath, - emptyList() + blockchain = BlockchainNetwork( + selectedWallet.currency.blockchain, + selectedWallet.currency.derivationPath, + emptyList() + ) ) - )) + ) } } @@ -161,13 +149,27 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } } + private fun updateViewMeasurements() { + val tvFiatAmount = binding.lWalletDetails.lBalance.tvFiatAmount + val paddingStart = when (tvFiatAmount.text) { + UNKNOWN_AMOUNT_SIGN -> 16f + else -> 12f + } + tvFiatAmount.setPadding( + tvFiatAmount.dpToPx(paddingStart).toInt(), + tvFiatAmount.paddingTop, + tvFiatAmount.paddingEnd, + tvFiatAmount.paddingBottom, + ) + } + private fun setupCurrency(currencyData: BalanceWidgetData, currency: Currency) = with(binding) { tvCurrencyTitle.text = currencyData.currency if (currency is Currency.Token) { - binding.tvCurrencySubtitle.text = currency.blockchain.tokenDisplayName() - binding.tvCurrencySubtitle.show() + tvCurrencySubtitle.text = currency.blockchain.tokenDisplayName() + tvCurrencySubtitle.show() } else { - binding.tvCurrencySubtitle.hide() + tvCurrencySubtitle.hide() } } @@ -199,9 +201,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } private fun handleCurrencyIcon(wallet: WalletData) = with(binding.lWalletDetails.lBalance) { - Picasso.get().loadCurrenciesIcon( - imageView = ivCurrency, - textView = tvTokenLetter, + loadCurrencyIcon( + currencyImageView = ivCurrency, + currencyTextView = tvTokenLetter, blockchain = wallet.currency.blockchain, token = (wallet.currency as? Currency.Token)?.token ) @@ -295,7 +297,10 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), lBalance.root.show() lBalance.groupBalance.hide() lBalance.tvError.show() - lBalance.tvError.setWarningStatus(R.string.wallet_balance_blockchain_unreachable, data.errorMessage) + lBalance.tvError.setWarningStatus( + R.string.wallet_balance_blockchain_unreachable, + data.errorMessage + ) } BalanceStatus.NoAccount -> { lBalance.root.hide() @@ -314,9 +319,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), return when (item.itemId) { R.id.menu_remove -> { store.state.walletState.getSelectedWalletData()?.let { walletData -> - store.dispatch(WalletAction.MultiWallet.RemoveWallet(walletData)) - store.dispatch(WalletAction.MultiWallet.SelectWallet(null)) - store.dispatch(NavigationAction.PopBackTo()) + store.dispatch(WalletAction.MultiWallet.TryToRemoveWallet(walletData)) true } false @@ -327,10 +330,6 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.wallet_details, menu) - val walletCanBeRemoved = store.state.walletState.canBeRemoved( - store.state.walletState.getSelectedWalletData() - ) - menu.getItem(0).isEnabled = walletCanBeRemoved } private fun TextView.setWarningStatus(mainMessage: Int, error: String? = null) { @@ -346,7 +345,11 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), setStatus(getString(mainMessage), R.color.darkGray4, null) } - private fun TextView.setStatus(text: String, @ColorRes color: Int, @DrawableRes drawable: Int?) { + private fun TextView.setStatus( + text: String, + @ColorRes color: Int, + @DrawableRes drawable: Int? + ) { this.text = text setTextColor(getColor(color)) setCompoundDrawablesWithIntrinsicBounds(drawable ?: 0, 0, 0, 0) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index 6a113fb7a8..176fa48a14 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -12,7 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.transition.TransitionInflater import by.kirich1409.viewbindingdelegate.viewBinding -import com.squareup.picasso.Picasso +import coil.load import com.tangem.tap.MainActivity import com.tangem.tap.common.extensions.show import com.tangem.tap.common.recyclerView.SpaceItemDecoration @@ -165,11 +165,11 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber currencyImageView.loadIcon( + iconUrl = getIconUrl(blockchain.toNetworkId()), + placeholderRes = blockchain.getRoundIconRes(), + onStart = { + if (blockchain.isTestnet()) { + currencyImageView.saturation = 0f + } else { + 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), + 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, + ) + }, + onSuccess = { + if (!blockchain.isTestnet()) { + currencyImageView.colorFilter = null + } + } + ) + } +} + +private inline fun ImageView.loadIcon( + iconUrl: String?, + placeholderRes: Int, + crossinline onStart: () -> Unit = {}, + crossinline onSuccess: () -> Unit = {}, + crossinline onError: () -> Unit = {}, +) { + ImageRequest.Builder(context) + .data(iconUrl) + .placeholder(placeholderRes) + .error(placeholderRes) + .fallback(placeholderRes) + .transformations( + RoundedCornersTransformation( + topLeft = 32f, + topRight = 32f, + bottomLeft = 32f, + bottomRight = 32f + ) + ) + .listener( + onStart = { onStart() }, + onSuccess = { _, _ -> onSuccess() }, + onError = { _, _ -> onError() } + ) + .target(imageView = this) + .build() + .also(context.imageLoader::enqueue) +} + +private fun getTokenIconUrl(token: Token, blockchain: Blockchain): String? { + return token.id?.let(::getIconUrl) + ?: token.getCustomIconUrl() + ?: IconsUtil.getTokenIconUri(blockchain, token) + ?.toString() +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt index f47a0b3ea1..6cce3b391b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt @@ -3,7 +3,7 @@ package com.tangem.tap.features.wallet.ui.wallet import android.content.Context import androidx.appcompat.app.AlertDialog import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletDialog +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.store import com.tangem.wallet.R diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index b7e0a307a5..2e0a84785f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -10,13 +10,9 @@ import com.tangem.tap.common.extensions.fitChipsByGroupWidth import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.redux.Currency -import com.tangem.tap.features.wallet.redux.TradeCryptoState -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletData -import com.tangem.tap.features.wallet.redux.WalletMainButton -import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.* import com.tangem.tap.features.wallet.ui.BalanceWidget import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper import com.tangem.tap.features.wallet.ui.WalletFragment diff --git a/app/src/main/res/drawable/ic_scan_card_24.xml b/app/src/main/res/drawable/ic_scan_card_24.xml deleted file mode 100644 index b77d547233..0000000000 --- a/app/src/main/res/drawable/ic_scan_card_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_wallet_24.xml b/app/src/main/res/drawable/ic_wallet_24.xml new file mode 100644 index 0000000000..b1c1514913 --- /dev/null +++ b/app/src/main/res/drawable/ic_wallet_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index 3b962facaf..17bf714628 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -22,8 +22,9 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:menu="@menu/wallet" - app:navigationIcon="@drawable/ic_scan_card_24" - app:navigationIconTint="@color/iconGray" + app:navigationIcon="@drawable/ic_wallet_24" + app:navigationIconTint="@color/darkGray6" + app:titleCentered="true" app:title="@string/wallet_title" /> @@ -151,28 +152,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" /> - - - - @@ -192,6 +171,28 @@ android:text="@string/main_manage_tokens" android:elevation="4dp" app:cornerRadius="8dp" - app:layout_constraintBottom_toBottomOf="parent" /> + tools:visibility="gone" /> + + + + diff --git a/app/src/main/res/layout/layout_balance.xml b/app/src/main/res/layout/layout_balance.xml index 0e3f124d94..6addd2be86 100644 --- a/app/src/main/res/layout/layout_balance.xml +++ b/app/src/main/res/layout/layout_balance.xml @@ -35,7 +35,8 @@ android:visibility="gone" app:drawableStartCompat="@drawable/ic_ok" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/tv_currency" /> + app:layout_constraintTop_toBottomOf="@id/tv_currency" + tools:visibility="visible" /> + tools:text="3.58 USD" /> + app:layout_constraintStart_toEndOf="@+id/tv_status_verified" + app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount" + tools:text="123.12387628 XTZ" /> + app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount" /> + tools:text="0.00434143 ETH" /> + tools:text="496304.28 RUB" /> + app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount" + tools:text="0.43 BTC" /> + app:layout_constraintTop_toBottomOf="@id/tv_amount" + tools:text="Some error" /> diff --git a/app/src/main/res/layout/layout_wallet_long_buttons.xml b/app/src/main/res/layout/layout_wallet_long_buttons.xml index f670b7fd5d..5fc11bef41 100644 --- a/app/src/main/res/layout/layout_wallet_long_buttons.xml +++ b/app/src/main/res/layout/layout_wallet_long_buttons.xml @@ -17,11 +17,8 @@ android:id="@+id/btn_confirm_long" style="@style/TapButtonWithIcon" android:layout_width="0dp" - android:layout_marginTop="30dp" - android:layout_marginEnd="16dp" - android:layout_marginBottom="8dp" android:text="@string/wallet_button_send" - app:icon="@drawable/ic_send" + app:icon="@drawable/ic_send" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/guideline" diff --git a/app/src/main/res/layout/layout_wallet_short_buttons.xml b/app/src/main/res/layout/layout_wallet_short_buttons.xml index ed60601395..e235511583 100644 --- a/app/src/main/res/layout/layout_wallet_short_buttons.xml +++ b/app/src/main/res/layout/layout_wallet_short_buttons.xml @@ -6,38 +6,32 @@ + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintStart_toStartOf="parent" + app:iconGravity="textEnd" + android:textAlignment="center" + app:layout_constraintVertical_bias="1" /> + app:layout_constraintStart_toEndOf="@id/btn_trade" + app:layout_constraintVertical_bias="1" /> diff --git a/app/src/main/res/menu/wallet.xml b/app/src/main/res/menu/wallet.xml index 7f6107b331..edd88afb93 100644 --- a/app/src/main/res/menu/wallet.xml +++ b/app/src/main/res/menu/wallet.xml @@ -5,6 +5,6 @@ android:id="@+id/details_menu" android:title="@string/details_title" android:icon="@drawable/ic_more_vertical_24" - app:iconTint="@color/iconGray" + app:iconTint="@color/darkGray6" app:showAsAction="ifRoom" /> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 97c8b2d0af..a74c2f7407 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -59,11 +59,6 @@ Gebühr Gesamt Höchstbetrag - Ungültige Adresse - Ungültiger Betrag - Der Betrag geht über die Bilanz hinaus - Der Gesamtbetrag geht über die Bilanz hinaus - Die Gebühr geht über die Bilanz hinaus Niedrig Normal Priorität @@ -73,7 +68,6 @@ %s %s und %s %s werden gesendet Bilanz: %s %s Die Transaktion wurde erfolgreich signiert und an den Blockchain-Knoten gesendet. Die Walletbilanz wird aktualisiert - Um ein Konto zu erstellen, senden Sie 1+ XLM an diese Adresse Details KartenID Emittent @@ -165,21 +159,12 @@ RECHTLICHER HAFTUNGSAUSSCHLUSS Nutzungsbedingungen Keine Internetverbindung - Das Zielkonto ist nicht erstellt. Der abzusendende Betrag soll %1$s %2$s + Gebühr oder mehr sein - Erhalt der Gebühr fehlgeschlagen - - Unbekannter Fehler Verifikation der PayString ist fehlgeschlagen PayString wird von der Blockchain nicht unterstützt PayString ist nicht registriert PayString-Anfrage ist fehlgeschlagen Die Adresse stimmt mit der Adresse Ihrer Brieftasche überein - Nicht genug Geld - Interner Fehler der Blockchain - Falsche Gebühr - Minimaler Betrag ist %s - Restbestand zu klein Die Adresse wurde erfolgreich kopiert @@ -192,8 +177,4 @@ RECHTLICHER HAFTUNGSAUSSCHLUSS Ihr Kontostand in dieser Brieftasche ist nicht Null, oder Sie haben unbestätigte Transaktionen. Es ist unmöglich die Funktion der Brieftasche zu löschen. Dies ist die derzeit aktive Wahl - Damit Sie beim nächsten Aufladen Ihrer Brieftasche keine erhöhte Provision zahlen, soll der Betrag um %s XTZ reduziert werden - Um %s XTZ reduzieren - Nein, alles senden - \ No newline at end of file diff --git a/app/src/main/res/values-de/strings_blockchain.xml b/app/src/main/res/values-de/strings_blockchain.xml new file mode 100644 index 0000000000..2f52667c19 --- /dev/null +++ b/app/src/main/res/values-de/strings_blockchain.xml @@ -0,0 +1,20 @@ + + + Nicht genug Geld + Interner Fehler der Blockchain + Falsche Gebühr + Minimaler Betrag ist %s + Restbestand zu klein + Das Zielkonto ist nicht erstellt. Der abzusendende Betrag soll %s %s + Gebühr oder mehr sein + Um ein Konto zu erstellen, senden Sie 1+ XLM an diese Adresse + Erhalt der Gebühr fehlgeschlagen + Unbekannter Fehler + Damit Sie beim nächsten Aufladen Ihrer Brieftasche keine erhöhte Provision zahlen, soll der Betrag um %s XTZ reduziert werden + Um %s XTZ reduzieren + Nein, alles senden + Ungültige Adresse + Ungültiger Betrag + Der Betrag geht über die Bilanz hinaus + Der Gesamtbetrag geht über die Bilanz hinaus + Die Gebühr geht über die Bilanz hinaus + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 3c887d74f0..a9a31d3866 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -47,5 +47,15 @@ If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds Custom + Notice + Attention + The server is not available, please try again later + Hide %s + Hide + You hide the token from the main screen, but you can add it back at any time. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + + %s network not found. Please, add it first and try again. \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9e6777a914..3b06614517 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -60,11 +60,6 @@ Commissions Total Somme maximale - Adresse incorrecte - Somme incorrecte - Le montant dépasse le solde - Le total dépasse le solde - Les commissions dépassent le solde Bas Normal Priorité @@ -74,7 +69,6 @@ Sera envoyé %s %s et %s %s Solde : %s %s La transaction a été signée avec succès et envoyée au nœud de blockchain. Le solde du portefeuille sera mis à jour après un certain temps - Pour créer un compte, envoyez 1+ XLM à cette adresse Référénces ID de la carte Emetteur @@ -163,20 +157,11 @@ Avertissement Conditions d\'utilisation Pas de connexion internet - Le compte cible n\'a pas été créé. Le montant à envoyer doit être de %1$s %2$s + commissions ou plus - Échec de réception des commissions - - Erreur inconnue La vérification de PayString a échoué PayString non pris en charge par la blockchain PayString non enregistré La demande de PayString a échoué L\'adresse est la même que celle de votre portefeuille - Solde insuffisant - Erreur interne de la blockchain - Commission non valide - Le montant minimal est de %ы - Le reste est trop petit L\'adresse a été copiée avec succès Saisissez d\'abord le PayString requis Posez pour scanner @@ -184,8 +169,5 @@ Avertissement Votre solde sur ce portefeuille n\'est pas nul, ou vous avez des transactions non confirmées. Impossible de supprimer la fonction du portefeuille Cette option est déjà active - Pour ne pas payer une commission élevée la prochaine fois que vous rechargez votre portefeuille, veuillez réduire le montant de %s XTZ - Réduire de% s XTZ - Non, envoyer toute la somme \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_blockchain.xml b/app/src/main/res/values-fr/strings_blockchain.xml new file mode 100644 index 0000000000..f6e2cdef63 --- /dev/null +++ b/app/src/main/res/values-fr/strings_blockchain.xml @@ -0,0 +1,20 @@ + + + Solde insuffisant + Erreur interne de la blockchain + Commission non valide + Le montant minimal est de %s + Le reste est trop petit + Le compte cible n\'a pas été créé. Le montant à envoyer doit être de %s %s + commissions ou plus + Pour créer un compte, envoyez 1+ XLM à cette adresse + Échec de réception des commissions + Erreur inconnue + Adresse incorrecte + Somme incorrecte + Le montant dépasse le solde + Le total dépasse le solde + Les commissions dépassent le solde + Pour ne pas payer une commission élevée la prochaine fois que vous rechargez votre portefeuille, veuillez réduire le montant de %s XTZ + Réduire de %s XTZ + Non, envoyer toute la somme + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml index 3c887d74f0..d34f57338a 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -47,5 +47,15 @@ If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds Custom + The server is not available, please try again later + Notice + Attention + Hide %s + Hide + You hide the token from the main screen, but you can add it back at any time. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + + %s network not found. Please, add it first and try again. \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a7011d4bcc..b45dafe795 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -58,10 +58,7 @@ Commissione Totale Importo totale - Indirizzo non valido - Importo non valido - Il totale supera il saldo - La commissione supera il saldo + Insufficiente Normale Prioritario @@ -71,7 +68,6 @@ Sarà inviato %1$s %2$s e %1$s %2$s Saldo: %1$s %2$s La transazione è stata firmata con successo e inviata al nodo blockchain. Il saldo del portafoglio verrà aggiornato dopo un po\' di tempo - Per creare un account, invia 1+ XLM a questo indirizzo Requisiti ID carta Emittente @@ -159,26 +155,16 @@ Salvo quanto diversamente previsto dalla legge, i proprietari o i contributori d Questa nota legale è stata modificata l\'ultima volta 01.10.2020. - - Per creare un account, invia %1$s %2$s a questo indirizzo - Impossibile ottenere la commissione Accetta - L\'importo supera il saldo Termini del servizio Nessuna connessione a Internet - Errore sconosciuto Verifica del PayString fallita PayString non supportato dalla blockchain PayString non registrato Richiesta PayString fallita L\'indirizzo corrisponde all\'indirizzo del tuo portafoglio - Saldo insufficiente - Errore interno della blockchain - Commissione non valida - L\'importo minimo è di %s - L\'importo residuo è molto basso L\'indirizzo è stato copiato con successo @@ -191,8 +177,4 @@ Questa nota legale è stata modificata l\'ultima volta 01.10.2020. Il tuo saldo su questo portafoglio non è pari a zero o hai transazioni non confermate. Non è possibile eliminare la funzione portafoglio. E\' l\'opzione attualmente attiva - Per evitare di pagare una commissione maggiore la prossima volta che ricarichi il tuo portafoglio, riduci l\'importo di %s XTZ - Riduci di %s XTZ - No, invia l\'intero importo - \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_blockchain.xml b/app/src/main/res/values-it/strings_blockchain.xml new file mode 100644 index 0000000000..cd0f690a23 --- /dev/null +++ b/app/src/main/res/values-it/strings_blockchain.xml @@ -0,0 +1,20 @@ + + + Saldo insufficiente + Errore interno della blockchain + Commissione non valida + L\'importo minimo è di %s + L\'importo residuo è molto basso + Errore sconosciuto + L\'importo supera il saldo + Per creare un account, invia %s %s a questo indirizzo + Impossibile ottenere la commissione + Per creare un account, invia 1+ XLM a questo indirizzo + Indirizzo non valido + Importo non valido + Il totale supera il saldo + La commissione supera il saldo + Per evitare di pagare una commissione maggiore la prossima volta che ricarichi il tuo portafoglio, riduci l\'importo di %s XTZ + Riduci di %s XTZ + No, invia l\'intero importo + \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml index 3c887d74f0..1a7d8051eb 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -47,5 +47,16 @@ If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds Custom + The server is not available, please try again later + Notice + Attention + + Hide %s + Hide + You hide the token from the main screen, but you can add it back at any time. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + + %s network not found. Please, add it first and try again. \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index c45da10b0e..1617484429 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -60,11 +60,6 @@ Комиссия Всего Максимальная сумма - Неверный адрес - Недопустимая сумма - Сумма превышает баланс - Общая сумма превышает баланс - Комиссия превышает баланс Низкий Нормальный Приоритетный @@ -108,30 +103,19 @@ Приложите, чтобы изменить пароль Неверный PayString Условия использования - Не удалось получить комиссию - Целевая учетная запись не создана. Сумма для отправки должна быть %1$s %2$s + плата за создание или больше Нет соединения с интернетом - Неизвестная ошибка Ошибка проверки PayString PayString не поддерживается блокчейном PayString не зарегистрирован Не удалось выполнить запрос PayString Адрес совпадает с адресом кошелька - Недостаточный баланс - Внутренняя ошибка блокчейна - Неверная комиссия - Минимальная сумма: %s - Сдача слишком мала - Для создания учетной записи отправьте 1+ XLM на этот адрес + Адрес скопирован в буфер обмена Сначала введите желаемую PayString Приложите, чтобы отсканировать Приложите карту Ваш баланс на этом кошельке не равен нулю, или у Вас есть неподтвержденные транзакции Это текущая активная опция - Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ - Уменьшить на %s XTZ - Нет, отправить все Ошибка сканирования карты. Попробуй снова. Купить Продать @@ -347,7 +331,7 @@ %1s (%2s) Эта карта не является векселем на предъявителя. В настоящее время мы не можем сопоставить количество подписей на карте с информацией в блокчейне. Это нормально, но в редких случаях может означать, что предыдущий владелец скрывает автономную подпись, что является проблемой безопасности.\n\nНе принимайте эту карту в качестве физического платежа от кого-то, кому Вы не доверяете.\n\nВо всех остальных отношениях - это совершенно безопасно.\n\nTangem — единственный аппаратный кошелек, предлагающий защиту от подсчета подписей. WalletConnect - Запрос на создание транзакции для %2s\n%3s\n\nСумма: %4s\nКомиссия: %5s\nВсего: %6s\nБаланс: %7s + Карта %1s\nЗапрос на создание транзакции для %2s\n%3s\n\nСумма: %4s\nКомиссия: %5s\nВсего: %6s\nБаланс: %7s Запрос на запуск сеанса для карты с идентификатором %1s\nдля %2s\n\nURL: %3s Сессии WalletConnect Сеанс WalletConnect открыт с %s diff --git a/app/src/main/res/values-ru/strings_blockchain.xml b/app/src/main/res/values-ru/strings_blockchain.xml new file mode 100644 index 0000000000..98b7ad7194 --- /dev/null +++ b/app/src/main/res/values-ru/strings_blockchain.xml @@ -0,0 +1,20 @@ + + + Недостаточный баланс + Внутренняя ошибка блокчейна + Неверная комиссия + Минимальная сумма: %s + Сдача слишком мала + Для создания учетной записи отправьте 1+ XLM на этот адрес + Не удалось получить комиссию + Целевая учетная запись не создана. Сумма для отправки должна быть %1$s %2$s + плата за создание или больше + Неизвестная ошибка + Неверный адрес + Недопустимая сумма + Сумма превышает баланс + Общая сумма превышает баланс + Комиссия превышает баланс + Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ + Уменьшить на %s XTZ + Нет, отправить все + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index 2147b19938..4359a84d9e 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -47,9 +47,20 @@ Если вы совершили ошибку с выбором сети при переводе средств с биржи, эта инструкция поможет вам восстановить средства Пользовательский + Уведомление + Внимание + Сервер недоступен, повторите попытку позднее Баланс В сумме учтены не все монеты Управление токенами Нет цены + + Скрыть %s + Скрыть + Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно. + Невозможно скрыть %s + Токен %s является основной валютой в сети %s и не может быть скрыт, до тех пор пока у вас в списке есть другие токены этой сети. + + Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 520b7bc183..23ff1e496f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -70,11 +70,6 @@ Fee Total Maximum amount - Invalid address - Invalid amount - Amount Exceeds Balance - Total Exceeds Balance - Fee Exceeds Balance Low Normal Priority @@ -173,23 +168,14 @@ \nThis disclaimer was amended for the last time on October 1st, 2020. Terms of service - Failed to get fee - Target account is not created. Amount to send should be %1$s %2$s + fee or more to create - No internet connection + No internet connection - Unknown error PayString verification failed PayString unsupported by blockchain PayString not registered PayString request failed Address is the same as wallet address - Insufficient balance - Blockchain internal error - Invalid Fee - Minimum amount is %s - Change is too small - To create account send 1+ XLM to this address Address was copied to clipboard @@ -201,9 +187,4 @@ Your balance on this wallet is not zero, or you have unconfirmed transactions This is the currently active option - - - To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ - Reduce by %s XTZ - No, send all - + \ No newline at end of file diff --git a/app/src/main/res/values/strings_blockchain.xml b/app/src/main/res/values/strings_blockchain.xml new file mode 100644 index 0000000000..35bc8cf334 --- /dev/null +++ b/app/src/main/res/values/strings_blockchain.xml @@ -0,0 +1,20 @@ + + + Insufficient balance + Blockchain internal error + Invalid Fee + Minimum amount is %s + Change is too small + To create account send 1+ XLM to this address + Failed to get fee + Target account is not created. Amount to send should be %s %s + fee or more to create + Unknown error + Invalid address + Invalid amount + Amount Exceeds Balance + Total Exceeds Balance + Fee Exceeds Balance + To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ + Reduce by %s XTZ + No, send all + \ No newline at end of file diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index 9190d7c980..c59bf4b50a 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -47,9 +47,20 @@ If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds Custom + Notice + Attention + The server is not available, please try again later Total balance The amount does not include some of your funds Manage tokens No rate + + Hide %s + Hide + You hide the token from the main screen, but you can add it back at any time. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + + %s network not found. Please, add it first and try again. diff --git a/app/src/main/res/values/strings_untranslatable.xml b/app/src/main/res/values/strings_untranslatable.xml deleted file mode 100644 index ff1f090a6f..0000000000 --- a/app/src/main/res/values/strings_untranslatable.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 649081be00..687dd82c75 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -141,7 +141,7 @@ Card: %s Tap card to bind to wallet connect - Card: %1s + Card: %1s\n Request to create transaction for %2s \n%3s diff --git a/domain/build.gradle b/domain/build.gradle index 169aea23f3..5a54411b94 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -59,7 +59,7 @@ dependencies { implementation implementation(project(path: ':network')) implementation implementation(project(path: ':common')) - implementation 'com.tangem:blockchain:develop-88' + implementation 'com.tangem:blockchain:develop-93' // implementation 'com.tangem:blockchain:0.0.1' implementation 'com.tangem.tangem-sdk-kotlin:core:develop-154' implementation 'com.tangem.tangem-sdk-kotlin:android:develop-154' diff --git a/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt b/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt index f841679ffb..3304349b69 100644 --- a/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt +++ b/domain/src/main/java/com/tangem/domain/common/extensions/TangemTechService.kt @@ -16,11 +16,13 @@ suspend fun TangemTechService.getTokens( suspend fun TangemTechService.getListOfCoins( networkIds: List, + active: Boolean? = null, searchText: String? = null, offset: Int? = null, limit: Int? = null ): Result = coins( networkIds = networkIds.joinToString(","), + active = active, searchText = searchText, offset = offset, limit = limit diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 06543032c9..a9d631e668 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -56,6 +56,17 @@ platform :android do "android.injected.signing.key.alias" => options[:key_alias], "android.injected.signing.key.password" => options[:key_password], }) + gradle( + task: "assemble", + build_type: "Release", + properties: { + 'versionCode' => options[:versionCode], + 'versionName' => options[:versionName], + "android.injected.signing.store.file" => options[:keystore], + "android.injected.signing.store.password" => options[:store_password], + "android.injected.signing.key.alias" => options[:key_alias], + "android.injected.signing.key.password" => options[:key_password], + }) end desc "Submit a new Beta Build to Firebase App Distribution" diff --git a/gradle.properties b/gradle.properties index 8f60b3bd0b..52a563ad69 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro org.gradle.parallel=true org.gradle.daemon=true android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true