From fe023d39da9996bac4f0c3380523bfea647a8759 Mon Sep 17 00:00:00 2001 From: Khushboo Mehta Date: Tue, 13 Jun 2023 13:00:05 +0200 Subject: [PATCH] feat(@desktop/wallet): Activity FIlter UI rest of the filters (UI only) --- storybook/pages/ActivityFilterMenuPage.qml | 309 +++++++++++++++--- storybook/src/Models/CollectiblesModel.qml | 18 +- storybook/src/Models/RecipientModel.qml | 63 ++++ storybook/src/Models/WalletAssetsModel.qml | 8 +- storybook/src/Models/qmldir | 1 + .../Wallet/controls/ActivityTypeCheckBox.qml | 34 +- .../Wallet/popups/ActivityFilterMenu.qml | 52 ++- .../ActivityCounterpartyFilterSubMenu.qml | 148 +++++++++ .../ActivityPeriodFilterSubMenu.qml | 45 +-- .../ActivityStatusFilterSubMenu.qml | 79 +++++ .../ActivityTokensFilterSubMenu.qml | 159 +++++++++ .../ActivityTypeFilterSubMenu.qml | 68 ++-- ui/imports/shared/views/HistoryView.qml | 19 +- ui/imports/utils/Constants.qml | 12 + 14 files changed, 887 insertions(+), 128 deletions(-) create mode 100644 storybook/src/Models/RecipientModel.qml create mode 100644 ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityCounterpartyFilterSubMenu.qml create mode 100644 ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityStatusFilterSubMenu.qml create mode 100644 ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTokensFilterSubMenu.qml diff --git a/storybook/pages/ActivityFilterMenuPage.qml b/storybook/pages/ActivityFilterMenuPage.qml index 38a10cac1d..fe68b404f0 100644 --- a/storybook/pages/ActivityFilterMenuPage.qml +++ b/storybook/pages/ActivityFilterMenuPage.qml @@ -3,15 +3,20 @@ import QtQuick.Controls 2.14 import AppLayouts.Wallet.controls 1.0 import AppLayouts.Wallet.popups 1.0 +import AppLayouts.stores 1.0 import StatusQ.Core.Theme 0.1 import StatusQ.Controls 0.1 import StatusQ.Popups 0.1 +import SortFilterProxyModel 0.2 + import Storybook 1.0 import Models 1.0 +import utils 1.0 + SplitView { id: root @@ -21,7 +26,7 @@ SplitView { QtObject { id: d - property int selectedTime: ActivityPeriodFilterSubMenu.All + property int selectedTime: Constants.TransactionTimePeriod.All function changeSelectedTime(newTime) { selectedTime = newTime } @@ -30,56 +35,246 @@ SplitView { dialog.toTimestamp = toTimestamp } property var typeFilters: [ - ActivityTypeFilterSubMenu.Send, - ActivityTypeFilterSubMenu.Receive, - ActivityTypeFilterSubMenu.Buy, - ActivityTypeFilterSubMenu.Swap, - ActivityTypeFilterSubMenu.Bridge] + Constants.TransactionType.Send, + Constants.TransactionType.Receive, + Constants.TransactionType.Buy, + Constants.TransactionType.Swap, + Constants.TransactionType.Bridge] + + function toggleType(type) { + let tempFilters = typeFilters + let allCheckedIs = false + if(tempFilters.length === 5) + allCheckedIs = true + + // if all were selected then only select one of them + if(allCheckedIs) { + tempFilters = [type] + } + else { + // if last one is being deselected, select all + if(tempFilters.length === 1 && tempFilters[0] === type) { + tempFilters = [ + Constants.TransactionType.Send, + Constants.TransactionType.Receive, + Constants.TransactionType.Buy, + Constants.TransactionType.Swap, + Constants.TransactionType.Bridge] + } + else { + let index = tempFilters.indexOf(type) + if(index === -1) { + tempFilters.push(type) + } + else { + tempFilters.splice(index, 1) + } + } + } + typeFilters = tempFilters + } + + property var statusFilters: [ + Constants.TransactionStatus.Failed, + Constants.TransactionStatus.Pending, + Constants.TransactionStatus.Complete, + Constants.TransactionStatus.Finished] + + function toggleStatus(status) { + let tempFilters = statusFilters + let allCheckedIs = false + if(tempFilters.length === 4) + allCheckedIs = true + + // if all were selected then only select one of them + if(allCheckedIs) { + tempFilters = [status] + } + else { + // if last one is being deselected, select all + if(tempFilters.length === 1 && tempFilters[0] === status) { + tempFilters = [ + Constants.TransactionStatus.Failed, + Constants.TransactionStatus.Pending, + Constants.TransactionStatus.Complete, + Constants.TransactionStatus.Finished] + } + else { + let index = tempFilters.indexOf(status) + if(index === -1) { + tempFilters.push(status) + } + else { + tempFilters.splice(index, 1) + } + } + } + statusFilters = tempFilters + } + + property var simulatedAssetsModel: WalletAssetsModel {} + function toggleToken(tokenSymbol) { + let tempodel = simulatedAssetsModel + let allChecked = true + let allChecked1 = true + let checkedTokens = [] + simulatedAssetsModel = [] + for (let k =0; k> ",address) + onUpdateRecentsFilter: console.warn("onUpdateRecentsFilter >> ",address) + + closePolicy: Popup.NoAutoClose + } StatusDateRangePicker { id: dialog anchors.centerIn: parent destroyOnClose: false fromTimestamp: new Date().setDate(new Date().getDate() - 7) // 7 days ago - onNewRangeSet: { - d.setCustomTimeRange(fromTimestamp, toTimestamp) - } + onNewRangeSet: d.setCustomTimeRange(fromTimestamp, toTimestamp) } } @@ -105,67 +300,91 @@ SplitView { RadioButton { checked: true text: "All" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.All} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.All} } RadioButton { text: "Today" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.Today} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.Today} } RadioButton { text: "Yesterday" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.Yesterday} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.Yesterday} } RadioButton { text: "ThisWeek" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.ThisWeek} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.ThisWeek} } RadioButton { text: "LastWeek" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.LastWeek} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.LastWeek} } RadioButton { text: "ThisMonth" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.ThisMonth} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.ThisMonth} } RadioButton { text: "LastMonth" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.LastMonth} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.LastMonth} } RadioButton { text: "Custom" - onCheckedChanged: if(checked) { d.selectedTime = ActivityPeriodFilterSubMenu.Custom} + onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.Custom} } } Row { spacing: 20 CheckBox { - id: sendCheckbox text: "Send" - checked: true + checked: d.typeFilters.includes(Constants.TransactionType.Send) + onClicked: d.toggleType(Constants.TransactionType.Send) } CheckBox { - id: receiveCheckbox text: "Receive" - checked: true + checked: d.typeFilters.includes(Constants.TransactionType.Receive) + onClicked: d.toggleType(Constants.TransactionType.Receive) } CheckBox { - id: buyCheckbox text: "Buy" - checked: true + checked: d.typeFilters.includes(Constants.TransactionType.Buy) + onClicked: d.toggleType(Constants.TransactionType.Buy) } CheckBox { - id: swapCheckbox text: "Swap" - checked: true + checked: d.typeFilters.includes(Constants.TransactionType.Swap) + onClicked: d.toggleType(Constants.TransactionType.Swap) } CheckBox { - id: bridgeCheckbox text: "Bridge" - checked: true + checked: d.typeFilters.includes(Constants.TransactionType.Bridge) + onClicked: d.toggleType(Constants.TransactionType.Bridge) } } + + Row { + spacing: 20 + CheckBox { + text: "Failed" + checked: d.statusFilters.includes(Constants.TransactionStatus.Failed) + onClicked: d.toggleStatus(Constants.TransactionStatus.Failed) + } + CheckBox { + text: "Pending" + checked: d.statusFilters.includes(Constants.TransactionStatus.Pending) + onClicked: d.toggleStatus(Constants.TransactionStatus.Pending) + } + CheckBox { + text: "Complete" + checked: d.statusFilters.includes(Constants.TransactionStatus.Complete) + onClicked: d.toggleStatus(Constants.TransactionStatus.Complete) + } + CheckBox { + text: "Finished" + checked: d.statusFilters.includes(Constants.TransactionStatus.Finished) + onClicked: d.toggleStatus(Constants.TransactionStatus.Finished) + } + } } } } diff --git a/storybook/src/Models/CollectiblesModel.qml b/storybook/src/Models/CollectiblesModel.qml index 3b447a2abb..00d7099592 100644 --- a/storybook/src/Models/CollectiblesModel.qml +++ b/storybook/src/Models/CollectiblesModel.qml @@ -8,13 +8,17 @@ ListModel { key: "Anniversary", iconSource: ModelsData.collectibles.anniversary, name: "Anniversary", - category: TokenCategories.Category.Community + category: TokenCategories.Category.Community, + checked: true, + allChecked: true }, { key: "Anniversary2", iconSource: ModelsData.collectibles.anniversary, name: "Anniversary2", category: TokenCategories.Category.Community, + checked: true, + allChecked: true }, { key: "CryptoKitties", @@ -64,19 +68,25 @@ ListModel { imageSource: ModelsData.collectibles.kitty5Big, name: "Magicat-4" } - ] + ], + checked: true, + allChecked: true }, { key: "SuperRare", iconSource: ModelsData.collectibles.superRare, name: "SuperRare", - category: TokenCategories.Category.Own + category: TokenCategories.Category.Own, + checked: true, + allChecked: true }, { key: "Custom", iconSource: ModelsData.collectibles.custom, name: "Custom Collectible", - category: TokenCategories.Category.General + category: TokenCategories.Category.General, + checked: true, + allChecked: true } ] diff --git a/storybook/src/Models/RecipientModel.qml b/storybook/src/Models/RecipientModel.qml new file mode 100644 index 0000000000..28660462fd --- /dev/null +++ b/storybook/src/Models/RecipientModel.qml @@ -0,0 +1,63 @@ +import QtQuick 2.15 + +QtObject { + + readonly property var savedAddresses: ListModel { + + ListElement { + name: "John" + address: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + ens: "" + favourite: true + chainShortNames: "eth:arb:opt" + isTest: false + checked: true + allChecked: true + } + + ListElement { + name: "Anthony" + address: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756ccx" + ens: "anthony.statusofus.eth" + favourite: true + chainShortNames: "" + isTest: false + checked: true + allChecked: true + } + + ListElement { + name: "Iuri" + address: "0xb794f5ea0ba39494ce839613fffba74279579268" + ens: "" + favourite: true + chainShortNames: "eth:" + isTest: false + checked: true + allChecked: true + } + } + + readonly property var recents: ListModel { + ListElement { + from: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756ccx" + to: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + checked: true + allChecked: true + } + + ListElement { + from: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756ccx" + to: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + checked: true + allChecked: true + } + + ListElement { + from: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756ccx" + to: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + checked: true + allChecked: true + } + } +} diff --git a/storybook/src/Models/WalletAssetsModel.qml b/storybook/src/Models/WalletAssetsModel.qml index abcbc100ad..f39f458d49 100644 --- a/storybook/src/Models/WalletAssetsModel.qml +++ b/storybook/src/Models/WalletAssetsModel.qml @@ -22,7 +22,9 @@ ListModel { amount: 3.234 } } - ] + ], + checked: true, + allChecked: true }, { totalBalance: 324343.3, @@ -44,7 +46,9 @@ ListModel { amount: 324343.3 } } - ] + ], + checked: true, + allChecked: true }, ] diff --git a/storybook/src/Models/qmldir b/storybook/src/Models/qmldir index b09b4e3ca7..df3383540e 100644 --- a/storybook/src/Models/qmldir +++ b/storybook/src/Models/qmldir @@ -13,3 +13,4 @@ singleton MintedTokensModel 1.0 MintedTokensModel.qml singleton ModelsData 1.0 ModelsData.qml singleton NetworksModel 1.0 NetworksModel.qml singleton PermissionsModel 1.0 PermissionsModel.qml +RecipientModel 1.0 RecipientModel.qml diff --git a/ui/app/AppLayouts/Wallet/controls/ActivityTypeCheckBox.qml b/ui/app/AppLayouts/Wallet/controls/ActivityTypeCheckBox.qml index 8b2c14ece9..c0df226a1e 100644 --- a/ui/app/AppLayouts/Wallet/controls/ActivityTypeCheckBox.qml +++ b/ui/app/AppLayouts/Wallet/controls/ActivityTypeCheckBox.qml @@ -3,39 +3,49 @@ import QtQuick.Controls 2.15 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 StatusListItem { id: root property bool checked: true property bool allChecked : false + property int type property ButtonGroup buttonGroup + property StatusAssetSettings assetSettings: StatusAssetSettings { + width: 24 + height: 24 + bgWidth: 0 + bgHeight: 0 + bgRadius: 0 + bgColor: Theme.palette.primaryColor3 + color: Theme.palette.primaryColor1 + } - signal actionTriggered(bool checked) + signal actionTriggered() height: 44 radius: 0 leftPadding: 21 rightPadding: 21 - asset.width: 24 - asset.height: 24 - asset.bgWidth: 0 - asset.bgHeight: 0 + asset: root.assetSettings statusListItemTitle.font.pixelSize: 13 - ButtonGroup.group: buttonGroup - onClicked: checkBox.nextCheckState() components: [ StatusCheckBox { id: checkBox tristate: true + checkable: true spacing: 0 leftPadding: 0 rightPadding: 0 - checkState: allChecked ? Qt.PartiallyChecked : root.checked ? Qt.Checked : Qt.Unchecked - nextCheckState: function() { - root.actionTriggered(checkBox.checked) - return Qt.PartiallyChecked - } + checkState: root.allChecked ? Qt.PartiallyChecked : root.checked ? Qt.Checked : Qt.Unchecked + nextCheckState: () => { + root.actionTriggered() + return checkState + } + ButtonGroup.group: buttonGroup } ] + onClicked: checkBox.nextCheckState() } diff --git a/ui/app/AppLayouts/Wallet/popups/ActivityFilterMenu.qml b/ui/app/AppLayouts/Wallet/popups/ActivityFilterMenu.qml index 9c5c1f5ec9..0c8b593eb7 100644 --- a/ui/app/AppLayouts/Wallet/popups/ActivityFilterMenu.qml +++ b/ui/app/AppLayouts/Wallet/popups/ActivityFilterMenu.qml @@ -14,7 +14,24 @@ StatusMenu { // Type filter property var typeFilters: [] - signal updateTypeFilter(int type, bool checked) + signal updateTypeFilter(int type) + + // Status filter + property var statusFilters: [] + signal updateStatusFilter(int status) + + // Assets filter + property var tokensList: [] + property var collectiblesList + signal updateTokensFilter(string tokenSymbol) + signal updateCollectiblesFilter(string name) + + // Counterparty filter + property var store + property var recentsList + property var savedAddressList + signal updateSavedAddressFilter(string adddress) + signal updateRecentsFilter(string address) implicitWidth: 176 @@ -32,12 +49,40 @@ StatusMenu { setSelectedTime(action) } selectedTime: root.selectedTime + closePolicy: root.closePolicy } ActivityTypeFilterSubMenu { id: typeMenu onBack: root.open() typeFilters: root.typeFilters - onActionTriggered: updateTypeFilter(action, checked) + onActionTriggered: updateTypeFilter(type) + closePolicy: root.closePolicy + } + ActivityStatusFilterSubMenu { + id: statusMenu + onBack: root.open() + statusFilters: root.statusFilters + onActionTriggered: updateStatusFilter(status) + closePolicy: root.closePolicy + } + ActivityTokensFilterSubMenu { + id: tokensMenu + height: Math.min(439, implicitHeight) + onBack: root.open() + tokensList: root.tokensList + collectiblesList: root.collectiblesList + onTokenToggled: updateTokensFilter(tokenSymbol) + onCollectibleToggled: updateCollectiblesFilter(name) + closePolicy: root.closePolicy + } + ActivityCounterpartyFilterSubMenu { + id: counterPartyMenu + height: Math.min(439, implicitHeight) + onBack: root.open() + store: root.store + recentsList: root.recentsList + savedAddressList: root.savedAddressList + closePolicy: root.closePolicy } } @@ -48,14 +93,17 @@ StatusMenu { ActivityFilterMenuItem { text: qsTr("Status") + onTriggered: statusMenu.popup(Qt.point(0, -8)) } ActivityFilterMenuItem { text: qsTr("Tokens") + onTriggered: tokensMenu.popup(Qt.point(0, -8)) } ActivityFilterMenuItem { text: qsTr("Counterparty") + onTriggered: counterPartyMenu.popup(Qt.point(0, -8)) } } diff --git a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityCounterpartyFilterSubMenu.qml b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityCounterpartyFilterSubMenu.qml new file mode 100644 index 0000000000..60d3c3b29a --- /dev/null +++ b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityCounterpartyFilterSubMenu.qml @@ -0,0 +1,148 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.13 + +import StatusQ.Popups 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Core.Utils 0.1 as StatusQUtils + +import shared.controls 1.0 + +import SortFilterProxyModel 0.2 + +import utils 1.0 + +import "../../../Wallet" +import "../../controls" + +StatusMenu { + id: root + + property var recentsList + property var savedAddressList + property var store + + signal back() + signal savedAddressToggled(string adddress) + signal recentsToggled(string address) + + property var searchTokenSymbolByAddressFn: function (address) { + return "" + } + + implicitWidth: 289 + + MenuBackButton { + id: backButton + width: parent.width + onClicked: { + close() + back() + } + } + + StatusSwitchTabBar { + id: tabBar + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: backButton.bottom + anchors.topMargin: 12 + width: parent.width - 16 + StatusSwitchTabButton { + text: qsTr("Recent") + } + StatusSwitchTabButton { + text: qsTr("Saved") + } + } + + StackLayout { + id: layout + width: parent.width + anchors.top: tabBar.bottom + anchors.topMargin: 12 + currentIndex: tabBar.currentIndex + + Column { + id: column1 + Layout.fillWidth: true + spacing: 0 + ButtonGroup { + id: recentsButtonGroup + exclusive: false + } + Repeater { + model: root.recentsList + delegate: ActivityTypeCheckBox { + readonly property int transactionType: model.to.toLowerCase() === store.overview.mixedcaseAddress.toLowerCase() ? Constants.TransactionType.Receive : Constants.TransactionType.Send + readonly property string fromName: store.getNameForAddress(model.from) + readonly property string toName: store.getNameForAddress(model.to) + width: parent.width + height: 44 + title: transactionType === Constants.TransactionType.Receive ? + fromName || StatusQUtils.Utils.elideText(model.from,6,4) : + toName || StatusQUtils.Utils.elideText(model.to,6,4) + subTitle: { + if (transactionType === Constants.TransactionType.Receive) { + return fromName ? StatusQUtils.Utils.elideText(model.from,6,4) : "" + } else { + return toName ? StatusQUtils.Utils.elideText(model.to,6,4): "" + } + } + statusListItemSubTitle.elide: Text.ElideMiddle + statusListItemSubTitle.wrapMode: Text.NoWrap + assetSettings.name: (transactionType === Constants.TransactionType.Receive ? fromName : toName) || "address" + assetSettings.isLetterIdenticon: transactionType === Constants.TransactionType.Receive ? + !!fromName : + !!toName + assetSettings.bgHeight: 32 + assetSettings.bgWidth: 32 + assetSettings.bgRadius: assetSettings.bgHeight/2 + assetSettings.width: 16 + assetSettings.height: 16 + buttonGroup: recentsButtonGroup + allChecked: model.allChecked + checked: model.checked + onActionTriggered: root.recentsToggled(transactionType === Constants.TransactionType.Receive ? fromName : toName) + } + } + } + + Column { + id: column2 + Layout.fillWidth: true + spacing: 0 + ButtonGroup { + id: savedButtonGroup + exclusive: false + } + Repeater { + model: root.savedAddressList + delegate: ActivityTypeCheckBox { + width: parent.width + height: 44 + title: model.name ?? "" + subTitle: { + if (model.ens.length > 0) { + return sensor.containsMouse ? Utils.richColorText(model.ens, Theme.palette.directColor1) : model.ens + } + else { + let elidedAddress = StatusQUtils.Utils.elideText(model.address,6,4) + return sensor.containsMouse ? WalletUtils.colorizedChainPrefix(model.chainShortNames) + Utils.richColorText(elidedAddress, Theme.palette.directColor1): model.chainShortNames + elidedAddress + } + } + statusListItemSubTitle.elide: Text.ElideMiddle + statusListItemSubTitle.wrapMode: Text.NoWrap + assetSettings.name: model.name + assetSettings.isLetterIdenticon: true + buttonGroup: savedButtonGroup + allChecked: model.allChecked + checked: model.checked + onActionTriggered: root.savedAddressToggled(model.address) + } + } + } + } + +} diff --git a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityPeriodFilterSubMenu.qml b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityPeriodFilterSubMenu.qml index 9ea069ac22..ba055fab9a 100644 --- a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityPeriodFilterSubMenu.qml +++ b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityPeriodFilterSubMenu.qml @@ -2,6 +2,8 @@ import QtQuick 2.15 import StatusQ.Popups 0.1 +import utils 1.0 + import "../../controls" StatusMenu { @@ -12,17 +14,6 @@ StatusMenu { signal back() signal actionTriggered(int action) - enum TimePeriod { - All, - Today, - Yesterday, - ThisWeek, - LastWeek, - ThisMonth, - LastMonth, - Custom - } - MenuBackButton { width: parent.width onClicked: { @@ -31,44 +22,44 @@ StatusMenu { } } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.All + checked: root.selectedTime === Constants.TransactionTimePeriod.All text: qsTr("All time") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.All) + onClicked: actionTriggered(Constants.TransactionTimePeriod.All) } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.Today + checked: root.selectedTime === Constants.TransactionTimePeriod.Today text: qsTr("Today") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.Today) + onClicked: actionTriggered(Constants.TransactionTimePeriod.Today) } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.Yesterday + checked: root.selectedTime === Constants.TransactionTimePeriod.Yesterday text: qsTr("Yesterday") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.Yesterday) + onClicked: actionTriggered(Constants.TransactionTimePeriod.Yesterday) } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.ThisWeek + checked: root.selectedTime === Constants.TransactionTimePeriod.ThisWeek text: qsTr("This week") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.ThisWeek) + onClicked: actionTriggered(Constants.TransactionTimePeriod.ThisWeek) } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.LastWeek + checked: root.selectedTime === Constants.TransactionTimePeriod.LastWeek text: qsTr("Last week") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.LastWeek) + onClicked: actionTriggered(Constants.TransactionTimePeriod.LastWeek) } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.ThisMonth + checked: root.selectedTime === Constants.TransactionTimePeriod.ThisMonth text: qsTr("This month") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.ThisMonth) + onClicked: actionTriggered(Constants.TransactionTimePeriod.ThisMonth) } StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.LastMonth + checked: root.selectedTime === Constants.TransactionTimePeriod.LastMonth text: qsTr("Last month") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.LastMonth) + onClicked: actionTriggered(Constants.TransactionTimePeriod.LastMonth) } StatusMenuSeparator {} StatusWalletMenuRadioButton { - checked: root.selectedTime === ActivityPeriodFilterSubMenu.Custom + checked: root.selectedTime === Constants.TransactionTimePeriod.Custom text: qsTr("Custom range") - onClicked: actionTriggered(ActivityPeriodFilterSubMenu.Custom) + onClicked: actionTriggered(Constants.TransactionTimePeriod.Custom) } } diff --git a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityStatusFilterSubMenu.qml b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityStatusFilterSubMenu.qml new file mode 100644 index 0000000000..54b7472d53 --- /dev/null +++ b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityStatusFilterSubMenu.qml @@ -0,0 +1,79 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +import StatusQ.Popups 0.1 + +import utils 1.0 + +import "../../controls" + +StatusMenu { + id: root + + property var statusFilters: [] + readonly property bool allChecked: statusFilters.length === typeButtonGroup.buttons.length + + signal back() + signal actionTriggered(int status) + + MenuBackButton { + width: parent.width + onClicked: { + close() + back() + } + } + + ButtonGroup { + id: typeButtonGroup + exclusive: false + } + + ActivityTypeCheckBox { + id: sendCheckbox + title: qsTr("Failed") + assetSettings.name: Style.svg("transaction/failed") + assetSettings.color: "transparent" + buttonGroup: typeButtonGroup + allChecked: root.allChecked + type: Constants.TransactionStatus.Failed + checked: statusFilters.includes(type) + onActionTriggered: root.actionTriggered(type) + } + + ActivityTypeCheckBox { + id: receiveCheckbox + title: qsTr("Pending") + assetSettings.name: Style.svg("transaction/pending") + assetSettings.color: "transparent" + buttonGroup: typeButtonGroup + allChecked: root.allChecked + type: Constants.TransactionStatus.Pending + checked: statusFilters.includes(type) + onActionTriggered: root.actionTriggered(type) + } + + ActivityTypeCheckBox { + id: buyCheckbox + title: qsTr("Complete") + assetSettings.name: Style.svg("transaction/verified") + assetSettings.color: "transparent" + buttonGroup: typeButtonGroup + allChecked: root.allChecked + type: Constants.TransactionStatus.Complete + checked: statusFilters.includes(type) + onActionTriggered: root.actionTriggered(type) + } + + ActivityTypeCheckBox { + id: swapCheckbox + title: qsTr("Finalised") + assetSettings.name: Style.svg("transaction/finished") + assetSettings.color: "transparent" + buttonGroup: typeButtonGroup + allChecked: root.allChecked + type: Constants.TransactionStatus.Finished + checked: statusFilters.includes(type) + onActionTriggered: root.actionTriggered(type) + } +} diff --git a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTokensFilterSubMenu.qml b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTokensFilterSubMenu.qml new file mode 100644 index 0000000000..de3831af95 --- /dev/null +++ b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTokensFilterSubMenu.qml @@ -0,0 +1,159 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.13 + +import StatusQ.Popups 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 + +import shared.controls 1.0 +import "../../controls" + +import SortFilterProxyModel 0.2 + +import utils 1.0 + +StatusMenu { + id: root + + property var tokensList + property var collectiblesList + + signal back() + signal tokenToggled(string tokenSymbol) + signal collectibleToggled(string name) + + property var searchTokenSymbolByAddressFn: function (address) { + return "" + } + + implicitWidth: 289 + + MenuBackButton { + id: backButton + width: parent.width + onClicked: { + close() + back() + } + } + + StatusSwitchTabBar { + id: tabBar + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: backButton.bottom + anchors.topMargin: 12 + width: parent.width - 16 + StatusSwitchTabButton { + text: qsTr("Assets") + } + StatusSwitchTabButton { + text: qsTr("Collectibles") + } + } + + StackLayout { + id: layout + width: parent.width + anchors.top: tabBar.bottom + anchors.topMargin: 12 + currentIndex: tabBar.currentIndex + + Column { + Layout.fillWidth: true + spacing: 8 + + ButtonGroup { + id: tokenButtonGroup + exclusive: false + } + + SearchBox { + id: tokensSearchBox + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width - 16 + input.height: 36 + placeholderText: qsTr("Search asset name") + } + + ColumnLayout { + width: parent.width + spacing: 0 + Repeater { + model: SortFilterProxyModel { + sourceModel: root.tokensList + filters: [ + ExpressionFilter { + expression: { + var tokenSymbolByAddress = root.searchTokenSymbolByAddressFn(tokensSearchBox.text) + return symbol.startsWith(tokensSearchBox.text.toUpperCase()) || name.toUpperCase().startsWith(tokensSearchBox.text.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress)) + } + } + ] + } + delegate: ActivityTypeCheckBox { + Layout.fillWidth: true + Layout.preferredHeight: 44 + title: model.name + titleAsideText: model.symbol + assetSettings.name: model.symbol ? Style.png("tokens/" + model.symbol) : "" + assetSettings.isImage: true + buttonGroup: tokenButtonGroup + allChecked: model.allChecked + checked: model.checked + onActionTriggered: root.tokenToggled(model.symbol) + } + } + } + } + + Column { + width: parent.width + spacing: 8 + + ButtonGroup { + id: collectibleButtonGroup + exclusive: false + } + + SearchBox { + id: collectiblesSearchBox + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width - 16 + input.height: 36 + placeholderText: qsTr("Search collectible name") + } + + ColumnLayout { + width: parent.width + spacing: 0 + Repeater { + model: SortFilterProxyModel { + sourceModel: root.collectiblesList + filters: [ + ExpressionFilter { + expression: { + return model.name.toUpperCase().startsWith(collectiblesSearchBox.text.toUpperCase()) + } + } + ] + } + delegate: ActivityTypeCheckBox { + Layout.fillWidth: true + Layout.preferredHeight: 44 + title: model.name + assetSettings.name: model.iconSource + assetSettings.bgWidth: 32 + assetSettings.bgHeight: 32 + assetSettings.bgRadius: assetSettings.bgHeight/2 + assetSettings.isImage: true + buttonGroup: collectibleButtonGroup + allChecked: model.allChecked + checked: model.checked + onActionTriggered: root.collectibleToggled(name) + } + } + } + } + } +} diff --git a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTypeFilterSubMenu.qml b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTypeFilterSubMenu.qml index ee327956d0..6ae9ddad96 100644 --- a/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTypeFilterSubMenu.qml +++ b/ui/app/AppLayouts/Wallet/popups/filterSubMenus/ActivityTypeFilterSubMenu.qml @@ -3,32 +3,18 @@ import QtQuick.Controls 2.15 import StatusQ.Popups 0.1 +import utils 1.0 + import "../../controls" StatusMenu { id: root - property var typeFilters:[] + property var typeFilters: [] + readonly property bool allChecked: typeFilters.length === typeButtonGroup.buttons.length signal back() - signal actionTriggered(int action, bool checked) - - property bool allChecked: { - let allCheckedIs = true - for(var i=0;i< root.contentChildren.length;i++) { - if(root.contentChildren[i].checkState === Qt.Unchecked) - allCheckedIs = false - } - return allCheckedIs - } - - enum TxType { - Send, - Receive, - Buy, - Swap, - Bridge - } + signal actionTriggered(int type) MenuBackButton { width: parent.width @@ -44,43 +30,57 @@ StatusMenu { } ActivityTypeCheckBox { + id: sendCheckbox title: qsTr("Send") - asset.name: "send" - checked: typeFilters.includes(ActivityTypeFilterSubMenu.Send) + assetSettings.name: "send" buttonGroup: typeButtonGroup - onActionTriggered: root.actionTriggered(ActivityTypeFilterSubMenu.Send, checked) allChecked: root.allChecked + type: Constants.TransactionType.Send + checked: typeFilters.includes(type) + onActionTriggered: root.actionTriggered(type) } + ActivityTypeCheckBox { + id: receiveCheckbox title: qsTr("Receive") - asset.name: "receive" + assetSettings.name: "receive" buttonGroup: typeButtonGroup - checked: typeFilters.includes(ActivityTypeFilterSubMenu.Receive) - onActionTriggered: root.actionTriggered(ActivityTypeFilterSubMenu.Receive, checked) allChecked: root.allChecked + type: Constants.TransactionType.Receive + checked: typeFilters.includes(type) + onActionTriggered: root.actionTriggered(type) } + ActivityTypeCheckBox { + id: buyCheckbox title: qsTr("Buy") - asset.name: "token" + assetSettings.name: "token" buttonGroup: typeButtonGroup - checked: typeFilters.includes(ActivityTypeFilterSubMenu.Buy) - onActionTriggered: root.actionTriggered(ActivityTypeFilterSubMenu.Buy, checked) allChecked: root.allChecked + type: Constants.TransactionType.Buy + checked: typeFilters.includes(type) + onActionTriggered: root.actionTriggered(type) } + ActivityTypeCheckBox { + id: swapCheckbox title: qsTr("Swap") - asset.name: "swap" + assetSettings.name: "swap" buttonGroup: typeButtonGroup - checked: typeFilters.includes(ActivityTypeFilterSubMenu.Swap) - onActionTriggered: root.actionTriggered(ActivityTypeFilterSubMenu.Swap, checked) allChecked: root.allChecked + type: Constants.TransactionType.Swap + checked: typeFilters.includes(type) + onActionTriggered: root.actionTriggered(type) } + ActivityTypeCheckBox { + id: bridgeCheckbox title: qsTr("Bridge") - asset.name: "bridge" + assetSettings.name: "bridge" buttonGroup: typeButtonGroup - checked: typeFilters.includes(ActivityTypeFilterSubMenu.Bridge) - onActionTriggered: root.actionTriggered(ActivityTypeFilterSubMenu.Bridge, checked) allChecked: root.allChecked + type: Constants.TransactionType.Bridge + checked: typeFilters.includes(type) + onActionTriggered: root.actionTriggered(type) } } diff --git a/ui/imports/shared/views/HistoryView.qml b/ui/imports/shared/views/HistoryView.qml index 24bc3b2698..b59cd54bd1 100644 --- a/ui/imports/shared/views/HistoryView.qml +++ b/ui/imports/shared/views/HistoryView.qml @@ -340,15 +340,30 @@ ColumnLayout { } } + // To-do connect with backend once its implemented ActivityFilterMenu { id: activityFilter - selectedTime: ActivityPeriodFilterSubMenu.All + selectedTime: Constants.TransactionTimePeriod.All onSetSelectedTime: { // To do connect with n=backend to set time range - if(selectedTime === ActivityPeriodFilterSubMenu.Custom) { + if(selectedTime === Constants.TransactionTimePeriod.Custom) { customDateRangePicker.open() } } + typeFilters: [ + Constants.TransactionType.Send, + Constants.TransactionType.Receive, + Constants.TransactionType.Buy, + Constants.TransactionType.Swap, + Constants.TransactionType.Bridge + ] + statusFilters: [ + Constants.TransactionStatus.Failed, + Constants.TransactionStatus.Pending, + Constants.TransactionStatus.Complete, + Constants.TransactionStatus.Finished + ] + store: RootStore } // To-do update once https://github.com/status-im/status-desktop/pull/10916 is updated and connect with backend values diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 16088fe45a..0c296123dd 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -961,6 +961,18 @@ QtObject { Destroy // TODO update value when added to backend } + // To-do sync with backend + enum TransactionTimePeriod { + All, + Today, + Yesterday, + ThisWeek, + LastWeek, + ThisMonth, + LastMonth, + Custom + } + readonly property QtObject walletSection: QtObject { readonly property string cancelledMessage: "cancelled" }