feat(@desktop/wallet): Transaction collectibles filtering (#12162)

This commit is contained in:
Cuteivist 2023-09-21 08:58:44 +02:00 committed by GitHub
parent 521be27ae0
commit fddcc3a83f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 142 additions and 39 deletions

View File

@ -30,6 +30,9 @@ proc toRef*[T](obj: T): ref T =
const FETCH_BATCH_COUNT_DEFAULT = 10 const FETCH_BATCH_COUNT_DEFAULT = 10
const FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT = 2000 const FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT = 2000
type
CollectiblesToTokenConverter* = proc (id: string): backend_activity.Token
QtObject: QtObject:
type type
Controller* = ref object of QObject Controller* = ref object of QObject
@ -54,6 +57,8 @@ QtObject:
requestId: int32 requestId: int32
collectiblesToTokenConverter: CollectiblesToTokenConverter
proc setup(self: Controller) = proc setup(self: Controller) =
self.QObject.setup self.QObject.setup
@ -236,7 +241,8 @@ QtObject:
proc newController*(requestId: int32, proc newController*(requestId: int32,
currencyService: currency_service.Service, currencyService: currency_service.Service,
tokenService: token_service.Service, tokenService: token_service.Service,
events: EventEmitter): Controller = events: EventEmitter,
collectiblesConverter: CollectiblesToTokenConverter): Controller =
new(result, delete) new(result, delete)
result.requestId = requestId result.requestId = requestId
@ -256,6 +262,8 @@ QtObject:
result.allAddressesSelected = false result.allAddressesSelected = false
result.chainIds = @[] result.chainIds = @[]
result.collectiblesToTokenConverter = collectiblesConverter
result.setup() result.setup()
result.setupEventHandlers() result.setupEventHandlers()
@ -284,6 +292,20 @@ QtObject:
self.currentActivityFilter.counterpartyAddresses = addresses self.currentActivityFilter.counterpartyAddresses = addresses
proc setFilterCollectibles*(self: Controller, collectiblesArrayJsonString: string) {.slot.} =
let collectiblesJson = parseJson(collectiblesArrayJsonString)
if collectiblesJson.kind != JArray:
error "invalid array of json strings"
return
var collectibles = newSeq[backend_activity.Token]()
for i in 0 ..< collectiblesJson.len:
let uid = collectiblesJson[i].getStr()
let token = self.collectiblesToTokenConverter(uid)
collectibles.add(token)
self.currentActivityFilter.collectibles = collectibles
# Depends on self.filterTokenCodes and self.chainIds, so should be called after updating them # Depends on self.filterTokenCodes and self.chainIds, so should be called after updating them
proc updateAssetsIdentities(self: Controller) = proc updateAssetsIdentities(self: Controller) =
var assets = newSeq[backend_activity.Token]() var assets = newSeq[backend_activity.Token]()

View File

@ -206,7 +206,7 @@ QtObject:
if self.metadata.tokenIn.isSome: if self.metadata.tokenIn.isSome:
let address = self.metadata.tokenIn.unsafeGet().address let address = self.metadata.tokenIn.unsafeGet().address
if address.isSome: if address.isSome:
return toHex(address.unsafeGet()) return "0x" & toHex(address.unsafeGet())
return "" return ""
QtProperty[string] tokenInAddress: QtProperty[string] tokenInAddress:
@ -216,7 +216,7 @@ QtObject:
if self.metadata.tokenOut.isSome: if self.metadata.tokenOut.isSome:
let address = self.metadata.tokenOut.unsafeGet().address let address = self.metadata.tokenOut.unsafeGet().address
if address.isSome: if address.isSome:
return toHex(address.unsafeGet()) return "0x" & toHex(address.unsafeGet())
return "" return ""
QtProperty[string] tokenOutAddress: QtProperty[string] tokenOutAddress:

View File

@ -35,6 +35,8 @@ import app_service/service/network_connection/service as network_connection_serv
import app_service/service/devices/service as devices_service import app_service/service/devices/service as devices_service
import backend/collectibles as backend_collectibles import backend/collectibles as backend_collectibles
import backend/activity as backend_activity
logScope: logScope:
topics = "wallet-section-module" topics = "wallet-section-module"
@ -120,13 +122,16 @@ proc newModule*(
result.networksService = networkService result.networksService = networkService
result.transactionService = transactionService result.transactionService = transactionService
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService, events) let collectiblesController = collectiblesc.newController(
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService, events)
result.collectiblesController = collectiblesc.newController(
requestId = int32(backend_collectibles.CollectiblesRequestID.WalletAccount), requestId = int32(backend_collectibles.CollectiblesRequestID.WalletAccount),
autofetch = false, autofetch = false,
events = events events = events
) )
result.collectiblesController = collectiblesController
let collectiblesToTokenConverter = proc(id: string): backend_activity.Token =
return collectiblesController.getActivityToken(id)
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService, events, collectiblesToTokenConverter)
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService, events, collectiblesToTokenConverter)
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events) result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
result.filter = initFilter(result.controller) result.filter = initFilter(result.controller)

