refactor(Wallet/SendModal): Created `WalletAccountsAdaptor` to be used in `SendModal`

- Created data transformation file called `WalletAccountsAdaptor` for `SendModal`. Now it contains the owned wallet accounts model data transformations.
- Added common formatting method for short chain ids to some utils and partially removed backend dependency.
This commit is contained in:
Noelia 2024-07-03 22:46:00 +02:00 committed by Noelia
parent 18e230bf91
commit bc74724672
12 changed files with 150 additions and 37 deletions

View File

@ -170,6 +170,7 @@ QtObject:
return (chainIds, enable) return (chainIds, enable)
# TODO: To be removed once all qml calls to this method are removed. Normally the formatting methods should live in the qml project.
proc getNetworkShortNames*(self: Model, preferredNetworks: string, areTestNetworksEnabled: bool): string = proc getNetworkShortNames*(self: Model, preferredNetworks: string, areTestNetworksEnabled: bool): string =
var networkString = "" var networkString = ""
let networks = preferredNetworks.split(":") let networks = preferredNetworks.split(":")

View File

@ -18,7 +18,6 @@ import Models 1.0
import Storybook 1.0 import Storybook 1.0
import AppLayouts.Wallet.controls 1.0 import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStores
import AppLayouts.Wallet.services.dapps 1.0 import AppLayouts.Wallet.services.dapps 1.0
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
@ -373,7 +372,7 @@ Item {
} }
} }
walletRootStore: WalletStores.RootStore { walletRootStore: QObject {
property string selectedAddress: "" property string selectedAddress: ""
property var filteredFlatModel: SortFilterProxyModel { property var filteredFlatModel: SortFilterProxyModel {
sourceModel: NetworksModel.flatNetworks sourceModel: NetworksModel.flatNetworks

View File

@ -14,7 +14,6 @@ import AppLayouts.Wallet.services.dapps 1.0
import AppLayouts.Wallet.services.dapps.types 1.0 import AppLayouts.Wallet.services.dapps.types 1.0
import AppLayouts.Profile.stores 1.0 import AppLayouts.Profile.stores 1.0
import AppLayouts.Wallet.panels 1.0 import AppLayouts.Wallet.panels 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStores
import shared.stores 1.0 import shared.stores 1.0
@ -121,7 +120,7 @@ Item {
Component { Component {
id: walletStoreComponent id: walletStoreComponent
WalletStores.RootStore { QtObject {
property string selectedAddress: "" property string selectedAddress: ""
readonly property ListModel filteredFlatModel: ListModel { readonly property ListModel filteredFlatModel: ListModel {
ListElement { chainId: 1 } ListElement { chainId: 1 }

View File

@ -261,7 +261,7 @@ Item {
mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2) mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2)
verify(delegateUnderTest.sensor.containsMouse) verify(delegateUnderTest.sensor.containsMouse)
compare(delegateUnderTest.title, swapAdaptor.nonWatchAccounts.get(i).name) compare(delegateUnderTest.title, swapAdaptor.nonWatchAccounts.get(i).name)
compare(delegateUnderTest.subTitle, WalletUtils.colorizedChainPrefix(root.swapAdaptor.getNetworkShortNames(swapAdaptor.nonWatchAccounts.get(i).preferredSharingChainIds)), "Randomly failing locally. Add a bug if you see this failing in CI") compare(delegateUnderTest.subTitle, WalletUtils.colorizedChainPrefix(WalletUtils.getNetworkShortNames(swapAdaptor.nonWatchAccounts.get(i).preferredSharingChainIds, root.swapStore.flatNetworks)), "Randomly failing locally. Add a bug if you see this failing in CI")
verify(delegateUnderTest.color, Theme.palette.baseColor2) verify(delegateUnderTest.color, Theme.palette.baseColor2)
} }

View File

@ -1,5 +1,13 @@
// This should not be a singleton. TODO: Remove it once the "real" Wallet root store is not a singleton anymore.
pragma Singleton
import QtQml 2.15 import QtQml 2.15
QtObject { QtObject {
id: root id: root
// TODO: Remove this. This stub should be empty. The color transformation should be done in adaptors or in the first model transformation steps.
function colorForChainShortName(chainShortName) {
return "#FF0000" // Just some random testing color
}
} }

View File

@ -1,6 +1,6 @@
ActivityFiltersStore 1.0 ActivityFiltersStore.qml ActivityFiltersStore 1.0 ActivityFiltersStore.qml
CollectiblesStore 1.0 CollectiblesStore.qml CollectiblesStore 1.0 CollectiblesStore.qml
RootStore 1.0 RootStore.qml singleton RootStore 1.0 RootStore.qml
SwapStore 1.0 SwapStore.qml SwapStore 1.0 SwapStore.qml
TokensStore 1.0 TokensStore.qml TokensStore 1.0 TokensStore.qml
WalletAssetsStore 1.0 WalletAssetsStore.qml WalletAssetsStore 1.0 WalletAssetsStore.qml

View File

@ -7,9 +7,39 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils import StatusQ.Core.Utils 0.1 as StatusQUtils
import "stores" as WalletStores import AppLayouts.Wallet.stores 1.0 as WalletStores
QtObject { QtObject {
function colorizedChainPrefixNew(chainColors, prefix) {
if (!prefix)
return ""
const prefixes = prefix.split(":").filter(Boolean)
let prefixStr = ""
const lastPrefixEndsWithColumn = prefix.endsWith(":")
const defaultColor = Theme.palette.baseColor1
for (let i in prefixes) {
const pref = prefixes[i]
let col = chainColors[pref]
if (!col)
col = defaultColor
prefixStr += Utils.richColorText(pref, col)
// Avoid adding ":" if it was not there for the last prefix,
// because when user manually edits the address, it breaks editing
if (!(i === (prefixes.length - 1) && !lastPrefixEndsWithColumn)) {
prefixStr += Utils.richColorText(":", Theme.palette.baseColor1)
}
}
return prefixStr
}
// TODO: Remove dependency to RootStore by requesting model or chainColors as a parameter. Indeed, this
// method should be just replaced by `colorizedChainPrefixNew`
// Issue #15494
function colorizedChainPrefix(prefix) { function colorizedChainPrefix(prefix) {
if (!prefix) if (!prefix)
return "" return ""
@ -28,7 +58,7 @@ QtObject {
prefixStr += Utils.richColorText(pref, col) prefixStr += Utils.richColorText(pref, col)
// Avoid adding ":" if it was not there for the last prefix, // Avoid adding ":" if it was not there for the last prefix,
// because when user manually edits the address, it breaks editing // because when user manually edits the address, it breaks editing
if (!(i == (prefixes.length - 1) && !lastPrefixEndsWithColumn)) { if (!(i === (prefixes.length - 1) && !lastPrefixEndsWithColumn)) {
prefixStr += Utils.richColorText(":", Theme.palette.baseColor1) prefixStr += Utils.richColorText(":", Theme.palette.baseColor1)
} }
} }
@ -88,4 +118,16 @@ QtObject {
return qsTr("> 5 minutes") return qsTr("> 5 minutes")
} }
} }
// Where: chainIds [string] - separated by `:`, e.g "42161:10:1"
function getNetworkShortNames(chainIds: string, flatNetworksModel) {
let networkString = ""
const chainIdsArray = chainIds.split(":")
for (let i = 0; i < chainIdsArray.length; i++) {
const nwShortName = StatusQUtils.ModelUtils.getByKey(flatNetworksModel, "chainId", Number(chainIdsArray[i]), "shortName")
if (!!nwShortName)
networkString = networkString + nwShortName + ':'
}
return networkString
}
} }

View File

@ -0,0 +1,80 @@
import QtQml 2.15
import AppLayouts.Wallet 1.0
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
import SortFilterProxyModel 0.2
QObject {
id: root
// Input parameters:
/**
Expected model structure:
address [string] - wallet account address, e.g "0x10b...eaf"
name [string] - wallet account name, e.g "Status account"
keyUid [string] - unique identifier, e.g "0x79e07.....006"
currencyBalance [var] - CurrencyAmount type
amount [string]
symbol [string]
displayDecimals [int]
stripTrailingZeroes [bool]
emoji [string] - custom emoji
walletType [string] - e.g "generated"
colorId [string] - e.g "YELLOW"
preferredSharingChainIds [string] - separated by `:`, e.g "42161:10:1"
position [int] - visual order, e.g: "1"
**/
property var accountsModel
property var flatNetworksModel
property bool areTestNetworksEnabled
// Output parameters:
/**
Model structure:
All roles from the source model are passed directly to the output model,
additionally:
colorizedChainShortNames [string] - build from `preferredSharingChainIds` adding different colors to different network short names
**/
readonly property alias model: sfpm
readonly property SortFilterProxyModel filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: root.flatNetworksModel
filters: ValueFilter { roleName: "isTest"; value: root.areTestNetworksEnabled }
}
QtObject {
id: d
property var chainColors: ({})
function initChainColors() {
for (let i = 0; i < root.flatNetworksModel.count; i++) {
const item = ModelUtils.get(root.flatNetworksModel, i)
chainColors[item.shortName] = item.chainColor
}
}
}
SortFilterProxyModel {
id: sfpm
sourceModel: root.accountsModel ?? null
proxyRoles: FastExpressionRole {
function getChainShortNames(preferredSharingChainIds){
const chainShortNames = WalletUtils.getNetworkShortNames(preferredSharingChainIds, root.flatNetworksModel)
return WalletUtils.colorizedChainPrefixNew(d.chainColors, chainShortNames)
}
name: "colorizedChainShortNames"
expectedRoles: ["preferredSharingChainIds"]
expression: getChainShortNames(model.preferredSharingChainIds)
}
}
onFlatNetworksModelChanged: d.initChainColors()
}

View File

@ -1,2 +1,3 @@
CollectiblesSelectionAdaptor 1.0 CollectiblesSelectionAdaptor.qml CollectiblesSelectionAdaptor 1.0 CollectiblesSelectionAdaptor.qml
TokenSelectorViewAdaptor 1.0 TokenSelectorViewAdaptor.qml TokenSelectorViewAdaptor 1.0 TokenSelectorViewAdaptor.qml
WalletAccountsAdaptor 1.0 WalletAccountsAdaptor.qml

View File

@ -33,6 +33,8 @@ QObject {
readonly property string uuid: d.uuid readonly property string uuid: d.uuid
// TO REVIEW: It has been created a `WalletAccountsAdaptor.qml` file.
// Probably this data transformation should live there since they have common base.
readonly property var nonWatchAccounts: SortFilterProxyModel { readonly property var nonWatchAccounts: SortFilterProxyModel {
sourceModel: root.swapStore.accounts sourceModel: root.swapStore.accounts
filters: ValueFilter { filters: ValueFilter {
@ -62,7 +64,7 @@ QObject {
FastExpressionRole { FastExpressionRole {
name: "colorizedChainPrefixes" name: "colorizedChainPrefixes"
function getChainShortNames(chainIds) { function getChainShortNames(chainIds) {
const chainShortNames = root.getNetworkShortNames(chainIds) const chainShortNames = WalletUtils.getNetworkShortNames(chainIds, root.filteredFlatNetworksModel)
return WalletUtils.colorizedChainPrefix(chainShortNames) return WalletUtils.colorizedChainPrefix(chainShortNames)
} }
expression: getChainShortNames(model.preferredSharingChainIds) expression: getChainShortNames(model.preferredSharingChainIds)
@ -217,18 +219,6 @@ QObject {
d.txHash = "" d.txHash = ""
} }
function getNetworkShortNames(chainIds) {
var networkString = ""
let chainIdsArray = chainIds.split(":")
for (let i = 0; i< chainIdsArray.length; i++) {
let nwShortName = ModelUtils.getByKey(root.filteredFlatNetworksModel, "chainId", Number(chainIdsArray[i]), "shortName")
if(!!nwShortName) {
networkString = networkString + nwShortName + ':'
}
}
return networkString
}
function formatCurrencyAmount(balance, symbol, options = null, locale = null) { function formatCurrencyAmount(balance, symbol, options = null, locale = null) {
return root.currencyStore.formatCurrencyAmount(balance, symbol, options, locale) return root.currencyStore.formatCurrencyAmount(balance, symbol, options, locale)
} }

View File

@ -5,7 +5,6 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 import StatusQ.Core.Utils 0.1
import AppLayouts.Wallet 1.0 import AppLayouts.Wallet 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStores
import AppLayouts.Wallet.services.dapps 1.0 import AppLayouts.Wallet.services.dapps 1.0
import AppLayouts.Wallet.services.dapps.types 1.0 import AppLayouts.Wallet.services.dapps.types 1.0
import AppLayouts.Profile.stores 1.0 import AppLayouts.Profile.stores 1.0
@ -31,7 +30,7 @@ QObject {
required property WalletConnectSDKBase wcSDK required property WalletConnectSDKBase wcSDK
required property DAppsStore store required property DAppsStore store
required property WalletStores.RootStore walletRootStore required property var walletRootStore
readonly property string selectedAccountAddress: walletRootStore.selectedAddress readonly property string selectedAccountAddress: walletRootStore.selectedAddress

View File

@ -21,6 +21,7 @@ import StatusQ.Core.Utils 0.1
import StatusQ.Popups.Dialog 0.1 import StatusQ.Popups.Dialog 0.1
import AppLayouts.Wallet.controls 1.0 import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.adaptors 1.0
import shared.popups.send.panels 1.0 import shared.popups.send.panels 1.0
import "./controls" import "./controls"
@ -80,6 +81,12 @@ StatusDialog {
QtObject { QtObject {
id: d id: d
readonly property WalletAccountsAdaptor accountsAdaptor: WalletAccountsAdaptor {
accountsModel: popup.store.accounts
flatNetworksModel: popup.store.flatNetworksModel
areTestNetworksEnabled: popup.store.areTestNetworksEnabled
}
property bool ensOrStickersPurpose: popup.preSelectedSendType === Constants.SendType.ENSRegister || property bool ensOrStickersPurpose: popup.preSelectedSendType === Constants.SendType.ENSRegister ||
popup.preSelectedSendType === Constants.SendType.ENSRelease || popup.preSelectedSendType === Constants.SendType.ENSRelease ||
popup.preSelectedSendType === Constants.SendType.ENSSetPubKey || popup.preSelectedSendType === Constants.SendType.ENSSetPubKey ||
@ -470,20 +477,7 @@ StatusDialog {
visible: !recipientInputLoader.ready && !d.isBridgeTx && !!d.selectedHolding visible: !recipientInputLoader.ready && !d.isBridgeTx && !!d.selectedHolding
savedAddressesModel: popup.store.savedAddressesModel savedAddressesModel: popup.store.savedAddressesModel
myAccountsModel: SortFilterProxyModel { myAccountsModel: d.accountsAdaptor.model
sourceModel: popup.store.accounts
proxyRoles: FastExpressionRole {
function getColorizedChainShortNames(preferredSharingChainIds, address){
const chainShortNames = popup.store.getNetworkShortNames(preferredSharingChainIds)
return WalletUtils.colorizedChainPrefix(chainShortNames) + address
}
name: "colorizedChainShortNames"
expectedRoles: ["preferredSharingChainIds", "address"]
expression: getColorizedChainShortNames(model.preferredSharingChainIds, model.address)
}
}
recentRecipientsModel: popup.store.tempActivityController1Model // Use Layer1 controller since this could go on top of other activity lists recentRecipientsModel: popup.store.tempActivityController1Model // Use Layer1 controller since this could go on top of other activity lists
onRecipientSelected: { onRecipientSelected: {