feat(savedaddresses): add save receiver address to the context menu in tx details view

This commit handles saved addresses changes and reflect them to the history view
and tx details view. In this context it handles the same way changes coming from sync
devices.

Also fix the issue when switching network mode.

Closes: #13095
This commit is contained in:
Sale Djenic 2024-02-14 11:49:22 +01:00 committed by saledjenic
parent 1410b03dd3
commit dbd7937d8b
10 changed files with 96 additions and 40 deletions

View File

@ -22,6 +22,8 @@ import app_service/common/types
import app_service/service/currency/service as currency_service import app_service/service/currency/service as currency_service
import app_service/service/transaction/service as transaction_service import app_service/service/transaction/service as transaction_service
import app_service/service/token/service as token_service import app_service/service/token/service as token_service
import app_service/service/wallet_account/service as wallet_account_service
import app_service/service/saved_address/service as saved_address_service
import app/modules/shared/wallet_utils import app/modules/shared/wallet_utils
import app/modules/shared_models/currency_amount import app/modules/shared_models/currency_amount
@ -47,6 +49,7 @@ QtObject:
currentActivityFilter: backend_activity.ActivityFilter currentActivityFilter: backend_activity.ActivityFilter
currencyService: currency_service.Service currencyService: currency_service.Service
tokenService: token_service.Service tokenService: token_service.Service
savedAddressService: saved_address_service.Service
activityDetails: ActivityDetails activityDetails: ActivityDetails
eventsHandler: EventsHandler eventsHandler: EventsHandler
@ -225,7 +228,29 @@ QtObject:
error "error requesting oldest activity timestamp: ", resJson.error error "error requesting oldest activity timestamp: ", resJson.error
return return
proc setupEventHandlers(self: Controller) = proc checkAllSavedAddresses(self: Controller) =
let appNetwork = self.savedAddressService.areTestNetworksEnabled()
let addressesToSearchThrough = self.savedAddressService.getSavedAddresses().filter(x => x.isTest == appNetwork)
for saDto in addressesToSearchThrough:
self.model.refreshItemsContainingAddress(saDto.address)
proc setupEventHandlers(self: Controller, events: EventEmitter) =
# setup in app direct event handlers
events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.checkAllSavedAddresses()
events.on(SIGNAL_SAVED_ADDRESSES_UPDATED) do(e:Args):
self.checkAllSavedAddresses()
events.on(SIGNAL_SAVED_ADDRESS_UPDATED) do(e:Args):
let args = SavedAddressArgs(e)
self.model.refreshItemsContainingAddress(args.address)
events.on(SIGNAL_SAVED_ADDRESS_DELETED) do(e:Args):
let args = SavedAddressArgs(e)
self.model.refreshItemsContainingAddress(args.address)
# setup other event handlers
self.eventsHandler.onFilteringDone(proc (jsonObj: JsonNode) = self.eventsHandler.onFilteringDone(proc (jsonObj: JsonNode) =
self.processResponse(jsonObj) self.processResponse(jsonObj)
) )
@ -271,7 +296,7 @@ QtObject:
error "error fetching collectibles: ", res.errorCode error "error fetching collectibles: ", res.errorCode
return return
try: try:
let items = res.collectibles.map(header => collectibleToItem(header)) let items = res.collectibles.map(header => collectibleToItem(header))
self.collectiblesModel.setItems(items, res.offset, res.hasMore) self.collectiblesModel.setItems(items, res.offset, res.hasMore)
except Exception as e: except Exception as e:
@ -285,6 +310,7 @@ 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,
savedAddressService: saved_address_service.Service,
events: EventEmitter, events: EventEmitter,
collectiblesConverter: CollectiblesToTokenConverter): Controller = collectiblesConverter: CollectiblesToTokenConverter): Controller =
new(result, delete) new(result, delete)
@ -294,6 +320,7 @@ QtObject:
result.recipientsModel = newRecipientsModel() result.recipientsModel = newRecipientsModel()
result.collectiblesModel = newCollectiblesModel() result.collectiblesModel = newCollectiblesModel()
result.tokenService = tokenService result.tokenService = tokenService
result.savedAddressService = savedAddressService
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter() result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
result.eventsHandler = newEventsHandler(result.requestId, events) result.eventsHandler = newEventsHandler(result.requestId, events)
@ -311,7 +338,7 @@ QtObject:
result.setup() result.setup()
result.setupEventHandlers() result.setupEventHandlers(events)
proc setFilterStatus*(self: Controller, statusesArrayJsonString: string) {.slot.} = proc setFilterStatus*(self: Controller, statusesArrayJsonString: string) {.slot.} =
let statusesJson = parseJson(statusesArrayJsonString) let statusesJson = parseJson(statusesArrayJsonString)

View File

@ -127,3 +127,11 @@ QtObject:
QtProperty[bool] hasMore: QtProperty[bool] hasMore:
read = getHasMore read = getHasMore
notify = hasMoreChanged notify = hasMoreChanged
proc refreshItemsContainingAddress*(self: Model, address: string) =
for i in 0..self.entries.high:
if cmpIgnoreCase(self.entries[i].getSender(), address) == 0 or
cmpIgnoreCase(self.entries[i].getRecipient(), address) == 0:
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.ActivityEntryRole.int])