View File

@ -2,6 +2,8 @@ import NimQml, Tables, strutils, strformat, sequtils, stint
import logging import logging
import ./collectibles_item, ./collectible_trait_model import ./collectibles_item, ./collectible_trait_model
import web3/ethtypes as eth
import backend/activity as backend_activity
type type
CollectibleRole* {.pure.} = enum CollectibleRole* {.pure.} = enum
@ -322,4 +324,20 @@ QtObject:
for item in self.items: for item in self.items:
if(cmpIgnoreCase(item.getId(), id) == 0): if(cmpIgnoreCase(item.getId(), id) == 0):
return item.getName() return item.getName()
return "" return ""
proc getActivityToken*(self: Model, id: string): backend_activity.Token =
for item in self.items:
if(cmpIgnoreCase(item.getId(), id) == 0):
result.tokenType = backend_activity.TokenType.Erc721
result.chainId = backend_activity.ChainId(item.getChainId())
var contract = item.getContractAddress()
if len(contract) > 0:
var address: eth.Address
address = eth.fromHex(eth.Address, contract)
result.address = some(address)
var tokenId = item.getTokenId()
if tokenId > 0:
result.tokenId = some(backend_activity.TokenId("0x" & stint.toHex(tokenId)))
return result
return result

View File

@ -8,6 +8,7 @@ import events_handler
import app/core/eventemitter import app/core/eventemitter
import backend/collectibles as backend_collectibles import backend/collectibles as backend_collectibles
import backend/activity as backend_activity
const FETCH_BATCH_COUNT_DEFAULT = 50 const FETCH_BATCH_COUNT_DEFAULT = 50
@ -123,7 +124,7 @@ QtObject:
let res = fromJson(response, backend_collectibles.FilterOwnedCollectiblesResponse) let res = fromJson(response, backend_collectibles.FilterOwnedCollectiblesResponse)
let isError = res.errorCode != ErrorCodeSuccess let isError = res.errorCode != backend_collectibles.ErrorCodeSuccess
if isError: if isError:
error "error fetching collectibles entries: ", res.errorCode error "error fetching collectibles entries: ", res.errorCode
@ -203,3 +204,6 @@ QtObject:
self.eventsHandler.updateSubscribedChainIDs(self.chainIds) self.eventsHandler.updateSubscribedChainIDs(self.chainIds)
self.resetModel() self.resetModel()
proc getActivityToken*(self: Controller, id: string): backend_activity.Token =
return self.model.getActivityToken(id)

View File

