From 2fcb0771e96e97d61276c484cc561c6f45c33492 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 9 Aug 2022 13:56:46 +0300 Subject: [PATCH 01/36] Updated on 2026-08-14 --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index ab3dab0c54..7097fccd86 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-100', + tangem_blockchain_sdk: 'develop-101', // tangem_blockchain_sdk: '0.0.1', ] @@ -10,4 +10,4 @@ ext.environmentConfig = [ environment : "ENVIRONMENT", testActionEnabled: "TEST_ACTION_ENABLED", logEnabled : "LOG_ENABLED", -] \ No newline at end of file +] From 53ccb3ae0a6c97421432fcb046fe3992f4fef82f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 9 Aug 2022 16:31:34 +0400 Subject: [PATCH 02/36] Updated on 2026-08-14 --- .../details/ui/walletconnect/WalletConnectScreen.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt index 086c2ae8b8..71a9386b36 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt @@ -52,11 +52,9 @@ fun WalletConnectScreen( } }, fab = { - AddSessionFab( - onAddSession = { - state.onAddSession(context.getFromClipboard()?.toString()) - }, - ) + if (!state.isLoading) { + AddSessionFab(onAddSession = { state.onAddSession(context.getFromClipboard()?.toString()) }) + } }, titleRes = R.string.wallet_connect_title, onBackClick = onBackPressed, From afda36ebbe5322050bfeb76d737ab3fc16754018 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 13:59:34 +0400 Subject: [PATCH 03/36] Updated on 2026-08-14 --- .../ui/common/DetailsComposeElements.kt | 58 +++++++++++++------ .../details/ui/details/DetailsScreen.kt | 48 +++++++-------- .../details/ui/resetcard/ResetCardScreen.kt | 36 +++++++++--- .../ui/securitymode/SecurityModeScreen.kt | 11 +++- 4 files changed, 96 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt b/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt index 4c5cd02e86..d8e6bf1b11 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/common/DetailsComposeElements.kt @@ -20,6 +20,7 @@ import androidx.compose.material.Text import androidx.compose.material.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -32,42 +33,61 @@ fun SettingsScreensScaffold( content: @Composable () -> Unit, background: @Composable (() -> Unit)? = null, fab: @Composable (() -> Unit)? = null, - titleRes: Int, + backgroundColor: Color = colorResource(id = R.color.background_primary), + titleRes: Int? = null, onBackClick: () -> Unit, modifier: Modifier = Modifier, ) { BackHandler(true, onBackClick) Scaffold( - topBar = { EmptyTopBarWithNavigation(onBackClick = onBackClick) }, + topBar = { + EmptyTopBarWithNavigation( + onBackClick = onBackClick, + backgroundColor = backgroundColor, + ) + }, modifier = modifier.systemBarsPadding(), - backgroundColor = colorResource(id = R.color.background_primary), + backgroundColor = backgroundColor, floatingActionButton = { fab?.invoke() }, ) { + if (titleRes != null) { + Box(modifier = modifier.fillMaxSize()) { + background?.invoke() - Box(modifier = modifier.fillMaxSize()) { - - background?.invoke() - - Column( - modifier = modifier.fillMaxWidth(), - ) { - Text( - text = stringResource(id = titleRes), - modifier = modifier.padding(start = 20.dp, end = 20.dp, bottom = 52.dp), - style = TangemTypography.headline1, - color = colorResource(id = R.color.text_primary_1), - ) - content() + Column(modifier = modifier.fillMaxWidth()) { + Text( + text = stringResource(id = titleRes), + modifier = modifier.padding(start = 20.dp, end = 20.dp, bottom = 52.dp), + style = TangemTypography.headline1, + color = colorResource(id = R.color.text_primary_1), + ) + content() + } } + } else { + content() } - } } +@Composable +fun ScreenTitle( + titleRes: Int, + modifier: Modifier = Modifier, +) { + Text( + text = stringResource(id = titleRes), + modifier = modifier.padding(start = 20.dp, end = 20.dp), + style = TangemTypography.headline1, + color = colorResource(id = R.color.text_primary_1), + ) +} + @Composable fun EmptyTopBarWithNavigation( onBackClick: () -> Unit, + backgroundColor: Color = colorResource(id = R.color.background_primary), modifier: Modifier = Modifier, ) { TopAppBar( @@ -81,7 +101,7 @@ fun EmptyTopBarWithNavigation( ) } }, - backgroundColor = colorResource(id = R.color.background_primary), + backgroundColor = backgroundColor, elevation = 0.dp, ) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt index 8d256d2c8b..24129ec514 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreen.kt @@ -10,9 +10,10 @@ 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.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -24,6 +25,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.tap.common.compose.TangemTypography +import com.tangem.tap.features.details.ui.common.ScreenTitle import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.wallet.R @@ -34,10 +36,7 @@ fun DetailsScreen( modifier: Modifier = Modifier, ) { SettingsScreensScaffold( - content = { - Content(state = state, modifier = modifier) - }, - titleRes = R.string.details_title, + content = { Content(state = state, modifier = modifier) }, onBackClick = onBackPressed, ) } @@ -50,37 +49,32 @@ fun Content( Column( modifier = modifier .fillMaxSize() - .padding(bottom = 40.dp), + .verticalScroll(rememberScrollState()), ) { - LazyColumn( - modifier = modifier - .fillMaxWidth() - .padding(bottom = 40.dp) - .weight(1f), - ) { - items(state.elements) { - if (it == SettingsElement.WalletConnect) { - WalletConnectDetailsItem( - onItemsClick = state.onItemsClick, - modifier = modifier, - ) - } else { - DetailsItem( - item = it, - appCurrency = state.appCurrency, - onItemsClick = state.onItemsClick, - modifier = modifier, - ) - } + ScreenTitle(titleRes = R.string.details_title, modifier.padding(bottom = 52.dp)) + state.elements.map { + if (it == SettingsElement.WalletConnect) { + WalletConnectDetailsItem( + onItemsClick = state.onItemsClick, + modifier = modifier, + ) + } else { + DetailsItem( + item = it, + appCurrency = state.appCurrency, + onItemsClick = state.onItemsClick, + modifier = modifier, + ) } } + Spacer(modifier = modifier.weight(1f)) TangemSocialAccounts(state.tangemLinks, state.onSocialNetworkClick) Spacer(modifier = Modifier.size(12.dp)) Text( text = "${stringResource(id = state.appNameRes)} ${state.tangemVersion}", style = TangemTypography.caption, color = colorResource(id = R.color.text_tertiary), - modifier = modifier.padding(start = 16.dp, end = 16.dp), + modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 40.dp), ) } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index 1b8fec5cdb..2c07b092ad 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -1,13 +1,16 @@ package com.tangem.tap.features.details.ui.resetcard import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.Icon @@ -15,6 +18,7 @@ import androidx.compose.material.IconToggleButton import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -22,6 +26,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.tap.common.compose.TangemTypography import com.tangem.tap.features.details.ui.common.DetailsMainButton +import com.tangem.tap.features.details.ui.common.ScreenTitle import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.wallet.R @@ -31,14 +36,18 @@ fun ResetCardScreen( onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - - SettingsScreensScaffold( - content = { ResetCardView(state = state, modifier = modifier) }, - background = - { Image(painter = painterResource(id = R.drawable.ic_reset_background), contentDescription = "") }, - titleRes = R.string.reset_card_to_factory_navigation_title, - onBackClick = onBackPressed, - ) + Box(modifier = modifier.background(colorResource(id = R.color.background_primary))) { + Image( + painter = painterResource(id = R.drawable.ic_reset_background), + contentDescription = "", + modifier = modifier.offset(y = (-16).dp), + ) + SettingsScreensScaffold( + content = { ResetCardView(state = state, modifier = modifier) }, + onBackClick = onBackPressed, + backgroundColor = Color.Transparent, + ) + } } @Composable @@ -51,7 +60,16 @@ fun ResetCardView( .fillMaxSize(), verticalArrangement = Arrangement.Bottom, ) { - + Box( + modifier = modifier, + ) { + ScreenTitle(titleRes = R.string.reset_card_to_factory_navigation_title) + } + Spacer( + modifier = modifier + .defaultMinSize(20.dp) + .weight(1f), + ) Text( text = stringResource(id = R.string.common_attention), modifier = modifier.padding(start = 20.dp, end = 20.dp), diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt index 1f8692b350..e18146767f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt @@ -6,10 +6,12 @@ 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.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectable import androidx.compose.material.RadioButton +import androidx.compose.material.RadioButtonDefaults import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -45,7 +47,8 @@ fun SecurityModeOptions( Column( modifier = modifier .fillMaxSize() - .padding(bottom = 28.dp), + .padding(bottom = 28.dp) + .offset(y = (-16).dp), verticalArrangement = Arrangement.SpaceBetween, ) { state.availableOptions.map { @@ -85,12 +88,16 @@ fun SecurityOption( .selectable( selected = selected, onClick = { state.onNewModeSelected(option) }, ) - .padding(start = 20.dp, end = 20.dp, bottom = 32.dp), + .padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 16.dp), ) { RadioButton( selected = selected, onClick = null, modifier = modifier.padding(end = 20.dp), + colors = RadioButtonDefaults.colors( + unselectedColor = colorResource(id = R.color.icon_secondary), + selectedColor = colorResource(id = R.color.icon_accent), + ), ) Column { From f05a47672c75490a8ba75b30578f336540595510 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 14:08:52 +0400 Subject: [PATCH 04/36] Updated on 2026-08-14 --- .../tangem/tap/features/details/redux/DetailsMiddleware.kt | 4 ---- .../tap/features/details/ui/details/DetailsScreenState.kt | 3 ++- .../tap/features/details/ui/details/DetailsViewModel.kt | 7 +++++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 537668094f..c8213d7d8c 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -12,7 +12,6 @@ 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.currenciesRepository -import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.wallet.models.hasSendableAmountsOrPendingTransactions @@ -39,9 +38,6 @@ class DetailsMiddleware { val uri = store.state.detailsState.cardTermsOfUseUrl if (uri != null) { store.dispatch(NavigationAction.OpenDocument(uri)) - } else { - store.dispatch(DisclaimerAction.ShowAcceptedDisclaimer) - store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer)) } } is DetailsAction.ReCreateTwinsWallet -> { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt index 68c8dc4eb0..1962a53261 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt @@ -24,7 +24,8 @@ enum class SettingsElement( AppCurrency(R.drawable.ic_currency, R.string.details_row_title_currency), AppSettings(R.drawable.ic_settings, R.string.app_settings_title), LinkMoreCards(R.drawable.ic_more_cards, R.string.details_row_title_create_backup), - TermsOfService(R.drawable.ic_text, R.string.disclaimer_title), + TermsOfService(R.drawable.ic_text, R.string.disclaimer_title), // General Terms of Service of the App + TermsOfUse(R.drawable.ic_text, R.string.details_row_title_card_tou), // Terms of Use for S2C cards only PrivacyPolicy(R.drawable.ic_lock, R.string.details_row_privacy_policy), ; } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt index c732d4350e..97ce019a84 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.details.ui.details +import com.tangem.domain.common.TapWorkarounds.isStart2Coin import com.tangem.tap.common.feedback.FeedbackEmail import com.tangem.tap.common.feedback.SupportInfo import com.tangem.tap.common.redux.AppState @@ -9,6 +10,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.isMultiwalletAllowed import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState +import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.home.LocaleRegionProvider import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.wallet.redux.WalletAction @@ -30,6 +32,7 @@ class DetailsViewModel(private val store: Store) { } SettingsElement.AppSettings -> null // TODO: until we implement settings from this screen SettingsElement.AppCurrency -> if (state.scanResponse?.card?.isMultiwalletAllowed != true) it else null + SettingsElement.TermsOfUse -> if (state.scanResponse?.card?.isStart2Coin == true) it else null else -> it } } @@ -72,6 +75,10 @@ class DetailsViewModel(private val store: Store) { store.dispatch(DetailsAction.CreateBackup) } SettingsElement.TermsOfService -> { + store.dispatch(DisclaimerAction.ShowAcceptedDisclaimer) + store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer)) + } + SettingsElement.TermsOfUse -> { store.dispatch(DetailsAction.ShowDisclaimer) } SettingsElement.PrivacyPolicy -> { From 9076ef1dd458d91450dd895e1771ec95d77dcf77 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 20:20:57 +0300 Subject: [PATCH 05/36] Updated on 2026-08-14 --- .../domain/tasks/product/ScanProductTask.kt | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 326b59acf3..7f1c152bba 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -68,16 +68,15 @@ class ScanProductTask( when (processorResult) { is CompletionResult.Success -> ScanTask().run(session) { scanTaskResult -> when (scanTaskResult) { - is CompletionResult.Success -> callback( - CompletionResult.Success( - processorResult.data + is CompletionResult.Success -> { + // it need because processorResult.data.card doesn't contains attestation result + // and CardWallet.derivedKeys + val processorScanResponseWithNewCard = processorResult.data.copy( + card = scanTaskResult.data ) - ) - is CompletionResult.Failure -> callback( - CompletionResult.Failure( - scanTaskResult.error - ) - ) + callback(CompletionResult.Success(processorScanResponseWithNewCard)) + } + is CompletionResult.Failure -> callback(CompletionResult.Failure(scanTaskResult.error)) } } is CompletionResult.Failure -> callback(CompletionResult.Failure(processorResult.error)) @@ -165,7 +164,6 @@ private class ScanWalletProcessor( } } } - private fun startLinkingForBackupIfNeeded( card: Card, session: CardSession, From a74007d920e8867c35462f12e91ecf776cb4b78f Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 20:21:14 +0300 Subject: [PATCH 06/36] Updated on 2026-08-14 --- .../domain/tasks/product/ScanProductTask.kt | 105 +++++++----------- 1 file changed, 43 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 7f1c152bba..e54c3744cb 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -101,11 +101,11 @@ private class ScanNoteProcessor : ProductCommandProcessor { callback( CompletionResult.Success( ScanResponse( - card, - ProductType.Note, - session.environment.walletData - ) - ) + card = card, + productType = ProductType.Note, + walletData = session.environment.walletData, + ), + ), ) } } @@ -116,19 +116,17 @@ private class ScanWalletProcessor( ) : ProductCommandProcessor { var primaryCard: PrimaryCard? = null - override fun proceed( card: Card, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit, ) { createMissingWalletsIfNeeded(card, session, callback) } - private fun createMissingWalletsIfNeeded( card: Card, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit, ) { if (card.wallets.isEmpty() || card.firmwareVersion < FirmwareVersion.MultiWalletAvailable) { startLinkingForBackupIfNeeded(card, session, callback) @@ -145,18 +143,12 @@ private class ScanWalletProcessor( when (result) { is CompletionResult.Success -> { PreflightReadTask( - PreflightReadMode.FullCardRead, - card.cardId + readMode = PreflightReadMode.FullCardRead, + cardId = card.cardId ).run(session) { readResult -> when (readResult) { - is CompletionResult.Success -> { - startLinkingForBackupIfNeeded(card, session, callback) - } - is CompletionResult.Failure -> callback( - CompletionResult.Failure( - readResult.error - ) - ) + is CompletionResult.Success -> startLinkingForBackupIfNeeded(card, session, callback) + is CompletionResult.Failure -> callback(CompletionResult.Failure(readResult.error)) } } } @@ -167,14 +159,11 @@ private class ScanWalletProcessor( private fun startLinkingForBackupIfNeeded( card: Card, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit, ) { - val activationIsFinished = - preferencesStorage.usedCardsPrefStorage.isActivationFinished(card.cardId) + val activationIsFinished = preferencesStorage.usedCardsPrefStorage.isActivationFinished(card.cardId) - if (card.backupStatus == Card.BackupStatus.NoBackup && - !activationIsFinished && card.wallets.isNotEmpty() - ) { + if (card.backupStatus == Card.BackupStatus.NoBackup && !activationIsFinished && card.wallets.isNotEmpty()) { StartPrimaryCardLinkingTask().run(session) { linkingResult -> when (linkingResult) { is CompletionResult.Success -> { @@ -190,11 +179,10 @@ private class ScanWalletProcessor( deriveKeysIfNeeded(card, session, callback) } } - private fun deriveKeysIfNeeded( card: Card, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit, ) { scope.launch { val derivations = collectDerivations(card) @@ -233,12 +221,13 @@ private class ScanWalletProcessor( private suspend fun getBlockchainsToDerive(card: Card): List { val currenciesRepository = currenciesRepository ?: return emptyList() - val cardCurrencies = currenciesRepository.loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed).toMutableList() + val cardCurrencies = currenciesRepository + .loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed).toMutableList() val blockchainsToDerive = cardCurrencies.ifEmpty { mutableListOf( BlockchainNetwork(Blockchain.Bitcoin, card), - BlockchainNetwork(Blockchain.Ethereum, card) + BlockchainNetwork(Blockchain.Ethereum, card), ) } @@ -246,7 +235,7 @@ private class ScanWalletProcessor( blockchainsToDerive.addAll( listOf( BlockchainNetwork(Blockchain.Ethereum, card), - BlockchainNetwork(Blockchain.EthereumTestnet, card) + BlockchainNetwork(Blockchain.EthereumTestnet, card), ) ) } @@ -303,52 +292,44 @@ private class ScanTwinProcessor : ProductCommandProcessor { is CompletionResult.Success -> { val publicKey = card.getSingleWallet()?.publicKey if (publicKey == null) { - callback( - CompletionResult.Success( - ScanResponse( - card, - ProductType.Twins, - null - ) - ) - ) - return@run - } - val verified = - TwinsHelper.verifyTwinPublicKey(readDataResult.data.issuerData, publicKey) - if (verified) { - val twinPublicKey = readDataResult.data.issuerData.sliceArray(0 until 65) - val walletData = session.environment.walletData val response = ScanResponse( - card, - ProductType.Twins, - walletData, - twinPublicKey.toHexString() + card = card, + productType = ProductType.Twins, + walletData = null, ) callback(CompletionResult.Success(response)) + return@run + } + + val verified = TwinsHelper.verifyTwinPublicKey(readDataResult.data.issuerData, publicKey) + val response = if (verified) { + val twinPublicKey = readDataResult.data.issuerData.sliceArray(0 until 65) + val walletData = session.environment.walletData + ScanResponse( + card = card, + productType = ProductType.Twins, + walletData = walletData, + secondTwinPublicKey = twinPublicKey.toHexString(), + ) } else { - callback( - CompletionResult.Success( - ScanResponse( - card, - ProductType.Twins, - null - ) - ) + ScanResponse( + card = card, + productType = ProductType.Twins, + walletData = null, ) } + callback(CompletionResult.Success(response)) } - is CompletionResult.Failure -> + is CompletionResult.Failure -> { callback(CompletionResult.Success(ScanResponse(card, ProductType.Twins, null))) + } } } } - } fun Card.getCurvesForNonCreatedWallets(): List { val curvesPresent = wallets.map { it.curve }.toSet() - val curvesForNonCreatedWallets = supportedCurves - .subtract(curvesPresent + EllipticCurve.Secp256r1) + val curvesForNonCreatedWallets = supportedCurves.subtract(curvesPresent + EllipticCurve.Secp256r1) return curvesForNonCreatedWallets.toList() } \ No newline at end of file From 007c47b6ed9a289d6820774347e78ac85e602914 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 20:34:45 +0300 Subject: [PATCH 07/36] Updated on 2026-08-14 --- .../features/send/redux/middlewares/SendMiddleware.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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 5eaa250690..df1e3dd5ba 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 @@ -219,8 +219,10 @@ private fun sendTransaction( return@launch } - withContext(Dispatchers.Main) { + withMainContext { + dispatch(SendAction.ChangeSendButtonState(ButtonState.ENABLED)) tangemSdk.config.linkedTerminal = isLinkedTerminal + when (sendResult) { is SimpleResult.Success -> { store.state.globalState.analyticsHandlers?.triggerEvent( @@ -260,12 +262,12 @@ private fun sendTransaction( card = card, ) - val error = (sendResult.error as? BlockchainSdkError) ?: return@withContext + val error = (sendResult.error as? BlockchainSdkError) ?: return@withMainContext when (error) { is BlockchainSdkError.WrappedTangemError -> { - val tangemSdkError = (error.tangemError as? TangemSdkError) ?: return@withContext - if (tangemSdkError is TangemSdkError.UserCancelled) return@withContext + val tangemSdkError = (error.tangemError as? TangemSdkError) ?: return@withMainContext + if (tangemSdkError is TangemSdkError.UserCancelled) return@withMainContext dispatch(SendAction.Dialog.SendTransactionFails.CardSdkError(tangemSdkError)) } @@ -294,7 +296,6 @@ private fun sendTransaction( } } } - dispatch(SendAction.ChangeSendButtonState(ButtonState.ENABLED)) } } } From 341cf5a0f48a503ef9426ace9544f32d0f54e0e4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 21:09:54 +0300 Subject: [PATCH 08/36] Updated on 2026-08-14 --- .../common/redux/global/GlobalMidlleware.kt | 29 ++++++---- .../exchangeServices/CardExchangeRules.kt | 54 +++++++++++++++++++ .../CurrencyExchangeManager.kt | 15 ++++-- .../exchangeServices/ExchangeService.kt | 5 +- 4 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt 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 db795840ef..4d227fcd92 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 @@ -15,6 +15,7 @@ import com.tangem.tap.currenciesRepository import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.network.exchangeServices.CardExchangeRules import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoApi import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService @@ -23,11 +24,11 @@ import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager -import java.util.Locale import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.DispatchFunction import org.rekotlin.Middleware +import java.util.* class GlobalMiddleware { companion object { @@ -62,9 +63,11 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di } } is GlobalAction.RestoreAppCurrency -> { - store.dispatch(GlobalAction.RestoreAppCurrency.Success( - preferencesStorage.fiatCurrenciesPrefStorage.getAppCurrency() - )) + store.dispatch( + GlobalAction.RestoreAppCurrency.Success( + preferencesStorage.fiatCurrenciesPrefStorage.getAppCurrency(), + ), + ) } is GlobalAction.HideWarningMessage -> { store.state.globalState.warningManager?.let { @@ -107,7 +110,13 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di secret = mercuryoSecret, ) val sellService = MoonPayService(moonPayKey, moonPaySecretKey) - val exchangeManager = CurrencyExchangeManager(buyService, sellService) + val cardProvider = { store.state.globalState.scanResponse?.card } + + val exchangeManager = CurrencyExchangeManager( + buyService = buyService, + sellService = sellService, + primaryRules = CardExchangeRules(cardProvider), + ) store.dispatchOnMain(GlobalAction.ExchangeManager.Init.Success(exchangeManager)) store.dispatchOnMain(GlobalAction.ExchangeManager.Update) } @@ -127,7 +136,7 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di store.state.globalState.analyticsHandlers, currenciesRepository, action.additionalBlockchainsToDerive, - action.messageResId + action.messageResId, ) withMainContext { store.dispatch(GlobalAction.ScanFailsCounter.ChooseBehavior(result)) @@ -150,15 +159,15 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di is Result.Success -> { store.dispatchOnMain( GlobalAction.FetchUserCountry.Success( - countryCode = result.data.code.lowercase() - ) + countryCode = result.data.code.lowercase(), + ), ) } is Result.Failure -> { store.dispatchOnMain( GlobalAction.FetchUserCountry.Success( - countryCode = Locale.getDefault().country.lowercase() - ) + countryCode = Locale.getDefault().country.lowercase(), + ), ) } } diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt new file mode 100644 index 0000000000..d6c0cfe6c5 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt @@ -0,0 +1,54 @@ +package com.tangem.tap.network.exchangeServices + +import com.tangem.common.card.Card +import com.tangem.domain.common.TapWorkarounds.isStart2Coin +import com.tangem.tap.features.demo.isDemoCard +import com.tangem.tap.features.wallet.models.Currency + +/** +[REDACTED_AUTHOR] + */ +class CardExchangeRules( + val cardProvider: () -> Card?, +) : ExchangeRules { + + override fun isBuyAllowed(): Boolean { + val card = cardProvider() ?: return false + + return when { + card.isDemoCard() -> false + card.isStart2Coin -> false + else -> true + } + } + + override fun isSellAllowed(): Boolean { + val card = cardProvider() ?: return false + + return when { + card.isDemoCard() -> false + card.isStart2Coin -> false + else -> true + } + } + + override fun availableForBuy(currency: Currency): Boolean { + val card = cardProvider() ?: return false + + return when { + card.isDemoCard() -> false + card.isStart2Coin -> false + else -> true + } + } + + override fun availableForSell(currency: Currency): Boolean { + val card = cardProvider() ?: return false + + return when { + card.isDemoCard() -> false + card.isStart2Coin -> false + else -> true + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index 8d1085d316..39f201a9b1 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -23,6 +23,7 @@ import java.math.BigDecimal class CurrencyExchangeManager( private val buyService: ExchangeService, private val sellService: ExchangeService, + private val primaryRules: ExchangeRules, ) : ExchangeService, ExchangeUrlBuilder { override suspend fun update() { @@ -30,10 +31,16 @@ class CurrencyExchangeManager( sellService.update() } - override fun isBuyAllowed(): Boolean = buyService.isBuyAllowed() - override fun isSellAllowed(): Boolean = sellService.isSellAllowed() - override fun availableForBuy(currency: Currency): Boolean = buyService.availableForBuy(currency) - override fun availableForSell(currency: Currency): Boolean = sellService.availableForSell(currency) + override fun isBuyAllowed(): Boolean = primaryRules.isBuyAllowed() && buyService.isBuyAllowed() + override fun isSellAllowed(): Boolean = primaryRules.isSellAllowed() && sellService.isSellAllowed() + + override fun availableForBuy(currency: Currency): Boolean { + return primaryRules.availableForBuy(currency) && buyService.availableForBuy(currency) + } + + override fun availableForSell(currency: Currency): Boolean { + return primaryRules.availableForSell(currency) && sellService.availableForSell(currency) + } override fun getUrl( action: Action, diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt index 712fd2d5e0..34f37dddf9 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt @@ -3,8 +3,11 @@ package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain import com.tangem.tap.features.wallet.models.Currency -interface ExchangeService { +interface ExchangeService: ExchangeRules { suspend fun update() +} + +interface ExchangeRules { fun isBuyAllowed(): Boolean fun isSellAllowed(): Boolean fun availableForBuy(currency: Currency):Boolean From 7ef9e9b9eb68c188a4be33eddca578144513a598 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 23:00:35 +0400 Subject: [PATCH 09/36] Updated on 2026-08-14 --- .../tangem/tap/features/demo/DemoHelper.kt | 4 +- .../features/details/redux/DetailsAction.kt | 1 + .../details/redux/DetailsMiddleware.kt | 107 ++++++++++-------- .../ui/cardsettings/CardSettingsViewModel.kt | 4 +- 4 files changed, 64 insertions(+), 52 deletions(-) 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 53a0878b74..72b7c51672 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 @@ -14,6 +14,7 @@ import com.tangem.common.CompletionResult import com.tangem.domain.common.ScanResponse import com.tangem.tap.common.extensions.dispatchNotification import com.tangem.tap.common.redux.AppState +import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction import com.tangem.tap.features.wallet.redux.WalletAction @@ -42,7 +43,8 @@ object DemoHelper { WalletAction.TradeCryptoAction.Buy::class.java, WalletAction.TradeCryptoAction.Sell::class.java, BackupAction.StartBackup::class.java, - WalletAction.ExploreAddress::class.java + WalletAction.ExploreAddress::class.java, + DetailsAction.ResetToFactory.Start::class.java, ) fun isDemoCard(scanResponse: ScanResponse): Boolean = isDemoCardId(scanResponse.card.cardId) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt index 9cb5cfe537..b421b69730 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt @@ -19,6 +19,7 @@ sealed class DetailsAction : Action { object ReCreateTwinsWallet : DetailsAction() sealed class ResetToFactory : DetailsAction() { + object Start : ResetToFactory() object Proceed : ResetToFactory() data class Confirm(val confirmed: Boolean) : ResetToFactory() object Failure : ResetToFactory() diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index c8213d7d8c..7825d58a8f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -12,6 +12,7 @@ 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.currenciesRepository +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.wallet.models.hasSendableAmountsOrPendingTransactions @@ -21,67 +22,74 @@ import com.tangem.tap.tangemSdkManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.rekotlin.Action import org.rekotlin.Middleware class DetailsMiddleware { private val eraseWalletMiddleware = EraseWalletMiddleware() private val manageSecurityMiddleware = ManageSecurityMiddleware() private val managePrivacyMiddleware = ManagePrivacyMiddleware() - val detailsMiddleware: Middleware = { _, _ -> + val detailsMiddleware: Middleware = { _, state -> { next -> { action -> - when (action) { - is DetailsAction.ResetToFactory -> eraseWalletMiddleware.handle(action) - is DetailsAction.ManageSecurity -> manageSecurityMiddleware.handle(action) - is DetailsAction.AppSettings -> managePrivacyMiddleware.handle(action) - is DetailsAction.ShowDisclaimer -> { - val uri = store.state.detailsState.cardTermsOfUseUrl - if (uri != null) { - store.dispatch(NavigationAction.OpenDocument(uri)) - } + handleAction(state, action) + next(action) + } + } + } + + private fun handleAction(state: () -> AppState?, action: Action) { + if (DemoHelper.tryHandle(state, action)) return + + when (action) { + is DetailsAction.ResetToFactory -> eraseWalletMiddleware.handle(action) + is DetailsAction.ManageSecurity -> manageSecurityMiddleware.handle(action) + is DetailsAction.AppSettings -> managePrivacyMiddleware.handle(action) + is DetailsAction.ShowDisclaimer -> { + val uri = store.state.detailsState.cardTermsOfUseUrl + if (uri != null) { + store.dispatch(NavigationAction.OpenDocument(uri)) + } + } + is DetailsAction.ReCreateTwinsWallet -> { + val wallet = + store.state.walletState.walletManagers.map { it.wallet }.firstOrNull() + if (wallet == null) { + store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet)) + store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins)) + } else { + if (wallet.hasSendableAmountsOrPendingTransactions()) { + val walletIsNotEmpty = + store.state.globalState.resources.strings.walletIsNotEmpty + store.dispatchNotification(walletIsNotEmpty) + } else { + store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet)) + store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins)) } - is DetailsAction.ReCreateTwinsWallet -> { - val wallet = - store.state.walletState.walletManagers.map { it.wallet }.firstOrNull() - if (wallet == null) { - store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet)) - store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins)) - } else { - if (wallet.hasSendableAmountsOrPendingTransactions()) { - val walletIsNotEmpty = - store.state.globalState.resources.strings.walletIsNotEmpty - store.dispatchNotification(walletIsNotEmpty) - } else { - store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet)) - store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins)) - } + } + } + is DetailsAction.CreateBackup -> { + store.state.detailsState.scanResponse?.let { + store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) + store.dispatch( + GlobalAction.Onboarding.Start( + it, + fromHomeScreen = false, + ), + ) + } + } + DetailsAction.ScanCard -> { + scope.launch { + when (val result = tangemSdkManager.scanCard()) { + is CompletionResult.Success -> { + val card = result.data + store.dispatchOnMain(DetailsAction.PrepareCardSettingsData(card)) } - } - is DetailsAction.CreateBackup -> { - store.state.detailsState.scanResponse?.let { - store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) - store.dispatch( - GlobalAction.Onboarding.Start( - it, - fromHomeScreen = false, - ), - ) - } - } - DetailsAction.ScanCard -> { - scope.launch { - when (val result = tangemSdkManager.scanCard()) { - is CompletionResult.Success -> { - val card = result.data - store.dispatchOnMain(DetailsAction.PrepareCardSettingsData(card)) - } - is CompletionResult.Failure -> { - } - } + is CompletionResult.Failure -> { } } } - next(action) } } } @@ -89,6 +97,9 @@ class DetailsMiddleware { class EraseWalletMiddleware { fun handle(action: DetailsAction.ResetToFactory) { when (action) { + is DetailsAction.ResetToFactory.Start -> { + store.dispatch(NavigationAction.NavigateTo(AppScreen.ResetToFactory)) + } is DetailsAction.ResetToFactory.Proceed -> { val card = store.state.detailsState.cardSettingsState?.card ?: return if (card.isTangemTwins()) { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt index a90886ff81..60affefd8b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt @@ -3,8 +3,6 @@ package com.tangem.tap.features.details.ui.cardsettings import com.tangem.domain.common.getTwinCardIdForUser import com.tangem.domain.common.isTangemTwins import com.tangem.tap.common.redux.AppState -import com.tangem.tap.common.redux.navigation.AppScreen -import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.details.redux.CardSettingsState import com.tangem.tap.features.details.redux.DetailsAction import org.rekotlin.Store @@ -64,7 +62,7 @@ class CardSettingsViewModel(private val store: Store) { store.dispatch(DetailsAction.ManageSecurity.ChangeAccessCode) } is CardInfo.ResetToFactorySettings -> { - store.dispatch(NavigationAction.NavigateTo(AppScreen.ResetToFactory)) + store.dispatch(DetailsAction.ResetToFactory.Start) } is CardInfo.SecurityMode -> { store.dispatch(DetailsAction.ManageSecurity.OpenSecurity) From 3993e752973abde6efb2d8ae70cc4c010d5292ac Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 23:01:52 +0400 Subject: [PATCH 10/36] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/common/DialogManager.kt | 2 +- .../redux/walletconnect/WalletConnectAction.kt | 2 +- .../redux/walletconnect/WalletConnectMiddleware.kt | 9 ++++++++- .../redux/walletconnect/WalletConnectState.kt | 4 +++- .../walletconnect/dialogs/ApproveWcSessionDialog.kt | 2 +- .../ui/walletconnect/dialogs/ChooseNetworkDialog.kt | 12 ++++++++---- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 07582f5c87..7af8cc775b 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -101,7 +101,7 @@ class DialogManager : StoreSubscriber { is WalletConnectDialog.ApproveWcSession -> ApproveWcSessionDialog.create(state.dialog.session, state.dialog.networks, context) is WalletConnectDialog.ChooseNetwork -> - ChooseNetworkDialog.create(state.dialog.networks, context) + ChooseNetworkDialog.create(state.dialog.session, state.dialog.networks, context) is WalletConnectDialog.ClipboardOrScanQr -> ClipboardOrScanQrDialog.create(state.dialog.clipboardUri, context) is WalletConnectDialog.RequestTransaction -> diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt index 0c852b3467..14a871fbd9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt @@ -47,7 +47,7 @@ sealed class WalletConnectAction : Action { val session: WalletConnectSession, ) : WalletConnectAction() - data class SelectNetwork(val networks: List) : WalletConnectAction() + data class SelectNetwork(val session: WalletConnectSession, val networks: List) : WalletConnectAction() data class ChooseNetwork(val blockchain: Blockchain) : WalletConnectAction() data class UpdateBlockchain( val updatedSession: WalletConnectSession, 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 4694af35f2..d98fb0b0f5 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 @@ -62,7 +62,14 @@ class WalletConnectMiddleware { } } is WalletConnectAction.SelectNetwork -> { - store.dispatch(GlobalAction.ShowDialog(WalletConnectDialog.ChooseNetwork(action.networks))) + store.dispatch( + GlobalAction.ShowDialog( + WalletConnectDialog.ChooseNetwork( + session = action.session, + networks = action.networks, + ), + ), + ) } is WalletConnectAction.ChooseNetwork -> { val data = state()?.walletConnectState?.newSessionData ?: 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 14181de2e6..0bdfaf69f6 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 @@ -95,10 +95,12 @@ sealed class WalletConnectDialog : StateDialog { object OpeningSessionRejected : WalletConnectDialog() object SessionTimeout : WalletConnectDialog() data class ApproveWcSession( - val session: WalletConnectSession, val networks: List, + val session: WalletConnectSession, + val networks: List, ) : WalletConnectDialog() data class ChooseNetwork( + val session: WalletConnectSession, val networks: List, ) : WalletConnectDialog() diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt index 1834618476..efa9da619b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt @@ -27,7 +27,7 @@ class ApproveWcSessionDialog { } if (networks.size > 1) { setNeutralButton(context.getText(R.string.wallet_connect_select_network)) { _, _ -> - store.dispatch(WalletConnectAction.SelectNetwork(networks)) + store.dispatch(WalletConnectAction.SelectNetwork(session = session, networks = networks)) } } setNegativeButton(context.getText(R.string.common_reject)) { _, _ -> diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt index 2b1779dafc..dedf44dd04 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt @@ -5,22 +5,26 @@ import androidx.appcompat.app.AlertDialog import com.tangem.blockchain.common.Blockchain import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession import com.tangem.tap.store import com.tangem.wallet.R object ChooseNetworkDialog { fun create( - blockchains: List, + session: WalletConnectSession, + networks: List, context: Context, ): AlertDialog { return AlertDialog.Builder(context) .setTitle(context.getString(R.string.wallet_connect_select_network)) - .setNegativeButton(context.getString(R.string.common_cancel)) { _, _ -> /* no-op */ } + .setNegativeButton(context.getString(R.string.common_cancel)) { _, _ -> + store.dispatch(WalletConnectAction.FailureEstablishingSession(session.session)) + } .setOnDismissListener { store.dispatch(GlobalAction.HideDialog()) } - .setSingleChoiceItems(blockchains.map { it.fullName }.toTypedArray(), 0) { _, which -> - blockchains.getOrNull(which)?.let { selectedBlockchain -> + .setSingleChoiceItems(networks.map { it.fullName }.toTypedArray(), 0) { _, which -> + networks.getOrNull(which)?.let { selectedBlockchain -> store.dispatch( WalletConnectAction.ChooseNetwork( blockchain = selectedBlockchain, From 6d7bbd068c2ac3e2d0761778aa51cd0ae5927333 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 23:05:01 +0400 Subject: [PATCH 11/36] Updated on 2026-08-14 --- app/src/main/res/values-de/strings_final.xml | 2 +- app/src/main/res/values-fr/strings_final.xml | 2 +- app/src/main/res/values-it/strings_final.xml | 2 +- app/src/main/res/values-ru/strings_final.xml | 2 +- app/src/main/res/values/strings_final.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 4fb2fa8dcb..96c0876eff 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -54,7 +54,7 @@ Hide token Hide %s Hide - You hide the token from the main screen, but you can add it back at any time. + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml index 55f342c1af..3fe6eb9f17 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -54,7 +54,7 @@ Hide token Hide %s Hide - You hide the token from the main screen, but you can add it back at any time. + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml index 939315c9a1..afe988cb58 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -54,7 +54,7 @@ Hide token Hide %s Hide - You hide the token from the main screen, but you can add it back at any time. + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index f7ddc1c883..415a83ca56 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -59,7 +59,7 @@ Скрыть токен Скрыть %s Скрыть - Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно. + Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами. Невозможно скрыть %s Токен %s является основной валютой в сети %s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети. diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index 53782ce6b3..ca04743898 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -59,7 +59,7 @@ Hide token Hide %s Hide - You are about to hide this token from the main screen. You can add it back anytime. + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. From 4e7cda3e3642f54f1f81a2dfcaff05e299f91664 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Aug 2022 23:24:58 +0400 Subject: [PATCH 12/36] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/common/DialogManager.kt | 2 +- .../details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 7af8cc775b..96cf1b874b 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -59,7 +59,7 @@ class DialogManager : StoreSubscriber { return } val context = context ?: return - if (dialog != null && dialog == state.dialog) return + if (dialog != null) return dialog = when (state.dialog) { is AppDialog.SimpleOkDialog -> SimpleOkDialog.create(state.dialog, context) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt index efa9da619b..4af9323fa1 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt @@ -27,6 +27,7 @@ class ApproveWcSessionDialog { } if (networks.size > 1) { setNeutralButton(context.getText(R.string.wallet_connect_select_network)) { _, _ -> + store.dispatch(GlobalAction.HideDialog(WalletConnectDialog.ApproveWcSession(session, networks))) store.dispatch(WalletConnectAction.SelectNetwork(session = session, networks = networks)) } } From a3a6f4304778bb00b1f52a62f0356840254c7dc4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 11 Aug 2022 15:44:24 +0300 Subject: [PATCH 13/36] Updated on 2026-08-14 --- .../tap/NavBarInsetsFragmentLifecycleCallback.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt index 94177e8463..ddedbca8f6 100644 --- a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt +++ b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt @@ -19,10 +19,17 @@ class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() { ) { if (v is ComposeView) return ViewCompat.setOnApplyWindowInsetsListener(v) { view, windowInsets -> - val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()) - view.updatePadding( - bottom = insets.bottom, - ) + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()) + if (view.fitsSystemWindows) { + view.updatePadding( + top = insets.top, + bottom = insets.bottom, + ) + } else { + view.updatePadding( + bottom = insets.bottom, + ) + } windowInsets } } From 0c8852a3740c13639e2b5d0066754426262c7ec7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 5 Aug 2022 13:23:02 +0300 Subject: [PATCH 14/36] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 12 +++++++++-- .../tap/common/feedback/FeedbackManager.kt | 20 +++++++++++++++++++ .../tap/persistence/PreferencesStorage.kt | 7 ++++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index adcd569b7f..0c69e5de88 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -122,11 +122,19 @@ class TapApplication : Application(), ImageLoaderFactory { ) val logWriter = TangemLogCollector( levels = logLevels, - messageFormatter = LogFormat.StairsFormatter() + messageFormatter = LogFormat.StairsFormatter(), ) Log.addLogger(logWriter) - store.dispatch(GlobalAction.SetFeedbackManager(FeedbackManager(infoHolder, logWriter))) + store.dispatch( + GlobalAction.SetFeedbackManager( + FeedbackManager( + infoHolder = infoHolder, + logCollector = logWriter, + preferencesStorage = preferencesStorage, + ), + ), + ) } private fun initAppsFlyer() { 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 c2bb70a931..ddd4e6ff6d 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 @@ -1,12 +1,14 @@ package com.tangem.tap.common.feedback import android.content.Context +import android.os.Build import com.tangem.domain.common.TapWorkarounds 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.persistence.PreferencesStorage import com.tangem.tap.withForegroundActivity import com.tangem.wallet.R import com.zendesk.logger.Logger @@ -14,6 +16,8 @@ import timber.log.Timber import zendesk.chat.Chat import zendesk.chat.ChatConfiguration import zendesk.chat.ChatEngine +import zendesk.chat.ChatProvidersConfiguration +import zendesk.chat.VisitorInfo import zendesk.configurations.Configuration import zendesk.messaging.MessagingActivity import java.io.File @@ -26,6 +30,7 @@ import java.io.StringWriter class FeedbackManager( val infoHolder: AdditionalFeedbackInfo, private val logCollector: TangemLogCollector, + private val preferencesStorage: PreferencesStorage, ) { fun initChat( context: Context, @@ -58,6 +63,7 @@ class FeedbackManager( fun openChat(feedbackData: FeedbackData) { feedbackData.prepare(infoHolder) foregroundActivityObserver.withForegroundActivity { activity -> + setChatVisitorInfo() setChatVisitorNote(activity, feedbackData) showMessagingActivity(activity) } @@ -82,6 +88,20 @@ class FeedbackManager( } } + private fun setChatVisitorInfo() { + if (preferencesStorage.chatFirstLaunchTime == null) { + preferencesStorage.chatFirstLaunchTime = System.currentTimeMillis() + } + val chatUserId = (preferencesStorage.chatFirstLaunchTime.toString() + Build.MODEL).hashCode() + val visitorInfo = VisitorInfo.builder() + .withName("User $chatUserId") + .build() + + Chat.INSTANCE.chatProvidersConfiguration = ChatProvidersConfiguration.builder() + .withVisitorInfo(visitorInfo) + .build() + } + private fun setChatVisitorNote( context: Context, feedbackData: FeedbackData, diff --git a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt index 15073fb931..aeab14497b 100644 --- a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt @@ -5,7 +5,7 @@ import android.content.Context import android.content.SharedPreferences import androidx.core.content.edit import com.tangem.common.json.MoshiJsonConverter -import java.util.Calendar +import java.util.* class PreferencesStorage(applicationContext: Application) { @@ -25,6 +25,10 @@ class PreferencesStorage(applicationContext: Application) { fiatCurrenciesPrefStorage.migrate() } + var chatFirstLaunchTime: Long? + get() = preferences.getLong(CHAT_FIRST_LAUNCH_KEY, 0).takeIf { it != 0L } + set(value) = preferences.edit { putLong(CHAT_FIRST_LAUNCH_KEY, value ?: 0) } + fun getCountOfLaunches(): Int = preferences.getInt(APP_LAUNCH_COUNT_KEY, 1) @Deprecated("Use UsedCardsPrefStorage instead") @@ -58,6 +62,7 @@ class PreferencesStorage(applicationContext: Application) { private const val DISCLAIMER_ACCEPTED_KEY = "disclaimerAccepted" private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown" private const val APP_LAUNCH_COUNT_KEY = "launchCount" + private const val CHAT_FIRST_LAUNCH_KEY = "chatFirstLaunchKey" } } From 138da32afccda6db347a732494239fa9c65e7cf6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 12 Aug 2022 13:44:18 +0300 Subject: [PATCH 15/36] Updated on 2026-08-14 --- app/src/main/res/values-ru/strings_final.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index 415a83ca56..359b5c0488 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -100,7 +100,7 @@ Подключение к Dapps Добавить еще карты - Вы можете объеденить до трех карт в одним кошельке. Это можно сделать только один раз. + Вы можете объединить до трех карт в одном кошельке. Это можно сделать только один раз. Privacy policy From 8e4f8877f78f2a66151ab9d4d45f580b8921afdf Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 12 Aug 2022 14:23:00 +0300 Subject: [PATCH 16/36] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt | 4 ++-- dependencies.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 72b7c51672..650ce5ea09 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 @@ -7,7 +7,7 @@ import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.TransactionSender import com.tangem.blockchain.common.TransactionSigner import com.tangem.blockchain.common.WalletManager -import com.tangem.blockchain.common.toBlockchainCustomError +import com.tangem.blockchain.common.toBlockchainSdkError import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.extensions.SimpleResult import com.tangem.common.CompletionResult @@ -484,7 +484,7 @@ class DemoTransactionSender( publicKey = walletManager.wallet.publicKey ) return when (signerResponse) { - is CompletionResult.Success -> SimpleResult.Failure(Exception(ID).toBlockchainCustomError()) + is CompletionResult.Success -> SimpleResult.Failure(Exception(ID).toBlockchainSdkError()) is CompletionResult.Failure -> SimpleResult.fromTangemSdkError(signerResponse.error) } } diff --git a/dependencies.gradle b/dependencies.gradle index 7097fccd86..3fdecfb84c 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-101', + tangem_blockchain_sdk: 'develop-103', // tangem_blockchain_sdk: '0.0.1', ] From 333bee7ef31d5e0da062fbba7ba86f498c875c13 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 15 Aug 2022 17:34:13 +0300 Subject: [PATCH 17/36] Updated on 2026-08-14 --- .../tap/NavBarInsetsFragmentLifecycleCallback.kt | 13 ++++++++----- .../main/res/layout/fragment_onboarding_main.xml | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt index ddedbca8f6..2239eacd70 100644 --- a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt +++ b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt @@ -18,19 +18,22 @@ class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() { savedInstanceState: Bundle?, ) { if (v is ComposeView) return + ViewCompat.setOnApplyWindowInsetsListener(v) { view, windowInsets -> - val insets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()) + val statusBarInsets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()) + val navigationBarInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()) + if (view.fitsSystemWindows) { view.updatePadding( - top = insets.top, - bottom = insets.bottom, + top = statusBarInsets.top, + bottom = navigationBarInsets.bottom, ) } else { view.updatePadding( - bottom = insets.bottom, + bottom = navigationBarInsets.bottom, ) } windowInsets } } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout/fragment_onboarding_main.xml b/app/src/main/res/layout/fragment_onboarding_main.xml index 82b94a5def..faa2c0c829 100644 --- a/app/src/main/res/layout/fragment_onboarding_main.xml +++ b/app/src/main/res/layout/fragment_onboarding_main.xml @@ -6,6 +6,7 @@ android:layout_height="match_parent" android:background="@color/backgroundWhite" android:clipChildren="false" + android:clipToPadding="false" android:fitsSystemWindows="true" android:orientation="vertical"> From dabfd209a729a6d55df0af485529ba0205f3a7a7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 16 Aug 2022 08:07:54 +0300 Subject: [PATCH 18/36] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/common/extensions/Specific.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt index 219e9339da..795bc8e268 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt @@ -116,6 +116,8 @@ fun BigDecimal.formatAmountAsSpannedString( val integer = amount.substringBefore('.') val reminder = amount.substringAfter('.') + // test formatter log Log.e("TEST ", BigDecimal("1234567890987654321.1234567890987654321").formatWithSpaces()) + return buildSpannedString { append(integer) append('.') @@ -136,7 +138,7 @@ fun BigDecimal.formatWithSpaces(): String { var index: Int = integerStr.length while (0 < index) { if (index <= 3) { - packets.add(0, integerStr) + packets.add(integerStr) break } index -= 3 @@ -145,7 +147,7 @@ fun BigDecimal.formatWithSpaces(): String { } return buildString { - packets.forEachIndexed { index, packet -> + packets.reversed().forEachIndexed { index, packet -> append(packet) if (index != packets.lastIndex) append(' ') } From 96fc2f8267e23fcdd48f55bc0d6392f031a2b73d Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 16 Aug 2022 21:34:57 +0400 Subject: [PATCH 19/36] Updated on 2026-08-14 --- .../ui/walletconnect/dialogs/ApproveWcSessionDialog.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt index 4af9323fa1..b9fd651bb8 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt @@ -5,7 +5,6 @@ import androidx.appcompat.app.AlertDialog import com.tangem.blockchain.common.Blockchain import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction -import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession import com.tangem.tap.store import com.tangem.wallet.R @@ -23,19 +22,22 @@ class ApproveWcSessionDialog { setTitle(context.getString(R.string.wallet_connect)) setMessage(message) setPositiveButton(context.getText(R.string.common_start)) { _, _ -> + store.dispatch(GlobalAction.HideDialog) store.dispatch(WalletConnectAction.ChooseNetwork(session.wallet.blockchain!!)) } if (networks.size > 1) { setNeutralButton(context.getText(R.string.wallet_connect_select_network)) { _, _ -> - store.dispatch(GlobalAction.HideDialog(WalletConnectDialog.ApproveWcSession(session, networks))) + store.dispatch(GlobalAction.HideDialog) store.dispatch(WalletConnectAction.SelectNetwork(session = session, networks = networks)) } } setNegativeButton(context.getText(R.string.common_reject)) { _, _ -> + store.dispatch(GlobalAction.HideDialog) store.dispatch(WalletConnectAction.FailureEstablishingSession(session.session)) } - setOnDismissListener { - store.dispatch(GlobalAction.HideDialog(WalletConnectDialog.ApproveWcSession(session, networks))) + setOnCancelListener { + store.dispatch(GlobalAction.HideDialog) + store.dispatch(WalletConnectAction.FailureEstablishingSession(session.session)) } }.create() } From 9720a85ab455810673f9ad050a3340b052c8b0c3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 16 Aug 2022 21:36:03 +0400 Subject: [PATCH 20/36] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/common/extensions/Store.kt | 2 +- .../java/com/tangem/tap/common/redux/global/GlobalAction.kt | 2 +- .../com/tangem/tap/common/redux/global/GlobalReducer.kt | 6 +----- .../main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt | 2 +- .../ui/walletconnect/dialogs/BnbTransactionDialog.kt | 2 +- .../details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt | 4 ++-- .../ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt | 2 +- .../details/ui/walletconnect/dialogs/PersonalSignDialog.kt | 2 +- .../details/ui/walletconnect/dialogs/TransactionDialog.kt | 2 +- .../products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt | 2 +- .../products/wallet/ui/dialogs/BackupInProgressDialog.kt | 4 ++-- .../wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt | 2 +- .../wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt | 4 ++-- 13 files changed, 16 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt index f29950807f..7a0488d1a5 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt @@ -76,6 +76,6 @@ fun Store<*>.dispatchDialogShow(dialog: StateDialog) { fun Store<*>.dispatchDialogHide() { scope.launch(Dispatchers.Main) { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index 5e74cc3d0b..4927405ccd 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -34,7 +34,7 @@ sealed class GlobalAction : Action { // dialogs data class ShowDialog(val stateDialog: StateDialog) : GlobalAction() - data class HideDialog(val stateDialog: StateDialog? = null) : GlobalAction() + object HideDialog : GlobalAction() sealed class Onboarding { data class Start(val scanResponse: ScanResponse?, val fromHomeScreen: Boolean = true) : GlobalAction() diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index d8804bb12a..449d47ae10 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -68,11 +68,7 @@ fun globalReducer(action: Action, state: AppState): GlobalState { globalState.copy(dialog = action.stateDialog) } is GlobalAction.HideDialog -> { - if (action.stateDialog == null || action.stateDialog == globalState.dialog) { - globalState.copy(dialog = null) - } else { - globalState - } + globalState.copy(dialog = null) } is GlobalAction.ExchangeManager.Init.Success -> { globalState.copy(exchangeManager = action.exchangeManager) diff --git a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt index fbb6528a7a..8cd6e7e5ba 100644 --- a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt +++ b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt @@ -51,7 +51,7 @@ class SimpleCancelableAlertDialog { setNegativeButton(context.getText(secondaryButtonRes)) { _, _ -> secondaryButtonAction()} } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt index 1763c140d0..2ec39ca844 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt @@ -58,7 +58,7 @@ class BnbTransactionDialog { store.dispatch(WalletConnectAction.RejectRequest(session, sessionId)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt index dedf44dd04..8e0ffe0f4a 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt @@ -21,7 +21,7 @@ object ChooseNetworkDialog { store.dispatch(WalletConnectAction.FailureEstablishingSession(session.session)) } .setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } .setSingleChoiceItems(networks.map { it.fullName }.toTypedArray(), 0) { _, which -> networks.getOrNull(which)?.let { selectedBlockchain -> @@ -30,7 +30,7 @@ object ChooseNetworkDialog { blockchain = selectedBlockchain, ), ) - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } } .create() diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt index 30604f69e9..809b37cf66 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt @@ -22,7 +22,7 @@ class ClipboardOrScanQrDialog { store.dispatch(NavigationAction.NavigateTo(AppScreen.QrScan)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt index ebbf5ac86c..789384c758 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt @@ -29,7 +29,7 @@ class PersonalSignDialog { store.dispatch(WalletConnectAction.RejectRequest(data.session, data.id)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt index 81d5fd6770..192fc3d9e1 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt @@ -45,7 +45,7 @@ class TransactionDialog { store.dispatch(WalletConnectAction.RejectRequest(data.session, data.id)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt index 0c8b5d924e..883ce390dc 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt @@ -20,7 +20,7 @@ class AddMoreBackupCardsDialog { } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt index f6ef3c6138..9b619eef7d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt @@ -13,10 +13,10 @@ class BackupInProgressDialog { setTitle(R.string.alert_title) setMessage(R.string.onboarding_backup_exit_warning) setPositiveButton(R.string.warning_button_ok) { _, _ -> - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt index 6ed98a06cc..8b88890be8 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt @@ -20,7 +20,7 @@ class ConfirmDiscardingBackupDialog { store.dispatch(BackupAction.DiscardSavedBackup) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) } setCancelable(false) }.create() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt index 9419fb3965..b51a53e29f 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt @@ -15,11 +15,11 @@ class UnfinishedBackupFoundDialog { setTitle(R.string.alert_title) setMessage(R.string.welcome_interrupted_backup_alert_message) setPositiveButton(R.string.welcome_interrupted_backup_alert_resume) { _, _ -> - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) store.dispatch(BackupAction.ResumeBackup) } setNegativeButton(R.string.welcome_interrupted_backup_alert_discard) { _, _ -> - store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.HideDialog) store.dispatch(GlobalAction.ShowDialog(BackupDialog.ConfirmDiscardingBackup)) } setCancelable(false) From 8e4adf2c0c77af5bf8d9bb3947cb8a8dfa6fe46a Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 16 Aug 2022 21:37:00 +0400 Subject: [PATCH 21/36] Updated on 2026-08-14 --- .../java/com/tangem/tap/common/extensions/WalletManager.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 39e0103066..58284b0cc0 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -22,9 +22,8 @@ import timber.log.Timber */ suspend fun WalletManager.safeUpdate(): Result = try { val scanResponse = store.state.globalState.scanResponse - ?: error("Scan response must not be null") - if (scanResponse.isDemoCard() || TestActions.testAmountInjectionForWalletManagerEnabled) { + if (scanResponse?.isDemoCard() == true || TestActions.testAmountInjectionForWalletManagerEnabled) { delay(500) TestActions.testAmountInjectionForWalletManagerEnabled = false Result.Success(wallet) From 21476816986b211f2a719e3e7c93940340bfedeb Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Aug 2022 09:56:12 +0300 Subject: [PATCH 22/36] Updated on 2026-08-14 --- .../wallet/ui/view/WalletDetailsButtonsRow.kt | 5 +- .../wallet/ui/wallet/MultiWalletView.kt | 52 +++++----- .../wallet/ui/wallet/SingleWalletView.kt | 94 +++++-------------- app/src/main/res/layout/fragment_wallet.xml | 27 ++---- .../view_wallet_details_buttons_row.xml | 62 ++++++------ 5 files changed, 95 insertions(+), 145 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt index 12efe010c8..1b7eff8f23 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt @@ -12,9 +12,10 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { + private val binding = ViewWalletDetailsButtonsRowBinding.inflate( LayoutInflater.from(context), - this + this, ) var onBuyClick: (() -> Unit)? = null @@ -36,7 +37,7 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( fun updateButtonsVisibility( buyAllowed: Boolean, sellAllowed: Boolean, - sendAllowed: Boolean + sendAllowed: Boolean, ) = with(binding) { btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) btnBuy.isEnabled = buyAllowed diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt index 4267ad7ebd..73504ddbfc 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.wallet.ui.wallet +import android.widget.Button import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import com.tangem.common.card.Card @@ -20,11 +21,11 @@ import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.WalletFragment import com.tangem.tap.features.wallet.ui.adapters.WalletAdapter +import com.tangem.tap.features.wallet.ui.view.WalletDetailsButtonsRow import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.FragmentWalletBinding - class MultiWalletView : WalletView() { private lateinit var walletsAdapter: WalletAdapter override fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) { @@ -33,14 +34,12 @@ class MultiWalletView : WalletView() { showMultiWalletView(binding) } - private fun showMultiWalletView(binding: FragmentWalletBinding) = with(binding) { tvTwinCardNumber.hide() rvPendingTransaction.hide() lCardBalance.root.hide() lAddress.root.hide() - lButtonsShort.root.hide() - lButtonsLong.root.hide() + rowButtons.hide() lSingleWalletBalance.root.hide() rvMultiwallet.show() btnAddToken.show() @@ -59,7 +58,6 @@ class MultiWalletView : WalletView() { } } - override fun onViewCreated() { setupWalletsRecyclerView() } @@ -86,17 +84,17 @@ class MultiWalletView : WalletView() { TokensAction.LoadCurrencies( supportedBlockchains = currenciesRepository.getBlockchains( card.firmwareVersion, - card.isTestCard + card.isTestCard, ), - scanResponse = store.state.globalState.scanResponse - ) + scanResponse = store.state.globalState.scanResponse, + ), ) store.dispatch(TokensAction.AllowToAddTokens(true)) store.dispatch( TokensAction.SetAddedCurrencies( wallets = state.walletsData, - derivationStyle = card.derivationStyle - ) + derivationStyle = card.derivationStyle, + ), ) store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens)) } @@ -105,7 +103,7 @@ class MultiWalletView : WalletView() { private fun handleBackupWarning( binding: FragmentWalletBinding, - showBackupWarning: Boolean + showBackupWarning: Boolean, ) = with(binding.lWalletBackupWarning) { root.isVisible = showBackupWarning root.setOnClickListener { @@ -128,11 +126,11 @@ class MultiWalletView : WalletView() { veilBalance.unVeil() } tvProcessing.animateVisibility( - show = totalBalance.state == ProgressState.Error + show = totalBalance.state == ProgressState.Error, ) tvBalance.text = totalBalance.fiatAmount.formatAmountAsSpannedString( - currencySymbol = totalBalance.fiatCurrency.symbol + currencySymbol = totalBalance.fiatCurrency.symbol, ) tvCurrencyName.text = totalBalance.fiatCurrency.code @@ -145,14 +143,14 @@ class MultiWalletView : WalletView() { private fun handleErrorStates( state: WalletState, binding: FragmentWalletBinding, - fragment: WalletFragment + fragment: WalletFragment, ) { when (state.primaryWallet?.currencyData?.status) { BalanceStatus.EmptyCard -> { showErrorState( binding, fragment.getText(R.string.wallet_error_empty_card), - fragment.getString(R.string.wallet_error_empty_card_subtitle) + fragment.getString(R.string.wallet_error_empty_card_subtitle), ) configureButtonsForEmptyWalletState(binding) } @@ -160,7 +158,7 @@ class MultiWalletView : WalletView() { showErrorState( binding, fragment.getText(R.string.wallet_error_unsupported_blockchain), - fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle) + fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle), ) } else -> { /* no-op */ @@ -184,9 +182,21 @@ class MultiWalletView : WalletView() { private fun configureButtonsForEmptyWalletState(binding: FragmentWalletBinding) = with(binding) { - lButtonsLong.root.show() - lButtonsLong.btnConfirmLong.setOnClickListener { store.dispatch(WalletAction.CreateWallet) } - lButtonsLong.btnConfirmLong.text = - fragment?.getText(R.string.wallet_button_create_wallet) + rowButtons.btnBuy.hide() + rowButtons.btnSell.hide() + rowButtons.btnTrade.hide() + rowButtons.show() + + rowButtons.btnSend.text = fragment?.getText(R.string.wallet_button_create_wallet) + rowButtons.onSendClick = { store.dispatch(WalletAction.CreateWallet) } } -} \ No newline at end of file +} + +private val WalletDetailsButtonsRow.btnBuy: Button + get() = this.findViewById(R.id.btn_buy) +private val WalletDetailsButtonsRow.btnSell: Button + get() = this.findViewById(R.id.btn_sell) +private val WalletDetailsButtonsRow.btnTrade: Button + get() = this.findViewById(R.id.btn_trade) +private val WalletDetailsButtonsRow.btnSend: Button + get() = this.findViewById(R.id.btn_send) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index bcbb6a06ff..fa046cc3f0 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -2,7 +2,6 @@ package com.tangem.tap.features.wallet.ui.wallet import android.view.View import android.view.ViewGroup -import android.widget.Button import androidx.recyclerview.widget.LinearLayoutManager import com.tangem.domain.common.TwinCardNumber import com.tangem.tap.common.extensions.beginDelayedTransition @@ -12,11 +11,15 @@ import com.tangem.tap.common.extensions.show import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.features.wallet.redux.WalletMainButton +import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.ui.BalanceWidget import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper import com.tangem.tap.features.wallet.ui.WalletFragment import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter +import com.tangem.tap.features.wallet.ui.view.WalletDetailsButtonsRow import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.FragmentWalletBinding @@ -55,7 +58,7 @@ class SingleWalletView : WalletView() { state.primaryWallet ?: return setupTwinCards(state.twinCardsState, binding) - setupButtons(state.primaryWallet, state.isTangemTwins, binding) + setupButtons(state.primaryWallet, binding) setupAddressCard(state.primaryWallet, binding) showPendingTransactionsIfPresent(state.primaryWallet.pendingTransactions) setupBalance(state, state.primaryWallet) @@ -79,9 +82,7 @@ class SingleWalletView : WalletView() { } } - private fun setupTwinCards( - twinCardsState: TwinCardsState?, binding: FragmentWalletBinding, - ) = with(binding) { + private fun setupTwinCards(twinCardsState: TwinCardsState?, binding: FragmentWalletBinding) = with(binding) { twinCardsState?.cardNumber?.let { cardNumber -> tvTwinCardNumber.show() val number = when (cardNumber) { @@ -96,19 +97,8 @@ class SingleWalletView : WalletView() { } } - private fun setupButtons( - state: WalletData, isTwinsWallet: Boolean, binding: FragmentWalletBinding, - ) = with(binding) { - setupButtonsType(state, binding) - val tradeState = state.tradeCryptoState - val btnConfirm = if (tradeState.isAvailableToSell() || tradeState.isAvailableToBuy()) { - lButtonsShort.btnConfirm - } else { - lButtonsLong.btnConfirmLong - } - - setupConfirmButton(state, btnConfirm, isTwinsWallet) - + private fun setupButtons(state: WalletData, binding: FragmentWalletBinding) = with(binding) { + setupRowButtons(state, rowButtons) lAddress.btnCopy.setOnClickListener { state.walletAddresses?.selectedAddress?.address?.let { addressString -> store.dispatch(WalletAction.CopyAddress(addressString, fragment!!.requireContext())) @@ -124,64 +114,22 @@ class SingleWalletView : WalletView() { ) } } - - setupTradeButton(binding, state.tradeCryptoState) } - private fun setupTradeButton(binding: FragmentWalletBinding, tradeCryptoState: TradeCryptoState) { - val allowedToBuy = tradeCryptoState.isAvailableToBuy() - val allowedToSell = tradeCryptoState.isAvailableToSell() - val action = when { - allowedToBuy && !allowedToSell -> WalletAction.TradeCryptoAction.Buy() - !allowedToBuy && allowedToSell -> WalletAction.TradeCryptoAction.Sell - allowedToBuy && allowedToSell -> WalletAction.DialogAction.ChooseTradeActionDialog - else -> null - } - val text = when { - allowedToBuy && !allowedToSell -> R.string.wallet_button_buy - !allowedToBuy && allowedToSell -> R.string.wallet_button_sell - allowedToBuy && allowedToSell -> R.string.wallet_button_trade - else -> R.string.wallet_button_trade - } - val icon = when { - allowedToBuy && !allowedToSell -> R.drawable.ic_arrow_up - !allowedToBuy && allowedToSell -> R.drawable.ic_arrow_down - allowedToBuy && allowedToSell -> R.drawable.ic_arrows_up_down - else -> null - } - with(binding) { - lButtonsShort.btnTrade.text = fragment?.getText(text) - icon?.let { lButtonsShort.btnTrade.setIconResource(it) } - lButtonsShort.btnTrade.setOnClickListener { if (action != null) store.dispatch(action) } - } - } + private fun setupRowButtons(state: WalletData, rowButtons: WalletDetailsButtonsRow) { + val allowedToBuy = state.tradeCryptoState.isAvailableToBuy() + val allowedToSell = state.tradeCryptoState.isAvailableToSell() + rowButtons.updateButtonsVisibility( + buyAllowed = allowedToBuy, + sellAllowed = allowedToSell, + sendAllowed = state.mainButton.enabled, + ) - private fun setupButtonsType(state: WalletData, binding: FragmentWalletBinding) = with(binding) { - if (state.tradeCryptoState.isAvailableToSell() || state.tradeCryptoState.isAvailableToBuy()) { - lButtonsLong.root.hide() - lButtonsShort.root.show() - } else { - lButtonsLong.root.show() - lButtonsShort.root.hide() - } - } + rowButtons.onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) } + rowButtons.onSendClick = { store.dispatch(WalletAction.TradeCryptoAction.Sell) } + rowButtons.onTradeClick = { store.dispatch(WalletAction.DialogAction.ChooseTradeActionDialog) } - private fun setupConfirmButton( - state: WalletData, btnConfirm: Button, isTwinsWallet: Boolean, - ) { - val buttonTitle = when (state.mainButton) { - is WalletMainButton.SendButton -> R.string.wallet_button_send - is WalletMainButton.CreateWalletButton -> { - if (!isTwinsWallet) { - R.string.wallet_button_create_wallet - } else { - R.string.wallet_button_create_twin_wallet - } - } - } - btnConfirm.text = fragment?.getString(buttonTitle) - btnConfirm.isEnabled = state.mainButton.enabled - btnConfirm.setOnClickListener { + rowButtons.onSendClick = { when (state.mainButton) { is WalletMainButton.SendButton -> store.dispatch(WalletAction.Send()) is WalletMainButton.CreateWalletButton -> store.dispatch(WalletAction.CreateWallet) diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index b2118902ec..fa0eaf1398 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -47,7 +47,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" - android:paddingBottom="74dp"> + android:paddingBottom="32dp"> - - - + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + tools:orientation="horizontal" + tools:parentTag="android.widget.LinearLayout"> - + + - - + + + + android:id="@+id/btn_send" + style="@style/TapButtonWithIcon" + android:layout_width="0dp" + android:layout_marginStart="6dp" + android:layout_weight="1" + android:text="@string/wallet_button_send" + app:icon="@drawable/ic_send" /> From 463be0148f4105394d98b02401e5c618a7111266 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Aug 2022 11:14:44 +0400 Subject: [PATCH 23/36] Updated on 2026-08-14 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 3fdecfb84c..d0b96119fd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-103', + tangem_blockchain_sdk: 'develop-104', // tangem_blockchain_sdk: '0.0.1', ] From c8d1293fd74b4acdff49d7f613c70718e1eeac5b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Aug 2022 10:15:14 +0300 Subject: [PATCH 24/36] Updated on 2026-08-14 --- .../send/redux/reducers/SendScreenReducer.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt index 673f19cb66..07936d3e49 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt @@ -3,7 +3,18 @@ package com.tangem.tap.features.send.redux.reducers import com.tangem.blockchain.common.AmountType import com.tangem.tap.common.CurrencyConverter import com.tangem.tap.common.entities.IndeterminateProgressButton -import com.tangem.tap.features.send.redux.* +import com.tangem.tap.features.send.redux.AddressPayIdActionUi +import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction +import com.tangem.tap.features.send.redux.AmountAction +import com.tangem.tap.features.send.redux.AmountActionUi +import com.tangem.tap.features.send.redux.FeeAction +import com.tangem.tap.features.send.redux.FeeActionUi +import com.tangem.tap.features.send.redux.PrepareSendScreen +import com.tangem.tap.features.send.redux.ReceiptAction +import com.tangem.tap.features.send.redux.ReleaseSendState +import com.tangem.tap.features.send.redux.SendAction +import com.tangem.tap.features.send.redux.SendScreenAction +import com.tangem.tap.features.send.redux.TransactionExtrasAction import com.tangem.tap.features.send.redux.states.ExternalTransactionData import com.tangem.tap.features.send.redux.states.IdStateHolder import com.tangem.tap.features.send.redux.states.SendState @@ -46,7 +57,8 @@ private class SendReducer : SendInternalReducer { sendState.copy(sendButtonState = IndeterminateProgressButton(action.state)) } is SendAction.Dialog.TezosWarningDialog -> sendState.copy(dialog = action) - is SendAction.Dialog.SendTransactionFails -> sendState.copy(dialog = action) + is SendAction.Dialog.SendTransactionFails.CardSdkError -> sendState.copy(dialog = action) + is SendAction.Dialog.SendTransactionFails.BlockchainSdkError -> sendState.copy(dialog = action) is SendAction.Dialog.Hide -> sendState.copy(dialog = null) is SendAction.Warnings.Set -> sendState.copy(sendWarningsList = action.warningList) is SendAction.SendSpecificTransaction -> From 2154393b803b660a80c14fff10758e786566c485 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Aug 2022 11:26:13 +0300 Subject: [PATCH 25/36] Updated on 2026-08-14 --- .../products/twins/redux/TwinCardsMiddleware.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index e95d03c36e..0dc7e10566 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -6,13 +6,19 @@ import com.tangem.common.extensions.guard import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE -import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.extensions.dispatchDialogShow +import com.tangem.tap.common.extensions.dispatchErrorNotification +import com.tangem.tap.common.extensions.dispatchOpenUrl +import com.tangem.tap.common.extensions.getAddressData +import com.tangem.tap.common.extensions.getToUpUrl +import com.tangem.tap.common.extensions.onCardScanned import com.tangem.tap.common.postUi import com.tangem.tap.common.redux.AppDialog 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.currenciesRepository import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.domain.twins.TwinCardsManager @@ -265,7 +271,8 @@ private fun handle(action: Action, dispatch: DispatchFunction) { store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet)) } CreateTwinWalletMode.RecreateWallet -> { - store.dispatch(NavigationAction.PopBackTo()) + currenciesRepository.removeCurrencies(scanResponse.card.cardId) + store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) } } } From 8731fc021a9b39ae19e5d9ae26f33377f97d55a7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Aug 2022 12:31:12 +0400 Subject: [PATCH 26/36] Updated on 2026-08-14 --- app/src/main/res/values-v29/zendesk_styles.xml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 app/src/main/res/values-v29/zendesk_styles.xml diff --git a/app/src/main/res/values-v29/zendesk_styles.xml b/app/src/main/res/values-v29/zendesk_styles.xml new file mode 100644 index 0000000000..628e83211a --- /dev/null +++ b/app/src/main/res/values-v29/zendesk_styles.xml @@ -0,0 +1,7 @@ + + + + + From ec5e27098542116161b74874eb841add9cfcf193 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Aug 2022 11:54:10 +0400 Subject: [PATCH 27/36] Updated on 2026-08-14 --- .../tap/features/wallet/ui/WalletFragment.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index fe3c9131e4..1389600f94 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -114,22 +114,26 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber { + isSaltPay && (walletView !is SaltPaySingleWalletView) -> { walletView = SaltPaySingleWalletView() + walletView.changeWalletView(this, binding) } - state.isMultiwalletAllowed && - state.primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && - walletView is SingleWalletView -> { + state.isMultiwalletAllowed && state.primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && + walletView !is MultiWalletView -> { walletView = MultiWalletView() + walletView.changeWalletView(this, binding) } - !state.isMultiwalletAllowed && walletView is MultiWalletView -> { + !state.isMultiwalletAllowed && walletView !is SingleWalletView -> { walletView = SingleWalletView() + walletView.changeWalletView(this, binding) } + else -> {} // we keep the same view unless we scan a card that requires a different view } - walletView.changeWalletView(this, binding) walletView.onNewState(state) if (!state.shouldShowDetails) { From 7851f5e885676e32f7bee46b951a1b0b0ef27706 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 00:26:53 +0300 Subject: [PATCH 28/36] Updated on 2026-08-14 --- .../tap/common/extensions/WalletManager.kt | 3 +- .../tap/common/redux/global/GlobalState.kt | 2 +- .../note/redux/OnboardingNoteState.kt | 2 +- .../products/twins/redux/TwinCardsState.kt | 2 +- .../tap/features/wallet/redux/WalletState.kt | 66 ++++--------------- .../middlewares/TradeCryptoMiddleware.kt | 27 ++++---- .../redux/reducers/OnWalletLoadedReducer.kt | 11 +--- .../wallet/redux/reducers/WalletReducer.kt | 40 +++++------ .../wallet/ui/WalletDetailsFragment.kt | 4 +- .../wallet/ui/wallet/SingleWalletView.kt | 6 +- .../CurrencyExchangeManager.kt | 8 +++ .../exchangeServices/ExchangeService.kt | 19 ++++++ 12 files changed, 81 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 58284b0cc0..311932f7c1 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -51,11 +51,10 @@ suspend fun WalletManager.safeUpdate(): Result = try { fun WalletManager?.getToUpUrl(): String? { val globalState = store.state.globalState - val exchangeManager = globalState.exchangeManager ?: return null val wallet = this?.wallet ?: return null val defaultAddress = wallet.address - return exchangeManager.getUrl( + return globalState.exchangeManager.getUrl( action = CurrencyExchangeManager.Action.Buy, blockchain = wallet.blockchain, cryptoCurrencyName = wallet.blockchain.currency, 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 62e5217866..1fed436b47 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 @@ -25,7 +25,7 @@ data class GlobalState( val appCurrency: FiatCurrency = FiatCurrency.Default, val scanCardFailsCounter: Int = 0, val dialog: StateDialog? = null, - val exchangeManager: CurrencyExchangeManager? = null, + val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(), val resources: AndroidResources = AndroidResources(), val analyticsHandlers: AnalyticsHandler? = null, val userCountryCode: String? = null, diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt index a9ebb0e757..ae7a2db594 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt @@ -26,7 +26,7 @@ data class OnboardingNoteState( get() = steps.indexOf(currentStep) val isBuyAllowed: Boolean by ReadOnlyProperty { _, _ -> - store.state.globalState.exchangeManager?.availableForBuy(walletBalance.currency) ?: false + store.state.globalState.exchangeManager.availableForBuy(walletBalance.currency) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt index 19cc8ad307..0b2e4b4d1a 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt @@ -56,7 +56,7 @@ data class TwinCardsState( get() = currentStep == TwinCardsStep.CreateSecondWallet || currentStep == TwinCardsStep.CreateThirdWallet val isBuyAllowed: Boolean by ReadOnlyProperty { _, _ -> - store.state.globalState.exchangeManager?.availableForBuy(walletBalance.currency) ?: false + store.state.globalState.exchangeManager.availableForBuy(walletBalance.currency) } } 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 ec3107b151..891b07a3fd 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 @@ -7,9 +7,6 @@ import com.tangem.blockchain.common.Wallet 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 @@ -17,12 +14,18 @@ import com.tangem.tap.common.toggleWidget.WidgetState import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState -import com.tangem.tap.features.wallet.models.* +import com.tangem.tap.features.wallet.models.Currency +import com.tangem.tap.features.wallet.models.PendingTransaction +import com.tangem.tap.features.wallet.models.TotalBalance +import com.tangem.tap.features.wallet.models.WalletRent +import com.tangem.tap.features.wallet.models.WalletWarning +import com.tangem.tap.features.wallet.models.hasPendingTransactions +import com.tangem.tap.features.wallet.models.hasSendableAmounts +import com.tangem.tap.features.wallet.models.isSendableAmount import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount import com.tangem.tap.features.wallet.redux.reducers.findProgressState import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData -import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.store import org.rekotlin.StateType import java.math.BigDecimal @@ -248,32 +251,6 @@ data class WalletState( return updatedWallets + remainingWallets } - fun updateTradeCryptoState( - exchangeManager: CurrencyExchangeManager?, - walletData: WalletData - ): WalletData { - return walletData.copy( - tradeCryptoState = TradeCryptoState.from( - exchangeManager, - walletData - ) - ) - } - - fun updateTradeCryptoState( - exchangeManager: CurrencyExchangeManager?, - walletDataList: List - ): List { - return walletDataList.map { - it.copy( - tradeCryptoState = TradeCryptoState.from( - exchangeManager, - it - ) - ) - } - } - private fun updateTotalBalance(): WalletState { val walletsData = this.wallets .flatMap(WalletStore::walletsData) @@ -352,39 +329,24 @@ data class Artwork( } } -data class TradeCryptoState( - val isAvailableToSell: () -> Boolean = { false }, - val isAvailableToBuy: () -> Boolean = { false }, -) { - companion object { - fun from( - exchangeManager: CurrencyExchangeManager?, - walletData: WalletData - ): TradeCryptoState { - val exchanger = exchangeManager ?: return walletData.tradeCryptoState - val currency = walletData.currency - - return TradeCryptoState( - isAvailableToSell = { exchanger.availableForSell(currency) }, - isAvailableToBuy = { exchanger.availableForBuy(currency) }, - ) - } - } -} - data class WalletData( val pendingTransactions: List = emptyList(), val hashesCountVerified: Boolean? = null, val walletAddresses: WalletAddresses? = null, val currencyData: BalanceWidgetData = BalanceWidgetData(), val updatingWallet: Boolean = false, - val tradeCryptoState: TradeCryptoState = TradeCryptoState(), val fiatRateString: String? = null, val fiatRate: BigDecimal? = null, val mainButton: WalletMainButton = WalletMainButton.SendButton(false), val currency: Currency, val walletRent: WalletRent? = null, ) { + val isAvailableToBuy: Boolean + get() = store.state.globalState.exchangeManager.availableForBuy(currency) + + val isAvailableToSell: Boolean + get() = store.state.globalState.exchangeManager.availableForSell(currency) + fun shouldShowMultipleAddress(): Boolean { val listOfAddresses = walletAddresses?.list ?: return false return listOfAddresses.size > 1 diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 064647d863..319c940a52 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -37,20 +37,18 @@ class TradeCryptoMiddleware { action: WalletAction.TradeCryptoAction.Buy, ) { if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { - store.dispatchOnMain( - WalletAction.DialogAction.RussianCardholdersWarningDialog - ) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog) return } val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return - val exchangeManager = store.state.globalState.exchangeManager ?: return val card = store.state.globalState.scanResponse?.card ?: return - val appCurrency = store.state.globalState.appCurrency val addresses = selectedWalletData.walletAddresses?.list.orEmpty() if (addresses.isEmpty()) return + val exchangeManager = store.state.globalState.exchangeManager + val appCurrency = store.state.globalState.appCurrency val currency = selectedWalletData.currency if (currency is Currency.Token && currency.blockchain.isTestnet()) { @@ -81,15 +79,13 @@ class TradeCryptoMiddleware { private fun proceedSellAction() { val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return - val exchangeManager = store.state.globalState.exchangeManager ?: return - val appCurrency = store.state.globalState.appCurrency + val appCurrency = store.state.globalState.appCurrency val addresses = selectedWalletData.walletAddresses?.list.orEmpty() if (addresses.isEmpty()) return val currency = selectedWalletData.currency - - exchangeManager.getUrl( + store.state.globalState.exchangeManager.getUrl( action = CurrencyExchangeManager.Action.Sell, blockchain = currency.blockchain, cryptoCurrencyName = currency.currencySymbol, @@ -100,8 +96,8 @@ class TradeCryptoMiddleware { private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) { val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return - val walletManager = - store.state.walletState.getWalletManager(selectedWalletData.currency) + + val walletManager = store.state.walletState.getWalletManager(selectedWalletData.currency) store.dispatchOnMain(PrepareSendScreen( coinAmount = walletManager?.wallet?.amounts?.get(AmountType.Coin), coinRate = selectedWalletData.fiatRate, @@ -116,11 +112,10 @@ class TradeCryptoMiddleware { } private fun openReceiptUrl(transactionId: String) { - val exchangeManager = store.state.globalState.exchangeManager ?: return - store.dispatchOnMain(NavigationAction.PopBackTo()) - exchangeManager.getSellCryptoReceiptUrl(CurrencyExchangeManager.Action.Sell, transactionId)?.let { - store.dispatchOnMain(NavigationAction.OpenUrl(it)) - } + store.state.globalState.exchangeManager.getSellCryptoReceiptUrl( + action = CurrencyExchangeManager.Action.Sell, + transactionId = transactionId, + )?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt index 482285de76..63d378718f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt @@ -13,7 +13,9 @@ import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.filterByToken import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.removeUnknownTransactions -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletMainButton +import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData @@ -38,8 +40,6 @@ class OnWalletLoadedReducer { val walletData = walletState.getWalletData(blockchainNetwork) ?: return walletState val fiatCurrency = store.state.globalState.appCurrency - val exchangeManager = store.state.globalState.exchangeManager - val coinAmountValue = wallet.amounts[AmountType.Coin]?.value val formattedAmount = coinAmountValue?.toFormattedCurrencyString( wallet.blockchain.decimals(), @@ -71,7 +71,6 @@ class OnWalletLoadedReducer { pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(isCoinSendButtonEnabled), currency = Currency.fromBlockchainNetwork(blockchainNetwork), - tradeCryptoState = TradeCryptoState.from(exchangeManager, walletData), ) val tokens = wallet.getTokens().mapNotNull { token -> @@ -104,7 +103,6 @@ class OnWalletLoadedReducer { ), pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled), - tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData), ) } val newWallets = tokens + newWalletData @@ -118,8 +116,6 @@ class OnWalletLoadedReducer { if (wallet.blockchain != walletState.primaryBlockchain) return walletState val fiatCurrencyName = store.state.globalState.appCurrency.code - val exchangeManager = store.state.globalState.exchangeManager - val token = wallet.getFirstToken() val tokenData = if (token != null) { val tokenAmount = wallet.getTokenAmount(token) @@ -167,7 +163,6 @@ class OnWalletLoadedReducer { ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(sendButtonEnabled), - tradeCryptoState = TradeCryptoState.from(exchangeManager, walletState.primaryWallet), ) val wallets = listOfNotNull(walletData) val updatedStore = walletState.getWalletStore(walletData?.currency)?.updateWallets(wallets) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index fba952b703..bf3d1552a9 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -6,7 +6,11 @@ import com.tangem.blockchain.common.Wallet import com.tangem.common.extensions.mapNotNullValues import com.tangem.domain.common.TwinCardNumber import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.extensions.toFiatRateString +import com.tangem.tap.common.extensions.toFiatString +import com.tangem.tap.common.extensions.toFiatValue +import com.tangem.tap.common.extensions.toFormattedCurrencyString +import com.tangem.tap.common.extensions.toFormattedFiatValue import com.tangem.tap.common.redux.AppState import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.getArtworkUrl @@ -14,7 +18,16 @@ import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.WalletRent -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.AddressData +import com.tangem.tap.features.wallet.redux.Artwork +import com.tangem.tap.features.wallet.redux.ErrorType +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletAddresses +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.features.wallet.redux.WalletMainButton +import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.store @@ -144,10 +157,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState { currencySymbol = walletData.currencyData.currencySymbol, ), mainButton = WalletMainButton.SendButton(false), - tradeCryptoState = TradeCryptoState.from( - exchangeManager, - walletData - ) ) } ) @@ -171,13 +180,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState { currencySymbol = wallet.currencyData.currencySymbol, ), mainButton = WalletMainButton.SendButton(false), - tradeCryptoState = TradeCryptoState.from(exchangeManager, wallet) ) } - val wallets = newState.updateTradeCryptoState( - exchangeManager, - newState.replaceSomeWallets(newWallets) - ) + val wallets = newState.replaceSomeWallets(newWallets) val walletStore = newState.getWalletStore(action.blockchain)?.updateWallets(wallets) newState = newState.updateWalletStore(walletStore) } @@ -210,14 +215,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) ) } - var updatedWalletStore = newState.getWalletStore(action.blockchain) + val updatedWalletStore = newState.getWalletStore(action.blockchain) ?.updateWallets(listOfNotNull(walletData)) - updatedWalletStore = - updatedWalletStore?.updateWallets( - newState.updateTradeCryptoState(exchangeManager, updatedWalletStore.walletsData) - ) - newState = newState.updateWalletStore(updatedWalletStore) } @@ -248,11 +248,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) ) } - val updatedWallets = - newState.updateTradeCryptoState( - exchangeManager, - walletStore!!.updateWallets(listOfNotNull(newWalletData) + tokenWallets).walletsData - ) + val updatedWallets = walletStore!!.updateWallets(listOfNotNull(newWalletData) + tokenWallets).walletsData newState = newState.updateWalletsData(updatedWallets) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 0f54d5b13a..a84d052625 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -199,8 +199,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } rowButtons.updateButtonsVisibility( - buyAllowed = selectedWallet.tradeCryptoState.isAvailableToBuy(), - sellAllowed = selectedWallet.tradeCryptoState.isAvailableToSell(), + buyAllowed = selectedWallet.isAvailableToBuy, + sellAllowed = selectedWallet.isAvailableToSell, sendAllowed = selectedWallet.mainButton.enabled, ) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index fa046cc3f0..7f473f4b4d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -117,11 +117,9 @@ class SingleWalletView : WalletView() { } private fun setupRowButtons(state: WalletData, rowButtons: WalletDetailsButtonsRow) { - val allowedToBuy = state.tradeCryptoState.isAvailableToBuy() - val allowedToSell = state.tradeCryptoState.isAvailableToSell() rowButtons.updateButtonsVisibility( - buyAllowed = allowedToBuy, - sellAllowed = allowedToSell, + buyAllowed = state.isAvailableToBuy, + sellAllowed = state.isAvailableToSell, sendAllowed = state.mainButton.enabled, ) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index 39f201a9b1..85720c4306 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -74,6 +74,14 @@ class CurrencyExchangeManager( } enum class Action { Buy, Sell } + + companion object { + fun dummy(): CurrencyExchangeManager = CurrencyExchangeManager( + buyService = ExchangeService.dummy(), + sellService = ExchangeService.dummy(), + primaryRules = ExchangeRules.dummy(), + ) + } } suspend fun CurrencyExchangeManager.buyErc20TestnetTokens( diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt index 34f37dddf9..f7db8b210f 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt @@ -5,6 +5,16 @@ import com.tangem.tap.features.wallet.models.Currency interface ExchangeService: ExchangeRules { suspend fun update() + + companion object { + fun dummy(): ExchangeService = object : ExchangeService { + override suspend fun update() {} + override fun isBuyAllowed(): Boolean = false + override fun isSellAllowed(): Boolean = false + override fun availableForBuy(currency: Currency): Boolean = false + override fun availableForSell(currency: Currency): Boolean = false + } + } } interface ExchangeRules { @@ -12,6 +22,15 @@ interface ExchangeRules { fun isSellAllowed(): Boolean fun availableForBuy(currency: Currency):Boolean fun availableForSell(currency: Currency):Boolean + + companion object { + fun dummy(): ExchangeRules = object : ExchangeRules { + override fun isBuyAllowed(): Boolean = false + override fun isSellAllowed(): Boolean = false + override fun availableForBuy(currency: Currency): Boolean = false + override fun availableForSell(currency: Currency): Boolean = false + } + } } interface ExchangeUrlBuilder { From cf692a7cd64faff7cdbb22c54e5388d6b07c7f12 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 00:32:29 +0300 Subject: [PATCH 29/36] Updated on 2026-08-14 --- .../tangem/tap/network/exchangeServices/CardExchangeRules.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt index d6c0cfe6c5..ecf9d850b3 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt @@ -16,7 +16,7 @@ class CardExchangeRules( val card = cardProvider() ?: return false return when { - card.isDemoCard() -> false + card.isDemoCard() -> true card.isStart2Coin -> false else -> true } @@ -36,7 +36,7 @@ class CardExchangeRules( val card = cardProvider() ?: return false return when { - card.isDemoCard() -> false + card.isDemoCard() -> true card.isStart2Coin -> false else -> true } From 3caf4762ab1ce46466f0cc2711d6df90fc8518db Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 00:54:17 +0300 Subject: [PATCH 30/36] Updated on 2026-08-14 --- .../tap/network/exchangeServices/mercuryo/MercuryoApi.kt | 9 --------- .../network/exchangeServices/mercuryo/MercuryoService.kt | 1 + 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt index 45494e0114..87565c3640 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt @@ -4,15 +4,6 @@ import com.squareup.moshi.Json import retrofit2.http.GET import retrofit2.http.Path -/** -[REDACTED_AUTHOR] - */ - - - -private val CurrenciesUrl = "https://api.mercuryo.io/v1.6/lib/currencies" - - interface MercuryoApi { diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt index 97190aa9fd..112e3660c8 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt @@ -130,6 +130,7 @@ class MercuryoService( private fun blockchainFromCurrencyName(currencyName: String): Blockchain? = when (currencyName) { "BNB" -> Blockchain.BSC "ETH" -> Blockchain.Ethereum + "ADA" -> Blockchain.CardanoShelley else -> Blockchain.values().find { it.currency.lowercase() == currencyName.lowercase() } } } From 6bcd70c9782b9641635fbf2302860de9ecb0215d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 01:38:31 +0300 Subject: [PATCH 31/36] Updated on 2026-08-14 --- .../com/tangem/tap/common/feature/Feature.kt | 8 +++++ .../tap/features/wallet/redux/WalletState.kt | 20 ++++++------ .../wallet/redux/reducers/WalletReducer.kt | 2 -- .../wallet/ui/WalletDetailsFragment.kt | 5 +-- .../wallet/ui/view/WalletDetailsButtonsRow.kt | 15 ++++++--- .../wallet/ui/wallet/SingleWalletView.kt | 32 ++++++++++++------- .../exchangeServices/CardExchangeRules.kt | 6 ++++ .../CurrencyExchangeManager.kt | 2 ++ .../exchangeServices/ExchangeService.kt | 18 +++++++---- .../mercuryo/MercuryoService.kt | 2 ++ .../moonpay/MoonPayService.kt | 2 ++ 11 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/feature/Feature.kt diff --git a/app/src/main/java/com/tangem/tap/common/feature/Feature.kt b/app/src/main/java/com/tangem/tap/common/feature/Feature.kt new file mode 100644 index 0000000000..ce1313c772 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/feature/Feature.kt @@ -0,0 +1,8 @@ +package com.tangem.tap.common.feature + +/** +[REDACTED_AUTHOR] + */ +interface Feature { + fun featureIsSwitchedOn():Boolean +} \ No newline at end of file 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 891b07a3fd..48c886d939 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 @@ -51,21 +51,15 @@ data class WalletState( // if you do not delegate - the application crashes on startup, // because twinCardsState has not been created yet - val twinCardsState: TwinCardsState by ReadOnlyProperty { thisRef, property -> + val twinCardsState: TwinCardsState by ReadOnlyProperty { _, _ -> store.state.twinCardsState } val isTangemTwins: Boolean get() = store.state.globalState.scanResponse?.isTangemTwins() == true - val primaryWallet: WalletData? = wallets.firstOrNull() - ?.walletsData?.firstOrNull() - val primaryWalletManager: WalletManager? = - if (wallets.isNotEmpty()) wallets[0].walletManager else null - - val shouldShowDetails: Boolean = - primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && - primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain + val isExchangeServiceFeatureOn: Boolean + get() = store.state.globalState.exchangeManager.featureIsSwitchedOn() val blockchains: List get() = wallets.mapNotNull { it.walletManager?.wallet?.blockchain } @@ -79,6 +73,14 @@ data class WalletState( val walletManagers: List get() = wallets.mapNotNull { it.walletManager } + val primaryWallet: WalletData? = wallets.firstOrNull()?.walletsData?.firstOrNull() + + val primaryWalletManager: WalletManager? = if (wallets.isNotEmpty()) wallets[0].walletManager else null + + val shouldShowDetails: Boolean = + primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && + primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain + fun getWalletManager(currency: Currency?): WalletManager? { if (currency?.blockchain == null) return null return getWalletStore(currency)?.walletManager diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index bf3d1552a9..a4b679512e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -30,7 +30,6 @@ import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData -import com.tangem.tap.store import org.rekotlin.Action import java.math.BigDecimal @@ -48,7 +47,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState { if (action !is WalletAction) return state.walletState - val exchangeManager = store.state.globalState.exchangeManager var newState = state.walletState when (action) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index a84d052625..ab07dd33d5 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -140,7 +140,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), setupAddressCard(selectedWallet) setupNoInternetHandling(state) setupBalanceData(selectedWallet.currencyData) - setupButtons(selectedWallet) + setupButtons(selectedWallet, state.isExchangeServiceFeatureOn) handleCurrencyIcon(selectedWallet) handleWarnings(selectedWallet) @@ -186,7 +186,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), ) } - private fun setupButtons(selectedWallet: WalletData) = with(binding) { + private fun setupButtons(selectedWallet: WalletData, isExchangeServiceFeatureOn: Boolean) = with(binding) { lWalletDetails.btnCopy.setOnClickListener { selectedWallet.walletAddresses?.selectedAddress?.address?.let { addressString -> store.dispatch(WalletAction.CopyAddress(addressString, requireContext())) @@ -199,6 +199,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } rowButtons.updateButtonsVisibility( + exchangeServiceFeatureOn = isExchangeServiceFeatureOn, buyAllowed = selectedWallet.isAvailableToBuy, sellAllowed = selectedWallet.isAvailableToSell, sendAllowed = selectedWallet.mainButton.enabled, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt index 1b7eff8f23..af6ec9280b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt @@ -35,14 +35,21 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( } fun updateButtonsVisibility( + exchangeServiceFeatureOn: Boolean, buyAllowed: Boolean, sellAllowed: Boolean, sendAllowed: Boolean, ) = with(binding) { - btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) - btnBuy.isEnabled = buyAllowed - btnSell.isVisible = !buyAllowed && sellAllowed - btnTrade.isVisible = buyAllowed && sellAllowed + if (exchangeServiceFeatureOn) { + btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) + btnBuy.isEnabled = buyAllowed + btnSell.isVisible = !buyAllowed && sellAllowed + btnTrade.isVisible = buyAllowed && sellAllowed + } else { + btnBuy.isVisible = false + btnSell.isVisible = false + btnTrade.isVisible = false + } btnSend.isEnabled = sendAllowed } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index 7f473f4b4d..ab271db8fb 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -58,7 +58,7 @@ class SingleWalletView : WalletView() { state.primaryWallet ?: return setupTwinCards(state.twinCardsState, binding) - setupButtons(state.primaryWallet, binding) + setupButtons(state.primaryWallet, binding, state.isExchangeServiceFeatureOn) setupAddressCard(state.primaryWallet, binding) showPendingTransactionsIfPresent(state.primaryWallet.pendingTransactions) setupBalance(state, state.primaryWallet) @@ -97,18 +97,23 @@ class SingleWalletView : WalletView() { } } - private fun setupButtons(state: WalletData, binding: FragmentWalletBinding) = with(binding) { - setupRowButtons(state, rowButtons) + private fun setupButtons( + walletData: WalletData, + binding: FragmentWalletBinding, + isExchangeServiceFeatureEnabled: Boolean, + ) = with(binding) { + setupRowButtons(walletData, rowButtons, isExchangeServiceFeatureEnabled) + lAddress.btnCopy.setOnClickListener { - state.walletAddresses?.selectedAddress?.address?.let { addressString -> + walletData.walletAddresses?.selectedAddress?.address?.let { addressString -> store.dispatch(WalletAction.CopyAddress(addressString, fragment!!.requireContext())) } } lAddress.btnShowQr.setOnClickListener { - state.walletAddresses?.selectedAddress?.let { selectedAddress -> + walletData.walletAddresses?.selectedAddress?.let { selectedAddress -> store.dispatch( WalletAction.DialogAction.QrCode( - currency = state.currency, + currency = walletData.currency, selectedAddress = selectedAddress, ), ) @@ -116,11 +121,16 @@ class SingleWalletView : WalletView() { } } - private fun setupRowButtons(state: WalletData, rowButtons: WalletDetailsButtonsRow) { + private fun setupRowButtons( + walletData: WalletData, + rowButtons: WalletDetailsButtonsRow, + isExchangeServiceFeatureEnabled: Boolean, + ) { rowButtons.updateButtonsVisibility( - buyAllowed = state.isAvailableToBuy, - sellAllowed = state.isAvailableToSell, - sendAllowed = state.mainButton.enabled, + exchangeServiceFeatureOn = isExchangeServiceFeatureEnabled, + buyAllowed = walletData.isAvailableToBuy, + sellAllowed = walletData.isAvailableToSell, + sendAllowed = walletData.mainButton.enabled, ) rowButtons.onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) } @@ -128,7 +138,7 @@ class SingleWalletView : WalletView() { rowButtons.onTradeClick = { store.dispatch(WalletAction.DialogAction.ChooseTradeActionDialog) } rowButtons.onSendClick = { - when (state.mainButton) { + when (walletData.mainButton) { is WalletMainButton.SendButton -> store.dispatch(WalletAction.Send()) is WalletMainButton.CreateWalletButton -> store.dispatch(WalletAction.CreateWallet) } diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt index ecf9d850b3..a7f7b9aec2 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt @@ -12,6 +12,12 @@ class CardExchangeRules( val cardProvider: () -> Card?, ) : ExchangeRules { + override fun featureIsSwitchedOn(): Boolean { + val card = cardProvider() ?: return false + + return !card.isStart2Coin + } + override fun isBuyAllowed(): Boolean { val card = cardProvider() ?: return false diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index 85720c4306..04c92fc542 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -26,6 +26,8 @@ class CurrencyExchangeManager( private val primaryRules: ExchangeRules, ) : ExchangeService, ExchangeUrlBuilder { + override fun featureIsSwitchedOn(): Boolean = primaryRules.featureIsSwitchedOn() + override suspend fun update() { buyService.update() sellService.update() diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt index f7db8b210f..8d6e8e2187 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt @@ -1,13 +1,22 @@ package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain +import com.tangem.tap.common.feature.Feature import com.tangem.tap.features.wallet.models.Currency -interface ExchangeService: ExchangeRules { +interface Exchanger { + fun isBuyAllowed(): Boolean + fun isSellAllowed(): Boolean + fun availableForBuy(currency: Currency):Boolean + fun availableForSell(currency: Currency):Boolean +} + +interface ExchangeService: Feature, Exchanger { suspend fun update() companion object { fun dummy(): ExchangeService = object : ExchangeService { + override fun featureIsSwitchedOn(): Boolean = false override suspend fun update() {} override fun isBuyAllowed(): Boolean = false override fun isSellAllowed(): Boolean = false @@ -17,14 +26,11 @@ interface ExchangeService: ExchangeRules { } } -interface ExchangeRules { - fun isBuyAllowed(): Boolean - fun isSellAllowed(): Boolean - fun availableForBuy(currency: Currency):Boolean - fun availableForSell(currency: Currency):Boolean +interface ExchangeRules: Feature, Exchanger { companion object { fun dummy(): ExchangeRules = object : ExchangeRules { + override fun featureIsSwitchedOn(): Boolean = false override fun isBuyAllowed(): Boolean = false override fun isSellAllowed(): Boolean = false override fun availableForBuy(currency: Currency): Boolean = false diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt index 97190aa9fd..4d00d9a42c 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt @@ -28,6 +28,8 @@ class MercuryoService( private val blockchainsAvailableToBuy = mutableListOf() private val tokensAvailableToBy = mutableMapOf>() + override fun featureIsSwitchedOn(): Boolean = true + override suspend fun update() { when (val result = performRequest { api.currencies(apiVersion) }) { is Result.Success -> { diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt index fa96286e84..00db516c5b 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt @@ -29,6 +29,8 @@ class MoonPayService( private var status: MoonPayStatus? = null + override fun featureIsSwitchedOn(): Boolean = true + override suspend fun update() { withIOContext { performRequest { From 21aef70b4f5fa3db2de67d3a04c067a7f40a3183 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 02:01:55 +0300 Subject: [PATCH 32/36] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_wallet.xml | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index fa0eaf1398..f53b6f7f6d 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -47,7 +47,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" - android:paddingBottom="32dp"> + android:paddingBottom="92dp"> - - + + + From e7cf31c1a20b0ea3d23d4e5789e07fb847085cd6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 02:03:58 +0300 Subject: [PATCH 33/36] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_wallet.xml | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index f53b6f7f6d..d5daad21ea 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -93,6 +93,17 @@ app:barrierDirection="bottom" app:constraint_referenced_ids="iv_card,tv_twin_card_number" /> + + - - Date: Fri, 19 Aug 2022 15:12:01 +0300 Subject: [PATCH 34/36] Updated on 2026-08-14 --- .../wallet/ui/view/WalletDetailsButtonsRow.kt | 18 ++++++------------ .../layout/view_wallet_details_buttons_row.xml | 6 +++--- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt index af6ec9280b..582b5f178c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt @@ -12,12 +12,10 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { - private val binding = ViewWalletDetailsButtonsRowBinding.inflate( LayoutInflater.from(context), this, ) - var onBuyClick: (() -> Unit)? = null var onSellClick: (() -> Unit)? = null var onTradeClick: (() -> Unit)? = null @@ -40,16 +38,12 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( sellAllowed: Boolean, sendAllowed: Boolean, ) = with(binding) { - if (exchangeServiceFeatureOn) { - btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) - btnBuy.isEnabled = buyAllowed - btnSell.isVisible = !buyAllowed && sellAllowed - btnTrade.isVisible = buyAllowed && sellAllowed - } else { - btnBuy.isVisible = false - btnSell.isVisible = false - btnTrade.isVisible = false - } + containerExchangeButtons.isVisible = exchangeServiceFeatureOn + + btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) + btnBuy.isEnabled = buyAllowed + btnSell.isVisible = !buyAllowed && sellAllowed + btnTrade.isVisible = buyAllowed && sellAllowed btnSend.isEnabled = sendAllowed } } \ No newline at end of file diff --git a/app/src/main/res/layout/view_wallet_details_buttons_row.xml b/app/src/main/res/layout/view_wallet_details_buttons_row.xml index 39017f271f..3f62e6c9fb 100644 --- a/app/src/main/res/layout/view_wallet_details_buttons_row.xml +++ b/app/src/main/res/layout/view_wallet_details_buttons_row.xml @@ -8,6 +8,7 @@ tools:parentTag="android.widget.LinearLayout"> + /> @@ -48,7 +49,6 @@ android:id="@+id/btn_send" style="@style/TapButtonWithIcon" android:layout_width="0dp" - android:layout_marginStart="6dp" android:layout_weight="1" android:text="@string/wallet_button_send" app:icon="@drawable/ic_send" /> From de95196ad0b8308faaa6143cd245411e8eba0d37 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 19:27:38 +0300 Subject: [PATCH 35/36] Updated on 2026-08-14 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index d0b96119fd..e1c383532f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-104', + tangem_blockchain_sdk: 'develop-105', // tangem_blockchain_sdk: '0.0.1', ] From 3b4f61f6a92855dc6aa23a4bc0a93dbc6b69a4a0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 19:29:46 +0300 Subject: [PATCH 36/36] Updated on 2026-08-14 --- app/src/main/res/layout/view_wallet_details_buttons_row.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/view_wallet_details_buttons_row.xml b/app/src/main/res/layout/view_wallet_details_buttons_row.xml index 3f62e6c9fb..0a6a51bfdd 100644 --- a/app/src/main/res/layout/view_wallet_details_buttons_row.xml +++ b/app/src/main/res/layout/view_wallet_details_buttons_row.xml @@ -22,7 +22,7 @@ android:text="@string/wallet_button_trade" android:visibility="gone" app:icon="@drawable/ic_arrows_up_down" - /> + tools:visibility="visible" />