From beba535d520f251f86c94764cc8dd13678d66fc1 Mon Sep 17 00:00:00 2001 From: Rafael Muhamedzyanov Date: Mon, 23 Oct 2023 15:49:58 +0600 Subject: [PATCH] Show transaction filters in separate page --- .../horizontalsystems/bankwallet/core/App.kt | 2 +- .../bankwallet/core/Interfaces.kt | 2 + .../core/managers/LocalStorageManager.kt | 14 + .../bankwallet/core/managers/SpamManager.kt | 24 +- .../transactions/FilterBlockchainFragment.kt | 135 ++++++++++ .../ITransactionRecordRepository.kt | 1 + .../transactions/TransactionAdapterWrapper.kt | 7 + .../transactions/TransactionFilterService.kt | 15 +- .../TransactionRecordRepository.kt | 10 + .../TransactionsFilterFragment.kt | 243 ++++++++++++++++++ .../transactions/TransactionsModule.kt | 2 +- .../transactions/TransactionsScreen.kt | 59 +---- .../transactions/TransactionsService.kt | 16 ++ .../transactions/TransactionsViewModel.kt | 16 +- app/src/main/res/drawable/ic_sort_24.xml | 24 ++ app/src/main/res/navigation/main_graph.xml | 6 + app/src/main/res/values/strings.xml | 7 + 17 files changed, 521 insertions(+), 62 deletions(-) create mode 100644 app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/FilterBlockchainFragment.kt create mode 100644 app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsFilterFragment.kt create mode 100644 app/src/main/res/drawable/ic_sort_24.xml diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt index 54fb91d07e3..c9e74ecc9bf 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt @@ -440,7 +440,7 @@ class App : CoreApp(), WorkConfiguration.Provider, ImageLoaderFactory { contactsRepository = contactsRepository ) - spamManager = SpamManager() + spamManager = SpamManager(localStorage) startTasks() } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt index ac10e98ee5e..00c6bd39204 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt @@ -111,6 +111,8 @@ interface ILocalStorage { val marketsTabEnabledFlow: StateFlow var nonRecommendedAccountAlertDismissedAccounts: Set var personalSupportEnabled: Boolean + var hideUnknownTokens: Boolean + var hideStablecoinsNegligibleAmount: Boolean fun getSwapProviderId(blockchainType: BlockchainType): String? fun setSwapProviderId(blockchainType: BlockchainType, providerId: String) diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/LocalStorageManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/LocalStorageManager.kt index 3d5e781b8bf..f5388779e74 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/LocalStorageManager.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/LocalStorageManager.kt @@ -79,6 +79,8 @@ class LocalStorageManager( private val PERSONAL_SUPPORT_ENABLED = "personal_support_enabled" private val APP_ID = "app_id" private val APP_AUTO_LOCK_INTERVAL = "app_auto_lock_interval" + private val HIDE_UNKNOWN_TOKENS = "hide_unknown_tokens" + private val HIDE_STABLECOINS_NEGLIGIBLE_AMOUNT = "hide_stablecoins_negligible_amount" private val gson by lazy { Gson() } @@ -454,6 +456,18 @@ class LocalStorageManager( preferences.edit().putBoolean(PERSONAL_SUPPORT_ENABLED, enabled).apply() } + override var hideUnknownTokens: Boolean + get() = preferences.getBoolean(HIDE_UNKNOWN_TOKENS, true) + set(value) { + preferences.edit().putBoolean(HIDE_UNKNOWN_TOKENS, value).apply() + } + + override var hideStablecoinsNegligibleAmount: Boolean + get() = preferences.getBoolean(HIDE_STABLECOINS_NEGLIGIBLE_AMOUNT, true) + set(value) { + preferences.edit().putBoolean(HIDE_STABLECOINS_NEGLIGIBLE_AMOUNT, value).apply() + } + private val _marketsTabEnabledFlow = MutableStateFlow(marketsTabEnabled) override val marketsTabEnabledFlow = _marketsTabEnabledFlow.asStateFlow() diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt index dd8c8192afb..63505828894 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt @@ -1,13 +1,21 @@ package io.horizontalsystems.bankwallet.core.managers +import io.horizontalsystems.bankwallet.core.ILocalStorage import io.horizontalsystems.bankwallet.entities.TransactionValue import io.horizontalsystems.bankwallet.entities.transactionrecords.evm.TransferEvent import java.math.BigDecimal -class SpamManager { +class SpamManager( + private val localStorage: ILocalStorage +) { private val stableCoinCodes = listOf("USDT", "USDC", "DAI", "BUSD", "EURS") private val negligibleValue = BigDecimal("0.01") + var hideUnknownTokens = localStorage.hideUnknownTokens + private set + var hideStablecoinsDust = localStorage.hideStablecoinsNegligibleAmount + private set + fun isSpam( incomingEvents: List, outgoingEvents: List @@ -26,16 +34,26 @@ class SpamManager { eventValue.value <= BigDecimal.ZERO } - else -> true + else -> hideUnknownTokens } } private fun spamValue(coinCode: String, value: BigDecimal): Boolean { - return if (stableCoinCodes.contains(coinCode)) { + return if (hideStablecoinsDust && stableCoinCodes.contains(coinCode)) { value < negligibleValue } else { value <= BigDecimal.ZERO } } + fun updateFilterHideUnknownTokens(hide: Boolean) { + localStorage.hideUnknownTokens = hide + hideUnknownTokens = hide + } + + fun updateFilterHideStablecoinsDust(hide: Boolean) { + localStorage.hideStablecoinsNegligibleAmount = hide + hideStablecoinsDust = hide + } + } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/FilterBlockchainFragment.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/FilterBlockchainFragment.kt new file mode 100644 index 00000000000..35007de6163 --- /dev/null +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/FilterBlockchainFragment.kt @@ -0,0 +1,135 @@ +package io.horizontalsystems.bankwallet.modules.transactions + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Icon +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import androidx.navigation.navGraphViewModels +import coil.compose.rememberAsyncImagePainter +import io.horizontalsystems.bankwallet.R +import io.horizontalsystems.bankwallet.core.BaseComposeFragment +import io.horizontalsystems.bankwallet.core.imageUrl +import io.horizontalsystems.bankwallet.ui.compose.ComposeAppTheme +import io.horizontalsystems.bankwallet.ui.compose.components.AppBar +import io.horizontalsystems.bankwallet.ui.compose.components.CellMultilineClear +import io.horizontalsystems.bankwallet.ui.compose.components.HsBackButton +import io.horizontalsystems.bankwallet.ui.compose.components.body_leah +import io.horizontalsystems.marketkit.models.Blockchain + +class FilterBlockchainFragment : BaseComposeFragment() { + + private val viewModel by navGraphViewModels(R.id.mainFragment) + + @Composable + override fun GetContent(navController: NavController) { + ComposeAppTheme { + FilterBlockchainScreen(navController, viewModel) + } + } +} + + +@Composable +fun FilterBlockchainScreen(navController: NavController, viewModel: TransactionsViewModel) { + val filterBlockchains by viewModel.filterBlockchainsLiveData.observeAsState() + + ComposeAppTheme { + Surface(color = ComposeAppTheme.colors.tyler) { + Column { + AppBar( + title = stringResource(R.string.Transactions_Filter_ChooseBlockchain), + navigationIcon = { + HsBackButton(onClick = navController::popBackStack) + } + ) + filterBlockchains?.let { blockchains -> + LazyColumn( + contentPadding = PaddingValues(bottom = 32.dp) + ) { + items(blockchains) { filterItem -> + BlockchainCell(viewModel, filterItem, navController) + } + } + } + } + } + } +} + +@Composable +private fun BlockchainCell( + viewModel: TransactionsViewModel, + filterItem: Filter, + navController: NavController +) { + CellMultilineClear(borderTop = true) { + Row( + modifier = Modifier + .fillMaxSize() + .clickable { + viewModel.onEnterFilterBlockchain(filterItem) + navController.popBackStack() + } + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + val blockchain = filterItem.item + if (blockchain != null) { + Image( + painter = rememberAsyncImagePainter( + model = blockchain.type.imageUrl, + error = painterResource(R.drawable.ic_platform_placeholder_32) + ), + modifier = Modifier + .padding(end = 16.dp) + .size(32.dp), + contentDescription = null + ) + body_leah( + modifier = Modifier + .padding(horizontal = 16.dp) + .weight(1f), + text = blockchain.name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } else { + Image( + painter = painterResource(R.drawable.icon_24_circle_coin), + modifier = Modifier + .padding(end = 16.dp) + .size(24.dp), + contentDescription = null + ) + body_leah(text = stringResource(R.string.Transactions_Filter_AllBlockchains)) + } + if (filterItem.selected) { + Spacer(modifier = Modifier.weight(1f)) + Icon( + painter = painterResource(R.drawable.icon_20_check_1), + contentDescription = null, + tint = ComposeAppTheme.colors.jacob + ) + } + } + } +} diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/ITransactionRecordRepository.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/ITransactionRecordRepository.kt index a978092657b..d3684f8d527 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/ITransactionRecordRepository.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/ITransactionRecordRepository.kt @@ -17,4 +17,5 @@ interface ITransactionRecordRepository : Clearable { fun setWalletAndBlockchain(transactionWallet: TransactionWallet?, blockchain: Blockchain?) fun setTransactionType(transactionType: FilterTransactionType) fun loadNext() + fun reload() } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionAdapterWrapper.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionAdapterWrapper.kt index f545298b4d8..64bef143769 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionAdapterWrapper.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionAdapterWrapper.kt @@ -26,6 +26,13 @@ class TransactionAdapterWrapper( subscribeForUpdates() } + fun reload() { + unsubscribeFromUpdates() + transactionRecords.clear() + allLoaded = false + subscribeForUpdates() + } + fun setTransactionType(transactionType: FilterTransactionType) { unsubscribeFromUpdates() diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionFilterService.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionFilterService.kt index 938cd744557..e1b94ea6ed7 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionFilterService.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionFilterService.kt @@ -1,12 +1,15 @@ package io.horizontalsystems.bankwallet.modules.transactions +import io.horizontalsystems.bankwallet.core.managers.SpamManager import io.horizontalsystems.bankwallet.entities.Wallet import io.horizontalsystems.marketkit.models.Blockchain import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -class TransactionFilterService { +class TransactionFilterService( + private val spamManager: SpamManager, +) { private var transactionWallets: List = listOf(null) var selectedWallet: TransactionWallet? = null private set @@ -17,6 +20,8 @@ class TransactionFilterService { private val _resetEnabled = MutableStateFlow(false) val resetEnabled = _resetEnabled.asStateFlow() + val filterHideUnknownTokens = spamManager.hideUnknownTokens + val filterHideStablecoinsDust = spamManager.hideStablecoinsDust private var blockchains: List = listOf(null) @@ -91,4 +96,12 @@ class TransactionFilterService { || selectedTransactionType != FilterTransactionType.All } } + + fun setFilterHideUnknownTokens(hide: Boolean) { + spamManager.updateFilterHideUnknownTokens(hide) + } + + fun setFilterHideStablecoinsDust(hide: Boolean) { + spamManager.updateFilterHideStablecoinsDust(hide) + } } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionRecordRepository.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionRecordRepository.kt index f51d78a9a3b..7a04f70d21b 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionRecordRepository.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionRecordRepository.kt @@ -169,6 +169,16 @@ class TransactionRecordRepository( } } + override fun reload() { + adaptersMap.forEach { (_, transactionAdapterWrapper) -> + transactionAdapterWrapper.reload() + } + unsubscribeFromUpdates() + allLoaded.set(false) + loadItems(1) + subscribeForUpdates() + } + private fun unsubscribeFromUpdates() { disposableUpdates?.dispose() } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsFilterFragment.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsFilterFragment.kt new file mode 100644 index 00000000000..edb4f54fc43 --- /dev/null +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsFilterFragment.kt @@ -0,0 +1,243 @@ +package io.horizontalsystems.bankwallet.modules.transactions + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Icon +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import androidx.navigation.navGraphViewModels +import io.horizontalsystems.bankwallet.R +import io.horizontalsystems.bankwallet.core.BaseComposeFragment +import io.horizontalsystems.bankwallet.core.slideFromRight +import io.horizontalsystems.bankwallet.modules.evmfee.ButtonsGroupWithShade +import io.horizontalsystems.bankwallet.ui.compose.ComposeAppTheme +import io.horizontalsystems.bankwallet.ui.compose.TranslatableString +import io.horizontalsystems.bankwallet.ui.compose.components.AppBar +import io.horizontalsystems.bankwallet.ui.compose.components.ButtonPrimaryYellow +import io.horizontalsystems.bankwallet.ui.compose.components.CellSingleLineLawrenceSection +import io.horizontalsystems.bankwallet.ui.compose.components.HsBackButton +import io.horizontalsystems.bankwallet.ui.compose.components.HsSwitch +import io.horizontalsystems.bankwallet.ui.compose.components.InfoText +import io.horizontalsystems.bankwallet.ui.compose.components.MenuItem +import io.horizontalsystems.bankwallet.ui.compose.components.VSpacer +import io.horizontalsystems.bankwallet.ui.compose.components.body_leah + +class TransactionsFilterFragment : BaseComposeFragment() { + + private val viewModel by navGraphViewModels(R.id.mainFragment) + + @Composable + override fun GetContent(navController: NavController) { + ComposeAppTheme { + FilterScreen( + navController, + viewModel + ) + } + } + +} + + +@Composable +fun FilterScreen( + navController: NavController, + viewModel: TransactionsViewModel, +) { + val filterResetEnabled by viewModel.filterResetEnabled.collectAsState() + val filterCoins by viewModel.filterCoinsLiveData.observeAsState() + val filterBlockchains by viewModel.filterBlockchainsLiveData.observeAsState() + val filterHideUnknownTokens = viewModel.filterHideUnknownTokens + val filterStablecoinsDust = viewModel.filterHideStablecoinsDust + + val filterCoin = filterCoins?.find { it.selected }?.item + val coinCode = filterCoin?.token?.coin?.code + val badge = filterCoin?.badge + val selectedCoinFilterTitle = when { + badge != null -> "$coinCode ($badge)" + else -> coinCode + } + + val filterBlockchain = filterBlockchains?.firstOrNull { it.selected }?.item + + ComposeAppTheme { + Scaffold( + backgroundColor = ComposeAppTheme.colors.tyler, + topBar = { + AppBar( + title = stringResource(R.string.Transactions_Filter), + navigationIcon = { + HsBackButton(onClick = navController::popBackStack) + }, + menuItems = listOf( + MenuItem( + title = TranslatableString.ResString(R.string.Button_Reset), + enabled = filterResetEnabled, + onClick = { + viewModel.resetFilters() + } + ) + ) + ) + } + ) { + Column(Modifier.padding(it)) { + Column( + modifier = Modifier + .weight(1f) + .verticalScroll(rememberScrollState()) + ) { + VSpacer(12.dp) + CellSingleLineLawrenceSection( + listOf { + FilterDropdownCell( + title = stringResource(R.string.Market_Filter_Blockchains), + value = filterBlockchain?.name, + onClick = { + navController.slideFromRight(R.id.filterBlockchainFragment) + } + ) + } + ) + VSpacer(32.dp) + CellSingleLineLawrenceSection( + listOf { + FilterDropdownCell( + title = stringResource(R.string.Transactions_Coins), + value = selectedCoinFilterTitle, + onClick = { + navController.slideFromRight(R.id.filterCoinFragment) + } + ) + } + ) + VSpacer(32.dp) + CellSingleLineLawrenceSection( + listOf { + FilterSwitch( + title = stringResource(R.string.Transactions_Filter_HideUnknownTokens), + enabled = filterHideUnknownTokens, + onChecked = { checked -> + viewModel.updateFilterHideUnknownTokens(checked) + } + ) + } + ) + VSpacer(32.dp) + CellSingleLineLawrenceSection( + listOf { + FilterSwitch( + title = stringResource(R.string.Transactions_Filter_StablecoinDustAmount), + enabled = filterStablecoinsDust, + onChecked = { checked -> + viewModel.updateFilterHideStablecoinsDust(checked) + } + ) + } + ) + InfoText( + text = stringResource(R.string.Transactions_Filter_StablecoinDustAmount_Description), + ) + VSpacer(24.dp) + } + + ButtonsGroupWithShade { + ButtonPrimaryYellow( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + title = stringResource(R.string.Button_Apply), + onClick = { + navController.popBackStack() + }, + ) + } + } + } + } +} + +@Composable +private fun FilterDropdownCell( + title: String, + value: String?, + onClick: () -> Unit +) { + Row( + modifier = Modifier + .fillMaxHeight() + .clickable { + onClick.invoke() + } + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + body_leah( + text = title, + modifier = Modifier.weight(1f), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Row( + Modifier.fillMaxHeight(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = value ?: stringResource(R.string.Any), + maxLines = 1, + style = ComposeAppTheme.typography.body, + color = if (value != null) ComposeAppTheme.colors.leah else ComposeAppTheme.colors.grey, + ) + Icon( + modifier = Modifier.padding(start = 4.dp), + painter = painterResource(id = R.drawable.ic_down_arrow_20), + contentDescription = null, + tint = ComposeAppTheme.colors.grey + ) + } + } +} + +@Composable +private fun FilterSwitch( + title: String, + enabled: Boolean, + onChecked: (Boolean) -> Unit, +) { + Row( + modifier = Modifier + .fillMaxHeight() + .clickable { onChecked(!enabled) } + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + body_leah( + text = title, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Spacer(Modifier.weight(1f)) + HsSwitch( + checked = enabled, + onCheckedChange = onChecked, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsModule.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsModule.kt index 91d121e8f1e..4bf2d4291a2 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsModule.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsModule.kt @@ -22,7 +22,7 @@ object TransactionsModule { App.contactsRepository, App.transactionAdapterManager, App.walletManager, - TransactionFilterService(), + TransactionFilterService(App.spamManager), NftMetadataService(App.nftMetadataManager) ), TransactionViewItemFactory(App.evmLabelManager, App.contactsRepository, App.balanceHiddenManager), diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsScreen.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsScreen.kt index 21bb58fa635..d4a719abaef 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsScreen.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsScreen.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import io.horizontalsystems.bankwallet.R import io.horizontalsystems.bankwallet.core.slideFromBottom +import io.horizontalsystems.bankwallet.core.slideFromRight import io.horizontalsystems.bankwallet.entities.ViewState import io.horizontalsystems.bankwallet.modules.balance.BalanceAccountsViewModel import io.horizontalsystems.bankwallet.modules.balance.BalanceModule @@ -46,7 +47,6 @@ fun TransactionsScreen( val transactions by viewModel.transactionList.observeAsState() val viewState by viewModel.viewState.observeAsState() val syncing by viewModel.syncingLiveData.observeAsState(false) - val filterResetEnabled by viewModel.filterResetEnabled.collectAsState() Surface(color = ComposeAppTheme.colors.tyler) { Column { @@ -55,10 +55,10 @@ fun TransactionsScreen( showSpinner = syncing, menuItems = listOf( MenuItem( - title = TranslatableString.ResString(R.string.Button_Reset), - enabled = filterResetEnabled, + title = TranslatableString.ResString(R.string.Transactions_Filter), + icon = R.drawable.ic_sort_24, onClick = { - viewModel.resetFilters() + navController.slideFromRight(R.id.transactionFilterFragment) } ) ) @@ -69,57 +69,6 @@ fun TransactionsScreen( onTransactionTypeClick = viewModel::setFilterTransactionType ) } - filterBlockchains?.let { filterBlockchains -> - CellHeaderSorting(borderBottom = true) { - var showFilterBlockchainDialog by remember { mutableStateOf(false) } - if (showFilterBlockchainDialog) { - SelectorDialogCompose( - title = stringResource(R.string.Transactions_Filter_Blockchain), - items = filterBlockchains.map { - SelectorItem(it.item?.name ?: stringResource(R.string.Transactions_Filter_AllBlockchains), it.selected, it) - }, - onDismissRequest = { - showFilterBlockchainDialog = false - }, - onSelectItem = viewModel::onEnterFilterBlockchain - ) - } - - val filterBlockchain = filterBlockchains.firstOrNull { it.selected }?.item - Row( - modifier = Modifier.fillMaxSize(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - ButtonSecondaryTransparent( - title = filterBlockchain?.name ?: stringResource(R.string.Transactions_Filter_AllBlockchains), - iconRight = R.drawable.ic_down_arrow_20, - onClick = { - showFilterBlockchainDialog = true - } - ) - - filterCoins?.let { filterCoins -> - val filterCoin = filterCoins.find { it.selected }?.item - - val coinCode = filterCoin?.token?.coin?.code - val badge = filterCoin?.badge - val title = when { - badge != null -> "$coinCode ($badge)" - else -> coinCode - } - - ButtonSecondaryTransparent( - title = title ?: stringResource(R.string.Transactions_Filter_AllCoins), - iconRight = R.drawable.ic_down_arrow_20, - onClick = { - navController.slideFromBottom(R.id.filterCoinFragment) - } - ) - } - } - } - } Crossfade(viewState, label = "") { viewState -> when (viewState) { diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsService.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsService.kt index 9e8bbf226f8..4e0ca801a65 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsService.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsService.kt @@ -34,6 +34,8 @@ class TransactionsService( private val nftMetadataService: NftMetadataService, ) : Clearable { val filterResetEnabled by transactionFilterService::resetEnabled + val filterHideUnknownTokens by transactionFilterService::filterHideUnknownTokens + val filterHideStablecoinsDust by transactionFilterService::filterHideStablecoinsDust private val itemsSubject = BehaviorSubject.create>() val itemsObservable: Observable> get() = itemsSubject @@ -310,6 +312,20 @@ class TransactionsService( } } + fun updateFilterHideUnknownTokens(hide: Boolean) { + executorService.submit { + transactionFilterService.setFilterHideUnknownTokens(hide) + transactionRecordRepository.reload() + } + } + + fun updateFilterHideStablecoinsDust(hide: Boolean) { + executorService.submit { + transactionFilterService.setFilterHideStablecoinsDust(hide) + transactionRecordRepository.reload() + } + } + fun resetFilters() { executorService.submit { transactionFilterService.reset() diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsViewModel.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsViewModel.kt index ef568a8bb25..99378b735ee 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsViewModel.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionsViewModel.kt @@ -1,5 +1,8 @@ package io.horizontalsystems.bankwallet.modules.transactions +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -38,6 +41,8 @@ class TransactionsViewModel( val filterBlockchainsLiveData = MutableLiveData>>() val transactionList = MutableLiveData>>() val viewState = MutableLiveData(ViewState.Loading) + var filterHideUnknownTokens by mutableStateOf(service.filterHideUnknownTokens) + var filterHideStablecoinsDust by mutableStateOf(service.filterHideStablecoinsDust) private val disposables = CompositeDisposable() @@ -120,7 +125,6 @@ class TransactionsViewModel( service.resetFilters() } - fun onBottomReached() { service.loadNext() } @@ -135,6 +139,16 @@ class TransactionsViewModel( } fun getTransactionItem(viewItem: TransactionViewItem) = service.getTransactionItem(viewItem.uid) + + fun updateFilterHideUnknownTokens(checked: Boolean) { + service.updateFilterHideUnknownTokens(checked) + filterHideUnknownTokens = checked + } + + fun updateFilterHideStablecoinsDust(checked: Boolean) { + service.updateFilterHideStablecoinsDust(checked) + filterHideStablecoinsDust = checked + } } data class TransactionItem( diff --git a/app/src/main/res/drawable/ic_sort_24.xml b/app/src/main/res/drawable/ic_sort_24.xml new file mode 100644 index 00000000000..ea0d8b52b53 --- /dev/null +++ b/app/src/main/res/drawable/ic_sort_24.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml index 6242e90d891..7838de3d84e 100644 --- a/app/src/main/res/navigation/main_graph.xml +++ b/app/src/main/res/navigation/main_graph.xml @@ -38,6 +38,12 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 307b37c6b83..a93bed3a4ca 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,6 +64,7 @@ Submit Try Again Share + Apply Can\'t be less than %1$s or more than %2$s Wrong integer number @@ -709,6 +710,7 @@ All Blockchains All Coins Choose Coin + Choose Blockchain Received Sent Swaps @@ -716,6 +718,11 @@ Unknown Transaction Transaction can not be parsed Multiple + Filter + Coins + Hide Unknown Tokens + Stablecoin Dust Amount + Hiding incoming transactions with the dust amount in stablecoins, this partially solves the address poisoning attack problems.