@ -25,6 +25,10 @@ Column {
activityFilterStore.updateFilterBase() activityFilterStore.updateFilterBase()
} }
function resetView() {
activityFilterMenu.resetView()
}
Flow { Flow {
width: parent.width width: parent.width
@ -157,10 +161,27 @@ Column {
Repeater { Repeater {
model: activityFilterStore.collectiblesFilter model: activityFilterStore.collectiblesFilter
delegate: ActivityFilterTagItem { delegate: ActivityFilterTagItem {
tagPrimaryLabel.text: activityFilterStore.collectiblesList.getName(modelData) id: collectibleTag
iconAsset.icon: activityFilterStore.collectiblesList.getImageUrl(modelData) property string uid: modelData
readonly property bool isValid: tagPrimaryLabel.text.length > 0
tagPrimaryLabel.text: activityFilterStore.collectiblesList.getName(uid)
iconAsset.icon: activityFilterStore.collectiblesList.getImageUrl(uid)
iconAsset.color: "transparent" iconAsset.color: "transparent"
onClosed: activityFilterStore.toggleCollectibles(model.id) onClosed: activityFilterStore.toggleCollectibles(uid)
Connections {
// Collectibles model is fetched asynchronousl, so data might not be available
target: activityFilterStore.collectiblesList
enabled: !collectibleTag.isValid
function onIsFetchingChanged() {
if (activityFilterStore.collectiblesList.isFetching)
return
collectibleTag.uid = ""
collectibleTag.uid = modelData
if (!collectibleTag.isValid)
activityFilterStore.collectiblesList.loadMore()
}
}
} }
} }
@ -228,7 +249,7 @@ Column {
collectiblesList: activityFilterStore.collectiblesList collectiblesList: activityFilterStore.collectiblesList
collectiblesFilter: activityFilterStore.collectiblesFilter collectiblesFilter: activityFilterStore.collectiblesFilter
onUpdateTokensFilter: activityFilterStore.toggleToken(tokenSymbol) onUpdateTokensFilter: activityFilterStore.toggleToken(tokenSymbol)
onUpdateCollectiblesFilter: activityFilterStore.toggleCollectibles(id) onUpdateCollectiblesFilter: activityFilterStore.toggleCollectibles(uid)
store: root.store store: root.store
recentsList: activityFilterStore.recentsList recentsList: activityFilterStore.recentsList

View File

@ -16,8 +16,9 @@ ColumnLayout {
property string nftName property string nftName
property string nftUrl property string nftUrl
property string tokenId property string tokenId
property string contractAddress property string tokenAddress
property bool strikethrough: false property bool strikethrough: false
property bool areTestNetworksEnabled: false
spacing: Style.current.padding spacing: Style.current.padding
@ -100,8 +101,11 @@ ColumnLayout {
icon.name: "external" icon.name: "external"
type: StatusRoundButton.Type.Quinary type: StatusRoundButton.Type.Quinary
radius: 8 radius: 8
visible: nftPreviewSensor.hovered && !!root.tokenId && !!root.contractAddress visible: nftPreviewSensor.hovered && !!root.tokenId && !!root.tokenAddress
onClicked: Global.openLink("https://etherscan.io/nft/%1/%2".arg(root.contractAddress).arg(root.tokenId)) onClicked: {
const link = areTestNetworksEnabled ? Constants.networkExplorerLinks.goerliEtherscan : Constants.networkExplorerLinks.etherscan
Global.openLink("%1/nft/%2/%3".arg(link).arg(root.tokenAddress).arg(root.tokenId))
}
} }
} }
} }

View File

