feat(@desktop/wallet): Glue for acitvity filter UI and backend

This commit is contained in:
Khushboo Mehta 2023-06-15 19:43:08 +02:00 committed by Khushboo-dev-cpp
parent 60d78eb0ad
commit 47c76714db
12 changed files with 385 additions and 613 deletions

View File

@ -5,6 +5,7 @@ import QtQuick.Layouts 1.14
import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.popups 1.0
import AppLayouts.Wallet.panels 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.stores 1.0
import StatusQ.Core 0.1
@ -31,285 +32,7 @@ SplitView {
QtObject {
id: d
property int selectedTime: Constants.TransactionTimePeriod.All
property double fromTimestamp: new Date().setDate(new Date().getDate() - 7)
property double toTimestamp: Date.now()
function changeSelectedTime(newTime) {
selectedTime = newTime
}
function setCustomTimeRange(fromTimestamp , toTimestamp) {
d.fromTimestamp = fromTimestamp
d.toTimestamp = toTimestamp
}
property var typeFilters: [
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<tempodel.count; k++) {
if(!tempodel.get(k).checked)
allChecked = false
else {
checkedTokens.push(tempodel.get(k))
}
}
if(allChecked) {
for (let i = 0; i<tempodel.count; i++) {
if(tempodel.get(i).symbol === tokenSymbol) {
tempodel.get(i).checked = true
}
else
tempodel.get(i).checked = false
}
}
else if(checkedTokens.length === 1 && checkedTokens[0].symbol === tokenSymbol) {
for (let j = 0; j<tempodel.count; j++) {
tempodel.get(j).checked = true
tempodel.get(j).allChecked = true
}
}
else {
for (let l =0; l<tempodel.count; l++) {
if(tempodel.get(l).symbol === tokenSymbol)
tempodel.get(l).checked = !tempodel.get(l).checked
}
}
for (let l =0; l<tempodel.count; l++) {
if(!tempodel.get(l).checked)
allChecked1 = false
}
for (let j =0; j<tempodel.count; j++) {
tempodel.get(j).allChecked = allChecked1
}
simulatedAssetsModel = tempodel
}
property var simulatedCollectiblesModel: CollectiblesModel {}
function toggleCollectibles(name) {
let tempodel = simulatedCollectiblesModel
let allChecked = true
let allChecked1 = true
let checkedTokens = []
simulatedCollectiblesModel = []
for (let k =0; k<tempodel.count; k++) {
if(!tempodel.get(k).checked)
allChecked = false
else {
checkedTokens.push(tempodel.get(k))
}
}
if(allChecked) {
for (let i = 0; i<tempodel.count; i++) {
if(tempodel.get(i).name === name) {
tempodel.get(i).checked = true
}
else
tempodel.get(i).checked = false
}
}
else if(checkedTokens.length === 1 && checkedTokens[0].name === name) {
for (let j = 0; j<tempodel.count; j++) {
tempodel.get(j).checked = true
tempodel.get(j).allChecked = true
}
}
else {
for (let l =0; l<tempodel.count; l++) {
if(tempodel.get(l).name === name)
tempodel.get(l).checked = !tempodel.get(l).checked
}
}
for (let l =0; l<tempodel.count; l++) {
if(!tempodel.get(l).checked)
allChecked1 = false
}
for (let j =0; j<tempodel.count; j++) {
tempodel.get(j).allChecked = allChecked1
}
simulatedCollectiblesModel = tempodel
}
property var recipeintModel: RecipientModel {}
property var simulatedSavedList: recipeintModel.savedAddresses
property var simulatedRecentsList: recipeintModel.recents
function toggleSavedAddress(address) {
let tempodel = simulatedSavedList
let allChecked = true
let allChecked1 = true
let checkedTokens = []
simulatedSavedList = []
for (let k =0; k<tempodel.count; k++) {
if(!tempodel.get(k).checked)
allChecked = false
else {
checkedTokens.push(tempodel.get(k))
}
}
if(allChecked) {
for (let i = 0; i<tempodel.count; i++) {
if(tempodel.get(i).address === address) {
tempodel.get(i).checked = true
}
else
tempodel.get(i).checked = false
}
}
else if(checkedTokens.length === 1 && checkedTokens[0].address === address) {
for (let j = 0; j<tempodel.count; j++) {
tempodel.get(j).checked = true
tempodel.get(j).allChecked = true
}
}
else {
for (let l =0; l<tempodel.count; l++) {
if(tempodel.get(l).address === address)
tempodel.get(l).checked = !tempodel.get(l).checked
}
}
for (let l =0; l<tempodel.count; l++) {
if(!tempodel.get(l).checked)
allChecked1 = false
}
for (let j =0; j<tempodel.count; j++) {
tempodel.get(j).allChecked = allChecked1
}
simulatedSavedList = tempodel
}
function toggleRecents(address) {
let tempodel = simulatedRecentsList
let allChecked = true
let allChecked1 = true
let checkedTokens = []
simulatedRecentsList = []
for (let k =0; k<tempodel.count; k++) {
if(!tempodel.get(k).checked)
allChecked = false
else {
checkedTokens.push(tempodel.get(k))
}
}
if(allChecked) {
for (let i = 0; i<tempodel.count; i++) {
let addresstoFind = tempodel.get(i).to.toLowerCase() === d.store.overview.mixedcaseAddress.toLowerCase() ? tempodel.get(i).from : tempodel.get(i).to
if(addresstoFind === address) {
tempodel.get(i).checked = true
}
else
tempodel.get(i).checked = false
}
}
else if(checkedTokens.length === 1 && (checkedTokens[0].to.toLowerCase() === d.store.overview.mixedcaseAddress.toLowerCase() ? checkedTokens[0].from : checkedTokens[0].to) === address) {
for (let j = 0; j<tempodel.count; j++) {
tempodel.get(j).checked = true
tempodel.get(j).allChecked = true
}
}
else {
for (let l =0; l<tempodel.count; l++) {
let addresstoFind = tempodel.get(l).to.toLowerCase() === d.store.overview.mixedcaseAddress.toLowerCase() ? tempodel.get(l).from : tempodel.get(l).to
if(addresstoFind === address )
tempodel.get(l).checked = !tempodel.get(l).checked
}
}
for (let m =0; m<tempodel.count; m++) {
if(!tempodel.get(m).checked)
allChecked1 = false
}
for (let n =0; n<tempodel.count; n++) {
tempodel.get(n).allChecked = allChecked1
}
simulatedRecentsList = tempodel
}
property var store: QtObject {
property var overview: ({
@ -333,6 +56,35 @@ SplitView {
return ""
}
}
property var activityController: QtObject {
function setFilterTime(fromTimestamp, toTimestamp) {
console.warn("activityController:: setFilterTime:: fromTimestamp: ",fromTimestamp, " toTimestamp:: ",toTimestamp)
}
function setFilterType(typeFilters) {
console.warn("activityController:: setFilterType:: ",typeFilters)
}
function setFilterStatus(statusFilters) {
console.warn("activityController:: setFilterStatus:: ",statusFilters)
}
function setFilterAssets(tokensFilter) {
console.warn("activityController:: setFilterAssets:: ",tokensFilter)
}
function setFilterToAddresses(filters) {
console.warn("activityController:: setFilterToAddresses:: ",filters)
}
function updateFilter() {
console.warn("activityController:: updateFilter")
}
}
}
ActivityFiltersStore {
id: actvityStore
tokensList: WalletAssetsModel {}
collectiblesList: CollectiblesModel {}
savedAddressesModel: d.recipeintModel.savedAddresses
activityController: d.activityController
areTestNetworksEnabled: false
}
Item {
@ -344,133 +96,7 @@ SplitView {
width: 800
anchors.centerIn: parent
store: d.store
fromTimestamp: d.fromTimestamp
toTimestamp: d.toTimestamp
selectedTime: d.selectedTime
typeFilters: d.typeFilters
statusFilters: d.statusFilters
assetsList: d.simulatedAssetsModel
collectiblesList: d.simulatedCollectiblesModel
savedAddressList: d.simulatedSavedList
recentsList: d.simulatedRecentsList
onChangeSelectedTime: d.changeSelectedTime(selectedTime)
onSetCustomTimeRange: d.setCustomTimeRange(from, to)
onToggleType: d.toggleType(type)
onToggleStatus: d.toggleStatus(status)
onToggleToken: d.toggleToken(tokenSymbol)
onToggleCollectibles: d.toggleCollectibles(name)
onToggleSavedAddress: d.toggleSavedAddress(address)
onToggleRecents: d.toggleRecents(address)
}
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumHeight: 100
SplitView.preferredHeight: 200
logsView.logText: logs.logText
ButtonGroup {
buttons: periodRow.children
}
Column {
spacing: 20
Row {
id: periodRow
spacing: 20
RadioButton {
checked: true
text: "All"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.All}
}
RadioButton {
text: "Today"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.Today}
}
RadioButton {
text: "Yesterday"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.Yesterday}
}
RadioButton {
text: "ThisWeek"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.ThisWeek}
}
RadioButton {
text: "LastWeek"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.LastWeek}
}
RadioButton {
text: "ThisMonth"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.ThisMonth}
}
RadioButton {
text: "LastMonth"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.LastMonth}
}
RadioButton {
text: "Custom"
onCheckedChanged: if(checked) { d.selectedTime = Constants.TransactionTimePeriod.Custom}
}
}
Row {
spacing: 20
CheckBox {
text: "Send"
checked: d.typeFilters.includes(Constants.TransactionType.Send)
onClicked: d.toggleType(Constants.TransactionType.Send)
}
CheckBox {
text: "Receive"
checked: d.typeFilters.includes(Constants.TransactionType.Receive)
onClicked: d.toggleType(Constants.TransactionType.Receive)
}
CheckBox {
text: "Buy"
checked: d.typeFilters.includes(Constants.TransactionType.Buy)
onClicked: d.toggleType(Constants.TransactionType.Buy)
}
CheckBox {
text: "Swap"
checked: d.typeFilters.includes(Constants.TransactionType.Swap)
onClicked: d.toggleType(Constants.TransactionType.Swap)
}
CheckBox {
text: "Bridge"
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)
}
}
activityFilterStore: actvityStore
}
}
}