View File

@ -137,8 +137,10 @@ proc newModule*(
result.transactionService = transactionService result.transactionService = transactionService
let collectiblesToTokenConverter = proc(id: string): backend_activity.Token = let collectiblesToTokenConverter = proc(id: string): backend_activity.Token =
return allCollectiblesModule.getAllCollectiblesModel().getActivityToken(id) return allCollectiblesModule.getAllCollectiblesModel().getActivityToken(id)
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService, events, collectiblesToTokenConverter) result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService,
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService, events, collectiblesToTokenConverter) savedAddressService, events, collectiblesToTokenConverter)
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService,
savedAddressService, 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

@ -43,6 +43,9 @@ proc areTestNetworksEnabled*(self: Controller): bool =
proc getSavedAddresses*(self: Controller): seq[saved_address_service.SavedAddressDto] = proc getSavedAddresses*(self: Controller): seq[saved_address_service.SavedAddressDto] =
return self.savedAddressService.getSavedAddresses() return self.savedAddressService.getSavedAddresses()
proc getSavedAddress*(self: Controller, address: string, ignoreNetworkMode: bool): SavedAddressDto =
return self.savedAddressService.getSavedAddress(address, ignoreNetworkMode)
proc createOrUpdateSavedAddress*(self: Controller, name: string, address: string, ens: string, colorId: string, proc createOrUpdateSavedAddress*(self: Controller, name: string, address: string, ens: string, colorId: string,
chainShortNames: string) = chainShortNames: string) =
self.savedAddressService.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames) self.savedAddressService.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)

View File

@ -88,13 +88,15 @@ method savedAddressNameExists*(self: Module, name: string): bool =
return self.view.getModel().nameExists(name, self.controller.areTestNetworksEnabled()) return self.view.getModel().nameExists(name, self.controller.areTestNetworksEnabled())
method getSavedAddressAsJson*(self: Module, address: string): string = method getSavedAddressAsJson*(self: Module, address: string): string =
let item = self.view.getModel().getItemByAddress(address, self.controller.areTestNetworksEnabled()) let saDto = self.controller.getSavedAddress(address, ignoreNetworkMode = false)
if saDto.isNil:
return ""
let jsonObj = %* { let jsonObj = %* {
"name": item.getName(), "name": saDto.name,
"address": item.getAddress(), "address": saDto.address,
"ens": item.getEns(), "ens": saDto.ens,
"colorId": item.getColorId(), "colorId": saDto.colorId,
"chainShortNames": item.getChainShortNames(), "chainShortNames": saDto.chainShortNames,
"isTest": item.getIsTest(), "isTest": saDto.isTest,
} }
return $jsonObj return $jsonObj

View File

@ -82,10 +82,11 @@ QtObject:
proc getSavedAddresses*(self: Service): seq[SavedAddressDto] = proc getSavedAddresses*(self: Service): seq[SavedAddressDto] =
return self.savedAddresses return self.savedAddresses
proc getSavedAddress*(self: Service, address: string): SavedAddressDto = proc getSavedAddress*(self: Service, address: string, ignoreNetworkMode: bool = true): SavedAddressDto =
for sa in self.savedAddresses: for sa in self.savedAddresses:
if cmpIgnoreCase(sa.address, address) == 0: if cmpIgnoreCase(sa.address, address) == 0 and
return sa (ignoreNetworkMode or sa.isTest == self.areTestNetworksEnabled()):
return sa
proc updateAddresses(self: Service, signal: string, arg: Args) = proc updateAddresses(self: Service, signal: string, arg: Args) =
self.savedAddresses = self.getAddresses() self.savedAddresses = self.getAddresses()

View File

@ -46,7 +46,7 @@ RightTabBaseView {
target: walletSection target: walletSection
function onFilterChanged() { function onFilterChanged() {
root.resetStack() root.resetView()
} }
} }
@ -198,9 +198,9 @@ RightTabBaseView {
showAllAccounts: RootStore.showAllAccounts showAllAccounts: RootStore.showAllAccounts
sendModal: root.sendModal sendModal: root.sendModal
filterVisible: filterButton.checked filterVisible: filterButton.checked
onLaunchTransactionDetail: function (entry, entryIndex) { onLaunchTransactionDetail: function (entryIndex) {
transactionDetailView.transactionIndex = entryIndex transactionDetailView.transactionIndex = entryIndex
transactionDetailView.transaction = entry transactionDetailView.transaction = Qt.binding(() => selectedTransaction)
stack.currentIndex = 3 stack.currentIndex = 3
} }
} }

View File

