diff --git a/storybook/pages/FirstTokenReceivedPopupPage.qml b/storybook/pages/FirstTokenReceivedPopupPage.qml
new file mode 100644
index 0000000000..2914f4af8b
--- /dev/null
+++ b/storybook/pages/FirstTokenReceivedPopupPage.qml
@@ -0,0 +1,258 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+
+import Storybook 1.0
+import Models 1.0
+
+import AppLayouts.Communities.popups 1.0
+import AppLayouts.Communities.helpers 1.0
+
+import utils 1.0
+
+SplitView {
+ Logs { id: logs }
+
+ SplitView {
+ orientation: Qt.Vertical
+ SplitView.fillWidth: true
+
+ Item {
+ SplitView.fillWidth: true
+ SplitView.fillHeight: true
+
+ PopupBackground {
+ anchors.fill: parent
+ }
+
+ Button {
+ anchors.centerIn: parent
+ text: "Reopen"
+
+ onClicked: dialog.open()
+ }
+
+ FirstTokenReceivedPopup {
+ id: dialog
+
+ anchors.centerIn: parent
+ closePolicy: Popup.NoAutoClose
+ visible: true
+ modal: false
+
+ communityId: "123"
+ communityName: communityNameText.text
+ communityLogo: ModelsData.collectibles.doodles
+ communitiesStore: QtObject {
+ function navigateToCommunity(id) {
+ logs.logEvent("FirstTokenReceivedPopup::onNavigateToCommunity: " + id)
+ }
+ }
+
+ tokenSymbol: tokenSymbolText.text
+ tokenName: tokenNameText.text
+ tokenAmount: tokenAmountText.text
+ tokenType: Constants.TokenType.ERC20
+ tokenImage: ModelsData.assets.eth
+
+ onHideClicked: logs.logEvent("FirstTokenReceivedPopup::onHideClicked")
+ }
+ }
+
+ LogsAndControlsPanel {
+ id: logsAndControlsPanel
+
+ SplitView.minimumHeight: 100
+ SplitView.preferredHeight: 150
+
+ logsView.logText: logs.logText
+ }
+ }
+
+ Pane {
+ SplitView.minimumWidth: 300
+ SplitView.preferredWidth: 300
+
+ Column {
+ spacing: 12
+
+ Label {
+ text: "Community Name"
+ font.bold: true
+ }
+
+ TextInput {
+ id: communityNameText
+
+ text: "Doodles"
+
+ }
+
+ Label {
+ text: "Community Logo"
+ font.bold: true
+ }
+
+ Column {
+
+ RadioButton {
+ id: doodleLogo
+
+ text: "Doodle"
+ checked: true
+
+ onCheckedChanged: dialog.communityLogo = ModelsData.collectibles.doodles
+ }
+
+ RadioButton {
+ id: manaLogo
+
+ text: "Mana"
+
+ onCheckedChanged: dialog.communityLogo = ModelsData.collectibles.mana
+ }
+
+ RadioButton {
+ id: superRareLogo
+
+ text: "Status"
+
+ onCheckedChanged: dialog.communityLogo = ModelsData.collectibles.custom
+ }
+ }
+
+ Label {
+ text: "Token amount"
+ font.bold: true
+ }
+
+ TextInput {
+ id: tokenAmountText
+
+ text: "1"
+ }
+
+ Label {
+ text: "Token name"
+ font.bold: true
+ }
+
+ TextInput {
+ id: tokenNameText
+
+ text: "DoodleCoin"
+ }
+
+ Label {
+ text: "Token symbol"
+ font.bold: true
+ }
+
+ TextInput {
+ id: tokenSymbolText
+
+ text: "DOO"
+ }
+
+ Label {
+ text: "Token Type"
+ font.bold: true
+ }
+
+ Column {
+
+ RadioButton {
+ id: assetType
+
+ text: "Asset"
+ checked: true
+
+ onCheckedChanged: dialog.tokenType = Constants.TokenType.ERC20
+ }
+
+ RadioButton {
+ id: collectibleType
+
+ text: "Collectible"
+
+ onCheckedChanged: dialog.tokenType = Constants.TokenType.ERC721
+ }
+ }
+
+ Label {
+ text: "Token Image"
+ font.bold: true
+ }
+
+ Column {
+
+ visible: assetType.checked
+
+ onVisibleChanged: {
+
+ if(visible) {
+ eth.checked = true
+ dialog.tokenImage = ModelsData.assets.eth
+ }
+ }
+ RadioButton {
+ id: eth
+
+ text: "Eth"
+ checked: true
+
+ onCheckedChanged: dialog.tokenImage = ModelsData.assets.eth
+ }
+
+ RadioButton {
+ text: "SuperRare"
+
+ onCheckedChanged: dialog.tokenImage = ModelsData.banners.superRare
+ }
+
+ RadioButton {
+ text: "SNT"
+
+ onCheckedChanged: dialog.tokenImage = ModelsData.assets.snt
+ }
+ }
+
+ Column {
+
+ visible: collectibleType.checked
+
+ onVisibleChanged: {
+ if(visible) {
+ superrare.checked = true
+ dialog.tokenImage = ModelsData.banners.superRare
+ }
+ }
+ RadioButton {
+ id: superrare
+
+ text: "SuperRare"
+ checked: true
+
+ onCheckedChanged: dialog.tokenImage = ModelsData.banners.superRare
+ }
+
+ RadioButton {
+ text: "Coinbase"
+
+ onCheckedChanged: dialog.tokenImage = ModelsData.banners.coinbase
+ }
+
+ RadioButton {
+ text: "Dragonereum"
+
+ onCheckedChanged: dialog.tokenImage = ModelsData.banners.dragonereum
+ }
+ }
+ }
+ }
+}
+
+// category: Popups
+
+// https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?type=design&node-id=18700%3A276658&mode=design&t=QzoyErtcBX8A54G7-1
+// https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?type=design&node-id=20765%3A244128&mode=design&t=X279c9Ix6QKMKWjM-1
diff --git a/ui/app/AppLayouts/Communities/popups/FirstTokenReceivedPopup.qml b/ui/app/AppLayouts/Communities/popups/FirstTokenReceivedPopup.qml
new file mode 100644
index 0000000000..8c2715ab0e
--- /dev/null
+++ b/ui/app/AppLayouts/Communities/popups/FirstTokenReceivedPopup.qml
@@ -0,0 +1,146 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQml.Models 2.15
+import QtQuick.Layouts 1.15
+
+import StatusQ.Core 0.1
+import StatusQ.Controls 0.1
+import StatusQ.Popups.Dialog 0.1
+import StatusQ.Components 0.1
+import StatusQ.Core.Theme 0.1
+import StatusQ.Core.Utils 0.1
+
+import AppLayouts.Communities.panels 1.0
+
+import utils 1.0
+
+StatusDialog {
+ id: root
+
+ // Community related props:
+ required property var communitiesStore
+ required property string communityId
+ required property string communityName
+ required property string communityLogo
+
+ // Token related props:
+ required property string tokenName
+ required property string tokenSymbol
+ required property string tokenImage
+ required property string tokenAmount
+ required property int tokenType // ERC20 or ERC721
+ readonly property bool isAssetType : tokenType === Constants.TokenType.ERC20
+
+ signal hideClicked
+
+ QtObject {
+ id: d
+
+ readonly property string contentText: root.isAssetType ? qsTr("Congratulations on receiving your first community asset:
%1 %2 (%3) minted by %4. Community assets are assets that have been minted by a community. As these assets cannot be verified, always double check their origin and validity before interacting with them. If in doubt, ask a trusted member or admin of the relevant community.").arg(root.tokenAmount).arg(root.tokenName).arg(root.tokenSymbol).arg(root.communityName)
+ : qsTr("Congratulations on receiving your first community collectible:
%1 %2 minted by %3. Community collectibles are collectibles that have been minted by a community. As these collectibles cannot be verified, always double check their origin and validity before interacting with them. If in doubt, ask a trusted member or admin of the relevant community.").arg(root.tokenAmount).arg(root.tokenName).arg(root.communityName)
+
+ }
+
+ width: 521 // by design
+ padding: 0
+
+ contentItem: StatusScrollView {
+ id: scrollView
+
+ contentWidth: availableWidth
+ padding: Style.current.padding
+
+ ColumnLayout {
+ spacing: Style.current.padding
+ width: scrollView.availableWidth
+
+ StatusRoundedImage {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.margins: Style.current.padding
+ Layout.preferredWidth: 68
+ Layout.preferredHeight: Layout.preferredWidth
+
+ radius: root.isAssetType ? width / 2 : 8
+ image.source: root.tokenImage
+ showLoadingIndicator: false
+ image.fillMode: Image.PreserveAspectCrop
+ }
+
+ StatusBaseText {
+ Layout.fillWidth: true
+
+ text: d.contentText
+ textFormat: Text.RichText
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ lineHeight: 1.2
+ }
+
+ // Navigate to community button
+ StatusListItem {
+ Layout.fillWidth: true
+ Layout.bottomMargin: Style.current.halfPadding
+
+ title: root.communityName
+ border.color: Theme.palette.baseColor2
+ asset.name: root.communityLogo
+ asset.isImage: true
+ asset.isLetterIdenticon: !asset.name
+ components: [
+ RowLayout {
+ StatusIcon {
+ Layout.alignment: Qt.AlignVCenter
+
+ icon: "arrow-right"
+ color: Theme.palette.primaryColor1
+ }
+
+ StatusBaseText {
+ Layout.alignment: Qt.AlignVCenter
+ Layout.rightMargin: Style.current.padding
+
+ text: qsTr("Visit Community")
+ font.pixelSize: Style.current.additionalTextSize
+ color: Theme.palette.primaryColor1
+ }
+ }
+ ]
+
+ onClicked: {
+ root.close()
+ root.communitiesStore.navigateToCommunity(root.communityId)
+ }
+ }
+ }
+ }
+
+ header: StatusDialogHeader {
+ headline.title: root.isAssetType ? qsTr("You received your first community asset") : qsTr("You received your first community collectible")
+ actions.closeButton.onClicked: root.close()
+ }
+
+ footer: StatusDialogFooter {
+ spacing: Style.current.padding
+ rightButtons: ObjectModel {
+ StatusFlatButton {
+ id: hideBtn
+
+ visible: false // TODO: #13293
+
+ text: root.isAssetType ? qsTr("Hide this asset") : qsTr("Hide this collectible")
+
+ onClicked: {
+ root.close()
+ root.hideClicked()
+ }
+ }
+
+ StatusButton {
+ id: acceptBtn
+
+ text: qsTr("Got it!")
+
+ onClicked: root.close()
+ }
+ }
+ }
+}
diff --git a/ui/app/AppLayouts/Communities/popups/qmldir b/ui/app/AppLayouts/Communities/popups/qmldir
index 11a660f258..53640c5169 100644
--- a/ui/app/AppLayouts/Communities/popups/qmldir
+++ b/ui/app/AppLayouts/Communities/popups/qmldir
@@ -9,6 +9,7 @@ EnableShardingPopup 1.0 EnableShardingPopup.qml
ExportControlNodePopup 1.0 ExportControlNodePopup.qml
FinaliseOwnershipDeclinePopup 1.0 FinaliseOwnershipDeclinePopup.qml
FinaliseOwnershipPopup 1.0 FinaliseOwnershipPopup.qml
+FirstTokenReceivedPopup 1.0 FirstTokenReceivedPopup.qml
HoldingsDropdown 1.0 HoldingsDropdown.qml
ImportControlNodePopup 1.0 ImportControlNodePopup.qml
InDropdown 1.0 InDropdown.qml
diff --git a/ui/app/mainui/Popups.qml b/ui/app/mainui/Popups.qml
index 0c37ad8899..8169ceb428 100644
--- a/ui/app/mainui/Popups.qml
+++ b/ui/app/mainui/Popups.qml
@@ -78,6 +78,7 @@ QtObject {
Global.openTransferOwnershipPopup.connect(openTransferOwnershipPopup)
Global.openFinaliseOwnershipPopup.connect(openFinaliseOwnershipPopup)
Global.openDeclineOwnershipPopup.connect(openDeclineOwnershipPopup)
+ Global.openFirstTokenReceivedPopup.connect(openFirstTokenReceivedPopup)
}
property var currentPopup
@@ -318,6 +319,20 @@ QtObject {
openPopup(declineOwnershipPopup, { communityName: communityName, communityId: communityId })
}
+ function openFirstTokenReceivedPopup(communityId, communityName, communityLogo, tokenSymbol, tokenName, tokenAmount, tokenType, tokenImage) {
+ openPopup(firstTokenReceivedPopup,
+ {
+ communityId: communityId,
+ communityName: communityName,
+ communityLogo: communityLogo,
+ tokenSymbol: tokenSymbol,
+ tokenName: tokenName,
+ tokenAmount: tokenAmount,
+ tokenType: tokenType,
+ tokenImage: tokenImage
+ })
+ }
+
readonly property list _components: [
Component {
id: removeContactConfirmationDialog
@@ -933,7 +948,17 @@ QtObject {
onDeclineClicked: root.ownershipDeclined()
}
- }
+ },
// End of components related to transfer community ownership flow.
+
+ Component {
+ id: firstTokenReceivedPopup
+
+ FirstTokenReceivedPopup {
+ communitiesStore: root.communitiesStore
+
+ onHideClicked: console.warn("TODO: OPEN HIDE POPUP")
+ }
+ }
]
}
diff --git a/ui/app/mainui/ToastsManager.qml b/ui/app/mainui/ToastsManager.qml
index dfa3773c6c..98ef668cba 100644
--- a/ui/app/mainui/ToastsManager.qml
+++ b/ui/app/mainui/ToastsManager.qml
@@ -129,7 +129,7 @@ QtObject {
}
// Community token received in the user wallet:
- function onCommunityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName) {
+ function onCommunityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName, symbol) {
// Some error control:
if(tokenType !== Constants.TokenType.ERC20 && tokenType !== Constants.TokenType.ERC721) {
@@ -139,9 +139,14 @@ QtObject {
var data = {
communityId: communityId,
+ communityName: communityName,
chainId: chainId,
txHash: txHash,
- tokenType: tokenType
+ tokenType: tokenType,
+ tokenName: name,
+ tokenSymbol: symbol,
+ tokenImage: image,
+ tokenAmount: balance
}
if(isFirst) {
@@ -216,7 +221,24 @@ QtObject {
console.warn("Unexpected transaction hash while trying to navigate to the details page: " + txHash)
return
case ToastsManager.ActionType.OpenFirstCommunityTokenPopup:
- console.warn("TODO: #12366")
+ if(actionData) {
+ var data = JSON.parse(actionData)
+ var communityId = data.communityId
+ var communityName = data.communityName
+ var tokenType = data.tokenType
+ var tokenName = data.tokenName
+ var tokenSymbol = data.tokenSymbol
+ var tokenImage = data.tokenImage
+ var tokenAmount = data.tokenAmount
+ Global.openFirstTokenReceivedPopup(communityId,
+ communityName,
+ rootChatStore.getCommunityDetailsAsJson(communityId).image,
+ tokenSymbol,
+ tokenName,
+ tokenAmount,
+ tokenType,
+ tokenImage);
+ }
return
default:
console.warn("ToastsManager: Action type is not defined")
diff --git a/ui/imports/shared/stores/CommunityTokensStore.qml b/ui/imports/shared/stores/CommunityTokensStore.qml
index 4954067639..276225e322 100644
--- a/ui/imports/shared/stores/CommunityTokensStore.qml
+++ b/ui/imports/shared/stores/CommunityTokensStore.qml
@@ -38,7 +38,8 @@ QtObject {
string communityId, string communityName,
string balance, int chainId,
string txHash, bool isFirst,
- int tokenType, string walletAccountName)
+ int tokenType, string walletAccountName,
+ string symbol)
// Minting tokens:
function deployCollectible(communityId, collectibleItem)
@@ -136,16 +137,18 @@ QtObject {
root.ownerTokenReceived(communityId, communityName)
}
- function onCommunityTokenReceived(name, image, communityId, communityName, communityColor /*Unused, can be removed*/, balance, chainId, txHash/*, isFirst, tokenType, walletAccountName*/) {
+ function onCommunityTokenReceived(name, image, communityId, communityName, communityColor /*Unused, can be removed*/, balance, chainId, txHash/*, isFirst, tokenType, walletAccountName, symbol*/) {
// TODO BACKEND: #13250
// ** `isFirst` property will be true if it's the first time the user receives a community asset and a community collectible
// ** `tokenType` property will determine if the received minted token is an ERC20 or an ERC720
// ** `walletAccountName` property will provide the wallet account name where the token was received
+ // ** `symbol` property will provide the token symbol
var isFirst = false
var tokenType = Constants.TokenType.ERC20
var walletAccountName = "Status account"
- root.communityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName)
+ var symbol = "NON"
+ root.communityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName, symbol)
}
function onSetSignerStateChanged(communityId, communityName, status, url) {
diff --git a/ui/imports/utils/Global.qml b/ui/imports/utils/Global.qml
index 5a368d4ecd..33bcb29b40 100644
--- a/ui/imports/utils/Global.qml
+++ b/ui/imports/utils/Global.qml
@@ -58,6 +58,14 @@ QtObject {
var sendModalPopup)
signal openFinaliseOwnershipPopup(string communityId)
signal openDeclineOwnershipPopup(string communityId, string communityName)
+ signal openFirstTokenReceivedPopup(string communityId,
+ string communityName,
+ string communityLogo,
+ string tokenSymbol,
+ string tokenName,
+ string tokenAmount,
+ int tokenType,
+ string tokenImage)
signal openLink(string link)
signal openLinkWithConfirmation(string link, string domain)