fix(@desktop/wallet): Activity UI filtering improvements

1. Handling case where filters result in no results
2. Fixed period filter
3. Used recipient model from go side
This commit is contained in:
Khushboo Mehta 2023-06-20 13:14:52 +02:00 committed by Khushboo-dev-cpp
parent ae9a52397c
commit 9be598ee32
7 changed files with 331 additions and 235 deletions

View File

@ -370,8 +370,9 @@ QtObject:
error "error fetching recipients: ", response.error error "error fetching recipients: ", response.error
return return
let result = json.to(response.result, backend_activity.GetAllRecipientsResponse) if response.result["addresses"] != newJNull():
self.recipientsModel.addAddresses(result.addresses, 0, result.hasMore) let result = json.to(response.result, backend_activity.GetAllRecipientsResponse)
self.recipientsModel.addAddresses(deduplicate(result.addresses), 0, result.hasMore)
proc loadMoreRecipients(self: Controller) {.slot.} = proc loadMoreRecipients(self: Controller) {.slot.} =
let response = backend_activity.getAllRecipients(self.recipientsModel.getCount(), FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT) let response = backend_activity.getAllRecipients(self.recipientsModel.getCount(), FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
@ -379,8 +380,9 @@ QtObject:
error "error fetching more recipient entries: ", response.error error "error fetching more recipient entries: ", response.error
return return
let result = json.to(response.result, backend_activity.GetAllRecipientsResponse) if response.result["addresses"] != newJNull():
self.recipientsModel.addAddresses(result.addresses, self.recipientsModel.getCount(), result.hasMore) let result = json.to(response.result, backend_activity.GetAllRecipientsResponse)
self.recipientsModel.addAddresses(deduplicate(result.addresses), self.recipientsModel.getCount(), result.hasMore)
proc getStartTimestamp*(self: Controller): int {.slot.} = proc getStartTimestamp*(self: Controller): int {.slot.} =
return if self.startTimestamp > 0: return if self.startTimestamp > 0:

View File

@ -7,171 +7,200 @@ import StatusQ.Controls 0.1
import utils 1.0 import utils 1.0
import shared.panels 1.0
import "../controls" import "../controls"
import "../popups" import "../popups"
Flow { Column {
id: root id: root
property var activityFilterStore property var activityFilterStore
property var store property var store
property bool isLoading: false
spacing: 8 spacing: 12
Component.onCompleted: { Component.onCompleted: {
activityFilterStore.updateFilterBase() activityFilterStore.updateFilterBase()
} }
StatusRoundButton { Flow {
id: filterButton width: parent.width
width: 32
height: 32
icon.name: "filter"
border.width: 1
border.color: Theme.palette.directColor8
type: StatusRoundButton.Type.Tertiary
onClicked: activityFilterMenu.popup(x, y + height + 4)
}
ActivityFilterTagItem { spacing: 8
tagPrimaryLabel.text: LocaleUtils.formatDate(activityFilterStore.fromTimestamp)
tagSecondaryLabel.text: { StatusRoundButton {
switch(activityFilterMenu.selectedTime) { id: filterButton
case Constants.TransactionTimePeriod.Today: width: 32
case Constants.TransactionTimePeriod.Yesterday: height: 32
return "" icon.name: "filter"
default: border.width: 1
return LocaleUtils.formatDate(activityFilterStore.toTimestamp) border.color: Theme.palette.directColor8
type: StatusRoundButton.Type.Tertiary
icon.color: Theme.palette.primaryColor1
onClicked: activityFilterMenu.popup(x, y + height + 4)
}
ActivityFilterTagItem {
tagPrimaryLabel.text: LocaleUtils.formatDate(activityFilterStore.fromTimestamp)
tagSecondaryLabel.text: {
switch(activityFilterMenu.selectedTime) {
case Constants.TransactionTimePeriod.Today:
case Constants.TransactionTimePeriod.Yesterday:
return ""
default:
return LocaleUtils.formatDate(activityFilterStore.toTimestamp)
}
}
middleLabel.text: {
switch(activityFilterMenu.selectedTime) {
case Constants.TransactionTimePeriod.Today:
case Constants.TransactionTimePeriod.Yesterday:
return ""
default:
return qsTr("to")
}
}
iconAsset.icon: "history"
visible: activityFilterMenu.selectedTime !== Constants.TransactionTimePeriod.All
onClosed: activityFilterStore.setSelectedTimestamp(Constants.TransactionTimePeriod.All)
}
Repeater {
model: activityFilterMenu.allTypesChecked ? 0: activityFilterStore.typeFilters
delegate: ActivityFilterTagItem {
property int type: activityFilterStore.typeFilters[index]
tagPrimaryLabel.text: switch(activityFilterStore.typeFilters[index]) {
case Constants.TransactionType.Send:
return qsTr("Send")
case Constants.TransactionType.Receive:
return qsTr("Receive")
case Constants.TransactionType.Buy:
return qsTr("Buy")
case Constants.TransactionType.Swap:
return qsTr("Swap")
case Constants.TransactionType.Bridge:
return qsTr("Bridge")
default:
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index])
return ""
}
iconAsset.icon: switch(activityFilterStore.typeFilters[index]) {
case Constants.TransactionType.Send:
return "send"
case Constants.TransactionType.Receive:
return "receive"
case Constants.TransactionType.Buy:
return "token"
case Constants.TransactionType.Swap:
return "swap"
case Constants.TransactionType.Bridge:
return "bridge"
default:
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index])
return ""
}
onClosed: activityFilterStore.toggleType(type)
} }
} }
middleLabel.text: {
switch(activityFilterMenu.selectedTime) { Repeater {
case Constants.TransactionTimePeriod.Today: model: activityFilterMenu.allStatusChecked ? 0 : activityFilterStore.statusFilters
case Constants.TransactionTimePeriod.Yesterday: delegate: ActivityFilterTagItem {
return "" property int status: activityFilterStore.statusFilters[index]
default: tagPrimaryLabel.text: switch(activityFilterStore.statusFilters[index]) {
return qsTr("to") case Constants.TransactionStatus.Failed:
return qsTr("Failed")
case Constants.TransactionStatus.Pending:
return qsTr("Pending")
case Constants.TransactionStatus.Complete:
return qsTr("Complete")
case Constants.TransactionStatus.Finished:
return qsTr("Finalised")
default:
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
return ""
}
iconAsset.icon: switch(activityFilterStore.statusFilters[index]) {
case Constants.TransactionStatus.Failed:
return Style.svg("transaction/failed")
case Constants.TransactionStatus.Pending:
return Style.svg("transaction/pending")
case Constants.TransactionStatus.Complete:
return Style.svg("transaction/verified")
case Constants.TransactionStatus.Finished:
return Style.svg("transaction/finished")
default:
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
return ""
}
iconAsset.color: "transparent"
onClosed: activityFilterStore.toggleStatus(status, activityFilterMenu.allStatusChecked)
} }
} }
iconAsset.icon: "history"
visible: activityFilterMenu.selectedTime !== Constants.TransactionTimePeriod.All
onClosed: activityFilterStore.setSelectedTimestamp(Constants.TransactionTimePeriod.All)
}
Repeater { Repeater {
model: activityFilterMenu.allTypesChecked ? 0: activityFilterStore.typeFilters model: activityFilterStore.tokensList
delegate: ActivityFilterTagItem { delegate: ActivityFilterTagItem {
property int type: activityFilterStore.typeFilters[index] tagPrimaryLabel.text: symbol
tagPrimaryLabel.text: switch(activityFilterStore.typeFilters[index]) { iconAsset.icon: Constants.tokenIcon(symbol)
case Constants.TransactionType.Send: iconAsset.color: "transparent"
return qsTr("Send") visible: !activityFilterMenu.allTokensChecked && activityFilterStore.tokensFilter.includes(symbol)
case Constants.TransactionType.Receive: onClosed: activityFilterStore.toggleToken(symbol)
return qsTr("Receive") }
case Constants.TransactionType.Buy: }
return qsTr("Buy")
case Constants.TransactionType.Swap: Repeater {
return qsTr("Swap") model: activityFilterStore.collectiblesList
case Constants.TransactionType.Bridge: delegate: ActivityFilterTagItem {
return qsTr("Bridge") tagPrimaryLabel.text: model.name
default: iconAsset.icon: model.imageUrl
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index]) iconAsset.color: "transparent"
return "" visible: !activityFilterMenu.allCollectiblesChecked && activityFilterStore.collectiblesFilter.includes(model.id)
} onClosed: activityFilterStore.toggleCollectibles(model.id)
iconAsset.icon: switch(activityFilterStore.typeFilters[index]) { }
case Constants.TransactionType.Send: }
return "send"
case Constants.TransactionType.Receive: Repeater {
return "receive" model: activityFilterStore.recentsList
case Constants.TransactionType.Buy: delegate: ActivityFilterTagItem {
return "token" tagPrimaryLabel.text: root.store.getNameForAddress(model.address) || StatusQUtils.Utils.elideText(model.address,6,4)
case Constants.TransactionType.Swap: visible: !activityFilterMenu.allRecentsChecked && activityFilterMenu.recentsFilters.includes(model.address)
return "swap" onClosed: activityFilterStore.toggleRecents(model.address)
case Constants.TransactionType.Bridge: }
return "bridge" }
default:
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index]) Repeater {
return "" model: activityFilterStore.savedAddressList
} delegate: ActivityFilterTagItem {
onClosed: activityFilterStore.toggleType(type) tagPrimaryLabel.text: ens.length > 0 ? ens : chainShortNames + StatusQUtils.Utils.elideText(address,6,4)
visible: !activityFilterMenu.allSavedAddressesChecked && activityFilterMenu.savedAddressFilters.includes(address)
onClosed: activityFilterStore.toggleSavedAddress(address)
}
} }
} }
Repeater { Separator {
model: activityFilterMenu.allStatusChecked ? 0 : activityFilterStore.statusFilters visible: noResultsAfterFilter.visible
delegate: ActivityFilterTagItem {
property int status: activityFilterStore.statusFilters[index]
tagPrimaryLabel.text: switch(activityFilterStore.statusFilters[index]) {
case Constants.TransactionStatus.Failed:
return qsTr("Failed")
case Constants.TransactionStatus.Pending:
return qsTr("Pending")
case Constants.TransactionStatus.Complete:
return qsTr("Complete")
case Constants.TransactionStatus.Finished:
return qsTr("Finalised")
default:
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
return ""
}
iconAsset.icon: switch(activityFilterStore.statusFilters[index]) {
case Constants.TransactionStatus.Failed:
return Style.svg("transaction/failed")
case Constants.TransactionStatus.Pending:
return Style.svg("transaction/pending")
case Constants.TransactionStatus.Complete:
return Style.svg("transaction/verified")
case Constants.TransactionStatus.Finished:
return Style.svg("transaction/finished")
default:
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
return ""
}
iconAsset.color: "transparent"
onClosed: activityFilterStore.toggleStatus(status, activityFilterMenu.allStatusChecked)
}
} }
Repeater { StatusBaseText {
model: activityFilterStore.tokensList id: noResultsAfterFilter
delegate: ActivityFilterTagItem { anchors.horizontalCenter: parent.horizontalCenter
tagPrimaryLabel.text: symbol anchors.topMargin: 16
iconAsset.icon: Constants.tokenIcon(symbol) visible: !root.isLoading && activityFilterStore.transactionsList.count === 0 && activityFilterStore.filtersSet
iconAsset.color: "transparent" text: qsTr("No activity items for the current filter")
visible: !activityFilterMenu.allTokensChecked && activityFilterStore.tokensFilter.includes(symbol) font.pixelSize: Style.current.primaryTextFontSize
onClosed: activityFilterStore.toggleToken(symbol) color: Theme.palette.baseColor1
}
} }
Repeater { StatusButton {
model: activityFilterStore.collectiblesList anchors.horizontalCenter: parent.horizontalCenter
delegate: ActivityFilterTagItem { visible: noResultsAfterFilter.visible
tagPrimaryLabel.text: model.name text: qsTr("Clear all filters")
iconAsset.icon: model.imageUrl size: StatusBaseButton.Size.Small
iconAsset.color: "transparent" onClicked: activityFilterStore.resetAllFilters()
visible: !activityFilterMenu.allCollectiblesChecked && activityFilterStore.collectiblesFilter.includes(model.id)
onClosed: activityFilterStore.toggleCollectibles(model.id)
}
}
Repeater {
model: activityFilterStore.recentsList
delegate: ActivityFilterTagItem {
property int transactionType: to.toLowerCase() === root.store.overview.mixedcaseAddress.toLowerCase() ? Constants.TransactionType.Receive : Constants.TransactionType.Send
tagPrimaryLabel.text: transactionType === Constants.TransactionType.Receive ?
root.store.getNameForAddress(from) || StatusQUtils.Utils.elideText(from,6,4) :
root.store.getNameForAddress(to) || StatusQUtils.Utils.elideText(to,6,4)
visible: !activityFilterMenu.allRecentsChecked && activityFilterMenu.recentsFilters.includes(transactionType === Constants.TransactionType.Receive ? from : to)
onClosed: activityFilterStore.toggleRecents(transactionType === Constants.TransactionType.Receive ? from : to)
}
}
Repeater {
model: activityFilterStore.savedAddressList
delegate: ActivityFilterTagItem {
tagPrimaryLabel.text: ens.length > 0 ? ens : chainShortNames + StatusQUtils.Utils.elideText(address,6,4)
visible: !activityFilterMenu.allSavedAddressesChecked && activityFilterMenu.savedAddressFilters.includes(address)
onClosed: activityFilterStore.toggleSavedAddress(address)
}
} }
ActivityFilterMenu { ActivityFilterMenu {
@ -207,6 +236,7 @@ Flow {
savedAddressFilters: activityFilterStore.savedAddressFilters savedAddressFilters: activityFilterStore.savedAddressFilters
onUpdateSavedAddressFilter: activityFilterStore.toggleSavedAddress(address) onUpdateSavedAddressFilter: activityFilterStore.toggleSavedAddress(address)
onUpdateRecentsFilter: activityFilterStore.toggleRecents(address) onUpdateRecentsFilter: activityFilterStore.toggleRecents(address)
onUpdateRecipientsModel: activityFilterStore.updateRecipientsModel()
} }
StatusDateRangePicker { StatusDateRangePicker {

View File

@ -41,6 +41,7 @@ StatusMenu {
property var recentsFilters property var recentsFilters
readonly property bool allRecentsChecked: counterPartyMenu.allRecentsChecked readonly property bool allRecentsChecked: counterPartyMenu.allRecentsChecked
signal updateRecentsFilter(string address) signal updateRecentsFilter(string address)
signal updateRecipientsModel()
// Collectibles filter // Collectibles filter
property var savedAddressList property var savedAddressList
@ -103,6 +104,7 @@ StatusMenu {
savedAddressFilters: root.savedAddressFilters savedAddressFilters: root.savedAddressFilters
onSavedAddressToggled: root.updateSavedAddressFilter(address) onSavedAddressToggled: root.updateSavedAddressFilter(address)
onRecentsToggled: root.updateRecentsFilter(address) onRecentsToggled: root.updateRecentsFilter(address)
onUpdateRecipientsModel: root.updateRecipientsModel()
closePolicy: root.closePolicy closePolicy: root.closePolicy
} }
} }

View File

@ -33,9 +33,12 @@ StatusMenu {
signal back() signal back()
signal savedAddressToggled(string address) signal savedAddressToggled(string address)
signal recentsToggled(string address) signal recentsToggled(string address)
signal updateRecipientsModel()
implicitWidth: 289 implicitWidth: 289
Component.onCompleted: root.updateRecipientsModel()
MenuBackButton { MenuBackButton {
id: backButton id: backButton
width: parent.width width: parent.width
@ -74,28 +77,25 @@ StatusMenu {
id: recentsButtonGroup id: recentsButtonGroup
exclusive: false exclusive: false
} }
Repeater { StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Recents")
visible: root.recentsList.count === 0
}
StatusListView {
width: parent.width
height: root.height - tabBar.height - 12
model: root.recentsList model: root.recentsList
delegate: ActivityTypeCheckBox { delegate: ActivityTypeCheckBox {
readonly property int transactionType: model.activityEntry.recipient.toLowerCase() === store.overview.mixedcaseAddress.toLowerCase() ? Constants.TransactionType.Receive : Constants.TransactionType.Send readonly property string name: store.getNameForAddress(model.address)
readonly property string fromName: store.getNameForAddress(model.activityEntry.sender) width: ListView.view.width
readonly property string toName: store.getNameForAddress(model.activityEntry.recipient)
width: parent.width
height: 44 height: 44
title: transactionType === Constants.TransactionType.Receive ? title: name || StatusQUtils.Utils.elideText(model.address,6,4)
fromName || StatusQUtils.Utils.elideText(model.activityEntry.sender,6,4) : subTitle: name ? StatusQUtils.Utils.elideText(model.address,6,4): ""
toName || StatusQUtils.Utils.elideText(model.activityEntry.recipient,6,4)
subTitle: {
if (transactionType === Constants.TransactionType.Receive) {
return fromName ? StatusQUtils.Utils.elideText(model.activityEntry.sender,6,4) : ""
} else {
return toName ? StatusQUtils.Utils.elideText(model.activityEntry.recipient,6,4): ""
}
}
statusListItemSubTitle.elide: Text.ElideMiddle statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap statusListItemSubTitle.wrapMode: Text.NoWrap
assetSettings.name: (transactionType === Constants.TransactionType.Receive ? fromName : toName) || "address" assetSettings.name: name || "address"
assetSettings.isLetterIdenticon: transactionType === Constants.TransactionType.Receive ? !!fromName : !!toName assetSettings.isLetterIdenticon: !!name
assetSettings.bgHeight: 32 assetSettings.bgHeight: 32
assetSettings.bgWidth: 32 assetSettings.bgWidth: 32
assetSettings.bgRadius: assetSettings.bgHeight/2 assetSettings.bgRadius: assetSettings.bgHeight/2
@ -103,8 +103,8 @@ StatusMenu {
assetSettings.height: 16 assetSettings.height: 16
buttonGroup: recentsButtonGroup buttonGroup: recentsButtonGroup
allChecked: root.allRecentsChecked allChecked: root.allRecentsChecked
checked: root.allRecentsChecked ? true : root.recentsFilters.includes(transactionType === Constants.TransactionType.Receive ? model.activityEntry.sender: model.activityEntry.recipient) checked: root.allRecentsChecked ? true : root.recentsFilters.includes(model.address)
onActionTriggered: root.recentsToggled(transactionType === Constants.TransactionType.Receive ? model.activityEntry.sender: model.activityEntry.recipient) onActionTriggered: root.recentsToggled(model.address)
} }
} }
} }
@ -117,10 +117,17 @@ StatusMenu {
id: savedButtonGroup id: savedButtonGroup
exclusive: false exclusive: false
} }
Repeater { StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Saved Address")
visible: root.savedAddressList.count === 0
}
StatusListView {
width: parent.width
height: root.height - tabBar.height - 12
model: root.savedAddressList model: root.savedAddressList
delegate: ActivityTypeCheckBox { delegate: ActivityTypeCheckBox {
width: parent.width width: ListView.view.width
height: 44 height: 44
title: model.name ?? "" title: model.name ?? ""
subTitle: { subTitle: {

View File

@ -76,6 +76,12 @@ StatusMenu {
exclusive: false exclusive: false
} }
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Assets")
visible: root.tokensList.count === 0
}
SearchBox { SearchBox {
id: tokensSearchBox id: tokensSearchBox
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@ -84,32 +90,31 @@ StatusMenu {
placeholderText: qsTr("Search asset name") placeholderText: qsTr("Search asset name")
} }
ColumnLayout { StatusListView {
width: parent.width width: parent.width
height: root.height - tabBar.height - tokensSearchBox.height - 12
spacing: 0 spacing: 0
Repeater { model: SortFilterProxyModel {
model: SortFilterProxyModel { sourceModel: root.tokensList
sourceModel: root.tokensList filters: ExpressionFilter {
filters: ExpressionFilter { enabled: root.tokensList.count > 0
enabled: root.tokensList.count > 0 expression: {
expression: { var tokenSymbolByAddress = root.searchTokenSymbolByAddressFn(tokensSearchBox.text)
var tokenSymbolByAddress = root.searchTokenSymbolByAddressFn(tokensSearchBox.text) return symbol.startsWith(tokensSearchBox.text.toUpperCase()) || name.toUpperCase().startsWith(tokensSearchBox.text.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
return symbol.startsWith(tokensSearchBox.text.toUpperCase()) || name.toUpperCase().startsWith(tokensSearchBox.text.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
}
} }
} }
delegate: ActivityTypeCheckBox { }
Layout.fillWidth: true delegate: ActivityTypeCheckBox {
Layout.preferredHeight: 44 width: ListView.view.width
title: model.name height: 44
titleAsideText: model.symbol title: model.name
assetSettings.name: model.symbol ? Constants.tokenIcon(symbol) : "" titleAsideText: model.symbol
assetSettings.isImage: true assetSettings.name: model.symbol ? Constants.tokenIcon(symbol) : ""
buttonGroup: tokenButtonGroup assetSettings.isImage: true
allChecked: root.allTokensChecked buttonGroup: tokenButtonGroup
checked: root.allTokensChecked || root.tokensFilter.includes(model.symbol) allChecked: root.allTokensChecked
onActionTriggered: root.tokenToggled(model.symbol) checked: root.allTokensChecked || root.tokensFilter.includes(model.symbol)
} onActionTriggered: root.tokenToggled(model.symbol)
} }
} }
} }
@ -123,6 +128,12 @@ StatusMenu {
exclusive: false exclusive: false
} }
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Collectibles")
visible: root.collectiblesList.count === 0
}
SearchBox { SearchBox {
id: collectiblesSearchBox id: collectiblesSearchBox
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@ -131,35 +142,34 @@ StatusMenu {
placeholderText: qsTr("Search collectible name") placeholderText: qsTr("Search collectible name")
} }
ColumnLayout { StatusListView {
width: parent.width width: parent.width
height: root.height - tabBar.height - tokensSearchBox.height - 12
spacing: 0 spacing: 0
Repeater { model: SortFilterProxyModel {
model: SortFilterProxyModel { sourceModel: root.collectiblesList
sourceModel: root.collectiblesList filters: ExpressionFilter {
filters: ExpressionFilter { enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text
enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text expression: {
expression: { let searchText = collectiblesSearchBox.text.toUpperCase()
let searchText = collectiblesSearchBox.text.toUpperCase() return name.toUpperCase().startsWith(searchText)
return name.toUpperCase().startsWith(searchText)
}
} }
} }
delegate: ActivityTypeCheckBox { }
Layout.fillWidth: true delegate: ActivityTypeCheckBox {
Layout.preferredHeight: 44 width: ListView.view.width
title: model.name height: 44
assetSettings.name: model.imageUrl title: model.name
assetSettings.isImage: true assetSettings.name: model.imageUrl
assetSettings.bgWidth: 32 assetSettings.isImage: true
assetSettings.bgHeight: 32 assetSettings.bgWidth: 32
assetSettings.bgRadius: assetSettings.bgHeight/2 assetSettings.bgHeight: 32
buttonGroup: collectibleButtonGroup assetSettings.bgRadius: assetSettings.bgHeight/2
allChecked: root.allCollectiblesChecked buttonGroup: collectibleButtonGroup
checked: root.allCollectiblesChecked || root.collectiblesFilter.includes(model.id) allChecked: root.allCollectiblesChecked
onActionTriggered: root.collectibleToggled(model.id) checked: root.allCollectiblesChecked || root.collectiblesFilter.includes(model.id)
loading: d.isFetching onActionTriggered: root.collectibleToggled(model.id)
} loading: d.isFetching
} }
} }
} }

View File

@ -7,8 +7,10 @@ import utils 1.0
QtObject { QtObject {
id: root id: root
property var transactionsList: walletSection.activityController.model
property var activityController: walletSection.activityController property var activityController: walletSection.activityController
property bool filtersSet: fromTimestamp !== 0 || toTimestamp !== 0 || property bool filtersSet: selectedTime !== Constants.TransactionTimePeriod.All ||
typeFilters.length !== 0 || typeFilters.length !== 0 ||
statusFilters.length !== 0 || statusFilters.length !== 0 ||
tokensFilter.length !== 0 || tokensFilter.length !== 0 ||
@ -22,40 +24,58 @@ QtObject {
property double toTimestamp: new Date().valueOf() property double toTimestamp: new Date().valueOf()
function setSelectedTimestamp(selcTime) { function setSelectedTimestamp(selcTime) {
selectedTime = selcTime selectedTime = selcTime
var currDate = new Date() // current date
switch(selectedTime) { switch(selectedTime) {
case Constants.TransactionTimePeriod.All: case Constants.TransactionTimePeriod.All:
fromTimestamp = 0 fromTimestamp = 0
toTimestamp = 0 toTimestamp = 0
break break
case Constants.TransactionTimePeriod.Today: case Constants.TransactionTimePeriod.Today:
fromTimestamp = currDate.valueOf() // Today let dt = new Date()
toTimestamp = fromTimestamp fromTimestamp = dt.setHours(0,0,0,0).valueOf() // Today
dt.setDate(dt.getDate() + 1) // next day...
dt.setHours(0, 0, 0, -1) // ... but just 1ms before midnight -> whole day included
toTimestamp = dt.valueOf()
break break
case Constants.TransactionTimePeriod.Yesterday: case Constants.TransactionTimePeriod.Yesterday:
fromTimestamp = new Date().setDate(currDate.getDate() - 1).valueOf() // Yesterday let dt1 = new Date()
toTimestamp = fromTimestamp dt1.setDate(dt1.getDate() - 1)
dt1.setHours(0, 0, 0, 0)
fromTimestamp = dt1.valueOf() // Yesterday
dt1.setDate(dt1.getDate() + 1)
dt1.setHours(0, 0, 0, -1)
toTimestamp = dt1.valueOf()
break break
case Constants.TransactionTimePeriod.ThisWeek: case Constants.TransactionTimePeriod.ThisWeek:
var firstDayOfCurrentWeek = currDate.getDate() - currDate.getDay() let dt2 = new Date()
fromTimestamp = new Date().setDate(firstDayOfCurrentWeek).valueOf() // This week let firstDayOfCurrentWeek = dt2.getDate() - dt2.getDay()
toTimestamp = currDate.valueOf() dt2.setDate(firstDayOfCurrentWeek)
dt2.setHours(0, 0, 0, 0)
fromTimestamp = dt2.valueOf() // This week
toTimestamp = new Date().valueOf()
break break
case Constants.TransactionTimePeriod.LastWeek: case Constants.TransactionTimePeriod.LastWeek:
fromTimestamp = new Date().setDate(currDate.getDate() - 7).valueOf() // Last week let dt3 = new Date()
toTimestamp = currDate.valueOf() dt3.setDate(dt3.getDate() - 7)
dt3.setHours(0, 0, 0, 0)
fromTimestamp = dt3.valueOf() // Last week
toTimestamp = new Date().valueOf()
break break
case Constants.TransactionTimePeriod.ThisMonth: case Constants.TransactionTimePeriod.ThisMonth:
fromTimestamp = new Date().setDate(1).valueOf() // This month let dt4 = new Date()
toTimestamp = currDate.valueOf() dt4.setDate(1)
dt4.setHours(0, 0, 0, 0)
fromTimestamp = dt4.valueOf() // This month
toTimestamp = new Date().valueOf()
break break
case Constants.TransactionTimePeriod.LastMonth: case Constants.TransactionTimePeriod.LastMonth:
let x = new Date() let dt5 = new Date()
x.setDate(1) dt5.setDate(1)
x.setMonth(x.getMonth()-1) dt5.setMonth(dt5.getMonth()-1)
fromTimestamp = x.valueOf() // Last month dt5.setHours(0, 0, 0, 0)
x.setDate(new Date(x.getFullYear(), x.getMonth(), 0).getDate() + 1) fromTimestamp = dt5.valueOf() // Last month
toTimestamp = x.valueOf() dt5.setDate(new Date(dt5.getFullYear(), dt5.getMonth(), 0).getDate() + 2)
dt5.setHours(0, 0, 0, -1)
toTimestamp = dt5.valueOf()
break break
default: default:
return "" return ""
@ -115,13 +135,14 @@ QtObject {
} }
// To-do get correct model unaffected by filters from go side property var recentsList: activityController.recipientsModel
property var recentsList: []
property var recentsFilters: [] property var recentsFilters: []
function updateRecipientsModel() {
activityController.updateRecipientsModel()
}
function toggleRecents(address) { function toggleRecents(address) {
// update filters // update filters
recentsFilters = toggleFilterState(recentsFilters, address, recentsList.count) recentsFilters = toggleFilterState(recentsFilters, address, recentsList.count)
// Set backend values
activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters))) activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters)))
activityController.updateFilter() activityController.updateFilter()
} }
@ -176,4 +197,29 @@ QtObject {
function updateFilterBase() { function updateFilterBase() {
activityController.updateFilterBase() activityController.updateFilterBase()
} }
function resetAllFilters() {
selectedTime = Constants.TransactionTimePeriod.All
fromTimestamp = activityController.startTimestamp * 1000
toTimestamp = new Date().valueOf()
activityController.setFilterTime(fromTimestamp/1000, toTimestamp/1000)
typeFilters = []
activityController.setFilterType(JSON.stringify(typeFilters))
statusFilters = []
activityController.setFilterStatus(JSON.stringify(statusFilters))
tokensFilter = []
activityController.setFilterAssets(JSON.stringify(tokensFilter), false)
collectiblesFilter = []
// To-do call update filter for collectibles
recentsFilters = []
savedAddressFilters = []
activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters)))
activityController.updateFilter()
}
} }

View File

@ -64,14 +64,13 @@ ColumnLayout {
text: qsTr("Activity for this account will appear here") text: qsTr("Activity for this account will appear here")
} }
// Tp-do make connections with nim once logic is ready
ActivityFilterPanel { ActivityFilterPanel {
id: filterComponent id: filterComponent
visible: !d.isLoading && (transactionListRoot.count !== 0 || d.activityFiltersStore.filtersSet) visible: !d.isLoading && (transactionListRoot.count !== 0 || d.activityFiltersStore.filtersSet)
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 50
activityFilterStore: d.activityFiltersStore activityFilterStore: d.activityFiltersStore
store: WalletStores.RootStore store: WalletStores.RootStore
isLoading: d.isLoading
} }
Item { Item {