View File

@ -9,16 +9,16 @@ ListModel {
iconSource: ModelsData.collectibles.anniversary,
name: "Anniversary",
category: TokenCategories.Category.Community,
checked: true,
allChecked: true
imageUrl: ModelsData.collectibles.anniversary,
id: 1767698
},
{
key: "Anniversary2",
iconSource: ModelsData.collectibles.anniversary,
name: "Anniversary2",
category: TokenCategories.Category.Community,
checked: true,
allChecked: true
imageUrl: ModelsData.collectibles.anniversary,
id: 1767699
},
{
key: "CryptoKitties",
@ -69,26 +69,28 @@ ListModel {
name: "Magicat-4"
}
],
checked: true,
allChecked: true
imageUrl: ModelsData.collectibles.cryptoKitties,
id: 1767700
},
{
key: "SuperRare",
iconSource: ModelsData.collectibles.superRare,
name: "SuperRare",
category: TokenCategories.Category.Own,
checked: true,
allChecked: true
imageUrl: ModelsData.collectibles.superRare,
id: 1767701
},
{
key: "Custom",
iconSource: ModelsData.collectibles.custom,
name: "Custom Collectible",
category: TokenCategories.Category.General,
checked: true,
allChecked: true
imageUrl: ModelsData.collectibles.custom,
id: 1767764
}
]
property bool isFetching: false
Component.onCompleted: append(data)
}

