From fae86bcb8dc19e224d98020e55e30b04667b68ca Mon Sep 17 00:00:00 2001 From: Cuteivist Date: Thu, 22 Feb 2024 15:41:19 +0100 Subject: [PATCH] feat(@wallet): Show community activity (#13627) --- .../main/wallet_section/activity/entry.nim | 8 +++++ src/backend/activity.nim | 24 ++++++++----- ui/app/AppLayouts/Wallet/WalletLayout.qml | 2 ++ .../Wallet/views/RightTabBaseView.qml | 1 + .../AppLayouts/Wallet/views/RightTabView.qml | 2 ++ .../Wallet/views/TransactionDetailView.qml | 2 ++ ui/app/mainui/AppMain.qml | 1 + .../shared/controls/TransactionDelegate.qml | 34 +++++++++++-------- ui/imports/shared/views/HistoryView.qml | 4 ++- 9 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/app/modules/main/wallet_section/activity/entry.nim b/src/app/modules/main/wallet_section/activity/entry.nim index 9a85a6308b..421290753e 100644 --- a/src/app/modules/main/wallet_section/activity/entry.nim +++ b/src/app/modules/main/wallet_section/activity/entry.nim @@ -273,3 +273,11 @@ QtObject: QtProperty[QVariant] amountCurrency: read = getAmountCurrency + + proc getCommunityId*(self: ActivityEntry): string {.slot.} = + if self.metadata.communityId.isSome(): + return self.metadata.communityId.unsafeGet() + return "" + + QtProperty[string] communityId: + read = getCommunityId \ No newline at end of file diff --git a/src/backend/activity.nim b/src/backend/activity.nim index 2819aab87e..fed22bdd82 100644 --- a/src/backend/activity.nim +++ b/src/backend/activity.nim @@ -285,6 +285,8 @@ type chainIdIn*: Option[ChainId] transferType*: Option[TransferType] + communityId*: Option[string] + # Mirrors status-go/services/wallet/activity/activity.go EntryData Data* = object payloadType*: PayloadType @@ -313,6 +315,8 @@ type nftName*: Option[string] nftUrl*: Option[string] + communityId*: Option[string] + # Mirrors services/wallet/activity/service.go ErrorCode ErrorCode* = enum ErrorCodeSuccess = 1, @@ -361,6 +365,7 @@ proc fromJson*(e: JsonNode, T: typedesc[Data]): Data {.inline.} = const transferTypeField = "transferType" const nftNameField = "nftName" const nftUrlField = "nftUrl" + const communityIdField = "communityId" result = T( payloadType: fromJson(e["payloadType"], PayloadType), transaction: if e.hasKey(transactionField): @@ -398,6 +403,7 @@ proc fromJson*(e: JsonNode, T: typedesc[Data]): Data {.inline.} = nftName: if e.contains(nftNameField): some(e[nftNameField].getStr()) else: none(string), nftUrl: if e.contains(nftUrlField): some(e[nftUrlField].getStr()) else: none(string), + communityId: if e.contains(communityIdField): some(e[communityIdField].getStr()) else: none(string), ) if e.hasKey(senderField) and e[senderField].kind != JNull: var address: eth.Address @@ -434,6 +440,7 @@ proc fromJson*(e: JsonNode, T: typedesc[ActivityEntry]): ActivityEntry {.inline. chainIdOut: data.chainIdOut, chainIdIn: data.chainIdIn, transferType: data.transferType, + communityId: data.communityId ) proc `$`*(self: ActivityEntry): string = @@ -449,14 +456,15 @@ proc `$`*(self: ActivityEntry): string = amountOut* {$self.amountOut}, amountIn* {$self.amountIn}, tokenOut* {$self.tokenOut}, - tokenIn* {$self.tokenIn} - symbolOut* {$self.symbolOut} - symbolIn* {$self.symbolIn} - sender* {$self.sender} - recipient* {$self.recipient} - chainIdOut* {$self.chainIdOut} - chainIdIn* {$self.chainIdIn} - transferType* {$self.transferType} + tokenIn* {$self.tokenIn}, + symbolOut* {$self.symbolOut}, + symbolIn* {$self.symbolIn}, + sender* {$self.sender}, + recipient* {$self.recipient}, + chainIdOut* {$self.chainIdOut}, + chainIdIn* {$self.chainIdIn}, + transferType* {$self.transferType}, + communityId* {$self.communityId} )""" proc fromJson*(e: JsonNode, T: typedesc[FilterResponse]): FilterResponse {.inline.} = diff --git a/ui/app/AppLayouts/Wallet/WalletLayout.qml b/ui/app/AppLayouts/Wallet/WalletLayout.qml index 16ba4a3cb8..4e3eb15ad2 100644 --- a/ui/app/AppLayouts/Wallet/WalletLayout.qml +++ b/ui/app/AppLayouts/Wallet/WalletLayout.qml @@ -21,6 +21,7 @@ Item { property bool hideSignPhraseModal: false property var store property var contactsStore + property var communitiesStore property var emojiPopup: null property var sendModalPopup property var networkConnectionStore @@ -186,6 +187,7 @@ Item { RightTabView { store: root.store contactsStore: root.contactsStore + communitiesStore: root.communitiesStore sendModal: root.sendModalPopup networkConnectionStore: root.networkConnectionStore diff --git a/ui/app/AppLayouts/Wallet/views/RightTabBaseView.qml b/ui/app/AppLayouts/Wallet/views/RightTabBaseView.qml index f3f3b5c8f8..98894876f5 100644 --- a/ui/app/AppLayouts/Wallet/views/RightTabBaseView.qml +++ b/ui/app/AppLayouts/Wallet/views/RightTabBaseView.qml @@ -11,6 +11,7 @@ FocusScope { property var store property var contactsStore + property var communitiesStore property var networkConnectionStore property var sendModal diff --git a/ui/app/AppLayouts/Wallet/views/RightTabView.qml b/ui/app/AppLayouts/Wallet/views/RightTabView.qml index 10a8296473..4b614d3a83 100644 --- a/ui/app/AppLayouts/Wallet/views/RightTabView.qml +++ b/ui/app/AppLayouts/Wallet/views/RightTabView.qml @@ -195,6 +195,7 @@ RightTabBaseView { id: historyView HistoryView { overview: RootStore.overview + communitiesStore: root.communitiesStore showAllAccounts: RootStore.showAllAccounts sendModal: root.sendModal filterVisible: filterButton.checked @@ -250,6 +251,7 @@ RightTabBaseView { } } showAllAccounts: RootStore.showAllAccounts + communitiesStore: root.communitiesStore sendModal: root.sendModal contactsStore: root.contactsStore networkConnectionStore: root.networkConnectionStore diff --git a/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml b/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml index d8459fbed1..108a191eb9 100644 --- a/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml +++ b/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml @@ -27,6 +27,7 @@ Item { property var overview: WalletStores.RootStore.overview property var contactsStore + property var communitiesStore property var networkConnectionStore property var transaction property int transactionIndex @@ -167,6 +168,7 @@ Item { timeStampText: root.isTransactionValid ? qsTr("Signed at %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)): "" rootStore: RootStore walletRootStore: WalletStores.RootStore + community: isModelDataValid && communityId && communitiesStore ? communitiesStore.getCommunityDetailsAsJson(communityId) : null onRetryClicked: d.retryTransaction() } diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index e9fe416c61..f43808d938 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -1269,6 +1269,7 @@ Item { objectName: "walletLayoutReal" store: appMain.rootStore contactsStore: appMain.rootStore.profileSectionStore.contactsStore + communitiesStore: appMain.communitiesStore emojiPopup: statusEmojiPopup.item sendModalPopup: sendModal networkConnectionStore: appMain.networkConnectionStore diff --git a/ui/imports/shared/controls/TransactionDelegate.qml b/ui/imports/shared/controls/TransactionDelegate.qml index d38c26448a..80829e1afe 100644 --- a/ui/imports/shared/controls/TransactionDelegate.qml +++ b/ui/imports/shared/controls/TransactionDelegate.qml @@ -61,7 +61,6 @@ StatusListItem { readonly property double outFiatValue: isModelDataValid && isMultiTransaction ? rootStore.getFiatValue(outCryptoValue, modelData.outSymbol): 0.0 readonly property double feeCryptoValue: 0.0 // TODO fill when bridge data is implemented readonly property double feeFiatValue: 0.0 // TODO fill when bridge data is implemented - readonly property string communityName: isModelDataValid && modelData.communityName ? modelData.communityName : "" readonly property string networkColor: isModelDataValid ? rootStore.getNetworkColor(modelData.chainId) : "" readonly property string networkName: isModelDataValid ? rootStore.getNetworkFullName(modelData.chainId) : "" readonly property string networkNameIn: isMultiTransaction ? rootStore.getNetworkFullName(modelData.chainIdIn) : "" @@ -69,7 +68,12 @@ StatusListItem { readonly property string addressNameTo: isModelDataValid ? walletRootStore.getNameForAddress(modelData.recipient) : "" readonly property string addressNameFrom: isModelDataValid ? walletRootStore.getNameForAddress(modelData.sender) : "" readonly property bool isNFT: isModelDataValid && modelData.isNFT - readonly property bool isCommunityAssetViaAirdrop: isModelDataValid && modelData.isCommunityAssetViaAirdrop ? modelData.isCommunityAssetViaAirdrop : false + readonly property bool isCommunityAssetViaAirdrop: isModelDataValid && !!communityId && modelData.txType === Constants.TransactionType.Mint + readonly property string communityId: isModelDataValid && modelData.communityId ? modelData.communityId : "" + property var community: null + readonly property bool isCommunityToken: !!community && Object.keys(community).length > 0 + readonly property string communityImage: isCommunityToken ? community.image : "" + readonly property string communityName: isCommunityToken ? community.name : "" readonly property string transactionValue: { if (!isModelDataValid) { @@ -109,14 +113,6 @@ StatusListItem { } } - readonly property string communityImage: { - if (!isModelDataValid || !root.isCommunityAssetViaAirdrop) - return "" - if (root.isCommunityAssetViaAirdrop) { - return modelData.communityImageUrl ? modelData.communityImageUrl : "" - } - } - readonly property string inTokenImage: isModelDataValid ? Constants.tokenIcon(modelData.inSymbol) : "" readonly property string toAddress: !!addressNameTo ? @@ -236,7 +232,7 @@ StatusListItem { case Constants.TransactionType.Bridge: case Constants.TransactionType.ContractDeployment: case Constants.TransactionType.Mint: - details += getSubtitle(true) + endl2 + details += getSubtitle(true, true) + endl2 break default: details += qsTr("%1 from %2 to %3 via %4").arg(transactionValue).arg(fromAddress).arg(toAddress).arg(networkName) + endl2 @@ -488,7 +484,17 @@ StatusListItem { return details.replace(/[\r\n\s]*$/, '') } - function getSubtitle(allAccounts) { + function getSubtitle(allAccounts, description) { + if (root.isCommunityAssetViaAirdrop) { + let communityInfo = "" + if (!description) { + // Showing image only in delegate. In description url shouldn't be showed + communityInfo += " " + } + communityInfo += root.communityName + return qsTr("%1 (community asset) from %2 via %3").arg(root.transactionValue).arg(communityInfo).arg(root.networkName) + } + switch(modelData.txType) { case Constants.TransactionType.Receive: if (allAccounts) @@ -670,9 +676,9 @@ StatusListItem { return "" } - return root.isCommunityAssetViaAirdrop ? qsTr("%1 (community asset) from %2 %3 via %4").arg(transactionValue).arg("").arg(communityName).arg(networkName) : getSubtitle(root.showAllAccounts) + return getSubtitle(root.showAllAccounts, false) } + statusListItemSubTitle.textFormat: root.isCommunityAssetViaAirdrop ? Text.RichText : Text.AutoText statusListItemSubTitle.maximumLoadingStateWidth: 400 statusListItemSubTitle.customColor: Theme.palette.directColor1 statusListItemSubTitle.font.pixelSize: root.loading ? d.loadingPixelSize : d.subtitlePixelSize diff --git a/ui/imports/shared/views/HistoryView.qml b/ui/imports/shared/views/HistoryView.qml index 7c7f8092e0..55589fe7af 100644 --- a/ui/imports/shared/views/HistoryView.qml +++ b/ui/imports/shared/views/HistoryView.qml @@ -28,6 +28,7 @@ ColumnLayout { id: root property var overview + property var communitiesStore property bool showAllAccounts: false property bool displayValues: true property var sendModal @@ -142,7 +143,7 @@ ColumnLayout { Loader { id: filterPanelLoader active: root.filterVisible && (d.isInitialLoading || transactionListRoot.count > 0 || WalletStores.RootStore.currentActivityFiltersStore.filtersSet) - visible: active + visible: active && !noTxs.visible asynchronous: true Layout.fillWidth: true sourceComponent: ActivityFilterPanel { @@ -490,6 +491,7 @@ ColumnLayout { walletRootStore: WalletStores.RootStore showAllAccounts: root.showAllAccounts displayValues: root.displayValues + community: isModelDataValid && !!communityId && !!root.communitiesStore ? root.communitiesStore.getCommunityDetailsAsJson(communityId) : null onClicked: { if (mouse.button === Qt.RightButton) { delegateMenu.openMenu(this, mouse, modelData)