From b36e2759afd59f3ee7109bf553122fed9b51970a Mon Sep 17 00:00:00 2001 From: Alex Jbanca Date: Wed, 17 Jul 2024 17:55:52 +0300 Subject: [PATCH] fix(Send): Fine tune the Send action on collectibles 1. Show Send Button on wallet footer when all accounts is selected 2. Hide Send Button in collectibles context menu and collectibles details view when the collectible is not owned by the user 3. Disable the Send Button in collectibles context menu and collectibles details view when the collectible is soulbound to squash: Fine tune send action on collectibles to squash: Fine tune send on collectibles to squash: Fine-tune collectibles --- storybook/pages/CollectiblesViewPage.qml | 1 + ui/app/AppLayouts/Wallet/WalletLayout.qml | 22 ++++++---- .../AppLayouts/Wallet/panels/WalletFooter.qml | 33 +++++++++++++-- .../Wallet/views/CollectiblesView.qml | 33 +++++++++++---- .../AppLayouts/Wallet/views/RightTabView.qml | 41 +++++++++++++++---- 5 files changed, 103 insertions(+), 27 deletions(-) diff --git a/storybook/pages/CollectiblesViewPage.qml b/storybook/pages/CollectiblesViewPage.qml index a868e8d32c..cddaf5d3a1 100644 --- a/storybook/pages/CollectiblesViewPage.qml +++ b/storybook/pages/CollectiblesViewPage.qml @@ -112,6 +112,7 @@ SplitView { qsTr("%1 community collectibles are now visible").arg(communityName), "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "") } + ownedAccountsModel: WalletAccountsModel {} networkFilters: d.networksChainsCurrentlySelected addressFilters: d.addressesSelected filterVisible: ctrlFilterVisible.checked diff --git a/ui/app/AppLayouts/Wallet/WalletLayout.qml b/ui/app/AppLayouts/Wallet/WalletLayout.qml index 70d0b9375d..d37b0d24c6 100644 --- a/ui/app/AppLayouts/Wallet/WalletLayout.qml +++ b/ui/app/AppLayouts/Wallet/WalletLayout.qml @@ -304,7 +304,7 @@ Item { const ownership = StatusQUtils.ModelUtils.get(tokenItem.ownership, 0) Global.openTransferOwnershipPopup(tokenItem.communityId, - tokenItem.communityName, + footer.communityName, tokenItem.communityImage, { "key": tokenItem.tokenId, @@ -316,14 +316,20 @@ Item { "tokenAddress": tokenItem.contractAddress }, root.sendModalPopup) - } else { - // Common send modal popup: - root.sendModalPopup.preSelectedSendType = Constants.SendType.Transfer - root.sendModalPopup.preSelectedHoldingID = walletStore.currentViewedHoldingID - root.sendModalPopup.preSelectedHoldingType = walletStore.currentViewedHoldingType - root.sendModalPopup.onlyAssets = false - root.sendModalPopup.open() + return } + + if (isHoldingSelected) { + const tokenItem = walletStore.currentViewedCollectible + const ownership = StatusQUtils.ModelUtils.get(tokenItem.ownership, 0) + root.sendModalPopup.preSelectedAccountAddress = ownership.accountAddress + } + // Common send modal popup: + root.sendModalPopup.preSelectedSendType = Constants.SendType.Transfer + root.sendModalPopup.preSelectedHoldingID = walletStore.currentViewedHoldingID + root.sendModalPopup.preSelectedHoldingType = walletStore.currentViewedHoldingType + root.sendModalPopup.onlyAssets = false + root.sendModalPopup.open() } onLaunchBridgeModal: { root.sendModalPopup.preSelectedSendType = Constants.SendType.Bridge diff --git a/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml b/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml index 348382f6b9..21607d69ad 100644 --- a/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml +++ b/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml @@ -2,9 +2,11 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 import QtQuick.Layouts 1.13 +import StatusQ 0.1 import StatusQ.Popups 0.1 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 +import StatusQ.Core.Utils 0.1 as SQUtils import utils 1.0 import shared.controls 1.0 @@ -37,6 +39,22 @@ Rectangle { (walletStore.currentViewedHoldingType === Constants.TokenType.ERC721 || walletStore.currentViewedHoldingType === Constants.TokenType.ERC1155) readonly property bool isCollectibleSoulbound: isCollectibleViewed && !!walletStore.currentViewedCollectible && walletStore.currentViewedCollectible.soulbound + + readonly property bool isCollectibleOwned: d.owningAccount.available + + readonly property bool hideCollectibleTransferActions: isCollectibleViewed && !isCollectibleOwned + + property string collectibleOwnerAddress + Binding on collectibleOwnerAddress { + when: d.isCollectibleViewed && !!root.walletStore.currentViewedCollectible && !!root.walletStore.currentViewedCollectible.ownership.ModelCount.count + value: SQUtils.ModelUtils.get(root.walletStore.currentViewedCollectible.ownership, 0).accountAddress + } + + readonly property ModelEntry owningAccount: ModelEntry { + sourceModel: d.isCollectibleViewed ? root.walletStore.nonWatchAccounts : null + key: "address" + value: d.collectibleOwnerAddress ?? "" + } } StatusModalDivider { @@ -55,11 +73,14 @@ Rectangle { text: root.isCommunityOwnershipTransfer ? qsTr("Send Owner token to transfer %1 Community ownership").arg(root.communityName) : qsTr("Send") interactive: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled onClicked: { - root.transactionStore.setSenderAccount(root.walletStore.selectedAddress) + if (!!root.walletStore.selectedAddress) + root.transactionStore.setSenderAccount(root.walletStore.selectedAddress) root.launchSendModal() } tooltip.text: d.isCollectibleSoulbound ? qsTr("Soulbound collectibles cannot be sent to another wallet") : networkConnectionStore.sendBuyBridgeToolTipText - visible: !walletStore.overview.isWatchOnlyAccount && walletStore.overview.canSend && !root.walletStore.showAllAccounts + visible: !walletStore.overview.isWatchOnlyAccount + && walletStore.overview.canSend + && !d.hideCollectibleTransferActions } StatusFlatButton { @@ -78,7 +99,11 @@ Rectangle { interactive: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled onClicked: root.launchBridgeModal() tooltip.text: d.isCollectibleSoulbound ? qsTr("Soulbound collectibles cannot be bridged to another wallet") : networkConnectionStore.sendBuyBridgeToolTipText - visible: !walletStore.overview.isWatchOnlyAccount && !root.isCommunityOwnershipTransfer && walletStore.overview.canSend && !root.walletStore.showAllAccounts + visible: !walletStore.overview.isWatchOnlyAccount + && !root.isCommunityOwnershipTransfer + && walletStore.overview.canSend + && !root.walletStore.showAllAccounts + && !d.hideCollectibleTransferActions } StatusFlatButton { @@ -94,7 +119,7 @@ Rectangle { id: swap interactive: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled - visible: Global.featureFlags.swapEnabled && !walletStore.overview.isWatchOnlyAccount + visible: Global.featureFlags.swapEnabled && !walletStore.overview.isWatchOnlyAccount && !d.hideCollectibleTransferActions tooltip.text: d.isCollectibleSoulbound ? qsTr("Soulbound collectibles cannot be swapped") : networkConnectionStore.sendBuyBridgeToolTipText icon.name: "swap" text: qsTr("Swap") diff --git a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml index 9affd78ec8..54f492b262 100644 --- a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml +++ b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml @@ -28,6 +28,7 @@ import SortFilterProxyModel 0.2 ColumnLayout { id: root + required property var ownedAccountsModel required property var controller required property string addressFilters required property string networkFilters @@ -466,10 +467,17 @@ ColumnLayout { onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.symbol, model.tokenType) onRightClicked: { + let ownedByUser = false + const ownedByAccount = ModelUtils.get(model.ownership, 0) + if (!!ownedByAccount && !!ownedByAccount.accountAddress) { + ownedByUser = ModelUtils.contains(root.ownedAccountsModel, "address", ownedByAccount.accountAddress, Qt.CaseInsensitive) + } + Global.openMenu(tokenContextMenu, this, {symbol: model.symbol, tokenName: model.name, tokenImage: model.imageUrl, communityId: model.communityId, communityName: model.communityName, - communityImage: model.communityImage, tokenType: model.tokenType}) + communityImage: model.communityImage, tokenType: model.tokenType, + soulbound: model.soulbound, ownedByUser: ownedByUser}) } onSwitchToCommunityRequested: (communityId) => root.switchToCommunityRequested(communityId) } @@ -478,6 +486,7 @@ ColumnLayout { Component { id: tokenContextMenu StatusMenu { + id: tokenMenu onClosed: destroy() property string symbol @@ -487,14 +496,24 @@ ColumnLayout { property string communityName property string communityImage property int tokenType + property bool ownedByUser + property bool soulbound - StatusAction { - enabled: root.sendEnabled - visibleOnDisabled: true - icon.name: "send" - text: qsTr("Send") - onTriggered: root.sendRequested(symbol, tokenType) + // Show send button for owned collectibles + // Disable send button for owned soulbound collectibles + Instantiator { + model: tokenMenu.ownedByUser ? 1 : 0 + delegate: StatusAction { + enabled: root.sendEnabled && !tokenMenu.soulbound + visibleOnDisabled: true + icon.name: "send" + text: qsTr("Send") + onTriggered: root.sendRequested(symbol, tokenType) + } + onObjectAdded: tokenMenu.insertAction(0, object) + onObjectRemoved: tokenMenu.removeAction(0) } + StatusAction { icon.name: "receive" text: qsTr("Receive") diff --git a/ui/app/AppLayouts/Wallet/views/RightTabView.qml b/ui/app/AppLayouts/Wallet/views/RightTabView.qml index a374680656..ad7fcc401a 100644 --- a/ui/app/AppLayouts/Wallet/views/RightTabView.qml +++ b/ui/app/AppLayouts/Wallet/views/RightTabView.qml @@ -248,6 +248,7 @@ RightTabBaseView { Component { id: collectiblesView CollectiblesView { + ownedAccountsModel: RootStore.nonWatchAccounts controller: RootStore.collectiblesStore.collectiblesController networkFilters: RootStore.networkFilters addressFilters: RootStore.addressFilters @@ -265,14 +266,38 @@ RightTabBaseView { stack.currentIndex = 1 } onSendRequested: (symbol, tokenType) => { - root.sendModal.preSelectedHoldingID = symbol - root.sendModal.preSelectedHoldingType = tokenType - root.sendModal.preSelectedSendType = tokenType === Constants.TokenType.ERC721 ? - Constants.SendType.ERC721Transfer: - Constants.SendType.ERC1155Transfer - root.sendModal.onlyAssets = false - root.sendModal.open() - } + const collectible = ModelUtils.getByKey(controller.sourceModel, "symbol", symbol) + if (collectible.communityPrivilegesLevel === Constants.TokenPrivilegesLevel.Owner) { + const ownerAccountItem = ModelUtils.get(collectible.ownership, 0) + Global.openTransferOwnershipPopup(collectible.communityId, + collectible.communityName, + collectible.communityImage, + { + "key": collectible.tokenId, + "privilegesLevel": collectible.communityPrivilegesLevel, + "chainId": collectible.chainId, + "name": collectible.name, + "artworkSource": collectible.communityImage, + "accountAddress": ownerAccountItem.accountAddress, + "tokenAddress": collectible.contractAddress + }, + root.sendModal) + return + + } + + if (!!collectible) { + const ownerAccountItem = ModelUtils.get(collectible.ownership, 0) + root.sendModal.preSelectedAccountAddress = ownerAccountItem.accountAddress + } + root.sendModal.preSelectedHoldingID = symbol + root.sendModal.preSelectedHoldingType = tokenType + root.sendModal.preSelectedSendType = tokenType === Constants.TokenType.ERC721 ? + Constants.SendType.ERC721Transfer: + Constants.SendType.ERC1155Transfer + root.sendModal.onlyAssets = false + root.sendModal.open() + } onReceiveRequested: (symbol) => root.launchShareAddressModal() onSwitchToCommunityRequested: (communityId) => Global.switchToCommunity(communityId) onManageTokensRequested: Global.changeAppSectionBySectionType(Constants.appSection.profile, Constants.settingsSubsection.wallet,