feat(SharedAddressesAccountSelector): Support for collectibles in account's delegate tags

Closes: #14102
This commit is contained in:
Michał Cieślak 2024-03-29 00:05:59 +01:00 committed by Michał
parent fc5daf2ee2
commit b91cf08066
12 changed files with 519 additions and 67 deletions

View File

@ -38,6 +38,7 @@ SplitView {
closePolicy: Popup.NoAutoClose closePolicy: Popup.NoAutoClose
isEditMode: ctrlIsEditMode.checked isEditMode: ctrlIsEditMode.checked
communityId: "community_id"
communityName: ctrlCommunityName.text communityName: ctrlCommunityName.text
communityIcon: { communityIcon: {
if (ctrlIconStatus.checked) if (ctrlIconStatus.checked)
@ -57,6 +58,7 @@ SplitView {
walletAccountsModel: WalletAccountsModel {} walletAccountsModel: WalletAccountsModel {}
walletAssetsModel: root.walletAssetStore.groupedAccountAssetsModel walletAssetsModel: root.walletAssetStore.groupedAccountAssetsModel
walletCollectiblesModel: ListModel {}
permissionsModel: ctrlPermissionsModel.currentValue permissionsModel: ctrlPermissionsModel.currentValue
assetsModel: AssetsModel {} assetsModel: AssetsModel {}
collectiblesModel: CollectiblesModel {} collectiblesModel: CollectiblesModel {}

View File

@ -0,0 +1,231 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import Storybook 1.0
import Models 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Communities.panels 1.0
SplitView {
id: root
orientation: Qt.Vertical
SplitView.fillWidth: true
Logs { id: logs }
readonly property WalletAssetsStore walletAssetStore: WalletAssetsStore {
assetsWithFilteredBalances: groupedAccountsAssetsModel
}
WalletAccountsModel {
id: walletAccountsModel
}
ListModel {
id: groupedAccountAssetsModel
ListElement {
symbol: "DAI"
balances: [
ListElement {
chainId: 5
balance: "20"
account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
},
ListElement {
chainId: 5
balance: "123456789123456789"
account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881"
}
]
}
ListElement {
symbol: "ETH"
balances: [
ListElement {
chainId: 420
balance: "1013151281976507736"
account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
},
ListElement {
chainId: 5
balance: "123456789123456789"
account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881"
}
]
}
}
SharedAddressesAccountSelector {
id: accountSelector
SplitView.fillWidth: true
SplitView.fillHeight: true
hasPermissions: true
uniquePermissionAssetsKeys: ["ETH", "DAI", "STT"]
uniquePermissionCollectiblesKeys: ["ATKN_key", "TMC1_key", "MYTKN_key"]
model: walletAccountsModel
walletAssetsModel: groupedAccountAssetsModel
walletCollectiblesModel: ListModel {
ListElement {
name: "TMaster-C1"
ownership: [
ListElement {
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "TMaster-C1"
ownership: [
ListElement {
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "TMaster-C1"
ownership: [
ListElement {
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "TMaster-C1"
ownership: [
ListElement {
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "TMaster-C1"
ownership: [
ListElement {
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "My token"
ownership: [
ListElement {
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "My token 2"
ownership: [
ListElement {
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "TMaster-C2"
ownership: [
ListElement {
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882"
balance: 1
}
]
communityId: "communityId_2"
}
ListElement {
name: "A token"
ownership: [
ListElement {
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
balance: 1
}
]
communityId: "communityId_1"
}
ListElement {
name: "A token"
ownership: [
ListElement {
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
balance: 1
}
]
communityId: "communityId_1"
}
}
communityCollectiblesModel: ListModel {
Component.onCompleted: {
append([
{
key: "TMC1_key",
symbol: "TMC1",
name: "TMaster-C1",
communityId: "communityId_1",
icon: ModelsData.collectibles.anniversary
},
{
key: "MYTKN_key",
symbol: "MYTKN",
name: "My token",
communityId: "communityId_1",
icon: ModelsData.collectibles.cryptoKitties
},
{
key: "ATKN_key",
symbol: "ATKN",
name: "A token",
communityId: "communityId_1",
icon: ModelsData.collectibles.mana
}
])
}
}
communityId: "communityId_1"
selectedSharedAddressesMap: new Map()//root.selectedSharedAddressesMap
getCurrencyAmount: (balance, symbol) => ({
amount: balance,
symbol: symbol.toUpperCase(),
displayDecimals: 2,
stripTrailingZeroes: false
})
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumHeight: 100
SplitView.preferredHeight: 200
logsView.logText: logs.logText
}
}
// category: Panels

View File

@ -1,58 +1,56 @@
import QtQuick 2.15 import QtQuick 2.15
import utils 1.0
ListModel { ListModel {
readonly property var data: [ readonly property var data: [
{ {
tokensKey: "DAI", tokensKey: "DAI",
balances: [ balances: [
{ account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "0"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "0" },
{ account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "123456789123456789"} { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "123456789123456789" }
] ]
}, },
{ {
tokensKey: "ETH", tokensKey: "ETH",
balances: [ balances: [
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1013151281976507736"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1013151281976507736" },
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 421613, balance: "473057568699284613"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 421613, balance: "473057568699284613" },
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "307400931315122839"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "307400931315122839" },
{account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "122082928968121891"}, { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "122082928968121891" },
{account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 421613, balance: "0"}, { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 421613, balance: "0" },
{account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "559133758939097000"} { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "559133758939097000" }
] ]
}, },
{ {
tokensKey: "STT", tokensKey: "STT",
balances: [ balances: [
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "999999999998998500000000000016777216"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "999999999998998500000000000016777216" },
{account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "1077000000000000000000"} { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "1077000000000000000000" }
] ]
}, },
{ {
tokensKey: "0x6b175474e89094c44da98b954eedeac495271e0f", tokensKey: "0x6b175474e89094c44da98b954eedeac495271e0f",
balances: [ balances: [
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "100"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "100" },
{account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "1"} { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "1" }
] ]
}, },
{ {
tokensKey: "0x6b175474e89094c44da98b954eedeac495271p0f", tokensKey: "0x6b175474e89094c44da98b954eedeac495271p0f",
balances: [ balances: [
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "20"}, { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "20" },
{account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "10"} { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "10" }
] ]
}, },
{ {
tokensKey: "0x6b175474e89094c44da98b954eedeac495271d0f", tokensKey: "0x6b175474e89094c44da98b954eedeac495271d0f",
balances: [ balances: [
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1"} { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1" }
] ]
}, },
{ {
tokensKey: "0x6b175474e89094c44da98b954eedeac495271a0f", tokensKey: "0x6b175474e89094c44da98b954eedeac495271a0f",
balances: [ balances: [
{account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1"} { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1" }
] ]
} }
] ]

View File

@ -17,7 +17,7 @@ public:
explicit PermissionUtilsInternal(QObject* parent = nullptr); explicit PermissionUtilsInternal(QObject* parent = nullptr);
//!< traverse the permissions @p model, and look for unique token keys recursively under holdingsListModel->key //!< traverse the permissions @p model, and look for unique token keys recursively under holdingsListModel->key
Q_INVOKABLE QStringList getUniquePermissionTokenKeys(QAbstractItemModel *model) const; Q_INVOKABLE QStringList getUniquePermissionTokenKeys(QAbstractItemModel *model, int type) const;
//!< traverse the permissions @p model, and look for unique channels recursively under channelsListModel->key; filtering out @p permissionTypes ([PermissionTypes.Type.FOO]) //!< traverse the permissions @p model, and look for unique channels recursively under channelsListModel->key; filtering out @p permissionTypes ([PermissionTypes.Type.FOO])
//! @return an array of `array<key,channelName>`, sorted by `channelName` //! @return an array of `array<key,channelName>`, sorted by `channelName`

View File

@ -32,6 +32,7 @@ Rectangle {
property var bottomModel: [] property var bottomModel: []
property Component bottomDelegate property Component bottomDelegate
property alias tagsModel: tagsRepeater.model property alias tagsModel: tagsRepeater.model
readonly property int tagsCount: tagsRepeater.count
property Component tagsDelegate property Component tagsDelegate
property var inlineTagModel: [] property var inlineTagModel: []
property Component inlineTagDelegate property Component inlineTagDelegate

View File

@ -26,7 +26,7 @@ PermissionUtilsInternal::PermissionUtilsInternal(QObject* parent)
{ {
} }
QStringList PermissionUtilsInternal::getUniquePermissionTokenKeys(QAbstractItemModel* model) const QStringList PermissionUtilsInternal::getUniquePermissionTokenKeys(QAbstractItemModel* model, int tokenType) const
{ {
if (!model) if (!model)
return {}; return {};
@ -53,13 +53,27 @@ QStringList PermissionUtilsInternal::getUniquePermissionTokenKeys(QAbstractItemM
continue; continue;
} }
const auto holdingItemsCount = holdingItems->rowCount(); const auto holdingItemsCount = holdingItems->rowCount();
const auto keyRole = roleByName(holdingItems, QStringLiteral("key"));
if (keyRole == -1) {
qWarning() << Q_FUNC_INFO << "Requested roleName 'key' not found!";
continue;
}
const auto typeRole = roleByName(holdingItems, QStringLiteral("type"));
if (typeRole == -1) {
qWarning() << Q_FUNC_INFO << "Requested roleName 'type' not found!";
continue;
}
for (int j = 0; j < holdingItemsCount; j++) { for (int j = 0; j < holdingItemsCount; j++) {
const auto keyRole = roleByName(holdingItems, QStringLiteral("key")); auto idx = holdingItems->index(j, 0);
if (keyRole == -1) { QString key = holdingItems->data(idx, keyRole).toString().toUpper();
qWarning() << Q_FUNC_INFO << "Requested roleName 'key' not found!"; int type = holdingItems->data(idx, typeRole).toInt();
continue;
} if (type == tokenType)
result.insert(holdingItems->data(holdingItems->index(j, 0), keyRole).toString().toUpper()); result.insert(key);
} }
} }
} }

View File

@ -70,8 +70,8 @@ QtObject {
item.multiplierIndex)) item.multiplierIndex))
} }
function getUniquePermissionTokenKeys(model) { function getUniquePermissionTokenKeys(model, tokenType) {
return Internal.PermissionUtils.getUniquePermissionTokenKeys(model) return Internal.PermissionUtils.getUniquePermissionTokenKeys(model, tokenType)
} }
function getUniquePermissionChannels(model, permissionsTypesArray = []) { function getUniquePermissionChannels(model, permissionsTypesArray = []) {

View File

@ -19,7 +19,13 @@ StatusListView {
property var walletAssetsModel property var walletAssetsModel
property bool hasPermissions property bool hasPermissions
property var uniquePermissionTokenKeys
property var uniquePermissionAssetsKeys
property var uniquePermissionCollectiblesKeys
property var walletCollectiblesModel
property var communityCollectiblesModel
property string communityId
property var getCurrencyAmount: function (balance, symbol){} property var getCurrencyAmount: function (balance, symbol){}
@ -31,9 +37,57 @@ StatusListView {
rightMargin: Style.current.padding rightMargin: Style.current.padding
bottomMargin: Style.current.padding bottomMargin: Style.current.padding
ModelChangeTracker {
id: communityCollectiblesModelTracker
model: communityCollectiblesModel
onRevisionChanged: {
const collectibles = ModelUtils.modelToArray(
communityCollectiblesModel,
["key", "name", "symbol", "icon", "communityId"])
.filter(e => e.communityId === communityId)
const keysToNames = {}
for (const c of collectibles)
keysToNames[c.key] = {
name: c.name,
symbol: c.symbol,
icon: c.icon
}
d.collectiblesMetadata
= uniquePermissionCollectiblesKeys.map(k => keysToNames[k])
d.collectiblesNames = d.collectiblesMetadata.map(c => c.name)
const namesToSymbols = {}
d.collectiblesMetadata.forEach(c => namesToSymbols[c.name] = c.symbol)
d.collectiblesNamesToSymbols = namesToSymbols
const namesToImages = {}
d.collectiblesMetadata.forEach(c => namesToImages[c.name] = c.icon)
d.collectiblesNamesToImages = namesToImages
}
Component.onCompleted: revisionChanged()
}
ModelChangeTracker {
id: filteredWalletCollectiblesTracker
model: filteredWalletCollectibles
}
QtObject { QtObject {
id: d id: d
property var collectiblesMetadata: []
property var collectiblesNames: []
property var collectiblesNamesToSymbols: ({})
property var collectiblesNamesToImages: ({})
readonly property int selectedSharedAddressesCount: root.selectedSharedAddressesMap.size readonly property int selectedSharedAddressesCount: root.selectedSharedAddressesMap.size
// UI // UI
@ -47,9 +101,9 @@ StatusListView {
exclusive: false exclusive: false
} }
function getTotalBalance(balances, decimals, symbol) { function getTotalBalance(balances, decimals) {
let totalBalance = 0 let totalBalance = 0
for(let i=0; i<balances.count; i++) { for(let i = 0; i < balances.count; i++) {
let balancePerAddressPerChain = ModelUtils.get(balances, i) let balancePerAddressPerChain = ModelUtils.get(balances, i)
totalBalance += AmountsArithmetic.toNumber(balancePerAddressPerChain.balance, decimals) totalBalance += AmountsArithmetic.toNumber(balancePerAddressPerChain.balance, decimals)
} }
@ -57,6 +111,62 @@ StatusListView {
} }
} }
SortFilterProxyModel {
id: filteredWalletCollectibles
sourceModel: walletCollectiblesModel
filters: [
ValueFilter {
roleName: "communityId"
value: root.communityId
},
FastExpressionFilter {
expression: d.collectiblesNames.includes(model.name)
expectedRoles: ["name"]
}
]
}
ListModel {
id: walletAccountCollectiblesModel
readonly property var data: {
filteredWalletCollectiblesTracker.revision
const usedCollectibles = ModelUtils.modelToArray(filteredWalletCollectibles)
const collectiblesGroupingMap = {}
for (const c of usedCollectibles) {
const key = `${c.name}_${c.ownership[0].accountAddress}`
if (!collectiblesGroupingMap[key])
collectiblesGroupingMap[key] = []
collectiblesGroupingMap[key].push(c)
}
const collectiblesGrouped = Object.values(collectiblesGroupingMap).map(e => {
const firstEntry = e[0]
return {
symbol: d.collectiblesNamesToSymbols[firstEntry.name] || "",
enabledNetworkBalance: e.length,
account: firstEntry.ownership[0].accountAddress,
type: Constants.TokenType.ERC721,
imageUrl: d.collectiblesNamesToImages[firstEntry.name] || ""
}
})
return collectiblesGrouped
}
onDataChanged: {
clear()
append(data)
}
}
spacing: Style.current.halfPadding spacing: Style.current.halfPadding
delegate: StatusListItem { delegate: StatusListItem {
readonly property string address: model.address.toLowerCase() readonly property string address: model.address.toLowerCase()
@ -65,7 +175,7 @@ StatusListView {
width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin
statusListItemTitle.font.weight: Font.Medium statusListItemTitle.font.weight: Font.Medium
title: model.name title: model.name
tertiaryTitle: !walletAccountAssetsModel.count && root.hasPermissions ? qsTr("No relevant tokens") : "" tertiaryTitle: root.hasPermissions && !tagsCount ? qsTr("No relevant tokens") : ""
SubmodelProxyModel { SubmodelProxyModel {
id: filteredBalances id: filteredBalances
@ -73,54 +183,123 @@ StatusListView {
submodelRoleName: "balances" submodelRoleName: "balances"
delegateModel: SortFilterProxyModel { delegateModel: SortFilterProxyModel {
sourceModel: submodel sourceModel: submodel
filters: FastExpressionFilter {
expression: listItem.address === model.account.toLowerCase() filters: RegExpFilter {
expectedRoles: ["account"] roleName: "account"
pattern: listItem.address
syntax: RegExpFilter.FixedString
caseSensitivity: Qt.CaseInsensitive
} }
} }
} }
SortFilterProxyModel {
id: accountCollectiblesModel
sourceModel: walletAccountCollectiblesModel
filters: RegExpFilter {
roleName: "account"
pattern: listItem.address
syntax: RegExpFilter.FixedString
caseSensitivity: Qt.CaseInsensitive
}
}
ConcatModel {
id: concatModel
sources: [
SourceModel {
// During initialization sfpm provides rowCount not taking
// filtering into account, deferring model assignment as
// a workaround
Component.onCompleted: model = walletAccountAssetsModel
},
SourceModel {
Component.onCompleted: model = accountCollectiblesModel
}
]
}
tagsModel: SortFilterProxyModel { tagsModel: SortFilterProxyModel {
sourceModel: concatModel
filters: ValueFilter {
roleName: "enabledNetworkBalance"
value: 0
inverted: true
}
sorters: RoleSorter {
roleName: "symbol"
}
}
SortFilterProxyModel {
id: walletAccountAssetsModel id: walletAccountAssetsModel
sourceModel: filteredBalances sourceModel: filteredBalances
function filterPredicate(symbol) { function filterPredicate(symbol) {
return root.uniquePermissionTokenKeys.includes(symbol.toUpperCase()) return root.uniquePermissionAssetsKeys.includes(symbol.toUpperCase())
} }
proxyRoles: FastExpressionRole { proxyRoles: [
name: "enabledNetworkBalance" FastExpressionRole {
expression: d.getTotalBalance(model.balances, model.decimals, model.symbol) name: "enabledNetworkBalance"
expectedRoles: ["balances", "decimals", "symbol"] expression: d.getTotalBalance(model.balances, model.decimals)
} expectedRoles: ["balances", "decimals"]
},
FastExpressionRole {
name: "type"
readonly property int typeVal: Constants.TokenType.ERC20
// Singletons cannot be used directly in sfpm's expressions
expression: typeVal
},
FastExpressionRole {
name: "imageUrl"
function getIcon(symbol) {
return Constants.tokenIcon(symbol.toUpperCase())
}
// Singletons cannot be used directly in sfpm's expressions
expression: getIcon(model.symbol)
expectedRoles: ["symbol"]
}
]
filters: FastExpressionFilter { filters: FastExpressionFilter {
expression: walletAccountAssetsModel.filterPredicate(model.symbol) expression: walletAccountAssetsModel.filterPredicate(model.symbol)
expectedRoles: ["symbol"] expectedRoles: ["symbol"]
} }
sorters: FastExpressionSorter {
expression: {
if (modelLeft.enabledNetworkBalance > modelRight.enabledNetworkBalance)
return -1 // descending, biggest first
else if (modelLeft.enabledNetworkBalance < modelRight.enabledNetworkBalance)
return 1
else
return 0
}
expectedRoles: ["enabledNetworkBalance"]
}
} }
statusListItemInlineTagsSlot.spacing: Style.current.padding statusListItemInlineTagsSlot.spacing: Style.current.padding
tagsDelegate: Row { tagsDelegate: Row {
spacing: 4 spacing: 4
StatusRoundedImage { StatusRoundedImage {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: 16 width: 16
height: 16 height: 16
image.source: Constants.tokenIcon(model.symbol.toUpperCase()) image.source: model.imageUrl
} }
StatusBaseText { StatusBaseText {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Theme.tertiaryTextFontSize font.pixelSize: Theme.tertiaryTextFontSize
text: LocaleUtils.currencyAmountToLocaleString(root.getCurrencyAmount(model.enabledNetworkBalance, model.symbol)) text: {
if (model.type === Constants.TokenType.ERC20)
return LocaleUtils.currencyAmountToLocaleString(
root.getCurrencyAmount(model.enabledNetworkBalance,
model.symbol))
return LocaleUtils.numberToLocaleString(model.enabledNetworkBalance)
+ " " + model.symbol
}
} }
} }
@ -137,10 +316,11 @@ StatusListView {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
icon.name: "airdrop" icon.name: "airdrop"
icon.color: hovered ? Theme.palette.primaryColor3 : icon.color: hovered ? Theme.palette.primaryColor3 :
checked ? Theme.palette.primaryColor1 : disabledTextColor checked ? Theme.palette.primaryColor1
: disabledTextColor
checkable: true checkable: true
checked: { checked: {
let obj = root.selectedSharedAddressesMap.get(listItem.address) const obj = root.selectedSharedAddressesMap.get(listItem.address)
if (!!obj) { if (!!obj) {
return obj.isAirdrop return obj.isAirdrop
} }
@ -150,9 +330,7 @@ StatusListView {
visible: shareAddressCheckbox.checked visible: shareAddressCheckbox.checked
opacity: enabled ? 1.0 : 0.3 opacity: enabled ? 1.0 : 0.3
onToggled: { onToggled: root.airdropAddressSelected(listItem.address)
root.airdropAddressSelected(listItem.address)
}
StatusToolTip { StatusToolTip {
text: qsTr("Use this address for any Community airdrops") text: qsTr("Use this address for any Community airdrops")
@ -162,15 +340,14 @@ StatusListView {
}, },
StatusCheckBox { StatusCheckBox {
id: shareAddressCheckbox id: shareAddressCheckbox
ButtonGroup.group: d.addressesGroup ButtonGroup.group: d.addressesGroup
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
checkable: true checkable: true
checked: root.selectedSharedAddressesMap.has(listItem.address) checked: root.selectedSharedAddressesMap.has(listItem.address)
enabled: !(d.selectedSharedAddressesCount === 1 && checked) // last cannot be unchecked enabled: !(d.selectedSharedAddressesCount === 1 && checked) // last cannot be unchecked
onToggled: { onToggled: root.toggleAddressSelection(model.keyUid, listItem.address)
root.toggleAddressSelection(model.keyUid, listItem.address)
}
} }
] ]
} }

View File

@ -35,12 +35,16 @@ Control {
property bool requirementsCheckPending: false property bool requirementsCheckPending: false
required property string communityId
required property string communityName required property string communityName
required property string communityIcon required property string communityIcon
required property var walletAssetsModel required property var walletAssetsModel
required property var walletCollectiblesModel
required property var walletAccountsModel // name, address, emoji, colorId, assets required property var walletAccountsModel // name, address, emoji, colorId, assets
required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet
required property var assetsModel required property var assetsModel
required property var collectiblesModel required property var collectiblesModel
@ -188,13 +192,27 @@ Control {
SharedAddressesAccountSelector { SharedAddressesAccountSelector {
id: accountSelector id: accountSelector
hasPermissions: d.hasPermissions hasPermissions: d.hasPermissions
uniquePermissionTokenKeys: PermissionsHelpers.getUniquePermissionTokenKeys(root.permissionsModel)
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: contentHeight + topMargin + bottomMargin Layout.preferredHeight: contentHeight + topMargin + bottomMargin
Layout.maximumHeight: hasPermissions ? permissionsView.implicitHeight > root.availableHeight / 2 ? root.availableHeight / 2 : root.availableHeight : -1 Layout.maximumHeight: hasPermissions ? permissionsView.implicitHeight > root.availableHeight / 2 ? root.availableHeight / 2 : root.availableHeight : -1
Layout.fillHeight: !hasPermissions Layout.fillHeight: !hasPermissions
uniquePermissionAssetsKeys:
PermissionsHelpers.getUniquePermissionTokenKeys(
root.permissionsModel, Constants.TokenType.ERC20)
uniquePermissionCollectiblesKeys:
PermissionsHelpers.getUniquePermissionTokenKeys(
root.permissionsModel, Constants.TokenType.ERC721)
model: root.walletAccountsModel model: root.walletAccountsModel
walletAssetsModel: root.walletAssetsModel walletAssetsModel: root.walletAssetsModel
walletCollectiblesModel: root.walletCollectiblesModel
communityId: root.communityId
communityCollectiblesModel: root.collectiblesModel
selectedSharedAddressesMap: root.selectedSharedAddressesMap selectedSharedAddressesMap: root.selectedSharedAddressesMap
onToggleAddressSelection: { onToggleAddressSelection: {

View File

@ -29,6 +29,7 @@ ProfilePopupInviteFriendsPanel 1.0 ProfilePopupInviteFriendsPanel.qml
ProfilePopupInviteMessagePanel 1.0 ProfilePopupInviteMessagePanel.qml ProfilePopupInviteMessagePanel 1.0 ProfilePopupInviteMessagePanel.qml
ProfilePopupOverviewPanel 1.0 ProfilePopupOverviewPanel.qml ProfilePopupOverviewPanel 1.0 ProfilePopupOverviewPanel.qml
RequirementsCheckPendingLoader 1.0 RequirementsCheckPendingLoader.qml RequirementsCheckPendingLoader 1.0 RequirementsCheckPendingLoader.qml
SharedAddressesAccountSelector 1.0 SharedAddressesAccountSelector.qml
SharedAddressesPanel 1.0 SharedAddressesPanel.qml SharedAddressesPanel 1.0 SharedAddressesPanel.qml
SharedAddressesSigningPanel 1.0 SharedAddressesSigningPanel.qml SharedAddressesSigningPanel 1.0 SharedAddressesSigningPanel.qml
SortableTokenHoldersList 1.0 SortableTokenHoldersList.qml SortableTokenHoldersList 1.0 SortableTokenHoldersList.qml

View File

@ -696,11 +696,11 @@ QtObject {
CommunityMembershipSetupDialog { CommunityMembershipSetupDialog {
id: dialogRoot id: dialogRoot
property string communityId
requirementsCheckPending: root.rootStore.requirementsCheckPending requirementsCheckPending: root.rootStore.requirementsCheckPending
walletAccountsModel: root.rootStore.walletAccountsModel walletAccountsModel: root.rootStore.walletAccountsModel
walletCollectiblesModel: WalletStore.RootStore.collectiblesStore.allCollectiblesModel
canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses
walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel
@ -929,8 +929,6 @@ QtObject {
CommunityMembershipSetupDialog { CommunityMembershipSetupDialog {
id: editSharedAddressesPopup id: editSharedAddressesPopup
property string communityId
readonly property var chatStore: ChatStore.RootStore { readonly property var chatStore: ChatStore.RootStore {
contactsStore: root.rootStore.contactStore contactsStore: root.rootStore.contactStore
chatCommunitySectionModule: { chatCommunitySectionModule: {
@ -953,7 +951,10 @@ QtObject {
canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses
walletAccountsModel: root.rootStore.walletAccountsModel walletAccountsModel: root.rootStore.walletAccountsModel
walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel
walletCollectiblesModel: WalletStore.RootStore.collectiblesStore.allCollectiblesModel
permissionsModel: { permissionsModel: {
root.rootStore.prepareTokenModelForCommunity(editSharedAddressesPopup.communityId) root.rootStore.prepareTokenModelForCommunity(editSharedAddressesPopup.communityId)
return root.rootStore.permissionsModel return root.rootStore.permissionsModel

View File

@ -24,6 +24,7 @@ StatusStackModal {
destroyOnClose: true destroyOnClose: true
property bool isEditMode: false property bool isEditMode: false
required property string communityId
required property string communityName required property string communityName
required property string communityIcon required property string communityIcon
required property bool requirementsCheckPending required property bool requirementsCheckPending
@ -33,7 +34,10 @@ StatusStackModal {
property bool isInvitationPending: false property bool isInvitationPending: false
required property var walletAccountsModel // name, address, emoji, colorId required property var walletAccountsModel // name, address, emoji, colorId
required property var walletAssetsModel required property var walletAssetsModel
required property var walletCollectiblesModel
required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet
required property var assetsModel required property var assetsModel
required property var collectiblesModel required property var collectiblesModel
@ -351,11 +355,14 @@ StatusStackModal {
SharedAddressesPanel { SharedAddressesPanel {
componentUid: d.shareAddressesUid componentUid: d.shareAddressesUid
isEditMode: root.isEditMode isEditMode: root.isEditMode
communityId: root.communityId
communityName: root.communityName communityName: root.communityName
communityIcon: root.communityIcon communityIcon: root.communityIcon
requirementsCheckPending: root.requirementsCheckPending requirementsCheckPending: root.requirementsCheckPending
walletAccountsModel: d.initialAddressesModel walletAccountsModel: d.initialAddressesModel
selectedSharedAddressesMap: d.selectedSharedAddressesMap selectedSharedAddressesMap: d.selectedSharedAddressesMap
currentSharedAddressesMap: d.currentSharedAddressesMap currentSharedAddressesMap: d.currentSharedAddressesMap
@ -366,6 +373,8 @@ StatusStackModal {
allAddressesToRevealBelongToSingleNonProfileKeypair: root.allAddressesToRevealBelongToSingleNonProfileKeypair allAddressesToRevealBelongToSingleNonProfileKeypair: root.allAddressesToRevealBelongToSingleNonProfileKeypair
walletAssetsModel: root.walletAssetsModel walletAssetsModel: root.walletAssetsModel
walletCollectiblesModel: root.walletCollectiblesModel
permissionsModel: root.permissionsModel permissionsModel: root.permissionsModel
assetsModel: root.assetsModel assetsModel: root.assetsModel
collectiblesModel: root.collectiblesModel collectiblesModel: root.collectiblesModel