From b91cf08066c867f858535e5ff525dc9d4018aeb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Fri, 29 Mar 2024 00:05:59 +0100 Subject: [PATCH] feat(SharedAddressesAccountSelector): Support for collectibles in account's delegate tags Closes: #14102 --- .../CommunityMembershipSetupDialogPage.qml | 2 + .../SharedAddressesAccountSelectorPage.qml | 231 +++++++++++++++++ .../src/Models/GroupedAccountsAssetsModel.qml | 34 ++- .../include/StatusQ/permissionutilsinternal.h | 2 +- .../src/StatusQ/Components/StatusListItem.qml | 1 + ui/StatusQ/src/permissionutilsinternal.cpp | 28 +- .../helpers/PermissionsHelpers.qml | 4 +- .../panels/SharedAddressesAccountSelector.qml | 245 +++++++++++++++--- .../panels/SharedAddressesPanel.qml | 20 +- ui/app/AppLayouts/Communities/panels/qmldir | 1 + ui/app/mainui/Popups.qml | 9 +- .../popups/CommunityMembershipSetupDialog.qml | 9 + 12 files changed, 519 insertions(+), 67 deletions(-) create mode 100644 storybook/pages/SharedAddressesAccountSelectorPage.qml diff --git a/storybook/pages/CommunityMembershipSetupDialogPage.qml b/storybook/pages/CommunityMembershipSetupDialogPage.qml index 29a42ab797..980ceb3404 100644 --- a/storybook/pages/CommunityMembershipSetupDialogPage.qml +++ b/storybook/pages/CommunityMembershipSetupDialogPage.qml @@ -38,6 +38,7 @@ SplitView { closePolicy: Popup.NoAutoClose isEditMode: ctrlIsEditMode.checked + communityId: "community_id" communityName: ctrlCommunityName.text communityIcon: { if (ctrlIconStatus.checked) @@ -57,6 +58,7 @@ SplitView { walletAccountsModel: WalletAccountsModel {} walletAssetsModel: root.walletAssetStore.groupedAccountAssetsModel + walletCollectiblesModel: ListModel {} permissionsModel: ctrlPermissionsModel.currentValue assetsModel: AssetsModel {} collectiblesModel: CollectiblesModel {} diff --git a/storybook/pages/SharedAddressesAccountSelectorPage.qml b/storybook/pages/SharedAddressesAccountSelectorPage.qml new file mode 100644 index 0000000000..7c40136613 --- /dev/null +++ b/storybook/pages/SharedAddressesAccountSelectorPage.qml @@ -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 diff --git a/storybook/src/Models/GroupedAccountsAssetsModel.qml b/storybook/src/Models/GroupedAccountsAssetsModel.qml index 91052a265b..95e61c083f 100644 --- a/storybook/src/Models/GroupedAccountsAssetsModel.qml +++ b/storybook/src/Models/GroupedAccountsAssetsModel.qml @@ -1,58 +1,56 @@ import QtQuick 2.15 -import utils 1.0 - ListModel { readonly property var data: [ { tokensKey: "DAI", balances: [ - { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "0"}, - { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "123456789123456789"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "0" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "123456789123456789" } ] }, { tokensKey: "ETH", balances: [ - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1013151281976507736"}, - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 421613, balance: "473057568699284613"}, - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "307400931315122839"}, - {account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "122082928968121891"}, - {account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 421613, balance: "0"}, - {account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "559133758939097000"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1013151281976507736" }, + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 421613, balance: "473057568699284613" }, + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "307400931315122839" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "122082928968121891" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 421613, balance: "0" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "559133758939097000" } ] }, { tokensKey: "STT", balances: [ - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "999999999998998500000000000016777216"}, - {account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "1077000000000000000000"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 5, balance: "999999999998998500000000000016777216" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 5, balance: "1077000000000000000000" } ] }, { tokensKey: "0x6b175474e89094c44da98b954eedeac495271e0f", balances: [ - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "100"}, - {account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "1"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "100" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "1" } ] }, { tokensKey: "0x6b175474e89094c44da98b954eedeac495271p0f", balances: [ - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "20"}, - {account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "10"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "20" }, + { account: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881", chainId: 420, balance: "10" } ] }, { tokensKey: "0x6b175474e89094c44da98b954eedeac495271d0f", balances: [ - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1" } ] }, { tokensKey: "0x6b175474e89094c44da98b954eedeac495271a0f", balances: [ - {account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1"} + { account: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240", chainId: 420, balance: "1" } ] } ] diff --git a/ui/StatusQ/include/StatusQ/permissionutilsinternal.h b/ui/StatusQ/include/StatusQ/permissionutilsinternal.h index da785f9ebc..47fa028090 100644 --- a/ui/StatusQ/include/StatusQ/permissionutilsinternal.h +++ b/ui/StatusQ/include/StatusQ/permissionutilsinternal.h @@ -17,7 +17,7 @@ public: explicit PermissionUtilsInternal(QObject* parent = nullptr); //!< 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]) //! @return an array of `array`, sorted by `channelName` diff --git a/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml b/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml index 0252940533..18d58524e0 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml @@ -32,6 +32,7 @@ Rectangle { property var bottomModel: [] property Component bottomDelegate property alias tagsModel: tagsRepeater.model + readonly property int tagsCount: tagsRepeater.count property Component tagsDelegate property var inlineTagModel: [] property Component inlineTagDelegate diff --git a/ui/StatusQ/src/permissionutilsinternal.cpp b/ui/StatusQ/src/permissionutilsinternal.cpp index 7a211dd739..46be477a32 100644 --- a/ui/StatusQ/src/permissionutilsinternal.cpp +++ b/ui/StatusQ/src/permissionutilsinternal.cpp @@ -26,7 +26,7 @@ PermissionUtilsInternal::PermissionUtilsInternal(QObject* parent) { } -QStringList PermissionUtilsInternal::getUniquePermissionTokenKeys(QAbstractItemModel* model) const +QStringList PermissionUtilsInternal::getUniquePermissionTokenKeys(QAbstractItemModel* model, int tokenType) const { if (!model) return {}; @@ -53,13 +53,27 @@ QStringList PermissionUtilsInternal::getUniquePermissionTokenKeys(QAbstractItemM continue; } 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++) { - const auto keyRole = roleByName(holdingItems, QStringLiteral("key")); - if (keyRole == -1) { - qWarning() << Q_FUNC_INFO << "Requested roleName 'key' not found!"; - continue; - } - result.insert(holdingItems->data(holdingItems->index(j, 0), keyRole).toString().toUpper()); + auto idx = holdingItems->index(j, 0); + QString key = holdingItems->data(idx, keyRole).toString().toUpper(); + int type = holdingItems->data(idx, typeRole).toInt(); + + if (type == tokenType) + result.insert(key); } } } diff --git a/ui/app/AppLayouts/Communities/helpers/PermissionsHelpers.qml b/ui/app/AppLayouts/Communities/helpers/PermissionsHelpers.qml index 58f0006f58..e72c3b4398 100644 --- a/ui/app/AppLayouts/Communities/helpers/PermissionsHelpers.qml +++ b/ui/app/AppLayouts/Communities/helpers/PermissionsHelpers.qml @@ -70,8 +70,8 @@ QtObject { item.multiplierIndex)) } - function getUniquePermissionTokenKeys(model) { - return Internal.PermissionUtils.getUniquePermissionTokenKeys(model) + function getUniquePermissionTokenKeys(model, tokenType) { + return Internal.PermissionUtils.getUniquePermissionTokenKeys(model, tokenType) } function getUniquePermissionChannels(model, permissionsTypesArray = []) { diff --git a/ui/app/AppLayouts/Communities/panels/SharedAddressesAccountSelector.qml b/ui/app/AppLayouts/Communities/panels/SharedAddressesAccountSelector.qml index 6b87059390..36ec5dc8d1 100644 --- a/ui/app/AppLayouts/Communities/panels/SharedAddressesAccountSelector.qml +++ b/ui/app/AppLayouts/Communities/panels/SharedAddressesAccountSelector.qml @@ -19,7 +19,13 @@ StatusListView { property var walletAssetsModel 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){} @@ -31,9 +37,57 @@ StatusListView { rightMargin: 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 { id: d + property var collectiblesMetadata: [] + property var collectiblesNames: [] + property var collectiblesNamesToSymbols: ({}) + property var collectiblesNamesToImages: ({}) + readonly property int selectedSharedAddressesCount: root.selectedSharedAddressesMap.size // UI @@ -47,9 +101,9 @@ StatusListView { exclusive: false } - function getTotalBalance(balances, decimals, symbol) { + function getTotalBalance(balances, decimals) { let totalBalance = 0 - for(let i=0; i { + 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 delegate: StatusListItem { readonly property string address: model.address.toLowerCase() @@ -65,7 +175,7 @@ StatusListView { width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin statusListItemTitle.font.weight: Font.Medium title: model.name - tertiaryTitle: !walletAccountAssetsModel.count && root.hasPermissions ? qsTr("No relevant tokens") : "" + tertiaryTitle: root.hasPermissions && !tagsCount ? qsTr("No relevant tokens") : "" SubmodelProxyModel { id: filteredBalances @@ -73,54 +183,123 @@ StatusListView { submodelRoleName: "balances" delegateModel: SortFilterProxyModel { sourceModel: submodel - filters: FastExpressionFilter { - expression: listItem.address === model.account.toLowerCase() - expectedRoles: ["account"] + + filters: RegExpFilter { + 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 { + sourceModel: concatModel + + filters: ValueFilter { + roleName: "enabledNetworkBalance" + value: 0 + inverted: true + } + + sorters: RoleSorter { + roleName: "symbol" + } + } + + SortFilterProxyModel { id: walletAccountAssetsModel + sourceModel: filteredBalances function filterPredicate(symbol) { - return root.uniquePermissionTokenKeys.includes(symbol.toUpperCase()) + return root.uniquePermissionAssetsKeys.includes(symbol.toUpperCase()) } - proxyRoles: FastExpressionRole { - name: "enabledNetworkBalance" - expression: d.getTotalBalance(model.balances, model.decimals, model.symbol) - expectedRoles: ["balances", "decimals", "symbol"] - } + proxyRoles: [ + FastExpressionRole { + name: "enabledNetworkBalance" + 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 { expression: walletAccountAssetsModel.filterPredicate(model.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 + tagsDelegate: Row { spacing: 4 StatusRoundedImage { anchors.verticalCenter: parent.verticalCenter width: 16 height: 16 - image.source: Constants.tokenIcon(model.symbol.toUpperCase()) + image.source: model.imageUrl } StatusBaseText { anchors.verticalCenter: parent.verticalCenter 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 icon.name: "airdrop" icon.color: hovered ? Theme.palette.primaryColor3 : - checked ? Theme.palette.primaryColor1 : disabledTextColor + checked ? Theme.palette.primaryColor1 + : disabledTextColor checkable: true checked: { - let obj = root.selectedSharedAddressesMap.get(listItem.address) + const obj = root.selectedSharedAddressesMap.get(listItem.address) if (!!obj) { return obj.isAirdrop } @@ -150,9 +330,7 @@ StatusListView { visible: shareAddressCheckbox.checked opacity: enabled ? 1.0 : 0.3 - onToggled: { - root.airdropAddressSelected(listItem.address) - } + onToggled: root.airdropAddressSelected(listItem.address) StatusToolTip { text: qsTr("Use this address for any Community airdrops") @@ -162,15 +340,14 @@ StatusListView { }, StatusCheckBox { id: shareAddressCheckbox + ButtonGroup.group: d.addressesGroup anchors.verticalCenter: parent.verticalCenter checkable: true checked: root.selectedSharedAddressesMap.has(listItem.address) enabled: !(d.selectedSharedAddressesCount === 1 && checked) // last cannot be unchecked - onToggled: { - root.toggleAddressSelection(model.keyUid, listItem.address) - } + onToggled: root.toggleAddressSelection(model.keyUid, listItem.address) } ] } diff --git a/ui/app/AppLayouts/Communities/panels/SharedAddressesPanel.qml b/ui/app/AppLayouts/Communities/panels/SharedAddressesPanel.qml index dbd318567f..a47cf6905a 100644 --- a/ui/app/AppLayouts/Communities/panels/SharedAddressesPanel.qml +++ b/ui/app/AppLayouts/Communities/panels/SharedAddressesPanel.qml @@ -35,12 +35,16 @@ Control { property bool requirementsCheckPending: false + required property string communityId required property string communityName required property string communityIcon required property var walletAssetsModel + required property var walletCollectiblesModel + required property var walletAccountsModel // name, address, emoji, colorId, assets required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet + required property var assetsModel required property var collectiblesModel @@ -188,13 +192,27 @@ Control { SharedAddressesAccountSelector { id: accountSelector hasPermissions: d.hasPermissions - uniquePermissionTokenKeys: PermissionsHelpers.getUniquePermissionTokenKeys(root.permissionsModel) + Layout.fillWidth: true Layout.preferredHeight: contentHeight + topMargin + bottomMargin Layout.maximumHeight: hasPermissions ? permissionsView.implicitHeight > root.availableHeight / 2 ? root.availableHeight / 2 : root.availableHeight : -1 Layout.fillHeight: !hasPermissions + + uniquePermissionAssetsKeys: + PermissionsHelpers.getUniquePermissionTokenKeys( + root.permissionsModel, Constants.TokenType.ERC20) + + uniquePermissionCollectiblesKeys: + PermissionsHelpers.getUniquePermissionTokenKeys( + root.permissionsModel, Constants.TokenType.ERC721) + model: root.walletAccountsModel walletAssetsModel: root.walletAssetsModel + walletCollectiblesModel: root.walletCollectiblesModel + + communityId: root.communityId + communityCollectiblesModel: root.collectiblesModel + selectedSharedAddressesMap: root.selectedSharedAddressesMap onToggleAddressSelection: { diff --git a/ui/app/AppLayouts/Communities/panels/qmldir b/ui/app/AppLayouts/Communities/panels/qmldir index 1b40e76b49..83d3406003 100644 --- a/ui/app/AppLayouts/Communities/panels/qmldir +++ b/ui/app/AppLayouts/Communities/panels/qmldir @@ -29,6 +29,7 @@ ProfilePopupInviteFriendsPanel 1.0 ProfilePopupInviteFriendsPanel.qml ProfilePopupInviteMessagePanel 1.0 ProfilePopupInviteMessagePanel.qml ProfilePopupOverviewPanel 1.0 ProfilePopupOverviewPanel.qml RequirementsCheckPendingLoader 1.0 RequirementsCheckPendingLoader.qml +SharedAddressesAccountSelector 1.0 SharedAddressesAccountSelector.qml SharedAddressesPanel 1.0 SharedAddressesPanel.qml SharedAddressesSigningPanel 1.0 SharedAddressesSigningPanel.qml SortableTokenHoldersList 1.0 SortableTokenHoldersList.qml diff --git a/ui/app/mainui/Popups.qml b/ui/app/mainui/Popups.qml index df66889b0e..69a08dd10d 100644 --- a/ui/app/mainui/Popups.qml +++ b/ui/app/mainui/Popups.qml @@ -696,11 +696,11 @@ QtObject { CommunityMembershipSetupDialog { id: dialogRoot - property string communityId - requirementsCheckPending: root.rootStore.requirementsCheckPending walletAccountsModel: root.rootStore.walletAccountsModel + walletCollectiblesModel: WalletStore.RootStore.collectiblesStore.allCollectiblesModel + canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel @@ -929,8 +929,6 @@ QtObject { CommunityMembershipSetupDialog { id: editSharedAddressesPopup - property string communityId - readonly property var chatStore: ChatStore.RootStore { contactsStore: root.rootStore.contactStore chatCommunitySectionModule: { @@ -953,7 +951,10 @@ QtObject { canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses walletAccountsModel: root.rootStore.walletAccountsModel + walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel + walletCollectiblesModel: WalletStore.RootStore.collectiblesStore.allCollectiblesModel + permissionsModel: { root.rootStore.prepareTokenModelForCommunity(editSharedAddressesPopup.communityId) return root.rootStore.permissionsModel diff --git a/ui/imports/shared/popups/CommunityMembershipSetupDialog.qml b/ui/imports/shared/popups/CommunityMembershipSetupDialog.qml index 96442d782b..8cbd1316b5 100644 --- a/ui/imports/shared/popups/CommunityMembershipSetupDialog.qml +++ b/ui/imports/shared/popups/CommunityMembershipSetupDialog.qml @@ -24,6 +24,7 @@ StatusStackModal { destroyOnClose: true property bool isEditMode: false + required property string communityId required property string communityName required property string communityIcon required property bool requirementsCheckPending @@ -33,7 +34,10 @@ StatusStackModal { property bool isInvitationPending: false required property var walletAccountsModel // name, address, emoji, colorId + required property var walletAssetsModel + required property var walletCollectiblesModel + required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet required property var assetsModel required property var collectiblesModel @@ -351,11 +355,14 @@ StatusStackModal { SharedAddressesPanel { componentUid: d.shareAddressesUid isEditMode: root.isEditMode + + communityId: root.communityId communityName: root.communityName communityIcon: root.communityIcon requirementsCheckPending: root.requirementsCheckPending walletAccountsModel: d.initialAddressesModel + selectedSharedAddressesMap: d.selectedSharedAddressesMap currentSharedAddressesMap: d.currentSharedAddressesMap @@ -366,6 +373,8 @@ StatusStackModal { allAddressesToRevealBelongToSingleNonProfileKeypair: root.allAddressesToRevealBelongToSingleNonProfileKeypair walletAssetsModel: root.walletAssetsModel + walletCollectiblesModel: root.walletCollectiblesModel + permissionsModel: root.permissionsModel assetsModel: root.assetsModel collectiblesModel: root.collectiblesModel