View File

@ -34,6 +34,7 @@ StatusListItem {
components: [
StatusCheckBox {
id: checkBox
visible: !root.loading
tristate: true
checkable: true
spacing: 0

View File

@ -13,25 +13,8 @@ import "../popups"
Flow {
id: root
property var activityFilterStore
property var store
property int selectedTime
property double fromTimestamp
property double toTimestamp
property var typeFilters
property var statusFilters
property var assetsList
property var collectiblesList
property var savedAddressList
property var recentsList
signal changeSelectedTime(int selectedTime)
signal setCustomTimeRange(string from, string to)
signal toggleType(int type)
signal toggleStatus(int status)
signal toggleToken(string tokenSymbol)
signal toggleCollectibles(string name)
signal toggleSavedAddress(string address)
signal toggleRecents(string address)
spacing: 8
@ -47,53 +30,18 @@ Flow {
}
ActivityFilterTagItem {
tagPrimaryLabel.text: {
var currDate = new Date; // current date
switch(root.selectedTime) {
case Constants.TransactionTimePeriod.Today:
return LocaleUtils.formatDate(currDate) // Today
case Constants.TransactionTimePeriod.Yesterday:
return LocaleUtils.formatDate(new Date().setDate(currDate.getDate() - 1)) // Yesterday
case Constants.TransactionTimePeriod.ThisWeek:
var firstDayOfCurrentWeek = currDate.getDate() - currDate.getDay()
return LocaleUtils.formatDate(currDate.setDate(firstDayOfCurrentWeek)) // This week
case Constants.TransactionTimePeriod.LastWeek:
return LocaleUtils.formatDate(new Date().setDate(currDate.getDate() - 7)) // Last week
case Constants.TransactionTimePeriod.ThisMonth:
return LocaleUtils.formatDate(currDate.setDate(1)) // This month
case Constants.TransactionTimePeriod.LastMonth:
currDate.setDate(1);
currDate.setMonth(currDate.getMonth()-1);
return LocaleUtils.formatDate(currDate) // Last month
case Constants.TransactionTimePeriod.Custom:
return LocaleUtils.formatDate(new Date(root.fromTimestamp)) // Custom
default:
return ""
}
}
tagPrimaryLabel.text: LocaleUtils.formatDate(activityFilterStore.fromTimestamp)
tagSecondaryLabel.text: {
switch(root.selectedTime) {
switch(activityFilterMenu.selectedTime) {
case Constants.TransactionTimePeriod.Today:
case Constants.TransactionTimePeriod.Yesterday:
return ""
case Constants.TransactionTimePeriod.ThisWeek:
case Constants.TransactionTimePeriod.LastWeek:
case Constants.TransactionTimePeriod.ThisMonth:
return LocaleUtils.formatDate(new Date)
case Constants.TransactionTimePeriod.LastMonth:
let x = new Date()
x.setDate(1);
x.setMonth(x.getMonth()-1);
x.setDate(new Date(x.getFullYear(), x.getMonth(), 0).getDate() + 1)
return LocaleUtils.formatDate(x)
case Constants.TransactionTimePeriod.Custom:
return LocaleUtils.formatDate(new Date(root.toTimestamp)) // Custom
default:
return ""
return LocaleUtils.formatDate(activityFilterStore.toTimestamp)
}
}
middleLabel.text:{
switch(root.selectedTime) {
middleLabel.text: {
switch(activityFilterMenu.selectedTime) {
case Constants.TransactionTimePeriod.Today:
case Constants.TransactionTimePeriod.Yesterday:
return ""
@ -101,17 +49,16 @@ Flow {
return qsTr("to")
}
}
iconAsset.icon: "history"
visible: root.selectedTime !== Constants.TransactionTimePeriod.All
onClosed: root.changeSelectedTime(Constants.TransactionTimePeriod.All)
visible: activityFilterMenu.selectedTime !== Constants.TransactionTimePeriod.All
onClosed: activityFilterStore.setSelectedTimestamp(Constants.TransactionTimePeriod.All)
}
Repeater {
model: activityFilterMenu.allTypesChecked ? 0: root.typeFilters
model: activityFilterMenu.allTypesChecked ? 0: activityFilterStore.typeFilters
delegate: ActivityFilterTagItem {
property int type: root.typeFilters[index]
tagPrimaryLabel.text: switch(root.typeFilters[index]) {
property int type: activityFilterStore.typeFilters[index]
tagPrimaryLabel.text: switch(activityFilterStore.typeFilters[index]) {
case Constants.TransactionType.Send:
return qsTr("Send")
case Constants.TransactionType.Receive:
@ -123,10 +70,10 @@ Flow {
case Constants.TransactionType.Bridge:
return qsTr("Bridge")
default:
console.warn("Unhandled type :: ",root.typeFilters[index])
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index])
return ""
}
iconAsset.icon: switch(root.typeFilters[index]) {
iconAsset.icon: switch(activityFilterStore.typeFilters[index]) {
case Constants.TransactionType.Send:
return "send"
case Constants.TransactionType.Receive:
@ -138,18 +85,18 @@ Flow {
case Constants.TransactionType.Bridge:
return "bridge"
default:
console.warn("Unhandled type :: ",root.typeFilters[index])
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index])
return ""
}
onClosed: root.toggleType(type)
onClosed: activityFilterStore.toggleType(type)
}
}
Repeater {
model: activityFilterMenu.allStatusChecked ? 0 : root.statusFilters
model: activityFilterMenu.allStatusChecked ? 0 : activityFilterStore.statusFilters
delegate: ActivityFilterTagItem {
property int type: root.statusFilters[index]
tagPrimaryLabel.text: switch(root.statusFilters[index]) {
property int status: activityFilterStore.statusFilters[index]
tagPrimaryLabel.text: switch(activityFilterStore.statusFilters[index]) {
case Constants.TransactionStatus.Failed:
return qsTr("Failed")
case Constants.TransactionStatus.Pending:
@ -159,10 +106,10 @@ Flow {
case Constants.TransactionStatus.Finished:
return qsTr("Finalised")
default:
console.warn("Unhandled status :: ",root.statusFilters[index])
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
return ""
}
iconAsset.icon: switch(root.statusFilters[index]) {
iconAsset.icon: switch(activityFilterStore.statusFilters[index]) {
case Constants.TransactionStatus.Failed:
return Style.svg("transaction/failed")
case Constants.TransactionStatus.Pending:
@ -172,96 +119,100 @@ Flow {
case Constants.TransactionStatus.Finished:
return Style.svg("transaction/finished")
default:
console.warn("Unhandled status :: ",root.statusFilters[index])
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
return ""
}
iconAsset.color: "transparent"
onClosed: root.toggleStatus(type)
onClosed: activityFilterStore.toggleStatus(status, activityFilterMenu.allStatusChecked)
}
}
Repeater {
model: root.assetsList
model: activityFilterStore.tokensList
delegate: ActivityFilterTagItem {
tagPrimaryLabel.text: symbol
iconAsset.icon: Constants.tokenIcon(symbol)
iconAsset.color: "transparent"
visible: !allChecked && checked
onClosed: root.toggleToken(symbol)
visible: !activityFilterMenu.allTokensChecked && activityFilterStore.tokensFilter.includes(symbol)
onClosed: activityFilterStore.toggleToken(symbol)
}
}
Repeater {
model: root.collectiblesList
model: activityFilterStore.collectiblesList
delegate: ActivityFilterTagItem {
tagPrimaryLabel.text: name
iconAsset.icon: model.iconSource
tagPrimaryLabel.text: model.name
iconAsset.icon: model.imageUrl
iconAsset.color: "transparent"
visible: !allChecked && checked
onClosed: root.toggleCollectibles(name)
visible: !activityFilterMenu.allCollectiblesChecked && activityFilterStore.collectiblesFilter.includes(model.id)
onClosed: activityFilterStore.toggleCollectibles(model.id)
}
}
Repeater {
model: root.recentsList
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: !allChecked && checked
onClosed: root.toggleRecents(transactionType === Constants.TransactionType.Receive ? from : to)
visible: !activityFilterMenu.allRecentsChecked && activityFilterMenu.recentsFilters.includes(transactionType === Constants.TransactionType.Receive ? from : to)
onClosed: activityFilterStore.toggleRecents(transactionType === Constants.TransactionType.Receive ? from : to)
}
}
Repeater {
model: root.savedAddressList
model: activityFilterStore.savedAddressList
delegate: ActivityFilterTagItem {
tagPrimaryLabel.text: ens.length > 0 ? ens : chainShortNames + StatusQUtils.Utils.elideText(address,6,4)
visible: !allChecked && checked
onClosed: root.toggleSavedAddress(address)
visible: !activityFilterMenu.allSavedAddressesChecked && activityFilterMenu.savedAddressFilters.includes(address)
onClosed: activityFilterStore.toggleSavedAddress(address)
}
}
ActivityFilterMenu {
id: activityFilterMenu
selectedTime: root.selectedTime
selectedTime: activityFilterStore.selectedTime
onSetSelectedTime: {
if(selectedTime === Constants.TransactionTimePeriod.Custom) {
dialog.open()
}
else
root.changeSelectedTime(selectedTime)
else {
activityFilterStore.setSelectedTimestamp(selectedTime)
}
}
typeFilters: root.typeFilters
onUpdateTypeFilter: root.toggleType(type)
typeFilters: activityFilterStore.typeFilters
onUpdateTypeFilter: activityFilterStore.toggleType(type, allFiltersCount)
statusFilters: root.statusFilters
onUpdateStatusFilter: root.toggleStatus(status)
statusFilters: activityFilterStore.statusFilters
onUpdateStatusFilter: activityFilterStore.toggleStatus(status, allFiltersCount)
tokensList: root.assetsList
collectiblesList: root.collectiblesList
onUpdateTokensFilter: root.toggleToken(tokenSymbol)
onUpdateCollectiblesFilter: root.toggleCollectibles(name)
tokensList: activityFilterStore.tokensList
tokensFilter: activityFilterStore.tokensFilter
collectiblesList: activityFilterStore.collectiblesList
collectiblesFilter: activityFilterStore.collectiblesFilter
onUpdateTokensFilter: activityFilterStore.toggleToken(tokenSymbol)
onUpdateCollectiblesFilter: activityFilterStore.toggleCollectibles(id)
store: root.store
recentsList: root.recentsList
savedAddressList: root.savedAddressList
onUpdateSavedAddressFilter: root.toggleSavedAddress(address)
onUpdateRecentsFilter: root.toggleRecents(address)
recentsList: activityFilterStore.recentsList
recentsFilters: activityFilterStore.recentsFilters
savedAddressList: activityFilterStore.savedAddressList
savedAddressFilters: activityFilterStore.savedAddressFilters
onUpdateSavedAddressFilter: activityFilterStore.toggleSavedAddress(address)
onUpdateRecentsFilter: activityFilterStore.toggleRecents(address)
}
StatusDateRangePicker {
id: dialog
anchors.centerIn: parent
// To-do sync with backend
fromTimestamp: root.fromTimestamp// 7 days ago
toTimestamp: root.toTimestamp
fromTimestamp: activityFilterStore.fromTimestamp
toTimestamp: activityFilterStore.toTimestamp
onNewRangeSet: {
root.setCustomTimeRange(fromTimestamp, toTimestamp)
root.changeSelectedTime(Constants.TransactionTimePeriod.Custom)
activityFilterStore.setCustomTimeRange(fromTimestamp, toTimestamp)
activityFilterStore.setSelectedTimestamp(Constants.TransactionTimePeriod.Custom)
}
}
}

View File

@ -8,33 +8,46 @@ import "./filterSubMenus"
StatusMenu {
id: root
property var store
// Time filter
property int selectedTime: ActivityFilterMenu.All
signal setSelectedTime(int selectedTime)
// Type filter
property var typeFilters: []
property bool allTypesChecked: typeMenu.allChecked
signal updateTypeFilter(int type)
readonly property bool allTypesChecked: typeMenu.allChecked
signal updateTypeFilter(int type, int allFiltersCount)
// Status filter
property var statusFilters: []
property bool allStatusChecked: statusMenu.allChecked
signal updateStatusFilter(int status)
readonly property bool allStatusChecked: statusMenu.allChecked
signal updateStatusFilter(int status, int allFiltersCount)
// Assets filter
// Tokens filter
property var tokensList: []
property var collectiblesList
property var tokensFilter: []
readonly property bool allTokensChecked: tokensMenu.allTokensChecked
signal updateTokensFilter(string tokenSymbol)
signal updateCollectiblesFilter(string name)
// Counterparty filter
property var store
// Collectibles filter
property var collectiblesList: []
property var collectiblesFilter: []
readonly property bool allCollectiblesChecked: tokensMenu.allCollectiblesChecked
signal updateCollectiblesFilter(double id)
// Recents filter
property var recentsList
property var savedAddressList
signal updateSavedAddressFilter(string address)
property var recentsFilters
readonly property bool allRecentsChecked: counterPartyMenu.allRecentsChecked
signal updateRecentsFilter(string address)
// Collectibles filter
property var savedAddressList
property var savedAddressFilters
readonly property bool allSavedAddressesChecked: counterPartyMenu.allSavedAddressesChecked
signal updateSavedAddressFilter(string address)
implicitWidth: 176
// Filter By Period
@ -57,14 +70,14 @@ StatusMenu {
id: typeMenu
onBack: root.open()
typeFilters: root.typeFilters
onActionTriggered: updateTypeFilter(type)
onActionTriggered: updateTypeFilter(type, allFiltersCount)
closePolicy: root.closePolicy
}
ActivityStatusFilterSubMenu {
id: statusMenu
onBack: root.open()
statusFilters: root.statusFilters
onActionTriggered: updateStatusFilter(status)
onActionTriggered: updateStatusFilter(status, allFiltersCount)
closePolicy: root.closePolicy
}
ActivityTokensFilterSubMenu {
@ -72,9 +85,11 @@ StatusMenu {
height: Math.min(439, tokensMenu.implicitHeight)
onBack: root.open()
tokensList: root.tokensList
tokensFilter: root.tokensFilter
collectiblesList: root.collectiblesList
collectiblesFilter: root.collectiblesFilter
onTokenToggled: updateTokensFilter(tokenSymbol)
onCollectibleToggled: updateCollectiblesFilter(name)
onCollectibleToggled: updateCollectiblesFilter(id)
closePolicy: root.closePolicy
}
ActivityCounterpartyFilterSubMenu {
@ -83,7 +98,9 @@ StatusMenu {
onBack: root.open()
store: root.store
recentsList: root.recentsList
recentsFilters: root.recentsFilters
savedAddressList: root.savedAddressList
savedAddressFilters: root.savedAddressFilters
onSavedAddressToggled: root.updateSavedAddressFilter(address)
onRecentsToggled: root.updateRecentsFilter(address)
closePolicy: root.closePolicy

View File

@ -20,18 +20,20 @@ import "../../controls"
StatusMenu {
id: root
property var recentsList
property var savedAddressList
property var store
property var recentsList
property var recentsFilters
readonly property bool allRecentsChecked: recentsFilters.length === 0
property var savedAddressList
property var savedAddressFilters
readonly property bool allSavedAddressesChecked: savedAddressFilters.length === 0
signal back()
signal savedAddressToggled(string address)
signal recentsToggled(string address)
property var searchTokenSymbolByAddressFn: function (address) {
return ""
}
implicitWidth: 289
MenuBackButton {
@ -75,36 +77,34 @@ StatusMenu {
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)
readonly property int transactionType: model.activityEntry.recipient.toLowerCase() === store.overview.mixedcaseAddress.toLowerCase() ? Constants.TransactionType.Receive : Constants.TransactionType.Send
readonly property string fromName: store.getNameForAddress(model.activityEntry.sender)
readonly property string toName: store.getNameForAddress(model.activityEntry.recipient)
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)
fromName || StatusQUtils.Utils.elideText(model.activityEntry.sender,6,4) :
toName || StatusQUtils.Utils.elideText(model.activityEntry.recipient,6,4)
subTitle: {
if (transactionType === Constants.TransactionType.Receive) {
return fromName ? StatusQUtils.Utils.elideText(model.from,6,4) : ""
return fromName ? StatusQUtils.Utils.elideText(model.activityEntry.sender,6,4) : ""
} else {
return toName ? StatusQUtils.Utils.elideText(model.to,6,4): ""
return toName ? StatusQUtils.Utils.elideText(model.activityEntry.recipient,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.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 ? model.from: model.to)
allChecked: root.allRecentsChecked
checked: root.allRecentsChecked ? true : root.recentsFilters.includes(transactionType === Constants.TransactionType.Receive ? model.activityEntry.sender: model.activityEntry.recipient)
onActionTriggered: root.recentsToggled(transactionType === Constants.TransactionType.Receive ? model.activityEntry.sender: model.activityEntry.recipient)
}
}
}
@ -137,8 +137,8 @@ StatusMenu {
assetSettings.name: model.name
assetSettings.isLetterIdenticon: true
buttonGroup: savedButtonGroup
allChecked: model.allChecked
checked: model.checked
allChecked: root.allSavedAddressesChecked
checked: root.allSavedAddressesChecked ? true : root.savedAddressFilters.includes(model.address)
onActionTriggered: root.savedAddressToggled(model.address)
}
}

View File

@ -11,7 +11,8 @@ StatusMenu {
id: root
property var statusFilters: []
readonly property bool allChecked: statusFilters.length === typeButtonGroup.buttons.length
readonly property bool allChecked: statusFilters.length === 0
readonly property int allFiltersCount: typeButtonGroup.buttons.length
signal back()
signal actionTriggered(int status)
@ -37,7 +38,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionStatus.Failed
checked: statusFilters.includes(type)
checked: root.allChecked || statusFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -49,7 +50,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionStatus.Pending
checked: statusFilters.includes(type)
checked: root.allChecked || statusFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -61,7 +62,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionStatus.Complete
checked: statusFilters.includes(type)
checked: root.allChecked || statusFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -73,7 +74,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionStatus.Finished
checked: statusFilters.includes(type)
checked: root.allChecked || statusFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
}

View File

@ -16,19 +16,27 @@ import utils 1.0
StatusMenu {
id: root
property var tokensList
property var collectiblesList
property var tokensFilter: []
property var tokensList: []
readonly property bool allTokensChecked: tokensFilter.length === 0
property var collectiblesList: []
property var collectiblesFilter: []
readonly property bool allCollectiblesChecked: collectiblesFilter.length === 0
signal back()
signal tokenToggled(string tokenSymbol)
signal collectibleToggled(string name)
signal collectibleToggled(double id)
property var searchTokenSymbolByAddressFn: function (address) {
return ""
}
property var searchTokenSymbolByAddressFn: function (address) { return "" }
implicitWidth: 289
QtObject {
id: d
property bool isFetching: root.collectiblesList.isFetching
}
MenuBackButton {
id: backButton
width: parent.width
@ -82,14 +90,13 @@ StatusMenu {
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))
}
filters: ExpressionFilter {
enabled: root.tokensList.count > 0
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
@ -99,8 +106,8 @@ StatusMenu {
assetSettings.name: model.symbol ? Constants.tokenIcon(symbol) : ""
assetSettings.isImage: true
buttonGroup: tokenButtonGroup
allChecked: model.allChecked
checked: model.checked
allChecked: root.allTokensChecked
checked: root.allTokensChecked || root.tokensFilter.includes(model.symbol)
onActionTriggered: root.tokenToggled(model.symbol)
}
}
@ -130,27 +137,28 @@ StatusMenu {
Repeater {
model: SortFilterProxyModel {
sourceModel: root.collectiblesList
filters: [
ExpressionFilter {
expression: {
return model.name.toUpperCase().startsWith(collectiblesSearchBox.text.toUpperCase())
}
filters: ExpressionFilter {
enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text
expression: {
let searchText = collectiblesSearchBox.text.toUpperCase()
return name.toUpperCase().startsWith(searchText)
}
]
}
}
delegate: ActivityTypeCheckBox {
Layout.fillWidth: true
Layout.preferredHeight: 44
title: model.name
assetSettings.name: model.iconSource
assetSettings.name: model.imageUrl
assetSettings.isImage: true
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)
allChecked: root.allCollectiblesChecked
checked: root.allCollectiblesChecked || root.collectiblesFilter.includes(model.id)
onActionTriggered: root.collectibleToggled(model.id)
loading: d.isFetching
}
}
}

View File

@ -11,7 +11,8 @@ StatusMenu {
id: root
property var typeFilters: []
readonly property bool allChecked: typeFilters.length === typeButtonGroup.buttons.length
readonly property bool allChecked: typeFilters.length === 0
readonly property int allFiltersCount: typeButtonGroup.buttons.length
signal back()
signal actionTriggered(int type)
@ -36,7 +37,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionType.Send
checked: typeFilters.includes(type)
checked: root.allChecked || typeFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -47,7 +48,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionType.Receive
checked: typeFilters.includes(type)
checked: root.allChecked || typeFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -58,7 +59,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionType.Buy
checked: typeFilters.includes(type)
checked: root.allChecked || typeFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -69,7 +70,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionType.Swap
checked: typeFilters.includes(type)
checked: root.allChecked || typeFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
@ -80,7 +81,7 @@ StatusMenu {
buttonGroup: typeButtonGroup
allChecked: root.allChecked
type: Constants.TransactionType.Bridge
checked: typeFilters.includes(type)
checked: root.allChecked || typeFilters.includes(type)
onActionTriggered: root.actionTriggered(type)
}
}

View File

@ -0,0 +1,176 @@
import QtQuick 2.13
import SortFilterProxyModel 0.2
import utils 1.0
QtObject {
id: root
property var activityController: walletSection.activityController
property bool filtersSet: fromTimestamp !== 0 || toTimestamp !== 0 ||
typeFilters.length !== 0 ||
statusFilters.length !== 0 ||
tokensFilter.length !== 0 ||
collectiblesFilter.length !== 0 ||
recentsFilters.length !== 0 ||
savedAddressFilters.length !== 0
// Time filters
property int selectedTime: Constants.TransactionTimePeriod.All
// To-do get this from the backend once oldest Tx timestamp is available
property double fromTimestamp
property double toTimestamp: new Date().valueOf()
function setSelectedTimestamp(selcTime) {
selectedTime = selcTime
var currDate = new Date() // current date
switch(selectedTime) {
case Constants.TransactionTimePeriod.All:
fromTimestamp = 0
toTimestamp = 0
break
case Constants.TransactionTimePeriod.Today:
fromTimestamp = currDate.valueOf() // Today
toTimestamp = fromTimestamp
break
case Constants.TransactionTimePeriod.Yesterday:
fromTimestamp = new Date().setDate(currDate.getDate() - 1).valueOf() // Yesterday
toTimestamp = fromTimestamp
break
case Constants.TransactionTimePeriod.ThisWeek:
var firstDayOfCurrentWeek = currDate.getDate() - currDate.getDay()
fromTimestamp = new Date().setDate(firstDayOfCurrentWeek).valueOf() // This week
toTimestamp = currDate.valueOf()
break
case Constants.TransactionTimePeriod.LastWeek:
fromTimestamp = new Date().setDate(currDate.getDate() - 7).valueOf() // Last week
toTimestamp = currDate.valueOf()
break
case Constants.TransactionTimePeriod.ThisMonth:
fromTimestamp = new Date().setDate(1).valueOf() // This month
toTimestamp = currDate.valueOf()
break
case Constants.TransactionTimePeriod.LastMonth:
let x = new Date()
x.setDate(1)
x.setMonth(x.getMonth()-1)
fromTimestamp = x.valueOf() // Last month
x.setDate(new Date(x.getFullYear(), x.getMonth(), 0).getDate() + 1)
toTimestamp = x.valueOf()
break
default:
return ""
}
activityController.setFilterTime(root.fromTimestamp/1000, root.toTimestamp/1000)
activityController.updateFilter()
}
function setCustomTimeRange(fromTimestamp, toTimestamp) {
root.fromTimestamp = fromTimestamp
root.toTimestamp = toTimestamp
activityController.setFilterTime(root.fromTimestamp/1000, root.toTimestamp/1000)
activityController.updateFilter()
}
// Type Filters
property var typeFilters: []
function toggleType(type, allFiltersCount) {
// update filters
typeFilters = toggleFilterState(typeFilters, type, allFiltersCount)
// Set backend values
activityController.setFilterType(JSON.stringify(typeFilters))
activityController.updateFilter()
}
// Status Filters
property var statusFilters: []
function toggleStatus(status, allFiltersCount) {
// update filters
statusFilters = toggleFilterState(statusFilters, status, allFiltersCount)
// Set backend values
activityController.setFilterStatus(JSON.stringify(statusFilters))
activityController.updateFilter()
}
// Tokens Filters
property var tokensList: walletSectionAssets.assets
property var tokensFilter: []
function toggleToken(symbol) {
// update filters
tokensFilter = toggleFilterState(tokensFilter, symbol, tokensList.count)
// Set backend values
activityController.setFilterAssets(JSON.stringify(tokensFilter))
activityController.updateFilter()
}
// Collectibles Filters
property var collectiblesList: walletSectionCollectibles.model
property var collectiblesFilter: []
function toggleCollectibles(id) {
// update filters
collectiblesFilter = toggleFilterState(collectiblesFilter, id, collectiblesList.count)
// To-do go side filtering is pending
// activityController.setFilterCollectibles(JSON.stringify(collectiblesFilter))
// activityController.updateFilter()
}
// To-do get correct model unaffected by filters from go side
property var recentsList: []
property var recentsFilters: []
function toggleRecents(address) {
// update filters
recentsFilters = toggleFilterState(recentsFilters, address, recentsList.count)
// Set backend values
activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters)))
activityController.updateFilter()
}
property var savedAddressesModel: walletSectionSavedAddresses.model
property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled
property var savedAddressList: SortFilterProxyModel {
sourceModel: savedAddressesModel
filters: [
ValueFilter {
roleName: "isTest"
value: areTestNetworksEnabled
}
]
}
property var savedAddressFilters: []
function toggleSavedAddress(address) {
// update filters
savedAddressFilters = toggleFilterState(savedAddressFilters, address, savedAddressList.count)
// Set backend values
activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters)))
activityController.updateFilter()
}
function toggleFilterState(filters, attribute, allFiltersCount) {
let tempFilters = filters
// if all were selected then only select one of them
if(tempFilters.length === 0) {
tempFilters = [attribute]
}
else {
// if last one is being deselected, select all
if(tempFilters.length === 1 && tempFilters[0] === attribute) {
tempFilters = []
}
else {
let index = tempFilters.indexOf(attribute)
if(index === -1) {
if(allFiltersCount === tempFilters.length + 1)
tempFilters = []
else
tempFilters.push(attribute)
}
else {
tempFilters.splice(index, 1)
}
}
}
return tempFilters
}
}

View File

@ -1 +1,2 @@
singleton RootStore 1.0 RootStore.qml
ActivityFiltersStore 1.0 ActivityFiltersStore.qml

View File

@ -33,6 +33,7 @@ ColumnLayout {
QtObject {
id: d
property bool isLoading: false
property var activityFiltersStore: WalletStores.ActivityFiltersStore{}
}
Connections {
@ -58,7 +59,7 @@ ColumnLayout {
id: noTxs
Layout.fillWidth: true
Layout.preferredHeight: 42
visible: !d.isLoading && transactionListRoot.count === 0
visible: !d.isLoading && transactionListRoot.count === 0 && !d.activityFiltersStore.filtersSet
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("Activity for this account will appear here")
}
@ -66,24 +67,11 @@ ColumnLayout {
// Tp-do make connections with nim once logic is ready
ActivityFilterPanel {
id: filterComponent
visible: !d.isLoading && transactionListRoot.count !== 0
visible: !d.isLoading && (transactionListRoot.count !== 0 || d.activityFiltersStore.filtersSet)
Layout.fillWidth: true
Layout.preferredHeight: 50
store: RootStore
selectedTime: Constants.TransactionTimePeriod.All
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
]
activityFilterStore: d.activityFiltersStore
store: WalletStores.RootStore
}
Separator {