@ -34,12 +34,23 @@ Item {
property bool showAllAccounts: false property bool showAllAccounts: false
readonly property bool isTransactionValid: transaction !== undefined && !!transaction readonly property bool isTransactionValid: transaction !== undefined && !!transaction
onTransactionChanged: d.updateTransactionDetails() onTransactionChanged: {
d.reEvaluateSender = !d.reEvaluateSender
d.reEvaluateRecipient = !d.reEvaluateRecipient
d.reEvaluateSender = !d.reEvaluateSender
d.reEvaluateRecipient = !d.reEvaluateRecipient
d.updateTransactionDetails()
}
Component.onCompleted: d.updateTransactionDetails() Component.onCompleted: d.updateTransactionDetails()
QtObject { QtObject {
id: d id: d
property bool reEvaluateSender: true
property bool reEvaluateRecipient: true
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 || transactionType === Constants.TransactionType.ContractDeployment readonly property bool isIncoming: transactionType === Constants.TransactionType.Received || transactionType === Constants.TransactionType.ContractDeployment
@ -281,7 +292,7 @@ Item {
width: parent.width width: parent.width
title: d.transactionType === Constants.TransactionType.Swap || d.transactionType === Constants.TransactionType.Bridge ? title: d.transactionType === Constants.TransactionType.Swap || d.transactionType === Constants.TransactionType.Bridge ?
qsTr("In") : qsTr("From") qsTr("In") : qsTr("From")
addresses: root.isTransactionValid ? [root.transaction.sender] : [] addresses: root.isTransactionValid && d.reEvaluateSender? [root.transaction.sender] : []
contactsStore: root.contactsStore contactsStore: root.contactsStore
rootStore: WalletStores.RootStore rootStore: WalletStores.RootStore
onButtonClicked: { onButtonClicked: {
@ -324,7 +335,7 @@ Item {
TransactionAddressTile { TransactionAddressTile {
width: parent.width width: parent.width
title: qsTr("To") title: qsTr("To")
addresses: root.isTransactionValid && visible ? [root.transaction.recipient] : [] addresses: root.isTransactionValid && visible && d.reEvaluateRecipient? [root.transaction.recipient] : []
contactsStore: root.contactsStore contactsStore: root.contactsStore
rootStore: WalletStores.RootStore rootStore: WalletStores.RootStore
onButtonClicked: addressMenu.openReceiverMenu(this, addresses[0], [d.networkShortName]) onButtonClicked: addressMenu.openReceiverMenu(this, addresses[0], [d.networkShortName])

View File

@ -66,6 +66,14 @@ Item {
implicitHeight: Math.max(44, contentColumn.height) + 12 implicitHeight: Math.max(44, contentColumn.height) + 12
onAddressChanged: {
d.refresh()
}
Component.onCompleted: {
d.refresh()
}
QtObject { QtObject {
id: d id: d
@ -79,7 +87,7 @@ Item {
property string walletAddressEmoji property string walletAddressEmoji
property string walletAddressColor property string walletAddressColor
Component.onCompleted: { function refresh() {
refreshContactData() refreshContactData()
refreshSavedAddressName() refreshSavedAddressName()
refreshWalletAddress() refreshWalletAddress()
@ -105,21 +113,6 @@ Item {
d.walletAddressColor = Utils.getColorForId(!!root.rootStore ? root.rootStore.getColorForWalletAddress(root.address) : "") d.walletAddressColor = Utils.getColorForId(!!root.rootStore ? root.rootStore.getColorForWalletAddress(root.address) : "")
} }
function getName() {
let name = ""
if (d.isContact) {
name = ProfileUtils.displayName(d.contactData.localNickname, d.contactData.name, d.contactData.displayName, d.contactData.alias)
}
return name || d.walletAddressName || d.savedAddressName
}
readonly property Connections savedAccountsConnection: Connections {
target: !!root.rootStore && !!root.rootStore.savedAddresses ? root.rootStore.savedAddresses.sourceModel ?? null : null
function onItemChanged(address) {
if (address === root.address)
d.refreshSavedAddressName()
}
}
readonly property Connections walletAccountsConnection: Connections { readonly property Connections walletAccountsConnection: Connections {
target: !!root.rootStore ? root.rootStore.accounts ?? null : null target: !!root.rootStore ? root.rootStore.accounts ?? null : null
@ -182,7 +175,13 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.directColor1 color: Theme.palette.directColor1
text: d.getName() text: {
let name = ""
if (d.isContact) {
name = ProfileUtils.displayName(d.contactData.localNickname, d.contactData.name, d.contactData.displayName, d.contactData.alias)
}
return name || d.walletAddressName || d.savedAddressName
}
visible: !!text visible: !!text
elide: Text.ElideRight elide: Text.ElideRight
} }

View File

@ -32,7 +32,9 @@ ColumnLayout {
property var sendModal property var sendModal
property bool filterVisible property bool filterVisible
signal launchTransactionDetail(var transaction, int entryIndex) property var selectedTransaction
signal launchTransactionDetail(int entryIndex)
function resetView() { function resetView() {
if (!!filterPanelLoader.item) { if (!!filterPanelLoader.item) {
@ -430,7 +432,8 @@ ColumnLayout {
if (mouse.button === Qt.RightButton) { if (mouse.button === Qt.RightButton) {
delegateMenu.openMenu(this, mouse, modelData) delegateMenu.openMenu(this, mouse, modelData)
} else { } else {
launchTransactionDetail(modelData, index) root.selectedTransaction = Qt.binding(() => model.activityEntry)
launchTransactionDetail(index)
} }
} }
} }