diff --git a/app/build.gradle b/app/build.gradle index 105d4d8323..ce5b525f66 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -144,7 +144,7 @@ dependencies { implementation("com.squareup.okhttp3:logging-interceptor") // Support - implementation("com.zendesk:support:5.0.9") + implementation("com.zendesk:chat:3.3.5") implementation("com.zendesk:messaging:5.2.4") //Crypto diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d180642a75..b460cf581a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -47,7 +47,7 @@ diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 59ee0bff06..bf673f7f88 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 59ee0bff06ee54f3202421c28f7fb6e3d421dad8 +Subproject commit bf673f7f88ed561cd8827447c4886f80f30b7e23 diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index b4d66ff10e..4e1c24d3c9 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -91,6 +91,11 @@ class MainActivity : AppCompatActivity(), SnackbarHandler { windowInsetsController.isAppearanceLightStatusBars = true windowInsetsController.isAppearanceLightNavigationBars = true + supportFragmentManager.registerFragmentLifecycleCallbacks( + NavBarInsetsFragmentLifecycleCallback(), + true + ) + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } diff --git a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt new file mode 100644 index 0000000000..94177e8463 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt @@ -0,0 +1,29 @@ +package com.tangem.tap + +import android.os.Bundle +import android.view.View +import androidx.compose.ui.platform.ComposeView +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks + +class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() { + override fun onFragmentViewCreated( + fm: FragmentManager, + f: Fragment, + v: View, + savedInstanceState: Bundle?, + ) { + if (v is ComposeView) return + ViewCompat.setOnApplyWindowInsetsListener(v) { view, windowInsets -> + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()) + view.updatePadding( + bottom = insets.bottom, + ) + windowInsets + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 518ad410c4..adcd569b7f 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -8,6 +8,7 @@ import com.google.firebase.ktx.Firebase import com.google.firebase.remoteconfig.ktx.remoteConfig import com.google.firebase.remoteconfig.ktx.remoteConfigSettings import com.tangem.Log +import com.tangem.LogFormat import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.domain.DomainLayer import com.tangem.network.common.MoshiConverter @@ -108,7 +109,21 @@ class TapApplication : Application(), ImageLoaderFactory { val infoHolder = AdditionalFeedbackInfo() infoHolder.setAppVersion(this) - val logWriter = TangemLogCollector() + val logLevels = listOf( + Log.Level.ApduCommand, + Log.Level.Apdu, + Log.Level.Tlv, + Log.Level.Nfc, + Log.Level.Command, + Log.Level.Session, + Log.Level.View, + Log.Level.Network, + Log.Level.Error, + ) + val logWriter = TangemLogCollector( + levels = logLevels, + messageFormatter = LogFormat.StairsFormatter() + ) Log.addLogger(logWriter) store.dispatch(GlobalAction.SetFeedbackManager(FeedbackManager(infoHolder, logWriter))) @@ -126,4 +141,5 @@ class TapApplication : Application(), ImageLoaderFactory { data class LogConfig( val coil: Boolean = BuildConfig.DEBUG, val storeAction: Boolean = BuildConfig.DEBUG, + val zendesk: Boolean = BuildConfig.DEBUG, ) \ No newline at end of file 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 3cb5aa96c8..e2490e7886 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 @@ -27,6 +27,7 @@ fun Blockchain.getRoundIconRes(): Int { Blockchain.BSC, Blockchain.BSCTestnet, Blockchain.Binance, Blockchain.BinanceTestnet -> R.drawable.ic_bsc_round Blockchain.Dogecoin -> R.drawable.ic_dogecoin_round Blockchain.Tron, Blockchain.TronTestnet -> R.drawable.ic_tron_round + Blockchain.Gnosis -> R.drawable.ic_gnosis_round else -> R.drawable.ic_tangem_logo } } @@ -53,6 +54,7 @@ fun Blockchain.getGreyedOutIconRes(): Int { Blockchain.BSC, Blockchain.BSCTestnet, Blockchain.Binance, Blockchain.BinanceTestnet -> R.drawable.ic_bsc_no_color Blockchain.Dogecoin -> R.drawable.ic_dogecoin_no_color Blockchain.Tron, Blockchain.TronTestnet -> R.drawable.ic_tron_no_color + Blockchain.Gnosis -> R.drawable.ic_gnosis_no_color else -> R.drawable.ic_tangem_logo } } diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt index 4e551608e5..c2bb70a931 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt @@ -6,18 +6,19 @@ import com.tangem.tap.common.extensions.sendEmail import com.tangem.tap.common.log.TangemLogCollector import com.tangem.tap.common.zendesk.ZendeskConfig import com.tangem.tap.foregroundActivityObserver +import com.tangem.tap.logConfig import com.tangem.tap.withForegroundActivity +import com.tangem.wallet.R +import com.zendesk.logger.Logger +import timber.log.Timber +import zendesk.chat.Chat +import zendesk.chat.ChatConfiguration +import zendesk.chat.ChatEngine +import zendesk.configurations.Configuration +import zendesk.messaging.MessagingActivity import java.io.File import java.io.FileWriter import java.io.StringWriter -import timber.log.Timber -import zendesk.configurations.Configuration -import zendesk.core.AnonymousIdentity -import zendesk.core.Zendesk -import zendesk.support.Support -import zendesk.support.request.RequestConfiguration -import zendesk.support.requestlist.RequestListActivity -import zendesk.support.requestlist.RequestListConfiguration /** [REDACTED_AUTHOR] @@ -30,14 +31,14 @@ class FeedbackManager( context: Context, zendeskConfig: ZendeskConfig, ) { - Zendesk.INSTANCE.init( - /* context = */ context, - /* zendeskUrl = */ zendeskConfig.url, - /* applicationId = */ zendeskConfig.appId, - /* oauthClientId = */ zendeskConfig.clientId, + Chat.INSTANCE.init( + context, + zendeskConfig.accountKey, + zendeskConfig.appId ) - Support.INSTANCE.init(Zendesk.INSTANCE) - Zendesk.INSTANCE.setIdentity(AnonymousIdentity()) + + // Zendesk logs + Logger.setLoggable(logConfig.zendesk) } fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) { @@ -57,11 +58,8 @@ class FeedbackManager( fun openChat(feedbackData: FeedbackData) { feedbackData.prepare(infoHolder) foregroundActivityObserver.withForegroundActivity { activity -> - RequestListActivity.builder() - .show( - /* context = */ activity, - /* configurations = */ buildConfigs(activity, feedbackData) - ) + setChatVisitorNote(activity, feedbackData) + showMessagingActivity(activity) } } @@ -84,20 +82,30 @@ class FeedbackManager( } } - private fun buildConfigs( + private fun setChatVisitorNote( context: Context, feedbackData: FeedbackData, - ): List { - return listOf( - // Request configuration - RequestConfiguration.Builder() - .withRequestSubject(context.getString(feedbackData.subjectResId)) - .config(), - // Request list configuration - RequestListConfiguration.Builder() - .withContactUsButtonVisible(true) - .config(), - ) + ) { + Chat.INSTANCE.providers() + ?.profileProvider() + ?.setVisitorNote(feedbackData.joinTogether(context, infoHolder)) + } + + private fun showMessagingActivity(context: Context) { + MessagingActivity.builder() + .withMultilineResponseOptionsEnabled(false) + .withBotLabelStringRes(R.string.chat_bot_name) + .withBotAvatarDrawable(R.mipmap.ic_launcher) + .withEngines(ChatEngine.engine()) + .show(context, buildChatConfig()) + } + + private fun buildChatConfig(): Configuration { + return ChatConfiguration.builder() + .withOfflineFormEnabled(true) + .withAgentAvailabilityEnabled(true) + .withPreChatFormEnabled(false) + .build() } private fun getSupportEmail(): String { diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt b/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt index c1ae08ebc2..54a56e17c3 100644 --- a/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt +++ b/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt @@ -1,25 +1,31 @@ package com.tangem.tap.common.log import com.tangem.Log +import com.tangem.LogFormat import com.tangem.TangemSdkLogger import java.text.SimpleDateFormat -import java.util.Date +import java.util.* + +class TangemLogCollector( + private val levels: List, + private val messageFormatter: LogFormat, +) : TangemSdkLogger { -class TangemLogCollector : TangemSdkLogger { private val dateFormatter = SimpleDateFormat("HH:mm:ss.SSS") private val logs = mutableListOf() private val mutex = Object() override fun log(message: () -> String, level: Log.Level) { - val time = dateFormatter.format(Date()) + if (!levels.contains(level)) return + synchronized(mutex) { - logs.add("$time: ${message()}\n") + val formattedMessage = messageFormatter.format(message, level) + val logMessage = "${dateFormatter.format(Date())}: $formattedMessage" + logs.add("$logMessage\n") } } fun getLogs(): List = synchronized(mutex) { logs.toList() } - fun clearLogs() { - synchronized(mutex) { logs.clear() } - } + fun clearLogs() = synchronized(mutex) { logs.clear() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt index 17cb291621..db795840ef 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt @@ -148,14 +148,14 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di val techService = store.state.domainNetworks.tangemTechService when (val result = techService.userCountry()) { is Result.Success -> { - store.dispatch( + store.dispatchOnMain( GlobalAction.FetchUserCountry.Success( countryCode = result.data.code.lowercase() ) ) } is Result.Failure -> { - store.dispatch( + store.dispatchOnMain( GlobalAction.FetchUserCountry.Success( countryCode = Locale.getDefault().country.lowercase() ) diff --git a/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt b/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt index aad872b7df..66569ee1b7 100644 --- a/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt +++ b/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt @@ -11,6 +11,8 @@ data class ZendeskConfig( val appId: String, @Json(name = "zendeskClientId") val clientId: String, + @Json(name = "zendeskAccountKey") + val accountKey: String, @Json(name = "zendeskUrl") val url: String, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt index 795e76fe06..bb94004636 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt @@ -91,7 +91,8 @@ class ConfigManager( blockchairApiKey = values.blockchairApiKey, blockchairAuthorizationToken = values.blockchairAuthorizationToken, blockcypherTokens = values.blockcypherTokens, - infuraProjectId = values.infuraProjectId + infuraProjectId = values.infuraProjectId, + tronGridApiKey = values.tronGridApiKey ), appsFlyerDevKey = values.appsFlyerDevKey, shopify = values.shopifyShop, diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt index fc63ed5e9a..6e119fc5e6 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt @@ -27,6 +27,7 @@ class ConfigValueModel( val appsFlyerDevKey: String, val shopifyShop: ShopifyShop?, val zendesk: ZendeskConfig?, + val tronGridApiKey: String, ) class ConfigModel(val features: FeatureModel?, val configValues: ConfigValueModel?) { diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt index aba7726098..3da00c517b 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt @@ -28,11 +28,15 @@ class WalletConnectNetworkUtils { peer.name.contains("BSC") -> { Blockchain.BSC } + peer.url.contains("honeyswap.1hive.eth.limo") -> { + // Check if something's changed after this bug report: + // https://github.com/1Hive/honeyswap-interface/issues/83 + Blockchain.Gnosis + } else -> { - Blockchain.Ethereum + Blockchain.Ethereum } } } - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt index f7ccf6156a..afbbbbb166 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -104,56 +104,25 @@ class DemoConfig { ?: Amount(BigDecimal.ZERO, blockchain).copy() private fun getReleaseIds(): List { - return (releaseDemoCardIds + - releaseDemoCardIds_19042022 + - testDemoCardIds).distinct() + return (releaseDemoCardIds + testDemoCardIds).distinct() } private val releaseDemoCardIds = mutableListOf( -// Tangem Wallet: - "AC01000000041100", - "AC01000000042462", - "AC01000000041647", - "AC01000000041621", - "AC01000000041217", + // === Not from the Google Sheet table === + "FB10000000000196", // Note BTC + "FB20000000000186", // Note ETH + "FB30000000000176", // Wallet "AC01000000041225", - "AC01000000041209", - "AC01000000041092", "AC01000000041472", - "AC01000000041662", - "AC01000000045754", - "AC01000000045960", -// Tangem Note BTC: - "AB01000000046530", - "AB01000000046720", - "AB01000000046746", "AB01000000046498", - "AB01000000046753", "AB01000000049608", - "AB01000000046761", "AB01000000049574", - "AB01000000046605", - "AB01000000046571", "AB01000000046704", - "AB01000000046647", -// Tangem Note Ethereum: "AB02000000051000", - "AB02000000050986", - "AB02000000051026", - "AB02000000051042", - "AB02000000051091", - "AB02000000051083", - "AB02000000050960", - "AB02000000051034", "AB02000000050911", - "AB02000000051133", - "AB02000000051158", - "AB02000000051059", - ) - // https://tangem.slack.com/archives/GMXC6PP71/p1650360610759269 - private val releaseDemoCardIds_19042022 = listOf( - // Wallet + // === Mvideo === + // Wallet "AC01000000045754", "AC01000000041662", "AC01000000041647", @@ -186,7 +155,58 @@ class DemoConfig { "AC01000000013497", "AC01000000013836", "AC01000000013505", -// Note BTC + "AC03000000046693", + "AC03000000046685", + "AC03000000046677", + "AC03000000046669", + "AC03000000046651", + "AC03000000046644", + "AC03000000046636", + "AC03000000046628", + "AC03000000046610", + "AC03000000046602", + "AC03000000046594", + "AC03000000046586", + "AC03000000046578", + "AC03000000046560", + "AC03000000046552", + "AC03000000046545", + "AC03000000046537", + "AC03000000046529", + "AC03000000046511", + "AC03000000046800", + "AC03000000046792", + "AC03000000046784", + "AC03000000046776", + "AC03000000046768", + "AC03000000046750", + "AC03000000046743", + "AC03000000046735", + "AC03000000046727", + "AC03000000046446", + "AC03000000046438", + "AC03000000046412", + "AC03000000046388", + "AC03000000046370", + "AC03000000046354", + "AC03000000046347", + "AC03000000046339", + "AC03000000046321", + "AC03000000046172", + "AC03000000046396", + "AC03000000046404", + "AC03000000046701", + "AC03000000046420", + "AC03000000046719", + "AC03000000046503", + "AC03000000046495", + "AC03000000046487", + "AC03000000046362", + "AC03000000046479", + "AC03000000046461", + "AC03000000046453", + + // Note BTC "AB01000000059608", "AB01000000046647", "AB01000000046571", @@ -219,7 +239,58 @@ class DemoConfig { "AB01000000015782", "AB01000000022598", "AB01000000022580", -// Note ETH + "AB01000000005688", + "AB07000000005696", + "AB07000000005902", + "AB07000000005910", + "AB07000000005928", + "AB07000000005936", + "AB07000000005944", + "AB07000000005993", + "AB07000000005985", + "AB07000000005977", + "AB07000000005969", + "AB07000000005951", + "AB07000000005605", + "AB07000000005803", + "AB07000000005811", + "AB07000000005829", + "AB07000000005837", + "AB07000000005845", + "AB07000000005852", + "AB07000000005860", + "AB07000000005878", + "AB07000000005886", + "AB07000000005894", + "AB07000000005704", + "AB07000000005712", + "AB07000000005720", + "AB07000000005738", + "AB07000000005746", + "AB07000000005514", + "AB07000000005522", + "AB07000000005563", + "AB07000000005571", + "AB07000000005589", + "AB07000000005597", + "AB07000000005613", + "AB07000000005621", + "AB07000000005639", + "AB07000000005647", + "AB07000000005654", + "AB07000000005662", + "AB07000000005670", + "AB07000000005530", + "AB07000000005548", + "AB07000000005555", + "AB07000000005753", + "AB07000000005761", + "AB07000000005779", + "AB07000000005787", + "AB07000000005795", + "AB07000000005506", + + // Note ETH "AB02000000051083", "AB02000000051059", "AB02000000051158", @@ -252,6 +323,123 @@ class DemoConfig { "AB02000000020252", "AB02000000018652", "AB02000000018561", + "AB08000000009481", + "AB08000000009473", + "AB08000000009705", + "AB08000000009897", + "AB08000000009689", + "AB08000000009671", + "AB08000000009465", + "AB08000000009457", + "AB08000000009440", + "AB08000000009432", + "AB08000000009424", + "AB08000000009416", + "AB08000000009408", + "AB08000000009390", + "AB08000000009374", + "AB08000000009382", + "AB08000000009267", + "AB08000000009275", + "AB08000000009283", + "AB08000000009291", + "AB08000000009309", + "AB08000000009317", + "AB08000000009325", + "AB08000000009333", + "AB08000000009341", + "AB08000000009358", + "AB08000000009366", + "AB08000000009077", + "AB08000000009143", + "AB08000000009168", + "AB08000000009184", + "AB08000000009192", + "AB08000000009200", + "AB08000000009226", + "AB08000000009218", + "AB08000000009234", + "AB08000000009242", + "AB08000000008574", + "AB08000000009069", + "AB08000000008525", + "AB08000000009051", + "AB08000000009135", + "AB08000000009150", + "AB08000000009176", + "AB08000000009085", + "AB08000000009093", + "AB08000000009101", + "AB08000000009119", + "AB08000000009127", + "AB08000000009259", + + // === Technopark === + // Wallet + "AC01000000044120", + "AC01000000044997", + "AC01000000044989", + "AC01000000043494", + "AC01000000043486", + "AC01000000044187", + "AC01000000043148", + "AC01000000044013", + "AC01000000043973", + "AC01000000044815", + "AC01000000044807", + "AC01000000043809", + "AC01000000043833", + "AC01000000043460", + "AC01000000043064", + "AC01000000044138", + "AC01000000044500", + "AC01000000044492", + "AC01000000044260", + "AC01000000044278", + + // Note BTC + "AB01000000049864", + "AB01000000053239", + "AB01000000053056", + "AB01000000054237", + "AB01000000054245", + "AB01000000054211", + "AB01000000054229", + "AB01000000053189", + "AB01000000054195", + "AB01000000050797", + "AB01000000053833", + "AB01000000052124", + "AB01000000051605", + "AB01000000052223", + "AB01000000052207", + "AB01000000052199", + "AB01000000047785", + "AB01000000047850", + "AB01000000047868", + "AB01000000048288", + + // Note ETH + "AB02000000049715", + "AB02000000049848", + "AB02000000049814", + "AB02000000049863", + "AB02000000049871", + "AB02000000049855", + "AB02000000049285", + "AB02000000049277", + "AB02000000049558", + "AB02000000049889", + "AB02000000049988", + "AB02000000049707", + "AB02000000049699", + "AB02000000049897", + "AB02000000049905", + "AB02000000049913", + "AB02000000049251", + "AB02000000049533", + "AB02000000049541", + "AB02000000049830", ) private val testDemoCardIds = listOf( @@ -281,7 +469,6 @@ class DemoTransactionSender( } } - override suspend fun send(transactionData: TransactionData, signer: TransactionSigner): SimpleResult { val dataToSign = randomString(32).toByteArray() val signerResponse = signer.sign( diff --git a/app/src/main/java/com/tangem/tap/features/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/features/feedback/FeedbackManager.kt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/ExpandedCurrencyItem.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/ExpandedCurrencyItem.kt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt index b96f055f59..698a4c9eb9 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt @@ -10,8 +10,8 @@ data class PendingTransaction( val type: PendingTransactionType, ) { val address: String? = when (type) { - PendingTransactionType.Incoming -> transactionData.destinationAddress - PendingTransactionType.Outgoing -> transactionData.sourceAddress + PendingTransactionType.Incoming -> transactionData.sourceAddress + PendingTransactionType.Outgoing -> transactionData.destinationAddress PendingTransactionType.Unknown -> null } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt index f54300f3ec..0b4a56fa11 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt @@ -4,7 +4,6 @@ sealed class WalletWarning( val showingPosition: Int, ) { object TransactionInProgress : WalletWarning(10) - object SolanaTokensUnsupported : WalletWarning(20) data class BalanceNotEnoughForFee(val blockchainFullName: String) : WalletWarning(30) data class Rent(val walletRent: WalletRent) : WalletWarning(40) } 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 d3d59422be..ec3107b151 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 @@ -8,6 +8,8 @@ import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType import com.tangem.common.extensions.isZero import com.tangem.domain.common.extensions.canHandleToken +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.extensions.toQrCode import com.tangem.tap.common.redux.global.CryptoCurrencyName @@ -395,19 +397,10 @@ data class WalletData( } fun assembleWarnings(): List { - val blockchain = currency.blockchain val walletWarnings = mutableListOf() if (currencyData.status == BalanceStatus.SameCurrencyTransactionInProgress) { walletWarnings.add(WalletWarning.TransactionInProgress) } - if (currency.isBlockchain()) { - if (blockchain == Blockchain.Solana || blockchain == Blockchain.SolanaTestnet) { - val card = store.state.globalState.scanResponse?.card - if (card?.canHandleToken(blockchain) == false) { - walletWarnings.add(WalletWarning.SolanaTokensUnsupported) - } - } - } if (walletRent != null) { walletWarnings.add(WalletWarning.Rent(walletRent)) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt index 6137f344e3..1e9e127e59 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt @@ -21,9 +21,6 @@ class WalletWarningConverter( message.blockchainFullName, message.blockchainFullName ) } - WalletWarning.SolanaTokensUnsupported -> { - context.getString(R.string.warning_token_send_unsupported_message) - } WalletWarning.TransactionInProgress -> { context.getString(R.string.wallet_pending_transaction_warning) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index b4f5f84a1f..78bbb4c3ed 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -9,7 +9,7 @@ import androidx.recyclerview.widget.RecyclerView import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.domain.common.TapWorkarounds.derivationStyle -import com.tangem.tap.common.extensions.getGreyedOutIconRes +import com.tangem.tap.common.extensions.getRoundIconRes import com.tangem.tap.common.extensions.getString import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show @@ -118,7 +118,7 @@ class WalletAdapter badgeCustomBalance.isVisible = isCustomCurrency ivBlockchain.isVisible = wallet.currency.isToken() - ivBlockchain.setImageResource(wallet.currency.blockchain.getGreyedOutIconRes()) + ivBlockchain.setImageResource(wallet.currency.blockchain.getRoundIconRes()) cardWallet.setOnClickListener { store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet)) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt index 35d89aaa27..b973c9cc52 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt @@ -24,7 +24,6 @@ class CurrencyIconView @JvmOverloads constructor( init { elevation = 0f cardElevation = 0f - radius = dpToPx(8f) - background = null + radius = dpToPx(6f) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/RoundedCornersCropTransformation.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/RoundedCornersCropTransformation.kt new file mode 100644 index 0000000000..7a9b0a3015 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/RoundedCornersCropTransformation.kt @@ -0,0 +1,58 @@ +package com.tangem.tap.features.wallet.ui.images + +import android.graphics.Bitmap +import android.graphics.BitmapShader +import android.graphics.Matrix +import android.graphics.Paint +import android.graphics.RectF +import android.graphics.Shader +import androidx.annotation.Px +import androidx.core.graphics.applyCanvas +import coil.size.Size +import coil.size.pxOrElse +import coil.transform.Transformation + +class RoundedCornersCropTransformation( + @Px val radiusPx: Float, +) : Transformation { + override val cacheKey: String = "${javaClass.name}-$radiusPx" + + override suspend fun transform(input: Bitmap, size: Size): Bitmap { + val outputWidth = size.width.pxOrElse { Int.MAX_VALUE } + val outputHeight = size.height.pxOrElse { Int.MAX_VALUE } + val outputSize = minOf(outputWidth, outputHeight) + val output = Bitmap.createBitmap(outputSize, outputSize, Bitmap.Config.ARGB_8888) + + val rect = RectF( + /* left = */ 0f, + /* top = */ 0f, + /* right = */ outputWidth.toFloat(), + /* bottom = */ outputHeight.toFloat() + ) + val matrix = Matrix().apply { + setTranslate( + /* dx = */ (outputWidth - input.width) * .5f, + /* dy = */ (outputHeight - input.height) * .5f + ) + } + val bitmapShader = BitmapShader( + /* bitmap = */ input, + /* tileX = */ Shader.TileMode.DECAL, + /* tileY = */ Shader.TileMode.DECAL + ).apply { + setLocalMatrix(matrix) + } + val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply { + shader = bitmapShader + } + + return output.applyCanvas { + drawRoundRect( + /* rect = */ rect, + /* rx = */ radiusPx, + /* ry = */ radiusPx, + /* paint = */ paint + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_gnosis_no_color.xml b/app/src/main/res/drawable/ic_gnosis_no_color.xml new file mode 100644 index 0000000000..a8d4069093 --- /dev/null +++ b/app/src/main/res/drawable/ic_gnosis_no_color.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_gnosis_round.xml b/app/src/main/res/drawable/ic_gnosis_round.xml new file mode 100644 index 0000000000..8734b7177b --- /dev/null +++ b/app/src/main/res/drawable/ic_gnosis_round.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/app/src/main/res/layout/item_currency_wallet.xml b/app/src/main/res/layout/item_currency_wallet.xml index 9ac49b1ad9..01860acfb1 100644 --- a/app/src/main/res/layout/item_currency_wallet.xml +++ b/app/src/main/res/layout/item_currency_wallet.xml @@ -6,14 +6,14 @@ android:layout_height="wrap_content"> + android:id="@+id/card_wallet" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="8dp" + android:background="@android:color/white" + android:elevation="3dp"> + app:layout_constraintEnd_toEndOf="@id/iv_currency" + app:layout_constraintStart_toStartOf="@id/iv_currency" + app:layout_constraintTop_toTopOf="@id/iv_currency" + tools:text="J" /> + layout="@layout/item_currency_wallet_content" + android:id="@+id/l_content" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_marginStart="8dp" + android:visibility="gone" + app:layout_constraintStart_toEndOf="@id/iv_currency" + app:layout_constraintEnd_toEndOf="parent" + tools:visibility="visible" /> + layout="@layout/item_currency_wallet_shimmer" + android:id="@+id/l_shimmer" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_marginStart="8dp" + app:layout_constraintStart_toEndOf="@id/iv_currency" + app:layout_constraintEnd_toEndOf="parent" /> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1fbdfd7a66..e90d92bbff 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -244,8 +244,8 @@ Ваша криптокарта активирована и готова к использованию Продолжить Баланс - Отправляйте только %s (%s) на этот адрес. Отправка любой другой валюты приведет к ее безвозвратной потере. - Отправляйте только %s (%s) из сети %s на этот адрес. Отправка любой другой валюты приведет к ее безвозвратной потере. + Отправляйте только %s (%s) на этот адрес. Иначе это может привести к утрате средств. + Отправляйте только %s (%s) из сети %s на этот адрес. Иначе это может привести к утрате средств. Если процесс повторного создания кошелька каким-либо образом прервется, вам придется начать все сначала. Процесс связывания карт частично завершен. Вы не можете выйти из него сейчас. Внутренняя ошибка: не удается создать менеджер кошельков diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index d4ddb9ad8c..a7ebbef56b 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -77,4 +77,6 @@ Да Задать вопрос + + Tangem Bot diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index 4c7ec8e0bd..f496ca1548 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -78,4 +78,6 @@ No Ask a question + + Tangem Bot diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 84f36c07bf..4a49d725cc 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -205,8 +205,8 @@ Your crypto card is activated and ready to be used Continue Balance - Send only %s (%s) to this address. Sending any other currency will result in its irreversible loss. - Send only %s (%s) from %s network to this address. Sending any other currency will result in its irreversible loss. + Send only %s (%s) to this address. Using other tokens and networks may result in loss of funds. + Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. If the process of re-creating the wallet gets interrupted in any way, you\'ll have to start over. The twinning process is partly complete. You can\'t exit it now. diff --git a/app/src/main/res/values/zendesk_styles.xml b/app/src/main/res/values/zendesk_styles.xml index 0022b241b1..ebb4fcab6b 100644 --- a/app/src/main/res/values/zendesk_styles.xml +++ b/app/src/main/res/values/zendesk_styles.xml @@ -4,15 +4,4 @@ @color/darkGray6 @color/darkGray6 - - // Contact us FAB style - diff --git a/dependencies.gradle b/dependencies.gradle index b4a597ff72..cbd16111f5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,12 +1,12 @@ ext.versions = [ - kotlin : '1.6.10', - build_gradle : '7.1.3', - tamgem_card_sdk : 'develop-156', - tamgem_blockchain_sdk: 'develop-96', + kotlin : '1.6.10', + build_gradle : '7.1.3', + tamgem_card_sdk : 'develop-157', + tamgem_blockchain_sdk: 'develop-99', ] ext.environmentConfig = [ environment : "ENVIRONMENT", testActionEnabled: "TEST_ACTION_ENABLED", logEnabled : "LOG_ENABLED", -] +] \ No newline at end of file diff --git a/domain/build.gradle b/domain/build.gradle index f4b0183cc8..d7a8832fd4 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -85,4 +85,4 @@ dependencies { testImplementation "com.google.truth:truth:1.1.3" androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' -} +} \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt index b69ffb1c49..8708f1a0a8 100644 --- a/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt +++ b/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt @@ -37,6 +37,7 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? { "tron" -> Blockchain.Tron "tron/test" -> Blockchain.TronTestnet "xrp", "ripple" -> Blockchain.XRP + "xdai" -> Blockchain.Gnosis else -> null } } @@ -78,6 +79,7 @@ fun Blockchain.toNetworkId(): String { Blockchain.XRP -> "xrp" Blockchain.Tron -> "tron" Blockchain.TronTestnet -> "tron/test" + Blockchain.Gnosis -> "xdai" } } @@ -102,6 +104,7 @@ fun Blockchain.toCoinId(): String { Blockchain.XRP -> "ripple" Blockchain.Dogecoin -> "dogecoin" Blockchain.Tron, Blockchain.TronTestnet -> "tron" - else -> "unknown" + Blockchain.Gnosis -> "xdai" + Blockchain.Unknown -> "unknown" } } \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt index 9a4b0be414..1c09b4116a 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt @@ -2,7 +2,6 @@ package com.tangem.domain.features.addCustomToken.redux import android.webkit.ValueCallback import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.DerivationStyle import com.tangem.common.extensions.guard import com.tangem.common.services.Result import com.tangem.domain.AddCustomTokenError @@ -571,17 +570,11 @@ private class AddCustomTokenReducer( supportedTokenNetworkIds = supportedTokenNetworkIds ) - var derivationPathState = state.screenState.derivationPath - derivationPathState = when (card.derivationStyle) { - DerivationStyle.LEGACY -> derivationPathState.copy(isVisible = true) - null, DerivationStyle.NEW -> derivationPathState.copy(isVisible = false) - } val form = Form(AddCustomTokenState.createFormFields(card, CustomTokenType.Blockchain)) state.copy( cardDerivationStyle = card.derivationStyle, form = form, tangemTechServiceManager = tangemTechServiceManager, - screenState = state.screenState.copy(derivationPath = derivationPathState) ) } is OnDestroy -> { diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt index ed18fe69f5..97c652da19 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt @@ -50,7 +50,7 @@ data class AddCustomTokenState( fun blockchainToName(blockchain: Blockchain, isDerivationPath: Boolean = false): String? { return when { - isDerivationPath -> blockchain.derivationPath(cardDerivationStyle)?.rawPath + isDerivationPath -> blockchain.derivationPath(DerivationStyle.LEGACY)?.rawPath else -> { when (blockchain) { Blockchain.Unknown -> null @@ -150,10 +150,21 @@ data class AddCustomTokenState( mainNetwork: Blockchain, derivationNetwork: Blockchain, derivationStyle: DerivationStyle? - ): com.tangem.common.hdWallet.DerivationPath? = when (derivationNetwork) { - Blockchain.Unknown -> mainNetwork - else -> derivationNetwork - }.derivationPath(derivationStyle) + ): com.tangem.common.hdWallet.DerivationPath? { + // If we allow user to select derivations, we need to provide different derivations + // (Legacy style derivations). + // But the mainNetwork derivation depends on whether a user has a card + // with legacy derivations or new style derivations. + val derivationStyleToUse = if (derivationNetwork == Blockchain.Unknown) { + derivationStyle + } else { + DerivationStyle.LEGACY + } + return when (derivationNetwork) { + Blockchain.Unknown -> mainNetwork + else -> derivationNetwork + }.derivationPath(derivationStyleToUse) + } internal fun createFormFields(card: Card, type: CustomTokenType): List> { return listOf(