From b8d5c8f4f21ca10881e25167f16b8bb77efadf65 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 21 Apr 2022 07:44:33 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/common/compose/OutlinedSpinner.kt | 40 ++++++++++-- .../ui/test/TestWalletDetailsActions.kt | 24 ++----- .../com/tangem/domain/common/form/Form.kt | 16 ++++- .../addCustomToken/redux/AddCustomTokenHub.kt | 65 +++++++++++++++---- .../redux/AddCustomTokenState.kt | 34 ++++++++-- 5 files changed, 138 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt b/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt index 1cc41acbf1..dfcdf48551 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt @@ -10,6 +10,7 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.common.extensions.VoidCallback import com.tangem.domain.common.form.Field import com.tangem.tap.common.extensions.ValueCallback +import timber.log.Timber /** [REDACTED_AUTHOR] @@ -27,14 +28,24 @@ fun OutlinedSpinner( isEnabled: Boolean = true, onClose: VoidCallback = {} ) { + val compositionCounter = remember { CompositionCounter(label) } + val counter = compositionCounter.increase(label) + val rIsExpanded = remember { mutableStateOf(false) } - val rSelectedItem = remember { mutableStateOf(selectedItem.value) } + val stateSelectedItem = remember { mutableStateOf(selectedItem.value) } + osLog(label, "recompose ------------------------------------", counter) + osLog(label, "selectedItem: $selectedItem", counter) + osLog(label, "stateSelectedItem: ${stateSelectedItem.value}", counter) if (!selectedItem.isUserInput) { - rSelectedItem.value = selectedItem.value + osLog(label, "stateSelectedItem.value: update = selectedItem.value", counter) + stateSelectedItem.value = selectedItem.value } + osLog(label, "stateSelectedItem: ${stateSelectedItem.value}", counter) val onDropDownItemSelectedInternal: (T) -> Unit = { - rSelectedItem.value = it + osLog(label, "onDropDownItemSelectedInternal: value: [${it.toString()}]", counter) + stateSelectedItem.value = it + osLog(label, "onDropDownItemSelectedInternal: stateSelectedItem: ${stateSelectedItem.value}", counter) rIsExpanded.value = false onItemSelected(it) } @@ -51,7 +62,7 @@ fun OutlinedSpinner( modifier = modifier, readOnly = true, enabled = isEnabled, - value = textFieldConverter(rSelectedItem.value), + value = textFieldConverter(stateSelectedItem.value), onValueChange = {}, label = { Text(label) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = rIsExpanded.value) }, @@ -74,6 +85,27 @@ fun OutlinedSpinner( } } +private fun osLog(id: String, log: String, counter: CompositionCounter) { + if (id == "Сеть") Timber.d( + "OutlinedSpinner[$id]:[${counter.count}] - $log" + ) +} + +class CompositionCounter( + val id: String, + count: Int = 0 +) { + var count: Int = count + private set + + fun increase(id: String): CompositionCounter { + if (this.id != id) return this + + count += 1 + return CompositionCounter(id, count) + } +} + @Preview @Composable fun TestSpinnerPreview() { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt index 1c32663fc8..e72efc46ac 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt @@ -1,10 +1,7 @@ package com.tangem.tap.features.wallet.ui.test -import com.tangem.blockchain.blockchains.solana.SolanaWalletManager import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.Blockchain -import com.tangem.domain.common.ScanResponse -import com.tangem.domain.common.TapWorkarounds.isTestCard +import com.tangem.blockchain.common.WalletManager import com.tangem.tap.common.TestAction import com.tangem.tap.common.TestActions import com.tangem.tap.domain.tokens.BlockchainNetwork @@ -68,7 +65,7 @@ private class SolanaRentWarningActionEmitter { } private fun setBalance(value: BigDecimal) { - val amount = Amount(getBlockchain()).copy(value = value) + val amount = Amount(getBlockchainNetwork().blockchain).copy(value = value) getWalletManager().apply { TestActions.testAmountInjectionForWalletManagerEnabled = true wallet.setAmount(amount) @@ -76,19 +73,12 @@ private class SolanaRentWarningActionEmitter { store.dispatch(WalletAction.LoadData) } - private fun getWalletManager(): SolanaWalletManager { - return store.state.walletState.getWalletManager(BlockchainNetwork( - blockchain = getBlockchain(), - card = scanResponse().card - )) as SolanaWalletManager + private fun getWalletManager(): WalletManager { + return store.state.walletState.getWalletManager(getBlockchainNetwork())!! } - private fun getBlockchain(): Blockchain = when { - scanResponse().card.isTestCard -> Blockchain.SolanaTestnet - else -> Blockchain.Solana - } - - private fun scanResponse(): ScanResponse { - return store.state.globalState.scanResponse ?: throw UnsupportedOperationException() + private fun getBlockchainNetwork(): BlockchainNetwork { + val currency = store.state.walletState.getSelectedWalletData()!!.currency + return BlockchainNetwork(currency.blockchain, currency.derivationPath, listOf()) } } \ No newline at end of file diff --git a/domain/src/main/java/com/tangem/domain/common/form/Form.kt b/domain/src/main/java/com/tangem/domain/common/form/Form.kt index 5788f13b1e..81758003bc 100644 --- a/domain/src/main/java/com/tangem/domain/common/form/Form.kt +++ b/domain/src/main/java/com/tangem/domain/common/form/Form.kt @@ -4,12 +4,26 @@ package com.tangem.domain.common.form [REDACTED_AUTHOR] */ class Form( - val fieldList: List>, + fieldList: List>, ) { + private val _fieldList: MutableList> = fieldList.toMutableList() + + val fieldList: List> + get() = _fieldList.toList() + fun getField(id: FieldId): DataField<*>? = fieldList.firstOrNull { it.id == id } fun getData(id: FieldId): Pair? = getField(id)?.getData() + fun setField(field: DataField<*>) { + val oldField = getField(field.id) ?: return + val oldIndexOfField = _fieldList.indexOf(oldField) + if (oldIndexOfField == -1) return + + _fieldList.removeAt(oldIndexOfField) + _fieldList.add(oldIndexOfField, field) + } + // convert this form data whatever you want fun visitDataConverter(converter: FieldDataConverter<*>) { fieldList.forEach { it.visitDataConverter(converter) } diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt index 672abcec92..33084f8cb8 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt @@ -65,31 +65,25 @@ internal class AddCustomTokenHub : BaseStoreHub("AddCustomT null -> { ContractAddress.removeError() unlockTokenFields() + changeBlockchainNetworkList() } AddCustomTokenError.FieldIsEmpty -> { ContractAddress.removeError() + changeBlockchainNetworkList() return } AddCustomTokenError.InvalidContractAddress -> { ContractAddress.addError(error) unlockTokenFields() + changeBlockchainNetworkList() return } else -> {} } - if (!action.contractAddress.isUserInput) return + manageFoundTokenChanges(requestInfoAboutToken(address)) } - is OnTokenNameChanged -> { - updateAddButton() - } - is OnTokenSymbolChanged -> { - updateAddButton() - } - is OnTokenDecimalsChanged -> { - updateAddButton() - } is OnTokenNetworkChanged -> { if (!action.blockchainNetwork.isUserInput) return @@ -122,13 +116,25 @@ internal class AddCustomTokenHub : BaseStoreHub("AddCustomT updateWarningAlreadyAdded(isAlreadyAdded) updateAddButton() } + is OnTokenNameChanged -> { + changeBlockchainNetworkList() + updateAddButton() + } + is OnTokenSymbolChanged -> { + changeBlockchainNetworkList() + updateAddButton() + } + is OnTokenDecimalsChanged -> { + changeBlockchainNetworkList() + updateAddButton() + } is OnAddCustomTokenClicked -> { val state = hubState val completeData = when { - state.tokensFieldsIsFilled() && state.networkIsSelected() -> { + state.getCustomTokenType() == CustomTokenType.Token && state.networkIsSelected() -> { state.gatherUserToken() } - !state.tokensFieldsIsFilled() && state.networkIsSelected() -> { + state.getCustomTokenType() == CustomTokenType.Blockchain && state.networkIsSelected() -> { state.gatherBlockchain() } else -> null @@ -146,6 +152,41 @@ internal class AddCustomTokenHub : BaseStoreHub("AddCustomT } } + /** + * This feature is only needed until Solana tokens are added. + * While they are not there - this function excludes the Solana blockchain if the user has + * filled in at least one field of the token. + */ + private suspend fun changeBlockchainNetworkList() { + val state = hubState + val networkBlockchainList = Network.getField().itemList + val newNetworkBlockchainList: List = state.getNetworks(state.getCustomTokenType()) + + val listsIdentical = newNetworkBlockchainList.toSet() == networkBlockchainList.toSet() + if (listsIdentical) return + + val networkFieldIsFilled = Network.isFilled() + val newNetworkField = Network.getField().copy(itemList = newNetworkBlockchainList) + if (networkFieldIsFilled) { + val listSameSize = networkBlockchainList.size == newNetworkBlockchainList.size + val newListLessThanOld = networkBlockchainList.size > newNetworkBlockchainList.size + if (listSameSize || newListLessThanOld) { +// check selected blockchain + val selectedBlockchain = Network.getFieldValue() + val defaultSelection = Blockchain.Unknown + if (!newNetworkBlockchainList.contains(selectedBlockchain) + && newNetworkBlockchainList.contains(defaultSelection) + ) { +// selectedBlockchain not present in the new list. Change selection to default + newNetworkField.data = Field.Data(defaultSelection, false) + } + } + } + + hubState.setField(newNetworkField) + dispatchOnMain(UpdateForm(hubState)) + } + private suspend fun updateWarningAlreadyAdded(isInAppSavedList: Boolean) { if (isInAppSavedList) { TokenAlreadyAdded.add() diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt index 1d359780bd..f7f01351ec 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenState.kt @@ -13,7 +13,7 @@ data class AddCustomTokenState( val appSavedCurrencies: List? = null, val onTokenAddCallback: ((CustomCurrency) -> Unit)? = null, val cardDerivationStyle: DerivationStyle? = null, - val form: Form = Form(createFormFields()), + val form: Form = Form(createFormFields(CustomTokenType.Blockchain)), val formValidators: Map> = createFormValidators(), val formErrors: Map = emptyMap(), val tokenId: String? = null, @@ -24,6 +24,10 @@ data class AddCustomTokenState( inline fun getField(id: FieldId): T = form.getField(id) as T + fun setField(field: DataField<*>) { + form.setField(field) + } + inline fun getValidator(id: FieldId): T = formValidators[id] as T fun getError(id: FieldId): AddCustomTokenError? = formErrors[id] @@ -80,6 +84,11 @@ data class AddCustomTokenState( return network.data.value != Blockchain.Unknown } + fun getCustomTokenType(): CustomTokenType = when { + tokensOneFieldsIsFilled() || tokensFieldsIsFilled() -> CustomTokenType.Token + else -> CustomTokenType.Blockchain + } + fun gatherUserToken(): CustomCurrency.CustomToken? = try { getToken() } catch (ex: Exception) { @@ -97,7 +106,7 @@ data class AddCustomTokenState( appSavedCurrencies = null, onTokenAddCallback = null, cardDerivationStyle = null, - form = Form(createFormFields()), + form = Form(createFormFields(CustomTokenType.Blockchain)), formErrors = emptyMap(), tokenId = null, warnings = emptySet(), @@ -118,6 +127,10 @@ data class AddCustomTokenState( .getConvertedData() } + fun getNetworks(type: CustomTokenType): List { + return getSupportedNetworks(type) + } + companion object { /** @@ -133,10 +146,10 @@ data class AddCustomTokenState( else -> derivationNetwork }.derivationPath(derivationStyle) - private fun createFormFields(): List> { + private fun createFormFields(type: CustomTokenType): List> { return listOf( TokenField(ContractAddress), - TokenBlockchainField(Network, getSupportedNetworks()), + TokenBlockchainField(Network, getSupportedNetworks(type)), TokenField(Name), TokenField(Symbol), TokenField(Decimals), @@ -154,17 +167,20 @@ data class AddCustomTokenState( ) } - private fun getSupportedNetworks(): List { - return listOf( + private fun getSupportedNetworks(type: CustomTokenType): List { + val networks = mutableListOf( Blockchain.Unknown, Blockchain.Ethereum, Blockchain.BSC, Blockchain.Binance, Blockchain.Polygon, Blockchain.Avalanche, -// Blockchain.Solana, // not supported until tokens added to the Blockchain SDK Blockchain.Fantom, + Blockchain.Solana, // should be unsupported for tokens until they are added to the Blockchain SDK ) + if (type == CustomTokenType.Token) networks.remove(Blockchain.Solana) + + return networks } private fun getSupportedDerivations(): List { @@ -186,4 +202,8 @@ data class AddCustomTokenState( ) } } +} + +enum class CustomTokenType { + Token, Blockchain } \ No newline at end of file