diff --git a/.gitignore b/.gitignore
index 25c98d5d1f..3e96fb9767 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
# Built application files
/build
+/buildSrc
# Local configuration file (sdk path, etc)
local.properties
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7fc608245b..0db8c6d7c9 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -13,9 +13,6 @@
-
-
-
@@ -205,4 +202,4 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a9226c6eff..ef93ea2179 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,16 +27,16 @@
@@ -45,10 +45,11 @@
android:value="true" />
@@ -125,13 +126,17 @@
-
+
-
+
{
preparedData = state.dialog.data,
context = context,
)
- is WalletConnectDialog.UnsupportedNetwork ->
+ is WalletConnectDialog.UnsupportedNetwork -> {
+ val warning = if (state.dialog.networks.isNullOrEmpty()) {
+ context.getString(R.string.wallet_connect_scanner_error_unsupported_network)
+ } else {
+ context.getString(R.string.wallet_connect_error_unsupported_blockchains) +
+ state.dialog.networks
+ }
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect_title,
- messageRes = R.string.wallet_connect_scanner_error_unsupported_network,
+ message = warning,
context = context,
)
+ }
is WalletConnectDialog.SessionProposalDialog -> {
SessionProposalDialog.create(
sessionProposal = state.dialog.sessionProposal,
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
index c9f2314efc..c4becfb45b 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
@@ -15,6 +15,7 @@ import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import org.rekotlin.StateType
data class GlobalState(
+ @Deprecated("Use scan response from selected user wallet")
val scanResponse: ScanResponse? = null,
val onboardingState: OnboardingState = OnboardingState(),
val cardVerifiedOnline: Boolean = false,
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 50182bde55..f9be91dcce 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
@@ -83,9 +83,9 @@ class TapWalletManager(
}
private fun setupWalletConnectV2(userWallet: UserWallet) {
- val cardId = if (userWallet.cardsInWallet.size == 1) {
+ val cardId = if (userWallet.scanResponse.card.backupStatus?.isActive != true) {
userWallet.cardId
- } else {
+ } else { // if wallet has backup, any card from wallet can be used to sign
null
}
scope.launch {
diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt
index 78f74e0c3d..4ea180e270 100644
--- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt
@@ -118,7 +118,9 @@ internal class BiometricUserWalletsListManager(
}
.flatMap { updatedUserWallet ->
saveInternal(updatedUserWallet, changeSelectedUserWallet = false)
- .map { updatedUserWallet }
+ }
+ .flatMap {
+ get(userWalletId)
}
}
diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt
index f344f46d4a..0bbd76b7bc 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt
@@ -1,13 +1,10 @@
package com.tangem.tap.domain.walletCurrencies.implementation
import com.tangem.blockchain.common.DerivationStyle
-import com.tangem.common.CompletionResult
-import com.tangem.common.flatMap
-import com.tangem.common.fold
-import com.tangem.common.map
-import com.tangem.domain.models.scan.CardDTO
+import com.tangem.common.*
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.util.UserWalletId
+import com.tangem.domain.models.scan.CardDTO
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.domain.model.UserWallet
import com.tangem.tap.domain.model.builders.WalletStoreBuilder
@@ -103,7 +100,7 @@ internal class DefaultWalletCurrenciesManager(
.flatMap {
updateWalletStores(userWallet, remainingCurrencies.toBlockchainNetworks())
}
- .map {
+ .doOnResult {
saveUserCurrencies(card, remainingCurrencies)
}
}
diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt
index e276bd51db..22dd64bff1 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt
@@ -7,16 +7,11 @@ import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.extensions.Result.Failure
import com.tangem.blockchain.extensions.Result.Success
-import com.tangem.common.CompletionResult
-import com.tangem.common.catching
+import com.tangem.common.*
import com.tangem.common.core.TangemError
-import com.tangem.common.flatMap
-import com.tangem.common.flatMapOnFailure
-import com.tangem.common.fold
-import com.tangem.common.map
import com.tangem.datasource.api.tangemTech.TangemTechApi
-import com.tangem.domain.common.util.hasDerivation
import com.tangem.domain.common.util.UserWalletId
+import com.tangem.domain.common.util.hasDerivation
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.common.TestActions
import com.tangem.tap.common.entities.FiatCurrency
@@ -25,15 +20,7 @@ import com.tangem.tap.domain.model.UserWallet
import com.tangem.tap.domain.model.WalletStoreModel
import com.tangem.tap.domain.walletStores.WalletStoresError
import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.replaceWalletStore
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.replaceWalletStores
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithAmounts
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithDemoAmounts
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithError
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithFiatRates
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithMissedDerivation
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithRent
-import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithUnreachable
+import com.tangem.tap.domain.walletStores.repository.implementation.utils.*
import com.tangem.tap.domain.walletStores.storage.WalletManagerStorage
import com.tangem.tap.domain.walletStores.storage.WalletStoresStorage
import com.tangem.tap.features.demo.DemoHelper
@@ -45,13 +32,8 @@ import com.tangem.tap.features.wallet.models.getPendingTransactions
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.async
-import kotlinx.coroutines.awaitAll
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.delay
+import kotlinx.coroutines.*
import kotlinx.coroutines.flow.firstOrNull
-import kotlinx.coroutines.withContext
import timber.log.Timber
import java.math.BigDecimal
import kotlin.time.Duration
@@ -200,37 +182,40 @@ internal class DefaultWalletAmountsRepository(
walletStore: WalletStoreModel,
walletManager: WalletManager?,
): CompletionResult {
- val hasMissedDerivations = with(walletStore) {
+ val isDerivationMissed = with(walletStore) {
derivationPath != null && !scanResponse.hasDerivation(blockchain, derivationPath.rawPath)
}
return when {
- hasMissedDerivations -> {
+ isDerivationMissed -> {
updateWalletStoreWithMissedDerivation(walletStore)
}
walletManager == null -> {
updateWalletStoreWithUnreachable(walletStore)
}
else -> {
- updateWalletManager(scanResponse, walletManager).map {
- updateWalletManagerInStorage(
- userWalletId,
- walletManager,
- )
- }.flatMap {
- updateWalletStoreWithAmounts(
- walletStore = walletStore,
- updatedWallet = walletManager.wallet,
- // FIXME: move DemoHelper to Demo core module maybe
- isDemo = DemoHelper.isDemoCardId(scanResponse.card.cardId),
- )
- }.flatMap { fetchWalletStoreRentIfNeeded(walletStore, walletManager) }.flatMapOnFailure { error ->
- updateWalletStoreWithError(
- walletStore = walletStore,
- wallet = walletManager.wallet,
- error = error,
- )
- }
+ updateWalletManager(scanResponse, walletManager)
+ .map {
+ updateWalletManagerInStorage(userWalletId, walletManager)
+ }
+ .flatMap {
+ updateWalletStoreWithAmounts(
+ walletStore = walletStore,
+ updatedWallet = walletManager.wallet,
+ // FIXME: move DemoHelper to Demo core module maybe
+ isDemo = DemoHelper.isDemoCardId(scanResponse.card.cardId),
+ )
+ }
+ .flatMap {
+ fetchWalletStoreRentIfNeeded(walletStore, walletManager)
+ }
+ .flatMapOnFailure { error ->
+ updateWalletStoreWithError(
+ walletStore = walletStore,
+ wallet = walletManager.wallet,
+ error = error,
+ )
+ }
}
}
}
diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt
index e315dace10..dc3169c18c 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt
@@ -33,7 +33,6 @@ import com.tangem.tap.domain.walletconnect2.domain.models.EthTransactionData
import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceTradeOrder
import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceTransferOrder
import com.tangem.tap.features.details.redux.walletconnect.*
-import com.tangem.tap.features.details.redux.walletconnect.WcEthTransactionType
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData
import com.tangem.tap.store
@@ -194,7 +193,12 @@ class WalletConnectSdkHelper {
val result = tangemSdkManager.runTaskAsync(command, initialMessage = Message(), cardId = cardId)
return when (result) {
is CompletionResult.Success -> {
- HEX_PREFIX + result.data
+ HEX_PREFIX + EthereumUtils.prepareTransactionToSend(
+ signature = result.data.signature,
+ transactionToSign = dataToSign,
+ walletPublicKey = data.walletManager.wallet.publicKey,
+ blockchain = data.walletManager.wallet.blockchain,
+ ).toHexString()
}
is CompletionResult.Failure -> {
(result.error as? TangemSdkError)?.let { Analytics.send(WalletConnect.SignError(it)) }
diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt
index 80d7ed0b09..01e3803798 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt
@@ -1,15 +1,22 @@
package com.tangem.tap.domain.walletconnect2.data
-import android.app.*
-import com.tangem.tap.domain.walletconnect2.domain.*
+import android.app.Application
+import com.tangem.tap.domain.walletconnect2.domain.WalletConnectRepository
+import com.tangem.tap.domain.walletconnect2.domain.WcJrpcRequestsDeserializer
import com.tangem.tap.domain.walletconnect2.domain.models.*
-import com.walletconnect.android.*
-import com.walletconnect.android.relay.*
-import com.walletconnect.web3.wallet.client.*
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import timber.log.*
-import javax.inject.*
+import com.walletconnect.android.Core
+import com.walletconnect.android.CoreClient
+import com.walletconnect.android.relay.ConnectionType
+import com.walletconnect.web3.wallet.client.Wallet
+import com.walletconnect.web3.wallet.client.Web3Wallet
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.launch
+import timber.log.Timber
+import javax.inject.Inject
class WalletConnectRepositoryImpl @Inject constructor(
private val application: Application,
@@ -181,7 +188,7 @@ class WalletConnectRepositoryImpl @Inject constructor(
userNamespaces = userNamespaces,
)
if (missingNetworks.isNotEmpty()) {
- Timber.e("Unsupported blockchains: $missingNetworks")
+ Timber.e("Not added blockchains: $missingNetworks")
scope.launch {
_events.emit(
WalletConnectEvents.SessionApprovalError(
diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt
index 03bd4e548e..ef202cd085 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt
@@ -1,13 +1,16 @@
package com.tangem.tap.domain.walletconnect2.domain
-import com.tangem.tap.common.extensions.*
-import com.tangem.tap.domain.walletconnect.*
+import com.tangem.tap.common.extensions.filterNotNull
+import com.tangem.tap.domain.walletconnect.WalletConnectSdkHelper
import com.tangem.tap.domain.walletconnect2.domain.models.*
-import com.tangem.tap.features.details.ui.walletconnect.*
-import com.tangem.utils.coroutines.*
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import timber.log.*
+import com.tangem.tap.features.details.ui.walletconnect.WcSessionForScreen
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import timber.log.Timber
class WalletConnectInteractor(
private val handler: WalletConnectEventsHandler,
@@ -34,11 +37,11 @@ class WalletConnectInteractor(
suspend fun startListening(userWalletId: String, cardId: String?) {
this.userWalletId = userWalletId
this.cardId = cardId
+ walletConnectRepository.updateSessions()
coroutineScope {
launch { subscribeToEvents() }
launch { subscribeToSessions() }
}
- walletConnectRepository.updateSessions()
}
private suspend fun subscribeToEvents() {
@@ -47,6 +50,14 @@ class WalletConnectInteractor(
when (wcEvent) {
is WalletConnectEvents.SessionProposal -> {
Timber.d("WC session proposal event received")
+ val unsupportedNetworks = wcEvent.chainIds
+ .filter { blockchainHelper.chainIdToNetworkIdOrNull(it) == null }
+ if (unsupportedNetworks.isNotEmpty()) {
+ val error = WalletConnectError.ApprovalErrorUnsupportedNetwork(unsupportedNetworks)
+ handler.onSessionRejected(error)
+ return@onEach
+ }
+
val networksFormatted = wcEvent.chainIds
.mapNotNull { blockchainHelper.chainIdToFullNameOrNull(it) }
.toString()
@@ -57,12 +68,7 @@ class WalletConnectInteractor(
is WalletConnectError.ApprovalErrorMissingNetworks -> {
val missingNetworks = wcEvent.error.missingChains
.map { blockchainHelper.chainIdToNetworkIdOrNull(it) }
- val containsUnsupportedNetworks = missingNetworks.any { it == null }
- if (containsUnsupportedNetworks) {
- WalletConnectError.ApprovalErrorUnsupportedNetwork
- } else {
- WalletConnectError.ApprovalErrorAddNetwork(missingNetworks.filterNotNull())
- }
+ WalletConnectError.ApprovalErrorAddNetwork(missingNetworks.filterNotNull())
}
else -> wcEvent.error
}
diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt
index bc93e31462..fe67571134 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt
@@ -130,7 +130,8 @@ class WcSessionRequestConverter(
): String? {
return sessionsRepository.loadSessions(userWalletId)
.firstOrNull { it.topic == sessionRequest.topic }
- ?.accounts?.firstOrNull { it.chainId == sessionRequest.chainId && it.walletAddress == walletAddress }
- ?.derivationPath
+ ?.accounts?.firstOrNull {
+ it.chainId == sessionRequest.chainId && it.walletAddress.lowercase() == walletAddress?.lowercase()
+ }?.derivationPath
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectError.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectError.kt
index 1f9b7f6771..35da4b88f8 100644
--- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectError.kt
+++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/WalletConnectError.kt
@@ -3,7 +3,7 @@ package com.tangem.tap.domain.walletconnect2.domain.models
sealed class WalletConnectError : Exception() {
data class ApprovalErrorMissingNetworks(val missingChains: List) : WalletConnectError()
data class ApprovalErrorAddNetwork(val networks: List) : WalletConnectError()
- object ApprovalErrorUnsupportedNetwork : WalletConnectError()
+ data class ApprovalErrorUnsupportedNetwork(val unsupportedNetworks: List) : WalletConnectError()
data class ExternalApprovalError(override val message: String?) : WalletConnectError()
object WrongUserWallet : WalletConnectError()
object UnsupportedMethod : WalletConnectError()
diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt
index f4478fc4fc..a203e348dd 100644
--- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/AddCustomTokenFragment.kt
@@ -4,9 +4,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalLifecycleOwner
-import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.transition.TransitionInflater
@@ -25,8 +26,6 @@ import dagger.hilt.android.AndroidEntryPoint
internal class AddCustomTokenFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
-
with(TransitionInflater.from(requireContext())) {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
@@ -41,7 +40,10 @@ internal class AddCustomTokenFragment : Fragment() {
}
TangemTheme {
- AddCustomTokenScreen(stateHolder = viewModel.uiState)
+ AddCustomTokenScreen(
+ modifier = Modifier.systemBarsPadding(),
+ stateHolder = viewModel.uiState,
+ )
}
}
}
diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenContent.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenContent.kt
index e57d82cc15..55afd696af 100644
--- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenContent.kt
+++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenContent.kt
@@ -8,11 +8,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.FabPosition
import androidx.compose.material.Scaffold
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
+import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
@@ -33,11 +29,12 @@ import com.tangem.tap.features.customtoken.impl.presentation.ui.components.AddCu
[REDACTED_AUTHOR]
*/
@Composable
-internal fun AddCustomTokenContent(state: AddCustomTokenStateHolder.Content) {
+internal fun AddCustomTokenContent(state: AddCustomTokenStateHolder.Content, modifier: Modifier = Modifier) {
BackHandler(onBack = state.onBackButtonClick)
var floatingButtonHeight by remember { mutableStateOf(0.dp) }
Scaffold(
+ modifier = modifier,
topBar = {
AddCustomTokenToolbar(
title = state.toolbar.title,
diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenScreen.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenScreen.kt
index 71d079e899..eb099e7ee8 100644
--- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenScreen.kt
+++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenScreen.kt
@@ -1,6 +1,7 @@
package com.tangem.tap.features.customtoken.impl.presentation.ui
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
@@ -15,10 +16,10 @@ import com.tangem.tap.features.customtoken.impl.presentation.states.AddCustomTok
[REDACTED_AUTHOR]
*/
@Composable
-internal fun AddCustomTokenScreen(stateHolder: AddCustomTokenStateHolder) {
+internal fun AddCustomTokenScreen(stateHolder: AddCustomTokenStateHolder, modifier: Modifier = Modifier) {
when (stateHolder) {
- is AddCustomTokenStateHolder.Content -> AddCustomTokenContent(state = stateHolder)
- is AddCustomTokenStateHolder.TestContent -> AddCustomTokenTestContent(state = stateHolder)
+ is AddCustomTokenStateHolder.Content -> AddCustomTokenContent(stateHolder, modifier)
+ is AddCustomTokenStateHolder.TestContent -> AddCustomTokenTestContent(stateHolder, modifier)
}
}
diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenTestContent.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenTestContent.kt
index c23fa86835..9304675ad7 100644
--- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenTestContent.kt
+++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenTestContent.kt
@@ -1,31 +1,11 @@
package com.tangem.tap.features.customtoken.impl.presentation.ui
import androidx.activity.compose.BackHandler
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material.BottomSheetScaffold
-import androidx.compose.material.BottomSheetScaffoldState
-import androidx.compose.material.BottomSheetState
-import androidx.compose.material.BottomSheetValue
-import androidx.compose.material.Divider
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material.FabPosition
-import androidx.compose.material.Text
-import androidx.compose.material.rememberBottomSheetScaffoldState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.key
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
+import androidx.compose.material.*
+import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@@ -59,7 +39,7 @@ import kotlinx.coroutines.launch
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
-internal fun AddCustomTokenTestContent(state: AddCustomTokenStateHolder.TestContent) {
+internal fun AddCustomTokenTestContent(state: AddCustomTokenStateHolder.TestContent, modifier: Modifier = Modifier) {
val coroutineScope = rememberCoroutineScope()
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(initialValue = BottomSheetValue.Collapsed),
@@ -77,6 +57,7 @@ internal fun AddCustomTokenTestContent(state: AddCustomTokenStateHolder.TestCont
var floatingButtonHeight by remember { mutableStateOf(0.dp) }
BottomSheetScaffold(
+ modifier = modifier,
sheetContent = {
SheetContent(
coroutineScope = coroutineScope,
diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/components/AddCustomTokenForm.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/components/AddCustomTokenForm.kt
index 0051e2e6c4..0090ef8223 100644
--- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/components/AddCustomTokenForm.kt
+++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/components/AddCustomTokenForm.kt
@@ -8,7 +8,6 @@ import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@@ -161,7 +160,6 @@ private fun SelectorField(model: AddCustomTokenSelectorField) {
expanded = isExpanded && isEnabled,
onDismissRequest = { isExpanded = false },
) {
- FocusRequester
model.items.forEachIndexed { index, item ->
DropdownMenuItem(
onClick = {
diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt
index 1d886914c7..297bf37f54 100644
--- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt
+++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt
@@ -41,6 +41,7 @@ import com.tangem.wallet.BuildConfig
import com.tangem.wallet.R
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.persistentListOf
+import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -207,7 +208,8 @@ internal class AddCustomTokenViewModel @Inject constructor(
val defaultNetwork = createNetworkSelectorItem(blockchain = Blockchain.Unknown)
return listOf(defaultNetwork) + Blockchain.values()
.filter { blockchain ->
- reduxStateHolder.scanResponse?.card?.supportedBlockchains()?.contains(blockchain) == true
+ reduxStateHolder.scanResponse?.card?.supportedBlockchains()?.contains(blockchain) == true &&
+ blockchain != Blockchain.Cardano
}
.sortedBy(Blockchain::fullName)
.map(::createNetworkSelectorItem)
@@ -270,7 +272,9 @@ internal class AddCustomTokenViewModel @Inject constructor(
type = DerivationPathSelectorType.CUSTOM,
),
) + Blockchain.values()
- .filter { blockchain -> blockchain.isSupportedInApp() && !blockchain.isTestnet() }
+ .filter { blockchain ->
+ blockchain.isSupportedInApp() && !blockchain.isTestnet() && blockchain != Blockchain.Cardano
+ }
.sortedBy(Blockchain::fullName)
.map(::createDerivationPathSelectorAdditionalItem)
}
@@ -510,7 +514,7 @@ internal class AddCustomTokenViewModel @Inject constructor(
val sameAddress = contractAddress == wrappedCurrency.token.contractAddress
val sameBlockchain =
Blockchain.fromNetworkId(networkSelectorValue.toNetworkId()) == wrappedCurrency.blockchain
- val isSameDerivationPath = getDerivationPath()?.rawPath == wrappedCurrency.derivationPath
+ val isSameDerivationPath = getDerivationPath().isSameDerivationPath(wrappedCurrency.derivationPath)
sameId && sameAddress && sameBlockchain && isSameDerivationPath
}
}
@@ -522,10 +526,15 @@ internal class AddCustomTokenViewModel @Inject constructor(
.filterIsInstance()
.any {
val networkSelectorValue = uiState.form.networkSelectorField.selectedItem.blockchain
- networkSelectorValue == it.blockchain && getDerivationPath()?.rawPath == it.derivationPath
+ networkSelectorValue == it.blockchain &&
+ getDerivationPath().isSameDerivationPath(it.derivationPath)
}
}
+ private fun DerivationPath?.isSameDerivationPath(rawDerivationPath: String?): Boolean {
+ return this == rawDerivationPath?.let { DerivationPath(it) }
+ }
+
private fun handleContractAddressErrorValidation(type: AddCustomTokenError) {
when {
isNetworkSelected() && type == AddCustomTokenError.InvalidContractAddress -> {
@@ -605,7 +614,11 @@ internal class AddCustomTokenViewModel @Inject constructor(
private inner class ActionsHandler(private val featureRouter: CustomTokenRouter) {
fun onBackButtonClick() {
- featureRouter.popBackStack()
+ viewModelScope.launch(dispatchers.main) {
+ // need delay before close, cause crashed in compose PopUpMenu as
+ delay(timeMillis = 100)
+ featureRouter.popBackStack()
+ }
}
fun onContactAddressValueChange(enteredValue: String) {
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 b83b2ad75a..c42aa9f320 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
@@ -66,7 +66,7 @@ class WalletConnectMiddleware {
walletConnectManager.restoreSessions(action.scanResponse)
}
is WalletConnectAction.HandleDeepLink -> {
- if (!action.wcUri.isNullOrBlank() && WalletConnectManager.isCorrectWcUri(action.wcUri)) {
+ if (!action.wcUri.isNullOrBlank()) {
store.dispatchOnMain(WalletConnectAction.OpenSession(action.wcUri))
}
}
@@ -238,7 +238,7 @@ class WalletConnectMiddleware {
return
}
val blockchain = action.blockchain.guard {
- store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork))
+ store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork()))
return
}
val walletManager = getWalletManager(
@@ -298,19 +298,25 @@ class WalletConnectMiddleware {
),
)
}
-
- WalletConnectError.ApprovalErrorUnsupportedNetwork -> {
- store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork))
- }
- is WalletConnectError.ExternalApprovalError -> {
+ is WalletConnectError.ApprovalErrorUnsupportedNetwork -> {
store.dispatchOnMain(
GlobalAction.ShowDialog(
- AppDialog.SimpleOkWarningDialog(
- message = action.error.message ?: "",
- ),
+ WalletConnectDialog.UnsupportedNetwork(action.error.unsupportedNetworks),
),
)
}
+ is WalletConnectError.ExternalApprovalError -> {
+ val message = action.error.message
+ if (!message.isNullOrEmpty()) {
+ store.dispatchOnMain(
+ GlobalAction.ShowDialog(
+ AppDialog.SimpleOkWarningDialog(
+ message = message,
+ ),
+ ),
+ )
+ }
+ }
else -> Unit
}
}
@@ -327,7 +333,7 @@ class WalletConnectMiddleware {
scope.launch { walletConnectInteractor.continueWithRequest(action.sessionRequest) }
}
is WalletConnectAction.RejectUnsupportedRequest -> {
- store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork))
+ store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork()))
}
}
}
@@ -337,7 +343,7 @@ class WalletConnectMiddleware {
chainId = chainId,
peer = session.peerMeta,
).guard {
- store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork))
+ store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork()))
return
}
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 71f4a14ca6..135f597dc1 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
@@ -91,7 +91,7 @@ data class WalletForSession(
sealed class WalletConnectDialog : StateDialog {
data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog()
object UnsupportedCard : WalletConnectDialog()
- object UnsupportedNetwork : WalletConnectDialog()
+ data class UnsupportedNetwork(val networks: List? = null) : WalletConnectDialog()
data class AddNetwork(val network: String) : WalletConnectDialog()
object OpeningSessionRejected : WalletConnectDialog()
object SessionTimeout : WalletConnectDialog()
diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt
index a08b9af8b2..91a8e803b3 100644
--- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt
@@ -24,7 +24,7 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
+ setFitSystemWindows(fit = true)
activity?.onBackPressedDispatcher?.addCallback(
this,
object : OnBackPressedCallback(true) {
@@ -47,6 +47,11 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
scannerView?.stopCamera()
}
+ override fun onDestroy() {
+ super.onDestroy()
+ setFitSystemWindows(fit = false)
+ }
+
override fun onResume() {
super.onResume()
scannerView?.setResultHandler(this)
@@ -55,7 +60,7 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
override fun handleResult(result: Result) {
store.dispatch(NavigationAction.PopBackTo())
- activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, false) }
+ setFitSystemWindows(fit = false)
if (!result.text.isNullOrBlank()) {
store.dispatch(WalletConnectAction.OpenSession(result.text))
}
@@ -83,4 +88,10 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
private fun requestPermission() {
requestPermissions(arrayOf(Manifest.permission.CAMERA), CameraView.PERMISSION_REQUEST_CODE)
}
+
+ private fun setFitSystemWindows(fit: Boolean) {
+ activity?.window?.let {
+ WindowCompat.setDecorFitsSystemWindows(it, fit)
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt
index c66271923f..d54adda3d5 100644
--- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt
@@ -6,7 +6,7 @@ import com.tangem.blockchain.blockchains.cosmos.CosmosTransactionExtras
import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
import com.tangem.blockchain.blockchains.ton.TonTransactionExtras
-import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
+import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder.XrpTransactionExtras
import com.tangem.blockchain.common.*
import com.tangem.blockchain.extensions.SimpleResult
import com.tangem.common.core.TangemSdkError
@@ -168,9 +168,7 @@ private fun sendTransaction(
transactionExtras.xlmMemo?.memo?.let { txData = txData.copy(extras = StellarTransactionExtras(it)) }
transactionExtras.binanceMemo?.memo?.let { txData = txData.copy(extras = BinanceTransactionExtras(it.toString())) }
- transactionExtras.xrpDestinationTag?.tag?.let {
- txData = txData.copy(extras = XrpTransactionBuilder.XrpTransactionExtras(it))
- }
+ transactionExtras.xrpDestinationTag?.tag?.let { txData = txData.copy(extras = XrpTransactionExtras(it)) }
transactionExtras.cosmosMemoState?.memo?.let { txData = txData.copy(extras = CosmosTransactionExtras(it)) }
transactionExtras.tonMemoState?.memo?.let { txData = txData.copy(extras = TonTransactionExtras(it)) }
@@ -250,17 +248,10 @@ private fun sendTransaction(
Analytics.send(
Basic.TransactionSent(
sentFrom = AnalyticsParam.TxSentFrom.Sell,
- memoType = if (txData.extras != null) MemoType.Full else MemoType.Empty,
- ),
- )
- Analytics.send(
- Token.Send.SelectedCurrency(
- currency = when (mainCurrencyType) {
- MainCurrencyType.FIAT -> CurrencyType.AppCurrency
- MainCurrencyType.CRYPTO -> CurrencyType.AppCurrency
- },
+ memoType = getMemoType(transactionExtras),
),
)
+ Analytics.sendSelectedCurrencyEvent(mainCurrencyType)
dispatch(WalletAction.TradeCryptoAction.FinishSelling(externalTransactionData.transactionId))
} else {
Analytics.send(
@@ -270,9 +261,10 @@ private fun sendTransaction(
token = amountToSend.currencySymbol,
feeType = feeType.convertToAnalyticsFeeType(),
),
- memoType = if (txData.extras != null) MemoType.Full else MemoType.Empty,
+ memoType = getMemoType(transactionExtras),
),
)
+ Analytics.sendSelectedCurrencyEvent(mainCurrencyType)
dispatch(NavigationAction.PopBackTo())
}
scope.launch(Dispatchers.IO) {
@@ -336,6 +328,25 @@ private fun sendTransaction(
}
}
+private fun getMemoType(transactionExtras: TransactionExtrasState): MemoType {
+ return when {
+ transactionExtras.isEmpty() -> MemoType.Empty
+ transactionExtras.isNull() -> MemoType.Null
+ else -> MemoType.Full
+ }
+}
+
+private fun Analytics.sendSelectedCurrencyEvent(mainCurrencyType: MainCurrencyType) {
+ send(
+ Token.Send.SelectedCurrency(
+ currency = when (mainCurrencyType) {
+ MainCurrencyType.FIAT -> CurrencyType.AppCurrency
+ MainCurrencyType.CRYPTO -> CurrencyType.Token
+ },
+ ),
+ )
+}
+
private fun updateFeedbackManagerInfo(
walletManager: WalletManager,
amountToSend: Amount,
diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt
index b1e3261e67..9f0851e06d 100644
--- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt
@@ -34,6 +34,21 @@ data class TransactionExtrasState(
val cosmosMemoState: CosmosMemoState? = null,
) : IdStateHolder {
override val stateId: StateId = StateId.TRANSACTION_EXTRAS
+
+ fun isNull(): Boolean {
+ return xlmMemo == null && binanceMemo == null && xrpDestinationTag == null && tonMemoState == null &&
+ cosmosMemoState == null
+ }
+
+ fun isEmpty(): Boolean {
+ val isXlmEmpty = xlmMemo?.viewFieldValue?.value?.isEmpty() ?: false
+ val isBinanceEmpty = binanceMemo?.viewFieldValue?.value?.isEmpty() ?: false
+ val isXrpEmpty = xrpDestinationTag?.viewFieldValue?.value?.isEmpty() ?: false
+ val isTonEmpty = tonMemoState?.viewFieldValue?.value?.isEmpty() ?: false
+ val isCosmosEmpty = cosmosMemoState?.viewFieldValue?.value?.isEmpty() ?: false
+
+ return isXlmEmpty || isBinanceEmpty || isXrpEmpty || isTonEmpty || isCosmosEmpty
+ }
}
enum class XlmMemoType {
@@ -105,6 +120,7 @@ data class TonMemoState(
val memo: String? = null,
val error: TransactionExtraError? = null,
)
+
data class CosmosMemoState(
val viewFieldValue: InputViewValue = InputViewValue(""),
val memo: String? = null,
diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/EditTextCustomPaste.kt b/app/src/main/java/com/tangem/tap/features/send/ui/EditTextCustomPaste.kt
index d3b563025d..d93147b24b 100644
--- a/app/src/main/java/com/tangem/tap/features/send/ui/EditTextCustomPaste.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/ui/EditTextCustomPaste.kt
@@ -5,14 +5,16 @@ import android.content.Context
import android.util.AttributeSet
import com.google.android.material.textfield.TextInputEditText
-class EditTextCustomPaste @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0,
-) : TextInputEditText(context, attrs, defStyleAttr) {
+class EditTextCustomPaste : TextInputEditText {
private var onSystemPasteButtonClickListener: (() -> Unit)? = null
+ constructor(context: Context) : super(context)
+
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
fun setOnSystemPasteButtonClickListener(callback: () -> Unit) {
onSystemPasteButtonClickListener = callback
}
diff --git a/app/src/main/java/com/tangem/tap/features/shop/data/DefaultShopRepository.kt b/app/src/main/java/com/tangem/tap/features/shop/data/DefaultShopRepository.kt
new file mode 100644
index 0000000000..74505b69d3
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/shop/data/DefaultShopRepository.kt
@@ -0,0 +1,37 @@
+package com.tangem.tap.features.shop.data
+
+import com.tangem.datasource.api.tangemTech.TangemTechApi
+import com.tangem.datasource.api.tangemTech.models.ShopResponse
+import com.tangem.tap.features.shop.domain.ShopRepository
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import com.tangem.utils.coroutines.runCatching
+import timber.log.Timber
+
+/**
+ * Default implementation of shop feature repository
+ *
+ * @property tangemTechApi TangemTech API
+ * @property dispatchers coroutine dispatchers provider
+ *
+[REDACTED_AUTHOR]
+ */
+internal class DefaultShopRepository(
+ private val tangemTechApi: TangemTechApi,
+ private val dispatchers: CoroutineDispatcherProvider,
+) : ShopRepository {
+
+ override suspend fun isShopifyOrderingAvailable(): Boolean {
+ return runCatching(dispatchers.io) { tangemTechApi.getShopInfo(name = SHOPIFY_NAME) }
+ .fold(
+ onSuccess = ShopResponse::isOrderingAvailable,
+ onFailure = {
+ Timber.e("Server error. isShopifyOrderingAvailable returns default value (true)")
+ true
+ },
+ )
+ }
+
+ private companion object {
+ const val SHOPIFY_NAME = "shopify"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/shop/di/ShopUseCaseModule.kt b/app/src/main/java/com/tangem/tap/features/shop/di/ShopUseCaseModule.kt
new file mode 100644
index 0000000000..2c00aa1181
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/shop/di/ShopUseCaseModule.kt
@@ -0,0 +1,28 @@
+package com.tangem.tap.features.shop.di
+
+import com.tangem.datasource.api.tangemTech.TangemTechApi
+import com.tangem.tap.features.shop.data.DefaultShopRepository
+import com.tangem.tap.features.shop.domain.DefaultShopifyOrderingAvailabilityUseCase
+import com.tangem.tap.features.shop.domain.ShopifyOrderingAvailabilityUseCase
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ViewModelComponent
+import dagger.hilt.android.scopes.ViewModelScoped
+
+@Module
+@InstallIn(ViewModelComponent::class)
+internal object ShopUseCaseModule {
+
+ @Provides
+ @ViewModelScoped
+ fun provideShopifyOrderingAvailabilityUseCase(
+ tangemTechApi: TangemTechApi,
+ dispatchers: CoroutineDispatcherProvider,
+ ): ShopifyOrderingAvailabilityUseCase {
+ return DefaultShopifyOrderingAvailabilityUseCase(
+ shopRepository = DefaultShopRepository(tangemTechApi, dispatchers),
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/shop/domain/DefaultShopifyOrderingAvailabilityUseCase.kt b/app/src/main/java/com/tangem/tap/features/shop/domain/DefaultShopifyOrderingAvailabilityUseCase.kt
new file mode 100644
index 0000000000..41bbe3d449
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/shop/domain/DefaultShopifyOrderingAvailabilityUseCase.kt
@@ -0,0 +1,15 @@
+package com.tangem.tap.features.shop.domain
+
+/**
+ * Default implementation of use case to define shopify ordering availability
+ *
+ * @property shopRepository shop feature repository
+ *
+[REDACTED_AUTHOR]
+ */
+internal class DefaultShopifyOrderingAvailabilityUseCase(
+ private val shopRepository: ShopRepository,
+) : ShopifyOrderingAvailabilityUseCase {
+
+ override suspend fun invoke() = shopRepository.isShopifyOrderingAvailable()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/shop/domain/ShopRepository.kt b/app/src/main/java/com/tangem/tap/features/shop/domain/ShopRepository.kt
new file mode 100644
index 0000000000..c8cd6f3780
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/shop/domain/ShopRepository.kt
@@ -0,0 +1,12 @@
+package com.tangem.tap.features.shop.domain
+
+/**
+ * Shop feature repository
+ *
+[REDACTED_AUTHOR]
+ */
+internal interface ShopRepository {
+
+ /** Get shopify ordering availability */
+ suspend fun isShopifyOrderingAvailable(): Boolean
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/shop/domain/ShopifyOrderingAvailabilityUseCase.kt b/app/src/main/java/com/tangem/tap/features/shop/domain/ShopifyOrderingAvailabilityUseCase.kt
new file mode 100644
index 0000000000..5f6c351ce2
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/shop/domain/ShopifyOrderingAvailabilityUseCase.kt
@@ -0,0 +1,12 @@
+package com.tangem.tap.features.shop.domain
+
+/**
+ * Use case to define shopify ordering availability
+ *
+[REDACTED_AUTHOR]
+ */
+internal interface ShopifyOrderingAvailabilityUseCase {
+
+ /** Get availability */
+ suspend operator fun invoke(): Boolean
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/shop/presentation/ShopViewModel.kt b/app/src/main/java/com/tangem/tap/features/shop/presentation/ShopViewModel.kt
new file mode 100644
index 0000000000..34966466cc
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/shop/presentation/ShopViewModel.kt
@@ -0,0 +1,39 @@
+package com.tangem.tap.features.shop.presentation
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.tangem.tap.features.shop.domain.ShopifyOrderingAvailabilityUseCase
+import com.tangem.tap.features.shop.redux.ShopAction
+import com.tangem.tap.proxy.AppStateHolder
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import com.tangem.utils.coroutines.runCatching
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+/**
+ * Shop screen view model
+ *
+ * @property shopifyOrderingAvailabilityUseCase use case to define shopify ordering availability
+ * @property dispatchers coroutine dispatchers provider
+ * @property appStateHolder redux state holder
+ *
+[REDACTED_AUTHOR]
+ */
+@HiltViewModel
+internal class ShopViewModel @Inject constructor(
+ private val shopifyOrderingAvailabilityUseCase: ShopifyOrderingAvailabilityUseCase,
+ private val dispatchers: CoroutineDispatcherProvider,
+ private val appStateHolder: AppStateHolder,
+) : ViewModel() {
+
+ /** Check ordering delay block visibility */
+ fun checkOrderingDelayBlockVisibility() {
+ viewModelScope.launch(dispatchers.main) {
+ val visibility = runCatching(dispatchers.io) { shopifyOrderingAvailabilityUseCase() }
+ .fold(onSuccess = { !it }, onFailure = { false })
+
+ appStateHolder.mainStore?.dispatch(action = ShopAction.SetOrderingDelayBlockVisibility(visibility))
+ }
+ }
+}
\ No newline at end of file
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 219753c469..54c6bcad43 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
@@ -8,38 +8,40 @@ import com.tangem.tap.common.shop.googlepay.GooglePayService
import com.tangem.wallet.R
import org.rekotlin.Action
-sealed class ShopAction : Action {
+sealed interface ShopAction : Action {
- object LoadProducts : ShopAction() {
- data class Success(val products: List) : ShopAction()
- object Failure : ShopAction(), NotificationAction {
+ 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() {
- data class Success(val promoCode: String?, val products: List) : ShopAction()
- object InvalidPromoCode : ShopAction()
+ data class ApplyPromoCode(val promoCode: String) : ShopAction {
+ data class Success(val promoCode: String?, val products: List) : ShopAction
+ object InvalidPromoCode : ShopAction
}
- object BuyWithGooglePay : ShopAction() {
- object UserCancelled : ShopAction()
- data class HandleGooglePayResponse(val resultCode: Int, val data: Intent?) : ShopAction()
+ object BuyWithGooglePay : ShopAction {
+ object UserCancelled : ShopAction
+ data class HandleGooglePayResponse(val resultCode: Int, val data: Intent?) : ShopAction
- data class Failure(val exception: Throwable) : ShopAction()
- object Success : ShopAction()
+ data class Failure(val exception: Throwable) : ShopAction
+ object Success : ShopAction
}
- object StartWebCheckout : ShopAction()
+ object StartWebCheckout : ShopAction
- data class CheckIfGooglePayAvailable(val googlePayService: GooglePayService) : ShopAction() {
- object Success : ShopAction()
- object Failure : ShopAction()
+ data class CheckIfGooglePayAvailable(val googlePayService: GooglePayService) : ShopAction {
+ object Success : ShopAction
+ object Failure : ShopAction
}
- data class SelectProduct(val productType: ProductType) : ShopAction()
+ data class SelectProduct(val productType: ProductType) : ShopAction
- object FinishSuccessfulOrder : ShopAction()
+ object FinishSuccessfulOrder : ShopAction
- object ResetState : ShopAction()
+ object ResetState : ShopAction
+
+ data class SetOrderingDelayBlockVisibility(val visibility: Boolean) : ShopAction
}
\ No newline at end of file
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 8a97a1a58c..60cb0667ad 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
@@ -6,63 +6,38 @@ object ShopReducer {
fun reduce(action: Action, state: ShopState): ShopState = internalReduce(action, state)
}
-@Suppress("ComplexMethod")
private fun internalReduce(action: Action, state: ShopState): ShopState {
if (action !is ShopAction) return state
return when (action) {
- is ShopAction.ApplyPromoCode -> state.copy(
- promoCode = action.promoCode,
- promoCodeLoading = true,
- )
- ShopAction.BuyWithGooglePay -> state
- ShopAction.LoadProducts -> state
- is ShopAction.LoadProducts.Success -> {
- state.copy(
- availableProducts = action.products,
- )
- }
- ShopAction.StartWebCheckout -> state
- ShopAction.ApplyPromoCode.InvalidPromoCode -> state.copy(
- promoCode = null,
- promoCodeLoading = false,
- )
+ is ShopAction.ApplyPromoCode -> state.copy(promoCode = action.promoCode, promoCodeLoading = true)
+ is ShopAction.LoadProducts.Success -> state.copy(availableProducts = action.products)
+ is ShopAction.ApplyPromoCode.InvalidPromoCode -> state.copy(promoCode = null, promoCodeLoading = false)
is ShopAction.ApplyPromoCode.Success -> {
state.copy(
promoCode = action.promoCode,
availableProducts = action.products,
promoCodeLoading = false,
+ )
+ }
+ is ShopAction.SelectProduct -> state.copy(selectedProduct = action.productType)
- )
- }
- is ShopAction.SelectProduct -> {
- state.copy(
- selectedProduct = action.productType,
- )
- }
- is ShopAction.CheckIfGooglePayAvailable -> {
- state
- }
- ShopAction.CheckIfGooglePayAvailable.Failure -> {
- state.copy(isGooglePayAvailable = false)
- }
- ShopAction.CheckIfGooglePayAvailable.Success -> {
- state.copy(isGooglePayAvailable = false) // TODO: change when we add support for GPay
- }
- is ShopAction.BuyWithGooglePay.Failure -> {
- state
- }
- is ShopAction.BuyWithGooglePay.HandleGooglePayResponse -> {
- state
- }
- ShopAction.BuyWithGooglePay.Success -> {
- state
- }
- ShopAction.BuyWithGooglePay.UserCancelled -> {
- state
- }
- ShopAction.FinishSuccessfulOrder -> state
- ShopAction.ResetState -> ShopState()
- ShopAction.LoadProducts.Failure -> state
+ // TODO: change when we add support for GPay
+ is ShopAction.CheckIfGooglePayAvailable.Failure -> state.copy(isGooglePayAvailable = false)
+ is ShopAction.CheckIfGooglePayAvailable.Success -> state.copy(isGooglePayAvailable = false)
+
+ is ShopAction.ResetState -> ShopState()
+ is ShopAction.SetOrderingDelayBlockVisibility -> state.copy(isOrderingDelayBlockVisible = action.visibility)
+ is ShopAction.BuyWithGooglePay,
+ is ShopAction.LoadProducts,
+ is ShopAction.StartWebCheckout,
+ is ShopAction.CheckIfGooglePayAvailable,
+ is ShopAction.BuyWithGooglePay.Failure,
+ is ShopAction.BuyWithGooglePay.HandleGooglePayResponse,
+ is ShopAction.BuyWithGooglePay.Success,
+ is ShopAction.BuyWithGooglePay.UserCancelled,
+ is ShopAction.FinishSuccessfulOrder,
+ is ShopAction.LoadProducts.Failure,
+ -> state
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopState.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopState.kt
index ebbbb7cb79..491e961e58 100644
--- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopState.kt
+++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopState.kt
@@ -10,6 +10,7 @@ data class ShopState(
val promoCode: String? = null,
val promoCodeLoading: Boolean = false,
val isGooglePayAvailable: Boolean = false, // TODO: change when we add support for GPay
+ val isOrderingDelayBlockVisible: Boolean = false,
) : StateType {
val total: String?
get() = availableProducts.firstOrNull { it.type == selectedProduct }?.totalSum?.finalValue
diff --git a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt
index dccbe4d7b7..56ffe54b0f 100644
--- a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt
@@ -9,28 +9,35 @@ import android.view.View.OnFocusChangeListener
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import androidx.activity.OnBackPressedCallback
+import androidx.fragment.app.viewModels
import by.kirich1409.viewbindingdelegate.viewBinding
import com.tangem.tap.common.GlobalLayoutStateHandler
import com.tangem.tap.common.KeyboardObserver
import com.tangem.tap.common.extensions.getQuantityString
+import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.common.shop.data.ProductType
import com.tangem.tap.features.BaseStoreFragment
+import com.tangem.tap.features.shop.presentation.ShopViewModel
import com.tangem.tap.features.shop.redux.ShopAction
import com.tangem.tap.features.shop.redux.ShopState
import com.tangem.tap.store
import com.tangem.wallet.R
import com.tangem.wallet.databinding.FragmentShopBinding
+import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
-class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber {
+@AndroidEntryPoint
+internal class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber {
private val binding: FragmentShopBinding by viewBinding(FragmentShopBinding::bind)
private var cardTranslationY = 70f
private lateinit var keyboardObserver: KeyboardObserver
+ private val viewModel by viewModels()
+
override fun subscribeToStore() {
store.subscribe(this) { state ->
state.skipRepeats { oldState, newState ->
@@ -43,6 +50,8 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber<
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ viewModel.checkOrderingDelayBlockVisibility()
+
activity?.onBackPressedDispatcher?.addCallback(
this,
object : OnBackPressedCallback(true) {
@@ -133,6 +142,7 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber<
animateProductSelection(state.selectedProduct)
handlePriceState(state)
handlePromoCodeState(state)
+ handleOrderingDelayBlock(isVisible = state.isOrderingDelayBlockVisible)
handleButtonsState(state)
}
@@ -173,6 +183,10 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber<
pbPromoCode.show(state.promoCodeLoading)
}
+ private fun handleOrderingDelayBlock(isVisible: Boolean) {
+ if (isVisible) binding.tvSoldOutDesc.show() else binding.tvSoldOutDesc.hide()
+ }
+
private fun handleButtonsState(state: ShopState) = with(binding) {
btnPayGooglePay.root.show(state.isGooglePayAvailable)
btnAlternativePayment.show(state.isGooglePayAvailable)
diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt
index e5ac57cfc8..8af509f84f 100644
--- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/TokensListFragment.kt
@@ -4,9 +4,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalLifecycleOwner
-import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.transition.TransitionInflater
@@ -25,8 +26,6 @@ import dagger.hilt.android.AndroidEntryPoint
internal class TokensListFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
-
with(TransitionInflater.from(requireContext())) {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
@@ -41,7 +40,10 @@ internal class TokensListFragment : Fragment() {
}
TangemTheme {
- TokensListScreen(stateHolder = viewModel.uiState)
+ TokensListScreen(
+ modifier = Modifier.systemBarsPadding(),
+ stateHolder = viewModel.uiState,
+ )
}
}
}
diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt
index d378d6ba75..44e620b8ac 100644
--- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt
+++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/ui/TokensListScreen.kt
@@ -56,12 +56,13 @@ import kotlinx.coroutines.flow.flowOf
[REDACTED_AUTHOR]
*/
@Composable
-internal fun TokensListScreen(stateHolder: TokensListStateHolder) {
+internal fun TokensListScreen(stateHolder: TokensListStateHolder, modifier: Modifier = Modifier) {
BackHandler(onBack = stateHolder.toolbarState.onBackButtonClick)
var floatingButtonHeight by remember { mutableStateOf(value = 0.dp) }
Scaffold(
+ modifier = modifier,
topBar = { TokensListToolbar(state = stateHolder.toolbarState) },
floatingActionButton = {
if (stateHolder is TokensListStateHolder.ManageContent) {
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 607d8c63c4..d86a41c389 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
@@ -9,7 +9,7 @@ import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken
import com.tangem.tap.common.extensions.addContext
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchErrorNotification
-import com.tangem.tap.common.extensions.dispatchOnMain
+import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
@@ -114,7 +114,8 @@ class MultiWalletMiddleware {
)
}
.doOnSuccess { updatedUserWallet ->
- store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(emptyList()))
+ store.dispatchWithMain(WalletAction.MultiWallet.AddMissingDerivations(emptyList()))
+ store.dispatchWithMain(GlobalAction.SaveScanResponse(updatedUserWallet.scanResponse))
store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true)
}
}
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 c7bde94141..d7a0da7703 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
@@ -17,6 +17,7 @@ import com.tangem.tap.common.analytics.events.MainScreen
import com.tangem.tap.common.analytics.events.Token
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
+import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.domain.TapError
@@ -97,12 +98,12 @@ class WalletMiddleware {
Timber.e("Unable to create wallet, no user wallet selected")
return@launch
}
+ val updatedScanResponse = selectedUserWallet.scanResponse.copy(
+ card = result.data,
+ )
+ store.dispatchWithMain(GlobalAction.SaveScanResponse(updatedScanResponse))
userWalletsListManager.update(selectedUserWallet.walletId) { userWallet ->
- userWallet.copy(
- scanResponse = userWallet.scanResponse.copy(
- card = result.data,
- ),
- )
+ userWallet.copy(scanResponse = updatedScanResponse)
}
}
is CompletionResult.Failure -> Unit
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt
index 3f72a34acb..f2d65a4fcf 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt
@@ -98,7 +98,7 @@ internal fun WalletDataModel.getAvailableActions(
internal fun WalletDataModel.shouldShowMultipleAddress(): Boolean {
val listOfAddresses = walletAddresses?.list.orEmpty()
- return listOfAddresses.size > 1
+ return listOfAddresses.size > 1 && currency.blockchain != Blockchain.BitcoinCash
}
internal fun WalletDataModel.assembleWarnings(
diff --git a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt
index aab3cfd808..35c2d83718 100644
--- a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt
+++ b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt
@@ -19,6 +19,7 @@ import javax.inject.Inject
*/
class AppStateHolder @Inject constructor() {
+ @Deprecated("Use scan response from selected user wallet")
var scanResponse: ScanResponse? = null
var walletState: WalletState? = null
var userTokensRepository: UserTokensRepository? = null
diff --git a/app/src/main/res/layout/fragment_shop.xml b/app/src/main/res/layout/fragment_shop.xml
index 523b68c535..0a61bf5b4a 100644
--- a/app/src/main/res/layout/fragment_shop.xml
+++ b/app/src/main/res/layout/fragment_shop.xml
@@ -271,7 +271,7 @@
android:layout_marginTop="14dp"
android:background="@drawable/shape_rectangle_rounded_4"
android:padding="16dp"
- android:text="@string/shop_sold_out_description_prefix"
+ android:text="@string/shop_sold_out_description"
android:textColor="@color/text_tertiary"
android:textSize="16sp" />
diff --git a/app/src/main/res/values-v24/bool.xml b/app/src/main/res/values-v24/bool.xml
new file mode 100644
index 0000000000..093ecf3bc6
--- /dev/null
+++ b/app/src/main/res/values-v24/bool.xml
@@ -0,0 +1,5 @@
+
+
+ false
+
+
diff --git a/app/src/main/res/values/bool.xml b/app/src/main/res/values/bool.xml
new file mode 100644
index 0000000000..d5677354f0
--- /dev/null
+++ b/app/src/main/res/values/bool.xml
@@ -0,0 +1,5 @@
+
+
+ true
+
+
diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt
index 4125f7ed48..992f6d0eb5 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt
@@ -51,4 +51,7 @@ interface TangemTechApi {
@Header("card_id") cardId: String,
@Body startReferralBody: StartReferralBody,
): ReferralResponse
+
+ @GET("shops")
+ suspend fun getShopInfo(@Query(value = "name") name: String): ShopResponse
}
\ No newline at end of file
diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/ShopResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/ShopResponse.kt
new file mode 100644
index 0000000000..6331011641
--- /dev/null
+++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/ShopResponse.kt
@@ -0,0 +1,14 @@
+package com.tangem.datasource.api.tangemTech.models
+
+import com.squareup.moshi.Json
+
+/**
+ * Shop response
+ *
+ * @property isOrderingAvailable ordering availability
+ *
+[REDACTED_AUTHOR]
+ */
+data class ShopResponse(
+ @Json(name = "canOrder") val isOrderingAvailable: Boolean,
+)
\ No newline at end of file
diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json
index 174175e4e6..b0b9550686 100644
--- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json
+++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json
@@ -9,7 +9,7 @@
},
{
"name": "NEW_CARD_SCANNING_ENABLED",
- "version": "4.7.0"
+ "version": "4.8.0"
},
{
"name": "REDESIGNED_WALLET_SCREEN_ENABLED",
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 8730764f58..6b0879d8e1 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -343,7 +343,7 @@
У меня есть промо-код…
Tangem Wallet
Другие способы оплаты
- Из-за большого количества заказов, которые мы получаем, cроки доставки могут быть увеличены.
+ Из-за высокого количества заказов, которые мы получаем, доставка может быть задержана на срок до 5 недель в зависимости от вашего местоположения
Итого
Сеть Solana взимает арендную плату в размере %1$s каждые 2 дня. Аккаунты, которые не могут позволить себе арендную плату, удаляются из сети. Пополните свой счет более чем на %2$s, чтобы не платить арендную плату.
Держите свои криптосбережения в безопасности. Приватные ключи надежно хранятся на карте.
@@ -463,6 +463,7 @@
Невозможно отправить транзакцию. Недостаточно средств.
Не удалось установить сессию WalletConnect. Пожалуйста, повторите попытку позже.
Не удалось установить сессию WalletConnect за отведённое время. Пожалуйста, повторите попытку позже.
+ Запрос на подключение через WalletConnect содержит неподдерживаемые блокчеины. Неподдерживаемые блокчеины:\n
Cоединение с этим Dapp сервисом не может быть установлено из-за его технической реализации.
Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново.
Вставить из буфера обмена
diff --git a/core/res/src/main/res/values-zh-rTW/strings.xml b/core/res/src/main/res/values-zh-rTW/strings.xml
index f9ce322037..ab1801d759 100644
--- a/core/res/src/main/res/values-zh-rTW/strings.xml
+++ b/core/res/src/main/res/values-zh-rTW/strings.xml
@@ -436,6 +436,7 @@
無法交易,無足夠資金
未能建立 WalletConnect 連接。請稍後再試
無法建立 WalletConnect 連接:超時錯誤。請稍後再試
+ 會話請求包含不支持 WalletConnect 連接的區塊鏈。不支持的區塊鏈:
由於技術問題,無法與此 Dapp 建立連接
沒有 %s 網路,請先加入後再試一次
從剪貼板貼上
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 0c933df75f..405c31d86a 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -339,7 +339,7 @@
I have a promo code…
Tangem Wallet
Other payment methods
- Due to the high volume of orders we are receiving, Shipping and Local Delivery orders may be delayed.
+ Due to the high volume of orders we are receiving shipping may be delayed up to 5 weeks depending on your location
Total
Solana network charges a rent of %1$s every 2 days. Accounts that can\'t afford the rent are purged from the network. Deposit your account with more than %2$s to use it for free.
Store your crypto assets secure while keeping private keys contained in your card
@@ -455,6 +455,7 @@
Can\'t send transaction. Not enough funds.
Failed to establish WalletConnect session. Please, try again later.
Failed to establish WalletConnect session: timeout error. Please, try again later.
+ Session request contains unsupported blockchains for WalletConnect connection. Unsupported blockchains:\n
Connection with this Dapp cannot be established due to its technical implementation.
%s network not found. Please, add it first and try again.
Paste from clipboard
diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt
index 151aecafc4..c891e19e44 100644
--- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt
+++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt
@@ -173,5 +173,6 @@ fun Blockchain.isSupportedInApp(): Boolean {
}
private val excludedBlockchains = listOf(
+ Blockchain.Ducatus,
Blockchain.Unknown,
)
\ No newline at end of file
diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt
index 938566bd50..b04b901b66 100644
--- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt
+++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt
@@ -4,11 +4,13 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
-import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.transition.TransitionInflater
+import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.referral.presentation.R
import com.tangem.feature.referral.router.ReferralRouter
import com.tangem.feature.referral.ui.ReferralScreen
@@ -28,13 +30,17 @@ class ReferralFragment : Fragment() {
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
viewModel.setRouter(ReferralRouter(fragmentManager = WeakReference(parentFragmentManager)))
viewModel.onScreenOpened()
return ComposeView(inflater.context).apply {
isTransitionGroup = true
setContent {
- ReferralScreen(stateHolder = viewModel.uiState)
+ TangemTheme {
+ ReferralScreen(
+ modifier = Modifier.systemBarsPadding(),
+ stateHolder = viewModel.uiState,
+ )
+ }
}
}
}
diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt
index 7f1ff6b6a8..7c3e8b2ddf 100644
--- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt
+++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt
@@ -5,41 +5,11 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.BottomSheetScaffold
-import androidx.compose.material.BottomSheetState
-import androidx.compose.material.BottomSheetValue
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material.Icon
-import androidx.compose.material.Snackbar
-import androidx.compose.material.SnackbarDuration
-import androidx.compose.material.SnackbarHost
-import androidx.compose.material.SnackbarHostState
-import androidx.compose.material.SnackbarResult
-import androidx.compose.material.Text
-import androidx.compose.material.rememberBottomSheetScaffoldState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.SideEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
+import androidx.compose.material.*
+import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -63,9 +33,7 @@ import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.referral.models.DemoModeException
import com.tangem.feature.referral.models.ReferralStateHolder
-import com.tangem.feature.referral.models.ReferralStateHolder.ErrorSnackbar
-import com.tangem.feature.referral.models.ReferralStateHolder.ReferralInfoContentState
-import com.tangem.feature.referral.models.ReferralStateHolder.ReferralInfoState
+import com.tangem.feature.referral.models.ReferralStateHolder.*
import com.tangem.feature.referral.presentation.R
import com.valentinilk.shimmer.shimmer
import kotlinx.coroutines.launch
@@ -77,47 +45,46 @@ import kotlinx.coroutines.launch
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
-internal fun ReferralScreen(stateHolder: ReferralStateHolder) {
+internal fun ReferralScreen(stateHolder: ReferralStateHolder, modifier: Modifier = Modifier) {
val coroutineScope = rememberCoroutineScope()
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed),
)
- TangemTheme {
- BottomSheetScaffold(
- sheetContent = {
- AgreementBottomSheetContent(
- url = when (val state = stateHolder.referralInfoState) {
- is ReferralInfoState.NonParticipantContent -> state.url
- is ReferralInfoState.ParticipantContent -> state.url
- is ReferralInfoState.Loading -> ""
- },
- )
- },
- scaffoldState = bottomSheetScaffoldState,
- sheetShape = RoundedCornerShape(
- topStart = TangemTheme.dimens.radius16,
- topEnd = TangemTheme.dimens.radius16,
- ),
- sheetElevation = TangemTheme.dimens.elevation24,
- sheetPeekHeight = TangemTheme.dimens.size0,
- content = {
- ReferralContent(
- stateHolder = stateHolder,
- onAgreementClick = {
- stateHolder.analytics.onAgreementClicked.invoke()
- coroutineScope.launch {
- if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {
- bottomSheetScaffoldState.bottomSheetState.expand()
- } else {
- bottomSheetScaffoldState.bottomSheetState.collapse()
- }
+ BottomSheetScaffold(
+ modifier = modifier,
+ sheetContent = {
+ AgreementBottomSheetContent(
+ url = when (val state = stateHolder.referralInfoState) {
+ is ReferralInfoState.NonParticipantContent -> state.url
+ is ReferralInfoState.ParticipantContent -> state.url
+ is ReferralInfoState.Loading -> ""
+ },
+ )
+ },
+ scaffoldState = bottomSheetScaffoldState,
+ sheetShape = RoundedCornerShape(
+ topStart = TangemTheme.dimens.radius16,
+ topEnd = TangemTheme.dimens.radius16,
+ ),
+ sheetElevation = TangemTheme.dimens.elevation24,
+ sheetPeekHeight = TangemTheme.dimens.size0,
+ content = {
+ ReferralContent(
+ stateHolder = stateHolder,
+ onAgreementClick = {
+ stateHolder.analytics.onAgreementClicked.invoke()
+ coroutineScope.launch {
+ if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {
+ bottomSheetScaffoldState.bottomSheetState.expand()
+ } else {
+ bottomSheetScaffoldState.bottomSheetState.collapse()
}
- },
- )
- },
- )
- }
+ }
+ },
+ )
+ },
+ )
}
@OptIn(ExperimentalFoundationApi::class)
@@ -487,7 +454,7 @@ private fun Preview_ReferralScreen_Participant_InLightTheme() {
TangemTheme(isDark = false) {
ReferralScreen(
stateHolder = ReferralStateHolder(
- headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
+ headerState = HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.ParticipantContent(
award = "10 USDT",
networkName = "Tron",
@@ -499,7 +466,7 @@ private fun Preview_ReferralScreen_Participant_InLightTheme() {
url = "",
),
errorSnackbar = null,
- analytics = ReferralStateHolder.Analytics(
+ analytics = Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
@@ -515,7 +482,7 @@ private fun Preview_ReferralScreen_Participant_InDarkTheme() {
TangemTheme(isDark = true) {
ReferralScreen(
stateHolder = ReferralStateHolder(
- headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
+ headerState = HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.ParticipantContent(
award = "10 USDT",
networkName = "Tron",
@@ -527,7 +494,7 @@ private fun Preview_ReferralScreen_Participant_InDarkTheme() {
url = "",
),
errorSnackbar = null,
- analytics = ReferralStateHolder.Analytics(
+ analytics = Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
@@ -543,7 +510,7 @@ private fun Preview_ReferralScreen_NonParticipant_InLightTheme() {
TangemTheme(isDark = false) {
ReferralScreen(
stateHolder = ReferralStateHolder(
- headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
+ headerState = HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.NonParticipantContent(
award = "10 USDT",
networkName = "Tron",
@@ -552,7 +519,7 @@ private fun Preview_ReferralScreen_NonParticipant_InLightTheme() {
onParticipateClicked = {},
),
errorSnackbar = null,
- analytics = ReferralStateHolder.Analytics(
+ analytics = Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
@@ -568,7 +535,7 @@ private fun Preview_ReferralScreen_NonParticipant_InDarkTheme() {
TangemTheme(isDark = true) {
ReferralScreen(
stateHolder = ReferralStateHolder(
- headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
+ headerState = HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.NonParticipantContent(
award = "10 USDT",
networkName = "Tron",
@@ -577,7 +544,7 @@ private fun Preview_ReferralScreen_NonParticipant_InDarkTheme() {
onParticipateClicked = {},
),
errorSnackbar = null,
- analytics = ReferralStateHolder.Analytics(
+ analytics = Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
@@ -593,10 +560,10 @@ private fun Preview_ReferralScreen_Loading_InLightTheme() {
TangemTheme(isDark = false) {
ReferralScreen(
stateHolder = ReferralStateHolder(
- headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
+ headerState = HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.Loading,
errorSnackbar = null,
- analytics = ReferralStateHolder.Analytics(
+ analytics = Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
@@ -612,10 +579,10 @@ private fun Preview_ReferralScreen_Loading_InDarkTheme() {
TangemTheme(isDark = true) {
ReferralScreen(
stateHolder = ReferralStateHolder(
- headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
+ headerState = HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.Loading,
errorSnackbar = null,
- analytics = ReferralStateHolder.Analytics(
+ analytics = Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt
index d62c79855f..954467d0fe 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt
@@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
-import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
@@ -34,8 +33,6 @@ internal class WalletFragment : Fragment() {
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
-
with(TransitionInflater.from(requireContext())) {
enterTransition = inflateTransition(R.transition.slide_right)
exitTransition = inflateTransition(R.transition.fade)
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt
index ac4d146213..fb6be5831b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt
@@ -34,10 +34,11 @@ import com.tangem.feature.wallet.presentation.common.component.DraggableNetworkG
import com.tangem.feature.wallet.presentation.common.component.DraggableTokenItem
@Composable
-internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder) {
+internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Modifier = Modifier) {
val tokensListState = rememberLazyListState()
Scaffold(
+ modifier = modifier,
topBar = {
TopBar(state.header, tokensListState)
},
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
index b06a719e1f..b963f8f7b7 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
@@ -1,13 +1,16 @@
package com.tangem.feature.wallet.presentation.router
import androidx.activity.compose.BackHandler
+import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
import androidx.fragment.app.Fragment
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
+import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.WalletFragment
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensScreen
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensViewModel
@@ -24,22 +27,30 @@ internal class DefaultWalletRouter : InnerWalletRouter {
@Composable
override fun Initialize() {
- NavHost(
- navController = rememberNavController().apply { navController = this },
- startDestination = WalletScreens.WALLET.name,
- ) {
- composable(WalletScreens.WALLET.name) {
- val viewModel = hiltViewModel().apply { router = this@DefaultWalletRouter }
- WalletScreen(state = viewModel.uiState)
- }
+ TangemTheme {
+ NavHost(
+ navController = rememberNavController().apply { navController = this },
+ startDestination = WalletScreens.WALLET.name,
+ ) {
+ composable(WalletScreens.WALLET.name) {
+ val viewModel = hiltViewModel().apply { router = this@DefaultWalletRouter }
+ WalletScreen(
+ modifier = Modifier.systemBarsPadding(),
+ state = viewModel.uiState,
+ )
+ }
- composable(WalletScreens.ORGANIZE_TOKENS.name) {
- BackHandler(onBack = ::popBackStack)
+ composable(WalletScreens.ORGANIZE_TOKENS.name) {
+ BackHandler(onBack = ::popBackStack)
- val viewModel: OrganizeTokensViewModel = hiltViewModel()
- .apply { router = this@DefaultWalletRouter }
+ val viewModel: OrganizeTokensViewModel = hiltViewModel()
+ .apply { router = this@DefaultWalletRouter }
- OrganizeTokensScreen(state = viewModel.uiState)
+ OrganizeTokensScreen(
+ modifier = Modifier.systemBarsPadding(),
+ state = viewModel.uiState,
+ )
+ }
}
}
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt
index 701f730a14..4c569efd54 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt
@@ -36,7 +36,7 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletTopBar
[REDACTED_AUTHOR]
*/
@Composable
-internal fun WalletScreen(state: WalletStateHolder) {
+internal fun WalletScreen(state: WalletStateHolder, modifier: Modifier = Modifier) {
BackHandler(onBack = state.onBackClick)
Scaffold(
@@ -48,7 +48,7 @@ internal fun WalletScreen(state: WalletStateHolder) {
}
LazyColumn(
- modifier = Modifier
+ modifier = modifier
.padding(scaffoldPaddings)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml
index 8cfc0a564c..269eb8f262 100644
--- a/gradle/dependencies.toml
+++ b/gradle/dependencies.toml
@@ -77,7 +77,7 @@ walletConnectWeb3 = "1.8.0"
# endregion Other libraries
# region Tangem
-tangemBlockchainSdk = "develop-246"
+tangemBlockchainSdk = "develop-247"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-266"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds