diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 14f7b50b6b..7c2ec7f173 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -157,22 +157,22 @@ class TapWalletManager { private fun loadMultiWalletData( card: Card, primaryBlockchain: Blockchain?, primaryWalletManager: WalletManager? ) { - val primaryTokens = primaryWalletManager?.cardTokens ?: emptySet() + val primaryTokens = primaryWalletManager?.cardTokens?.toList() ?: emptyList() val savedCurrencies = currenciesRepository.loadCardCurrencies(card.cardId) if (savedCurrencies == null) { if (primaryBlockchain != null && primaryWalletManager != null) { store.dispatch(WalletAction.MultiWallet.SaveCurrencies( CardCurrencies( - blockchains = setOf(primaryBlockchain), tokens = primaryTokens + blockchains = listOf(primaryBlockchain), tokens = primaryTokens ))) store.dispatch(WalletAction.MultiWallet.AddWalletManagers(primaryWalletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchains(listOf(primaryBlockchain))) store.dispatch(WalletAction.MultiWallet.AddTokens(primaryTokens.toList())) } else { - val blockchains = setOf(Blockchain.Bitcoin, Blockchain.Ethereum) + val blockchains = listOf(Blockchain.Bitcoin, Blockchain.Ethereum) store.dispatch(WalletAction.MultiWallet.SaveCurrencies( - CardCurrencies(blockchains = blockchains, tokens = emptySet()) + CardCurrencies(blockchains = blockchains, tokens = emptyList()) )) val walletManagers = walletManagerFactory.makeWalletManagersForApp(card, blockchains.toList()) diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index 26aa55369c..18ea01ebbc 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -14,14 +14,14 @@ import com.tangem.tap.network.createMoshi class CurrenciesRepository(val context: Application) { private val moshi = createMoshi() - private val blockchainsAdapter: JsonAdapter> = moshi.adapter( - Types.newParameterizedType(Set::class.java, Blockchain::class.java) + private val blockchainsAdapter: JsonAdapter> = moshi.adapter( + Types.newParameterizedType(List::class.java, Blockchain::class.java) ) - private val tokensAdapter: JsonAdapter> = moshi.adapter( - Types.newParameterizedType(Set::class.java, TokenDao::class.java) + private val tokensAdapter: JsonAdapter> = moshi.adapter( + Types.newParameterizedType(List::class.java, TokenDao::class.java) ) - private val obsoleteTokensAdapter: JsonAdapter> = moshi.adapter( - Types.newParameterizedType(Set::class.java, ObsoleteTokenDao::class.java) + private val obsoleteTokensAdapter: JsonAdapter> = moshi.adapter( + Types.newParameterizedType(List::class.java, ObsoleteTokenDao::class.java) ) fun loadCardCurrencies(cardId: String): CardCurrencies? { @@ -51,48 +51,48 @@ class CurrenciesRepository(val context: Application) { } fun removeToken(cardId: String, token: Token) { - val tokens = loadSavedTokens(cardId).filterNot { it == token }.toSet() + val tokens = loadSavedTokens(cardId).filterNot { it == token } saveTokens(cardId, tokens) } fun removeBlockchain(cardId: String, blockchain: Blockchain) { - val blockchains = loadSavedBlockchains(cardId).filterNot { it == blockchain }.toSet() + val blockchains = loadSavedBlockchains(cardId).filterNot { it == blockchain } saveBlockchains(cardId, blockchains) } - private fun loadSavedTokens(cardId: String): Set { + private fun loadSavedTokens(cardId: String): List { val json = try { context.readFileText(getFileNameForTokens(cardId)) } catch (exception: Exception) { - return emptySet() + return emptyList() } return try { - tokensAdapter.fromJson(json)!!.map { it.toToken() }.toSet() + tokensAdapter.fromJson(json)!!.map { it.toToken() } } catch (exception: Exception) { try { - obsoleteTokensAdapter.fromJson(json)!!.map { it.toToken() }.toSet() + obsoleteTokensAdapter.fromJson(json)!!.map { it.toToken() } } catch (exception: Exception) { - emptySet() + emptyList() } } } - private fun saveTokens(cardId: String, tokens: Set) { - val json = tokensAdapter.toJson(tokens.map { TokenDao.fromToken(it) }.toSet()) + private fun saveTokens(cardId: String, tokens: List) { + val json = tokensAdapter.toJson(tokens.map { TokenDao.fromToken(it) }.distinct()) context.rewriteFile(json, getFileNameForTokens(cardId)) } - private fun loadSavedBlockchains(cardId: String): Set { + private fun loadSavedBlockchains(cardId: String): List { return try { val json = context.readFileText(getFileNameForBlockchains(cardId)) - blockchainsAdapter.fromJson(json) ?: emptySet() + blockchainsAdapter.fromJson(json) ?: emptyList() } catch (exception: Exception) { - emptySet() + emptyList() } } - private fun saveBlockchains(cardId: String, blockchains: Set) { + private fun saveBlockchains(cardId: String, blockchains: List) { val json = blockchainsAdapter.toJson(blockchains) context.rewriteFile(json, getFileNameForBlockchains(cardId)) } @@ -224,12 +224,12 @@ data class ObsoleteTokenDao( @JsonClass(generateAdapter = true) data class CardCurrenciesDao( - val tokens: Set, - val blockchains: Set, + val tokens: List, + val blockchains: List, ) { fun toCardCurrencies(): CardCurrencies { return CardCurrencies( - tokens = tokens.map { it.toToken() }.toSet(), + tokens = tokens.map { it.toToken() }.distinct(), blockchains = blockchains ) } @@ -237,7 +237,7 @@ data class CardCurrenciesDao( companion object { fun fromCardCurrencies(cardCurrencies: CardCurrencies): CardCurrenciesDao { return CardCurrenciesDao( - tokens = cardCurrencies.tokens.map { TokenDao.fromToken(it) }.toSet(), + tokens = cardCurrencies.tokens.map { TokenDao.fromToken(it) }.distinct(), blockchains = cardCurrencies.blockchains ) } @@ -245,6 +245,6 @@ data class CardCurrenciesDao( } data class CardCurrencies( - val tokens: Set, - val blockchains: Set, + val tokens: List, + val blockchains: List, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt index cb51e326dd..ac9be2e1a0 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt @@ -10,6 +10,7 @@ import com.tangem.tap.common.extensions.show import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction +import com.tangem.tap.domain.isMultiwalletAllowed import com.tangem.tap.domain.twins.getTwinCardIdForUser import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState @@ -112,6 +113,7 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber { dispatch(FeeAction.FeeCalculation.SetFeeError(FeeAction.Error.REQUEST_FAILED)) - dispatch(FeeAction.ChangeLayoutVisibility(main = false, controls = false, chipGroup = false)) + dispatch(FeeAction.ChangeLayoutVisibility(main = false)) } } dispatch(AmountActionUi.CheckAmountToSend) 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 26d2f8dd27..5f3e43fd59 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 @@ -254,7 +254,7 @@ fun extractErrorsForAmountField(errors: EnumSet): EnumSet { - val notAcceptable = listOf(TransactionError.FeeExceedsBalance, TransactionError.FeeExceedsBalance) + val notAcceptable = listOf(TransactionError.AmountExceedsBalance, TransactionError.FeeExceedsBalance) if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it) } TransactionError.InvalidAmountValue -> showIntoAmountField.add(it) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt index f5da58ab54..d0a1a13072 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt @@ -45,7 +45,7 @@ class FeeReducer : SendInternalReducer { state.copy( mainLayoutIsVisible = getVisibility(state.mainLayoutIsVisible, action.main), controlsLayoutIsVisible = getVisibility(state.controlsLayoutIsVisible, action.controls), - feeChipGroupIsVisible = getVisibility(state.mainLayoutIsVisible, action.chipGroup) + feeChipGroupIsVisible = getVisibility(state.feeChipGroupIsVisible, action.chipGroup) ) } is FeeAction.FeeCalculation.SetFeeResult -> { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt index 66a7dd928b..878eed1113 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt @@ -33,7 +33,7 @@ private fun internalReduce(action: Action, state: AppState): TokensState { } private fun List.toCardCurrencies(): CardCurrencies { - val tokens = mapNotNull { (it.currency as? Currency.Token)?.token }.toSet() - val blockchains = mapNotNull { (it.currency as? Currency.Blockchain)?.blockchain }.toSet() + val tokens = mapNotNull { (it.currency as? Currency.Token)?.token }.distinct() + val blockchains = mapNotNull { (it.currency as? Currency.Blockchain)?.blockchain }.distinct() return CardCurrencies(tokens = tokens, blockchains = blockchains) } \ 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 54e7f12586..e766e87035 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 @@ -132,12 +132,31 @@ data class WalletState( fun replaceWalletInWallets(walletData: WalletData?): List { if (walletData == null) return wallets - return wallets.filter { it.currencyData.currency != walletData.currencyData.currency } + walletData + var changed = false + val updatedWallets = wallets.map { + if (it.currencyData.currency == walletData.currencyData.currency) { + changed = true + walletData + } else { + it + } + } + return if (changed) updatedWallets else wallets + walletData } fun replaceSomeWallets(newWallets: List): List { - val currencies = newWallets.map { it.currencyData.currency } - return wallets.filter { !currencies.contains(it.currencyData.currency) } + newWallets + val remainingWallets: MutableList = newWallets.toMutableList() + val updatedWallets = wallets.map { wallet -> + val newWallet = newWallets + .firstOrNull { wallet.currencyData.currency == it.currencyData.currency } + if (newWallet == null) { + wallet + } else { + remainingWallets.remove(newWallet) + newWallet + } + } + return updatedWallets + remainingWallets } fun addWalletManagers(newWalletManagers: List): WalletState { 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 f2072f7cf3..9a4051f137 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 @@ -84,7 +84,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS btn_share.setOnClickListener { store.dispatch(WalletAction.ShowDialog.QrCode) } - btn_top_up.setOnClickListener { store.dispatch(WalletAction.TradeCryptoAction.Buy) } + btn_trade.setOnClickListener { store.dispatch(WalletAction.TradeCryptoAction.Buy) } btn_sell.setOnClickListener { store.dispatch(WalletAction.TradeCryptoAction.Sell) } } @@ -138,7 +138,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS srl_wallet_details.isRefreshing = false } - btn_top_up.isEnabled = selectedWallet.tradeCryptoState.buyingAllowed + btn_trade.isEnabled = selectedWallet.tradeCryptoState.buyingAllowed btn_sell.show(selectedWallet.tradeCryptoState.sellingAllowed) } @@ -286,7 +286,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.meny_remove -> { + R.id.menu_remove -> { store.state.walletState.getSelectedWalletData()?.let { walletData -> store.dispatch(WalletAction.MultiWallet.RemoveWallet(walletData)) store.dispatch(WalletAction.MultiWallet.SelectWallet(null)) @@ -300,9 +300,11 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - if (store.state.walletState.canBeRemoved(store.state.walletState.getSelectedWalletData())) { - inflater.inflate(R.menu.wallet_details, menu) - } + inflater.inflate(R.menu.wallet_details, menu) + val walletCanBeRemoved = store.state.walletState.canBeRemoved( + store.state.walletState.getSelectedWalletData() + ) + menu.getItem(0).isEnabled = walletCanBeRemoved } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index b90adc2cb6..f804f6acef 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -18,7 +18,6 @@ import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.item_currency_wallet.view.* -import java.math.BigDecimal class WalletAdapter : ListAdapter(DiffUtilCallback) { @@ -28,36 +27,8 @@ class WalletAdapter } fun submitList(list: List, primaryBlockchain: Blockchain?, primaryToken: Token? = null) { - val listModified = list.toMutableList() - val primaryBlockchainWallet = when ( - val index = listModified.indexOfFirst { - (it.currency as? Currency.Blockchain)?.blockchain == primaryBlockchain - } - ) { - -1 -> null - else -> listModified.removeAt(index) - } - - - val primaryTokenWallet = if (primaryToken == null) null else when ( - val index = listModified.indexOfFirst { (it.currency as? Currency.Token)?.token == primaryToken } - ) { - -1 -> null - else -> listModified.removeAt(index) - } - - if (list.all { it.currencyData.fiatAmountFormatted == null }) { - val sortedList = listOfNotNull(primaryBlockchainWallet, primaryTokenWallet) + listModified - super.submitList(sortedList) - return - } - - val sorted = listModified.sortedWith( - compareByDescending { it.currencyData.fiatAmount ?: BigDecimal.ZERO } - .thenBy { it.currencyData.currency } - ) - val sortedList = listOfNotNull(primaryBlockchainWallet, primaryTokenWallet) + sorted - super.submitList(sortedList) + // We used this method to sort the list of currencies. Sorting is disabled for now. + super.submitList(list) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletsViewHolder { 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 2522ba7135..874c3abfec 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 @@ -142,12 +142,10 @@ class SingleWalletView : WalletView { } btn_show_qr.setOnClickListener { store.dispatch(WalletAction.ShowDialog.QrCode) } - btn_top_up.setOnClickListener { - tradeCryptoAction(state.tradeCryptoState) - } + setupTradeButton(fragment, state.tradeCryptoState) } - private fun tradeCryptoAction(tradeCryptoState: TradeCryptoState) { + private fun setupTradeButton(fragment: WalletFragment, tradeCryptoState: TradeCryptoState) { val allowedToBuy = tradeCryptoState.buyingAllowed val allowedToSell = tradeCryptoState.sellingAllowed val action = when { @@ -156,7 +154,23 @@ class SingleWalletView : WalletView { allowedToBuy && allowedToSell -> WalletAction.ShowDialog.ChooseTradeActionDialog else -> null } - if (action != null) store.dispatch(action) + 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_short_btn + !allowedToBuy && allowedToSell -> R.drawable.ic_arrow_down_short_button + allowedToBuy && allowedToSell -> R.drawable.ic_arrows_up_down_short_btn + else -> R.string.wallet_button_trade + } + with(fragment) { + btn_trade.text = getText(text) + btn_trade.setCompoundDrawablesWithIntrinsicBounds(0, icon, 0, 0) + btn_trade.setOnClickListener { if (action != null) store.dispatch(action) } + } } private fun setupButtonsType(state: WalletData, fragment: WalletFragment) = with(fragment) { diff --git a/app/src/main/res/color/menu_item_color.xml b/app/src/main/res/color/menu_item_color.xml new file mode 100644 index 0000000000..f8d7307051 --- /dev/null +++ b/app/src/main/res/color/menu_item_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_down_short_button.xml b/app/src/main/res/drawable/ic_arrow_down_short_button.xml new file mode 100644 index 0000000000..18b58e3f6c --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_down_short_button.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/app/src/main/res/layout/fragment_details.xml b/app/src/main/res/layout/fragment_details.xml index 70c51c9eb3..90df722e29 100644 --- a/app/src/main/res/layout/fragment_details.xml +++ b/app/src/main/res/layout/fragment_details.xml @@ -43,27 +43,46 @@ android:layout_marginEnd="16dp" android:layout_marginBottom="33dp"> + + + + + app:layout_constraintTop_toBottomOf="@id/tv_card_title" /> + + + + + - - + app:layout_constraintTop_toBottomOf="@id/tv_security_title" /> + app:layout_constraintTop_toBottomOf="@id/tv_erase_wallet" /> + @@ -187,6 +222,37 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_settings_title" /> + + + + + app:layout_constraintTop_toBottomOf="@id/tv_card_tou" /> - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_wallet_details.xml b/app/src/main/res/layout/fragment_wallet_details.xml index 7b61f56d8d..27da2ac50f 100644 --- a/app/src/main/res/layout/fragment_wallet_details.xml +++ b/app/src/main/res/layout/fragment_wallet_details.xml @@ -23,6 +23,7 @@ android:layout_height="?attr/actionBarSize" app:menu="@menu/wallet_details" app:navigationIcon="@drawable/ic_baseline_arrow_back_24" + android:theme="@style/ThemeOverlay.MyTheme.Toolbar" app:title=" " /> @@ -131,7 +132,7 @@ app:constraint_referenced_ids="l_wallet_details,card_pending_transaction_warning" /> + app:constraint_referenced_ids="btn_trade, btn_sell" /> diff --git a/app/src/main/res/layout/layout_wallet_short_buttons.xml b/app/src/main/res/layout/layout_wallet_short_buttons.xml index be494ee95b..61217164ee 100644 --- a/app/src/main/res/layout/layout_wallet_short_buttons.xml +++ b/app/src/main/res/layout/layout_wallet_short_buttons.xml @@ -9,6 +9,7 @@ android:id="@+id/btn_scan_short" style="@style/TapBlackButton" android:layout_width="0dp" + android:layout_height="52dp" android:layout_marginStart="16dp" android:layout_marginTop="30dp" android:layout_marginBottom="33dp" @@ -17,14 +18,15 @@ android:paddingTop="7dp" android:text="@string/wallet_button_scan" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@id/btn_top_up" + app:layout_constraintEnd_toStartOf="@id/btn_trade" app:layout_constraintStart_toStartOf="parent" app:layout_constraintVertical_bias="1" /> \ No newline at end of file diff --git a/app/src/main/res/menu/wallet_details.xml b/app/src/main/res/menu/wallet_details.xml index 9622311e82..08ba8df389 100644 --- a/app/src/main/res/menu/wallet_details.xml +++ b/app/src/main/res/menu/wallet_details.xml @@ -2,7 +2,7 @@ \ No newline at end of file diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index f189ef8196..314565b97f 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -89,6 +89,7 @@ ex. USD Coin ex. USDC Added + Remove token //Details Blockchain diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 43173d1bad..286cddae59 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -20,6 +20,14 @@ @android:color/white + + +