@ -34,7 +34,7 @@ StatusMenu {
property var collectiblesList: [] property var collectiblesList: []
property var collectiblesFilter: [] property var collectiblesFilter: []
readonly property bool allCollectiblesChecked: tokensMenu.allCollectiblesChecked readonly property bool allCollectiblesChecked: tokensMenu.allCollectiblesChecked
signal updateCollectiblesFilter(double id) signal updateCollectiblesFilter(string uid)
// Recents filter // Recents filter
property var recentsList property var recentsList
@ -52,6 +52,11 @@ StatusMenu {
implicitWidth: 176 implicitWidth: 176
function resetView() {
counterPartyMenu.resetView()
tokensMenu.resetView()
}
// Filter By Period // Filter By Period
ActivityFilterMenuItem { ActivityFilterMenuItem {
text: qsTr("Period") text: qsTr("Period")
@ -92,7 +97,7 @@ StatusMenu {
collectiblesList: root.collectiblesList collectiblesList: root.collectiblesList
collectiblesFilter: root.collectiblesFilter collectiblesFilter: root.collectiblesFilter
onTokenToggled: updateTokensFilter(tokenSymbol) onTokenToggled: updateTokensFilter(tokenSymbol)
onCollectibleToggled: updateCollectiblesFilter(id) onCollectibleToggled: updateCollectiblesFilter(uid)
closePolicy: root.closePolicy closePolicy: root.closePolicy
} }
ActivityCounterpartyFilterSubMenu { ActivityCounterpartyFilterSubMenu {

View File

@ -40,6 +40,10 @@ StatusMenu {
Component.onCompleted: root.updateRecipientsModel() Component.onCompleted: root.updateRecipientsModel()
function resetView() {
searchBox.reset()
}
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 12 spacing: 12

View File

@ -26,15 +26,20 @@ StatusMenu {
signal back() signal back()
signal tokenToggled(string tokenSymbol) signal tokenToggled(string tokenSymbol)
signal collectibleToggled(double id) signal collectibleToggled(string uid)
property var searchTokenSymbolByAddressFn: function (address) { return "" } // TODO property var searchTokenSymbolByAddressFn: function (address) { return "" } // TODO
implicitWidth: 289 implicitWidth: 289
function resetView() {
tokensSearchBox.reset()
collectiblesSearchBox.reset()
}
QtObject { QtObject {
id: d id: d
property bool isFetching: root.collectiblesList.isFetching readonly property bool isFetching: root.collectiblesList.isFetching
} }
contentItem: ColumnLayout { contentItem: ColumnLayout {
@ -99,12 +104,14 @@ StatusMenu {
Layout.fillHeight: true Layout.fillHeight: true
spacing: 0 spacing: 0
model: SortFilterProxyModel { model: SortFilterProxyModel {
id: tokenProxyModel
sourceModel: root.tokensList sourceModel: root.tokensList
filters: ExpressionFilter { filters: ExpressionFilter {
readonly property string tokenSearchValue: tokensSearchBox.text.toUpperCase()
readonly property string tokenSymbolByAddress: root.searchTokenSymbolByAddressFn(tokensSearchBox.text)
enabled: root.tokensList.count > 0 enabled: root.tokensList.count > 0
expression: { expression: {
const tokenSymbolByAddress = root.searchTokenSymbolByAddressFn(tokensSearchBox.text) return symbol.startsWith(tokenSearchValue) || name.toUpperCase().startsWith(tokenSearchValue) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
return symbol.startsWith(tokensSearchBox.text.toUpperCase()) || name.toUpperCase().startsWith(tokensSearchBox.text.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
} }
} }
} }
@ -155,28 +162,30 @@ StatusMenu {
spacing: 0 spacing: 0
reuseItems: true reuseItems: true
model: SortFilterProxyModel { model: SortFilterProxyModel {
id: collectibleProxyModel
sourceModel: root.collectiblesList sourceModel: root.collectiblesList
filters: ExpressionFilter { filters: ExpressionFilter {
enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text
readonly property string searchText: collectiblesSearchBox.text.toUpperCase()
expression: { expression: {
const searchText = collectiblesSearchBox.text.toUpperCase() return String(name).toUpperCase().startsWith(searchText)
return name.toUpperCase().startsWith(searchText)
} }
} }
} }
delegate: ActivityTypeCheckBox { delegate: ActivityTypeCheckBox {
required property var model
width: ListView.view.width width: ListView.view.width
height: 44 height: 44
title: model.name title: model.name ?? ""
assetSettings.name: model.imageUrl assetSettings.name: model.imageUrl ?? ""
assetSettings.isImage: true assetSettings.isImage: true
assetSettings.bgWidth: 32 assetSettings.bgWidth: 32
assetSettings.bgHeight: 32 assetSettings.bgHeight: 32
assetSettings.bgRadius: assetSettings.bgHeight/2 assetSettings.bgRadius: assetSettings.bgHeight/2
buttonGroup: collectibleButtonGroup buttonGroup: collectibleButtonGroup
allChecked: root.allCollectiblesChecked allChecked: root.allCollectiblesChecked
checked: root.allCollectiblesChecked || root.collectiblesFilter.includes(model.id) checked: !loading && (root.allCollectiblesChecked || root.collectiblesFilter.includes(model.uid))
onActionTriggered: root.collectibleToggled(model.id) onActionTriggered: root.collectibleToggled(model.uid)
loading: d.isFetching loading: d.isFetching
} }
} }

View File

@ -191,15 +191,13 @@ QtObject {
// To-do: Get list of collectibles with activity from backend // To-do: Get list of collectibles with activity from backend
property var collectiblesList: walletSection.collectiblesController.model property var collectiblesList: walletSection.collectiblesController.model
property var collectiblesFilter: [] property var collectiblesFilter: []
function toggleCollectibles(id) { function toggleCollectibles(uid) {
// update filters // update filters
collectiblesFilter = d.toggleFilterState(collectiblesFilter, id, collectiblesList.count) collectiblesFilter = d.toggleFilterState(collectiblesFilter, uid, collectiblesList.count)
// TODO go side filtering is pending activityController.setFilterCollectibles(JSON.stringify(collectiblesFilter))
// activityController.setFilterCollectibles(JSON.stringify(collectiblesFilter)) activityController.updateFilter()
// activityController.updateFilter()
} }
property var recentsList: activityController.recipientsModel property var recentsList: activityController.recipientsModel
property bool loadingRecipients: activityController.status.loadingRecipients property bool loadingRecipients: activityController.status.loadingRecipients
property var recentsFilters: [] property var recentsFilters: []
@ -251,7 +249,7 @@ QtObject {
activityController.setFilterStatus(JSON.stringify(statusFilters)) activityController.setFilterStatus(JSON.stringify(statusFilters))
activityController.setFilterAssets(JSON.stringify(tokensFilter), false) activityController.setFilterAssets(JSON.stringify(tokensFilter), false)
activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters))) activityController.setFilterToAddresses(JSON.stringify(recentsFilters.concat(savedAddressFilters)))
// TODO call update filter for collectibles activityController.setFilterCollectibles(JSON.stringify(collectiblesFilter))
activityController.updateFilter() activityController.updateFilter()
} }
@ -266,7 +264,6 @@ QtObject {
collectiblesFilter = [] collectiblesFilter = []
recentsFilters = [] recentsFilters = []
savedAddressFilters = [] savedAddressFilters = []
// TODO reset filter for collectibles
applyAllFilters() applyAllFilters()
} }

View File

@ -30,6 +30,7 @@ Item {
function resetView() { function resetView() {
stack.currentIndex = 0 stack.currentIndex = 0
root.currentTabIndex = 0 root.currentTabIndex = 0
historyView.resetView()
} }
function resetStack() { function resetStack() {
@ -141,6 +142,7 @@ Item {
} }
} }
HistoryView { HistoryView {
id: historyView
overview: RootStore.overview overview: RootStore.overview
showAllAccounts: root.showAllAccounts showAllAccounts: root.showAllAccounts
onLaunchTransactionDetail: function (entry, entryIndex) { onLaunchTransactionDetail: function (entry, entryIndex) {

View File

@ -40,7 +40,7 @@ Item {
property var details: null property var details: null
readonly property bool isDetailsValid: details !== undefined && !!details readonly property bool isDetailsValid: details !== undefined && !!details
readonly property bool isIncoming: transactionType === Constants.TransactionType.Received readonly property bool isIncoming: transactionType === Constants.TransactionType.Received || transactionType === Constants.TransactionType.ContractDeployment
readonly property string networkShortName: root.isTransactionValid ? RootStore.getNetworkShortName(transaction.chainId) : "" readonly property string networkShortName: root.isTransactionValid ? RootStore.getNetworkShortName(transaction.chainId) : ""
readonly property string networkIcon: isTransactionValid ? RootStore.getNetworkIcon(transaction.chainId) : "network/Network=Custom" readonly property string networkIcon: isTransactionValid ? RootStore.getNetworkIcon(transaction.chainId) : "network/Network=Custom"
readonly property int blockNumber: isDetailsValid ? details.blockNumber : 0 readonly property int blockNumber: isDetailsValid ? details.blockNumber : 0
@ -188,7 +188,8 @@ Item {
nftUrl: root.isTransactionValid && !!transaction.nftImageUrl ? transaction.nftImageUrl : "" nftUrl: root.isTransactionValid && !!transaction.nftImageUrl ? transaction.nftImageUrl : ""
strikethrough: d.transactionType === Constants.TransactionType.Destroy strikethrough: d.transactionType === Constants.TransactionType.Destroy
tokenId: root.isTransactionValid ? transaction.tokenID : "" tokenId: root.isTransactionValid ? transaction.tokenID : ""
contractAddress: d.isDetailsValid ? d.details.contract : "" tokenAddress: root.isTransactionValid ? transaction.tokenAddress : ""
areTestNetworksEnabled: WalletStores.RootStore.areTestNetworksEnabled
} }
Column { Column {
@ -561,6 +562,7 @@ Item {
RowLayout { RowLayout {
width: parent.width width: parent.width
visible: amountSentTile.visible || amountReceiveTile.visible || feesTile.visible || totalTile.visible
StatusBaseText { StatusBaseText {
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
font.pixelSize: 15 font.pixelSize: 15
@ -580,6 +582,7 @@ Item {
DetailsPanel { DetailsPanel {
TransactionDataTile { TransactionDataTile {
id: amountSentTile
width: parent.width width: parent.width
title: qsTr("Amount sent") title: qsTr("Amount sent")
subTitle: transactionHeader.isMultiTransaction ? d.outCryptoValueFormatted : d.cryptoValueFormatted subTitle: transactionHeader.isMultiTransaction ? d.outCryptoValueFormatted : d.cryptoValueFormatted
@ -598,6 +601,7 @@ Item {
} }
} }
TransactionDataTile { TransactionDataTile {
id: amountReceiveTile
width: parent.width width: parent.width
title: transactionHeader.transactionStatus === Constants.TransactionStatus.Pending ? qsTr("Amount to receive") : qsTr("Amount received") title: transactionHeader.transactionStatus === Constants.TransactionStatus.Pending ? qsTr("Amount to receive") : qsTr("Amount received")
subTitle: { subTitle: {
@ -625,6 +629,7 @@ Item {
visible: !!subTitle visible: !!subTitle
} }
TransactionDataTile { TransactionDataTile {
id: feesTile
width: parent.width width: parent.width
title: d.symbol ? qsTr("Fees") : qsTr("Estimated max fee") title: d.symbol ? qsTr("Fees") : qsTr("Estimated max fee")
subTitle: { subTitle: {
@ -659,6 +664,7 @@ Item {
visible: !!subTitle visible: !!subTitle
} }
TransactionDataTile { TransactionDataTile {
id: totalTile
width: parent.width width: parent.width
readonly property bool fieldIsHidden: (transactionHeader.isNFT && d.isIncoming) || !d.symbol readonly property bool fieldIsHidden: (transactionHeader.isNFT && d.isIncoming) || !d.symbol
readonly property bool showMaxFee: d.transactionType === Constants.TransactionType.ContractDeployment && transactionHeader.transactionStatus === Constants.TransactionStatus.Pending readonly property bool showMaxFee: d.transactionType === Constants.TransactionType.ContractDeployment && transactionHeader.transactionStatus === Constants.TransactionStatus.Pending

View File

@ -504,8 +504,8 @@ StatusListItem {
return qsTr("Via %1 on %2").arg(name).arg(networkName) return qsTr("Via %1 on %2").arg(name).arg(networkName)
case Constants.TransactionType.Mint: case Constants.TransactionType.Mint:
if (allAccounts) if (allAccounts)
return qsTr("%1 via %2 in %4").arg(transactionValue).arg(networkName).arg(toAddress) return qsTr("%1 via %2 in %3").arg(transactionValue).arg(networkName).arg(toAddress)
return qsTr("%1 via %2").arg(transactionValue).arg(networkName).arg(networkName) return qsTr("%1 via %2").arg(transactionValue).arg(networkName)
default: default:
if (allAccounts) if (allAccounts)
return qsTr("%1 from %2 to %3 via %4").arg(transactionValue).arg(fromAddress).arg(toAddress).arg(networkName) return qsTr("%1 from %2 to %3 via %4").arg(transactionValue).arg(fromAddress).arg(toAddress).arg(networkName)

View File

@ -31,6 +31,12 @@ ColumnLayout {
signal launchTransactionDetail(var transaction, int entryIndex) signal launchTransactionDetail(var transaction, int entryIndex)
function resetView() {
if (!!filterPanelLoader.item) {
filterPanelLoader.item.resetView()
}
}
onVisibleChanged: { onVisibleChanged: {
if (!visible) if (!visible)
return return