diff --git a/src/app/modules/shared_models/link_preview_model.nim b/src/app/modules/shared_models/link_preview_model.nim index 9a22c1f5ca..ef5261ced0 100644 --- a/src/app/modules/shared_models/link_preview_model.nim +++ b/src/app/modules/shared_models/link_preview_model.nim @@ -35,6 +35,8 @@ type StatusCommunityChannelCommunityPreview StatusCommunityChannelCommunityPreviewIcon StatusCommunityChannelCommunityPreviewBanner + # Status transaction + StatusTransactionPreview QtObject: type @@ -105,6 +107,8 @@ QtObject: ModelRole.StatusCommunityChannelCommunityPreview.int:"statusCommunityChannelCommunityPreview", ModelRole.StatusCommunityChannelCommunityPreviewIcon.int:"statusCommunityChannelCommunityPreviewIcon", ModelRole.StatusCommunityChannelCommunityPreviewBanner.int:"statusCommunityChannelCommunityPreviewBanner", + # Transaction + ModelRole.StatusTransactionPreview.int:"statusTransactionPreview", }.toTable method data(self: Model, index: QModelIndex, role: int): QVariant = @@ -165,6 +169,9 @@ QtObject: of ModelRole.StatusCommunityChannelCommunityPreviewBanner: if (let community = item.linkPreview.getChannelCommunity(); community) != nil: result = newQVariant(community.getBanner()) + of ModelRole.StatusTransactionPreview: + if item.linkPreview.statusTransactionPreview != nil: + result = newQVariant(item.linkPreview.statusTransactionPreview) else: result = newQVariant() diff --git a/src/app_service/service/message/dto/link_preview.nim b/src/app_service/service/message/dto/link_preview.nim index 651b6008f4..0c9fd933b0 100644 --- a/src/app_service/service/message/dto/link_preview.nim +++ b/src/app_service/service/message/dto/link_preview.nim @@ -1,6 +1,6 @@ import json, stew/shims/strformat, tables import ./status_link_preview, ./standard_link_preview -import ./status_contact_link_preview, ./status_community_link_preview, ./status_community_channel_link_preview +import ./status_contact_link_preview, ./status_community_link_preview, ./status_community_channel_link_preview, ./status_transaction_link_preview import ../../contacts/dto/contact_details import ../../community/dto/community include ../../../common/json_utils @@ -13,6 +13,7 @@ type StatusContactPreview StatusCommunityPreview StatusCommunityChannelPreview + StatusTransactionPreview LinkPreview* = ref object url*: string @@ -21,6 +22,7 @@ type statusContactPreview*: StatusContactLinkPreview statusCommunityPreview*: StatusCommunityLinkPreview statusCommunityChannelPreview*: StatusCommunityChannelLinkPreview + statusTransactionPreview*: StatusTransactionLinkPreview proc delete*(self: LinkPreview) = if self.standardPreview != nil: @@ -31,6 +33,8 @@ proc delete*(self: LinkPreview) = self.statusCommunityPreview.delete if self.statusCommunityChannelPreview != nil: self.statusCommunityChannelPreview.delete + if self.statusTransactionPreview != nil: + self.statusTransactionPreview.delete proc initLinkPreview*(url: string): LinkPreview = result = LinkPreview() @@ -57,19 +61,24 @@ proc toLinkPreview*(jsonObj: JsonNode, standard: bool): LinkPreview = elif jsonObj.getProp("channel", node): result.previewType = PreviewType.StatusCommunityChannelPreview result.statusCommunityChannelPreview = toStatusCommunityChannelLinkPreview(node) + elif jsonObj.getProp("transaction", node): + result.previewType = PreviewType.StatusTransactionPreview + result.statusTransactionPreview = toStatusTransactionLinkPreview(node) proc `$`*(self: LinkPreview): string = let standardPreview = if self.standardPreview != nil: $self.standardPreview else: "" let contactPreview = if self.statusContactPreview != nil: $self.statusContactPreview else: "" let communityPreview = if self.statusCommunityPreview != nil: $self.statusCommunityPreview else: "" let channelPreview = if self.statusCommunityChannelPreview != nil: $self.statusCommunityChannelPreview else: "" + let transactionPreview = if self.statusTransactionPreview != nil: $self.statusTransactionPreview else: "" result = fmt"""LinkPreview( url: {self.url}, previewType: {self.previewType}, standardPreview: {standardPreview}, contactPreview: {contactPreview}, communityPreview: {communityPreview}, - channelPreview: {channelPreview} + channelPreview: {channelPreview}, + transactionPreview: {transactionPreview} )""" proc `%`*(self: LinkPreview): JsonNode = @@ -78,7 +87,8 @@ proc `%`*(self: LinkPreview): JsonNode = "standardPreview": if self.standardPreview != nil: %self.standardPreview else: newJNull(), "contactPreview": if self.statusContactPreview != nil: %self.statusContactPreview else: newJNull(), "communityPreview": if self.statusCommunityPreview != nil: %self.statusCommunityPreview else: newJNull(), - "channelPreview": if self.statusCommunityChannelPreview != nil: %self.statusCommunityChannelPreview else: newJNull() + "channelPreview": if self.statusCommunityChannelPreview != nil: %self.statusCommunityChannelPreview else: newJNull(), + "transactionPreview": if self.statusTransactionPreview != nil: %self.statusTransactionPreview else: newJNull() } proc empty*(self: LinkPreview): bool = @@ -91,6 +101,8 @@ proc empty*(self: LinkPreview): bool = return self.statusCommunityPreview == nil or self.statusCommunityPreview.empty() of PreviewType.StatusCommunityChannelPreview: return self.statusCommunityChannelPreview == nil or self.statusCommunityChannelPreview.empty() + of PreviewType.StatusTransactionPreview: + return self.statusTransactionPreview == nil or self.statusTransactionPreview.empty() else: return true @@ -119,6 +131,11 @@ proc extractLinkPreviewsLists*(input: seq[LinkPreview]): (seq[StandardLinkPrevie statusLinkPreview.url = preview.url statusLinkPreview.channel = preview.statusCommunityChannelPreview status.add(statusLinkPreview) + of PreviewType.StatusTransactionPreview: + let statusLinkPreview = StatusLinkPreview() + statusLinkPreview.url = preview.url + statusLinkPreview.transaction = preview.statusTransactionPreview + status.add(statusLinkPreview) else: discard diff --git a/src/app_service/service/message/dto/status_link_preview.nim b/src/app_service/service/message/dto/status_link_preview.nim index cabe24a8d3..e0e815a88e 100644 --- a/src/app_service/service/message/dto/status_link_preview.nim +++ b/src/app_service/service/message/dto/status_link_preview.nim @@ -2,6 +2,7 @@ import json, chronicles import status_contact_link_preview import status_community_link_preview import status_community_channel_link_preview +import status_transaction_link_preview include ../../../common/json_utils @@ -10,6 +11,7 @@ type StatusLinkPreview* = ref object contact*: StatusContactLinkPreview community*: StatusCommunityLinkPreview channel*: StatusCommunityChannelLinkPreview + transaction*: StatusTransactionLinkPreview proc toStatusLinkPreview*(jsonObj: JsonNode): StatusLinkPreview = result = StatusLinkPreview() @@ -27,6 +29,10 @@ proc toStatusLinkPreview*(jsonObj: JsonNode): StatusLinkPreview = if jsonObj.getProp("channel", channel): result.channel = toStatusCommunityChannelLinkPreview(contact) + var transaction: JsonNode + if jsonObj.getProp("transaction", transaction): + result.transaction = toStatusTransactionLinkPreview(transaction) + proc `%`*(self: StatusLinkPreview): JsonNode = var obj = %*{ "url": self.url @@ -37,4 +43,6 @@ proc `%`*(self: StatusLinkPreview): JsonNode = obj["community"] = %*self.community if self.channel != nil: obj["channel"] = %*self.channel + if self.transaction != nil: + obj["transaction"] = %*self.transaction return obj diff --git a/src/app_service/service/message/dto/status_transaction_link_preview.nim b/src/app_service/service/message/dto/status_transaction_link_preview.nim new file mode 100644 index 0000000000..fea8a32281 --- /dev/null +++ b/src/app_service/service/message/dto/status_transaction_link_preview.nim @@ -0,0 +1,110 @@ +import json, stew/shims/strformat, NimQml, chronicles + +include ../../../common/json_utils + +QtObject: + type StatusTransactionLinkPreview* = ref object of QObject + txType: int + amount: string + asset: string + toAsset: string + address: string + chainId: int + + proc setup*(self: StatusTransactionLinkPreview) = + self.QObject.setup() + + proc delete*(self: StatusTransactionLinkPreview) = + self.QObject.delete() + + proc newStatusTransactionLinkPreview*(txType: int, amount: string, asset: string, toAsset: string, address: string, chainId: int): StatusTransactionLinkPreview = + new(result, delete) + result.setup() + result.txType = txType + result.amount = amount + result.asset = asset + result.toAsset = toAsset + result.address = address + result.chainId = chainId + + proc txTypeChanged*(self: StatusTransactionLinkPreview) {.signal.} + proc getTxType*(self: StatusTransactionLinkPreview): int {.slot.} = + result = self.txType + QtProperty[int] txType: + read = getTxType + notify = txTypeChanged + + proc amountChanged*(self: StatusTransactionLinkPreview) {.signal.} + proc getAmount*(self: StatusTransactionLinkPreview): string {.slot.} = + result = self.amount + QtProperty[string] amount: + read = getAmount + notify = amountChanged + + proc assetChanged*(self: StatusTransactionLinkPreview) {.signal.} + proc getAsset*(self: StatusTransactionLinkPreview): string {.slot.} = + result = self.asset + QtProperty[string] asset: + read = getAsset + notify = assetChanged + + proc toAssetChanged*(self: StatusTransactionLinkPreview) {.signal.} + proc getToAsset*(self: StatusTransactionLinkPreview): string {.slot.} = + result = self.toAsset + QtProperty[string] toAsset: + read = getToAsset + notify = toAssetChanged + + proc addressChanged*(self: StatusTransactionLinkPreview) {.signal.} + proc getAddress*(self: StatusTransactionLinkPreview): string {.slot.} = + result = self.address + QtProperty[string] address: + read = getAddress + notify = addressChanged + + proc chainIdChanged*(self: StatusTransactionLinkPreview) {.signal.} + proc getChainId*(self: StatusTransactionLinkPreview): int {.slot.} = + result = self.chainId + QtProperty[int] chainId: + read = getChainId + notify = chainIdChanged + + proc toStatusTransactionLinkPreview*(jsonObj: JsonNode): StatusTransactionLinkPreview = + var txType: int + var amount: string + var asset: string + var toAsset: string + var address: string + var chainId: int + + discard jsonObj.getProp("txType", txType) + discard jsonObj.getProp("amount", amount) + discard jsonObj.getProp("asset", asset) + discard jsonObj.getProp("toAsset", toAsset) + discard jsonObj.getProp("address", address) + discard jsonObj.getProp("chainId", chainId) + + result = newStatusTransactionLinkPreview(txType, amount, asset, toAsset, address, chainId) + + proc `$`*(self: StatusTransactionLinkPreview): string = + result = fmt"""StatusTransactionLinkPreview( + txType: {self.txType}, + amount: {self.amount}, + asset: {self.asset}, + toAsset: {self.toAsset}, + address: {self.address}, + chainId: {self.chainId} + )""" + + proc `%`*(self: StatusTransactionLinkPreview): JsonNode = + return %* { + "txType": self.txType, + "amount": self.amount, + "asset": self.asset, + "toAsset": self.toAsset, + "address": self.address, + "chainId": self.chainId + } + + proc empty*(self: StatusTransactionLinkPreview): bool = + return self.amount.len == 0 and self.asset.len == 0 and self.toAsset.len == 0 and self.address.len == 0 \ No newline at end of file diff --git a/ui/imports/shared/controls/chat/LinkPreviewCard.qml b/ui/imports/shared/controls/chat/LinkPreviewCard.qml index 840baf772e..b58c7f1fcd 100644 --- a/ui/imports/shared/controls/chat/LinkPreviewCard.qml +++ b/ui/imports/shared/controls/chat/LinkPreviewCard.qml @@ -17,6 +17,7 @@ CalloutCard { readonly property LinkData linkData: LinkData { } readonly property UserData userData: UserData { } + readonly property TransactionData transactionData: TransactionData { } readonly property CommunityData communityData: CommunityData { } readonly property ChannelData channelData: ChannelData { } @@ -284,7 +285,57 @@ CalloutCard { PropertyChanges { target: footerLoader; active: false; visible: !root.userData.bio; Layout.fillHeight: true } PropertyChanges { target: title; text: root.userData.name } PropertyChanges { target: description; text: root.userData.bio; Layout.minimumHeight: 32; visible: true } + }, + State { + name: "transaction" + when: root.type === Constants.LinkPreviewType.StatusTransaction + PropertyChanges { target: root; implicitHeight: 187 } + PropertyChanges { target: bannerImageLoader; visible: false } + PropertyChanges { target: footerLoader; active: false; visible: false } + PropertyChanges { + target: title; + text: { + switch(root.transactionData.txType) { + case Constants.SendType.Bridge: + return qsTr("Bridge transaction") + case Constants.SendType.Swap: + return qsTr("Swap transaction") + default: + return qsTr("Send transaction") + } + } + } + PropertyChanges { + target: description; + text: { + let description = "" + switch(root.transactionData.txType) { + case Constants.SendType.Bridge: + description += qsTr("Bridge") + " " + break + case Constants.SendType.Swap: + description += qsTr("Swap") + " " + break + default: + description += qsTr("Send") + " " + break + } + if (root.transactionData.amount) { + description += root.transactionData.amount + " " + } + if (root.transactionData.asset) { + description += root.transactionData.asset + " " + } + if (root.transactionData.address) { + description += qsTr("to %1").arg(root.transactionData.address) + " " + } + if (root.transactionData.chainId) { + description += qsTr("on %1").arg(root.transactionData.chainId) // TODO use network name + } + } + } } + ] QtObject { diff --git a/ui/imports/shared/controls/chat/LinkPreviewMiniCard.qml b/ui/imports/shared/controls/chat/LinkPreviewMiniCard.qml index cdb0b05464..962101e9d8 100644 --- a/ui/imports/shared/controls/chat/LinkPreviewMiniCard.qml +++ b/ui/imports/shared/controls/chat/LinkPreviewMiniCard.qml @@ -25,6 +25,7 @@ CalloutCard { readonly property UserData userData: UserData { } readonly property CommunityData communityData: CommunityData { } readonly property ChannelData channelData: ChannelData { } + readonly property TransactionData transactionData: TransactionData { } required property int previewState required property int type @@ -147,7 +148,28 @@ CalloutCard { asset.charactersLen: 2 asset.color: Theme.palette.miscColor9 } + }, + State { + name: "loadedTransaction" + when: root.previewState === LinkPreviewMiniCard.State.Loaded && root.type === Constants.LinkPreviewType.StatusTransaction + extend: "loaded" + PropertyChanges { target: titleText; text: qsTr("Transaction") } + PropertyChanges { + target: subtitleText; visible: true; + text: { + switch(root.transactionData.txType) { + case Constants.SendType.Bridge: + return qsTr("Bridge") + case Constants.SendType.Swap: + return qsTr("Swap") + default: + return qsTr("Send") + } + } + } + PropertyChanges { target: favIcon; visible: false } } + ] contentItem: Item { diff --git a/ui/imports/shared/controls/chat/private/TransactionData.qml b/ui/imports/shared/controls/chat/private/TransactionData.qml new file mode 100644 index 0000000000..8ac0e88428 --- /dev/null +++ b/ui/imports/shared/controls/chat/private/TransactionData.qml @@ -0,0 +1,10 @@ +import QtQuick 2.15 + +QtObject { + property int txType + property string asset + property string toAsset + property string amount + property string address + property int chainId +} diff --git a/ui/imports/shared/controls/delegates/LinkPreviewCardDelegate.qml b/ui/imports/shared/controls/delegates/LinkPreviewCardDelegate.qml index 07f578fc24..3b04e6db36 100644 --- a/ui/imports/shared/controls/delegates/LinkPreviewCardDelegate.qml +++ b/ui/imports/shared/controls/delegates/LinkPreviewCardDelegate.qml @@ -48,6 +48,7 @@ LinkPreviewCard { required property var statusCommunityChannelCommunityPreview required property var statusCommunityChannelCommunityPreviewIcon required property var statusCommunityChannelCommunityPreviewBanner + required property var statusTransactionPreview //View properties type: root.previewType @@ -91,4 +92,12 @@ LinkPreviewCard { color: statusCommunityChannelCommunityPreview ? statusCommunityChannelCommunityPreview.color : "" } } + transactionData { + txType: statusTransactionPreview ? statusTransactionPreview.txType : "" + asset: statusTransactionPreview ? statusTransactionPreview.asset : "" + toAsset: statusTransactionPreview ? statusTransactionPreview.toAsset : "" + amount: statusTransactionPreview ? statusTransactionPreview.amount : "" + chainId: statusTransactionPreview ? statusTransactionPreview.chainId : "" + address: statusTransactionPreview ? statusTransactionPreview.address : "" + } } diff --git a/ui/imports/shared/controls/delegates/LinkPreviewMiniCardDelegate.qml b/ui/imports/shared/controls/delegates/LinkPreviewMiniCardDelegate.qml index 4520508736..1d4d13bf92 100644 --- a/ui/imports/shared/controls/delegates/LinkPreviewMiniCardDelegate.qml +++ b/ui/imports/shared/controls/delegates/LinkPreviewMiniCardDelegate.qml @@ -42,6 +42,7 @@ LinkPreviewMiniCard { required property var statusCommunityChannelCommunityPreview required property var statusCommunityChannelCommunityPreviewIcon required property var statusCommunityChannelCommunityPreviewBanner + required property var statusTransactionPreview previewState: !root.unfurled ? LinkPreviewMiniCard.State.Loading : root.unfurled && !root.empty ? LinkPreviewMiniCard.State.Loaded : LinkPreviewMiniCard.State.LoadingFailed type: root.previewType @@ -83,4 +84,12 @@ LinkPreviewMiniCard { color: statusCommunityChannelCommunityPreview ? statusCommunityChannelCommunityPreview.color : "" } } + transactionData { + txType: statusTransactionPreview ? statusTransactionPreview.txType : "" + asset: statusTransactionPreview ? statusTransactionPreview.asset : "" + toAsset: statusTransactionPreview ? statusTransactionPreview.toAsset : "" + amount: statusTransactionPreview ? statusTransactionPreview.amount : "" + chainId: statusTransactionPreview ? statusTransactionPreview.chainId : "" + address: statusTransactionPreview ? statusTransactionPreview.address : "" + } } diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index ce106b0c64..888a3f6def 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -1410,7 +1410,8 @@ QtObject { Standard = 1, StatusContact = 2, StatusCommunity = 3, - StatusCommunityChannel = 4 + StatusCommunityChannel = 4, + StatusTransaction = 5 } enum StandardLinkPreviewType {