From 02cf07044d363198b8da5884af6c8606dec9fc35 Mon Sep 17 00:00:00 2001 From: Noelia Date: Tue, 7 Mar 2023 12:32:45 +0100 Subject: [PATCH] feat(MintToken): Created Preview collectible page - Added navigation between pages. - Added main layout and properties (some backend integration still pending). - Added holders model with mocked data. - Added mint tokens footer component. Closes #8734 and #8737 --- ui/StatusQ/src/assets/img/icons/retail.svg | 9 + .../Chat/layouts/SettingsPageLayout.qml | 8 + .../CommunityMintTokensSettingsPanel.qml | 211 ++++++++++++++- .../communities/MintTokensFooterPanel.qml | 81 ++++++ .../panels/communities/TokenHoldersPanel.qml | 90 +++++++ .../AppLayouts/Chat/panels/communities/qmldir | 2 + .../Chat/stores/CommunitiesStore.qml | 47 +++- .../Chat/views/CommunitySettingsView.qml | 1 - .../communities/CommunityCollectibleView.qml | 255 ++++++++++++++++++ .../CommunityNewCollectibleView.qml | 95 ++----- .../AppLayouts/Chat/views/communities/qmldir | 3 +- .../Wallet/controls/NetworkFilter.qml | 4 +- 12 files changed, 728 insertions(+), 78 deletions(-) create mode 100644 ui/StatusQ/src/assets/img/icons/retail.svg create mode 100644 ui/app/AppLayouts/Chat/panels/communities/MintTokensFooterPanel.qml create mode 100644 ui/app/AppLayouts/Chat/panels/communities/TokenHoldersPanel.qml create mode 100644 ui/app/AppLayouts/Chat/views/communities/CommunityCollectibleView.qml diff --git a/ui/StatusQ/src/assets/img/icons/retail.svg b/ui/StatusQ/src/assets/img/icons/retail.svg new file mode 100644 index 0000000000..86c517f7d0 --- /dev/null +++ b/ui/StatusQ/src/assets/img/icons/retail.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml b/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml index ad537a8b1f..fbb182b011 100644 --- a/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml +++ b/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml @@ -16,7 +16,9 @@ Item { property string title property Component content + // optional + property Component footer property bool dirty: false property bool editable: false property bool headerButtonVisible: false @@ -89,6 +91,12 @@ Item { sourceComponent: root.content } + + Loader { + visible: !!root.footer + Layout.fillWidth: true + sourceComponent: root.footer + } } SettingsDirtyToastMessage { diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml index bfebf8e148..952fa07995 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml @@ -1,4 +1,9 @@ import QtQuick 2.14 +import QtQuick.Layouts 1.14 + +import StatusQ.Core 0.1 +import StatusQ.Components 0.1 +import StatusQ.Core.Theme 0.1 import AppLayouts.Chat.layouts 1.0 import AppLayouts.Chat.views.communities 1.0 @@ -16,7 +21,11 @@ SettingsPageLayout { function navigateBack() { if (root.state === d.newCollectibleViewState) { - root.state = d.welcomeViewState + root.state = d.initialState + } else if (root.state === d.previewCollectibleViewState) { + root.state = d.newCollectibleViewState + } else if (root.state === d.collectibleViewState) { + root.state = d.mintedCollectibleViewState } } @@ -25,13 +34,73 @@ SettingsPageLayout { readonly property string welcomeViewState: "WELCOME" readonly property string newCollectibleViewState: "NEW_COLLECTIBLE" + readonly property string previewCollectibleViewState: "PREVIEW_COLLECTIBLE" + readonly property string mintedCollectibleViewState: "MINTED_COLLECTIBLE" + readonly property string collectibleViewState: "VIEW_COLLECTIBLE" + + readonly property string welcomePageTitle: qsTr("Mint tokens") + readonly property string newCollectiblePageTitle: qsTr("Create new collectible") + readonly property string backButtonText: qsTr("Back") + readonly property string backTokensText: qsTr("Tokens") + + property bool preview: false + + readonly property string initialState: root.tokensModel.count > 0 ? d.mintedCollectibleViewState : d.welcomeViewState } - state: d.welcomeViewState + QtObject { + id: collectibleItem + + property int deployState + property url artworkSource + property string collectibleName + property string symbol + property string description + property string supplyText + property bool infiniteSupply: true + property bool transferable: true + property bool selfDestruct: true + property int chainId + property string chainName + property string chainIcon + + function initialize() { + deployState = 1 + artworkSource = "" + collectibleName = "" + symbol = "" + description = "" + supplyText = "" + infiniteSupply = true + transferable = true + selfDestruct = true + chainId = -1 + chainName = "" + chainIcon = "" + } + + // TO CHECK: Some backend properties are not working correctly + function loadData(model) { + deployState = model.deployState + collectibleName = model.name + description = model.description + supplyText = model.supply.toString() + infiniteSupply = model.infiniteSupply + transferable = model.transferable + chainName = communitiesStore.getChainName(model.chainId) // Backend NOT WORKING + chainIcon = communitiesStore.getChainIcon(model.chainId) // Backend NOT WORKING + artworkSource = model.tokenUri // Backend NOT WORKING + symbol = model.symbol // Backend NOT WORKING + selfDestruct = model.selfDestruct // Backend NOT WORKING + chainId = model.chainId // Backend NOT WORKING + } + } + + state: d.initialState states: [ State { name: d.welcomeViewState - PropertyChanges {target: root; title: qsTr("Mint tokens")} + PropertyChanges {target: root; title: d.welcomePageTitle} PropertyChanges {target: root; previousPageName: ""} PropertyChanges {target: root; content: welcomeView} PropertyChanges {target: root; headerButtonVisible: true} @@ -40,17 +109,47 @@ SettingsPageLayout { }, State { name: d.newCollectibleViewState - PropertyChanges {target: root; title: qsTr("Create new collectible")} - PropertyChanges {target: root; previousPageName: qsTr("Mint tokens")} + PropertyChanges {target: root; title: d.newCollectiblePageTitle} + PropertyChanges {target: root; previousPageName: d.welcomePageTitle} PropertyChanges {target: root; content: newCollectiblesView} PropertyChanges {target: root; headerButtonVisible: false} PropertyChanges {target: root; headerWidth: 0} + }, + State { + name: d.previewCollectibleViewState + PropertyChanges {target: root; title: collectibleItem.collectibleName} + PropertyChanges {target: root; previousPageName: d.backButtonText} + PropertyChanges {target: root; content: collectibleView} + PropertyChanges {target: root; headerButtonVisible: false} + PropertyChanges {target: root; headerWidth: 0} + PropertyChanges {target: d; preview: true} + }, + State { + name: d.mintedCollectibleViewState + PropertyChanges {target: root; title: d.welcomePageTitle} + PropertyChanges {target: root; previousPageName: ""} + PropertyChanges {target: root; content: mintedTokensView} + PropertyChanges {target: root; headerButtonVisible: true} + PropertyChanges {target: root; headerButtonText: qsTr("Create new token")} + PropertyChanges {target: root; headerWidth: root.viewWidth} + PropertyChanges {target: d; preview: false} + }, + State { + name: d.collectibleViewState + PropertyChanges {target: root; title: collectibleItem.collectibleName} + PropertyChanges {target: root; previousPageName: d.backTokensText} + PropertyChanges {target: root; content: collectibleView} + PropertyChanges {target: root; headerButtonVisible: false} + PropertyChanges {target: root; headerWidth: 0} + PropertyChanges {target: root; footer: mintTokenFooter} + PropertyChanges {target: d; preview: false} } ] onHeaderButtonClicked: { - if(root.state === d.welcomeViewState) { + if(root.state === d.welcomeViewState || root.state === d.mintedCollectibleViewState) { root.state = d.newCollectibleViewState + collectibleItem.initialize() } } @@ -77,7 +176,53 @@ SettingsPageLayout { CommunityNewCollectibleView { anchors.fill: parent store: root.communitiesStore - tokensModel: root.tokensModel + name: collectibleItem.collectibleName + artworkSource: collectibleItem.artworkSource + symbol: collectibleItem.symbol + description: collectibleItem.description + supplyText: collectibleItem.supplyText + infiniteSupply: collectibleItem.infiniteSupply + transferable: collectibleItem.transferable + selfDestruct: collectibleItem.selfDestruct + chainId: collectibleItem.chainId + chainName: collectibleItem.chainName + chainIcon: collectibleItem.chainIcon + + onNameChanged: collectibleItem.collectibleName = name + onArtworkSourceChanged: collectibleItem.artworkSource = artworkSource + onSymbolChanged: collectibleItem.symbol = symbol + onDescriptionChanged: collectibleItem.description = description + onSupplyTextChanged: collectibleItem.supplyText = supplyText + onInfiniteSupplyChanged: collectibleItem.infiniteSupply = infiniteSupply + onTransferableChanged: collectibleItem.transferable = transferable + onSelfDestructChanged: collectibleItem.selfDestruct = selfDestruct + onChainIdChanged: collectibleItem.chainId = chainId + onChainNameChanged: collectibleItem.chainName = chainName + onChainIconChanged: collectibleItem.chainIcon = chainIcon + onPreviewClicked: root.state = d.previewCollectibleViewState + } + } + + Component { + id: collectibleView + + CommunityCollectibleView { + anchors.fill: parent + preview: d.preview + holdersModel: root.communitiesStore.holdersModel + deployState: collectibleItem.deployState + name: collectibleItem.collectibleName + artworkSource: collectibleItem.artworkSource + symbol: collectibleItem.symbol + description: collectibleItem.description + supplyText: collectibleItem.supplyText + infiniteSupply: collectibleItem.infiniteSupply + transferable: collectibleItem.transferable + selfDestruct: collectibleItem.selfDestruct + chainId: collectibleItem.chainId + chainName: collectibleItem.chainName + chainIcon: collectibleItem.chainIcon + onMintCollectible: { root.communitiesStore.mintCollectible(root.communityId, root.transactionStore.currentAccount.address, /*TODO use address from SendModal*/ @@ -90,6 +235,58 @@ SettingsPageLayout { selfDestruct, chainId, artworkSource) + + root.state = d.mintedCollectibleViewState + } + } + } + + Component { + id: mintTokenFooter + + MintTokensFooterPanel { + airdropEnabled: false + retailEnabled: false + remotelySelfDestructEnabled: false + burnEnabled: false + } + } + + // TEMPORAL: + Component { + id: mintedTokensView + + // TEMPORAL: + Item { + anchors.fill: parent + + ColumnLayout { + id: backendChecker + width: parent.width + + StatusBaseText { + text: qsTr("Collectibles") + font.pixelSize: Theme.primaryTextFontSize + color: Theme.palette.baseColor1 + } + + // TODO: We can probably use some wallet components (i.e. CollectibleView.qml) + ListView { + Layout.preferredWidth: 560 + Layout.preferredHeight: childrenRect.height + model: root.tokensModel + delegate: StatusListItem { + width: parent.width + title: model.name + " - " + model.symbol + subTitle: model.description + titleAsideText: model.supply + label: model.deployState + onClicked: { + root.state = d.collectibleViewState + collectibleItem.loadData(model) + } + } + } } } } diff --git a/ui/app/AppLayouts/Chat/panels/communities/MintTokensFooterPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/MintTokensFooterPanel.qml new file mode 100644 index 0000000000..dcbe1e1897 --- /dev/null +++ b/ui/app/AppLayouts/Chat/panels/communities/MintTokensFooterPanel.qml @@ -0,0 +1,81 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.13 + +import StatusQ.Popups 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core.Theme 0.1 + +import utils 1.0 + +Control { + id: root + + property alias airdropEnabled: airdropButton.enabled + property alias retailEnabled: retailButton.enabled + property alias remotelySelfDestructEnabled: remotelySelfDestructButton.enabled + property alias burnEnabled: burnButton.enabled + + signal airdropClicked + signal retailClicked + signal remotelySelfDestructClicked + signal burnClicked + + height: 61 // by design + spacing: Style.current.padding + contentItem: Item { + anchors.fill: parent + + StatusModalDivider { + width: parent.width + anchors.top: parent.top + } + + RowLayout { + anchors.centerIn: parent + spacing: root.spacing + + StatusFlatButton { + id: airdropButton + + icon.name: "airdrop" + text: qsTr("Airdrop") + + onClicked: root.airdropClicked() + } + + StatusFlatButton { + id: retailButton + + icon.name: "token-sale" + text: qsTr("Retail") + + onClicked: root.retailClicked() + } + + StatusFlatButton { + id: remotelySelfDestructButton + + icon.name: "retail" + text: qsTr("Remotely self destruct") + type: StatusBaseButton.Type.Danger + borderColor: "transparent" + + onClicked: root.remoteSelfDestructClicked() + } + + StatusFlatButton { + id: burnButton + + icon.name: "delete" + text: qsTr("Burn") + type: StatusBaseButton.Type.Danger + borderColor: "transparent" + + onClicked: root.burnClicked() + } + } + } +} + + diff --git a/ui/app/AppLayouts/Chat/panels/communities/TokenHoldersPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/TokenHoldersPanel.qml new file mode 100644 index 0000000000..2fb11ee5c5 --- /dev/null +++ b/ui/app/AppLayouts/Chat/panels/communities/TokenHoldersPanel.qml @@ -0,0 +1,90 @@ +import QtQuick 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls 2.14 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Components 0.1 + +import SortFilterProxyModel 0.2 + +import utils 1.0 +import shared.controls 1.0 + +Control { + id: root + + // Expected roles: ensName, walletAddress, imageSource and amount + property var model + + property string tokenName + + QtObject { + id: d + + readonly property int red2Color: 4 + } + + contentItem: ColumnLayout { + anchors.fill: parent + spacing: Style.current.padding + + StatusBaseText { + visible: !root.preview + Layout.fillWidth: true + wrapMode: Text.Wrap + font.pixelSize: Style.current.primaryTextFontSize + color: Theme.palette.baseColor1 + text: qsTr("All %1 token holders").arg(root.tokenName) + } + + SortFilterProxyModel { + id: filteredModel + + sourceModel: root.model + filters: ExpressionFilter { + enabled: searcher.enabled + expression: { + searcher.text + return model.ensName.toLowerCase().includes(searcher.text.toLowerCase()) || + model.walletAddress.toLowerCase().includes(searcher.text.toLowerCase()) + } + } + } + + SearchBox { + id: searcher + Layout.fillWidth: true + topPadding: 0 + bottomPadding: 0 + minimumHeight: 36 // by design + maximumHeight: minimumHeight + enabled: root.model.count > 0 + placeholderText: enabled ? qsTr("Search") : qsTr("No placeholders to search") + } + + StatusListView { + id: holders + + Layout.fillWidth: true + Layout.preferredHeight: childrenRect.height + leftMargin: -Style.current.padding + model: filteredModel + delegate: StatusListItem { + readonly property bool unknownHolder: model.ensName === "" + readonly property string formattedTitle: unknownHolder ? "?" : model.ensName + + sensor.enabled: false + width: ListView.view.width + title: formattedTitle + statusListItemTitle.visible: !unknownHolder + subTitle: model.walletAddress + asset.name: model.imageSource + asset.isImage: true + asset.isLetterIdenticon: unknownHolder + asset.color: Theme.palette.userCustomizationColors[d.red2Color] + } + } + } +} diff --git a/ui/app/AppLayouts/Chat/panels/communities/qmldir b/ui/app/AppLayouts/Chat/panels/communities/qmldir index edf906fe2d..cd1c9cd2a5 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/qmldir +++ b/ui/app/AppLayouts/Chat/panels/communities/qmldir @@ -5,6 +5,8 @@ CommunityProfilePopupInviteFriendsPanel 1.0 CommunityProfilePopupInviteFriendsPa CommunityProfilePopupInviteMessagePanel 1.0 CommunityProfilePopupInviteMessagePanel.qml HidePermissionPanel 1.0 HidePermissionPanel.qml JoinPermissionsOverlayPanel 1.0 JoinPermissionsOverlayPanel.qml +MintTokensFooterPanel 1.0 MintTokensFooterPanel.qml PermissionConflictWarningPanel 1.0 PermissionConflictWarningPanel.qml PermissionDuplicationWarningPanel 1.0 PermissionDuplicationWarningPanel.qml PermissionQualificationPanel 1.0 PermissionQualificationPanel.qml +TokenHoldersPanel 1.0 TokenHoldersPanel.qml diff --git a/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml b/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml index 39ed0cfdb6..ed367f067d 100644 --- a/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml +++ b/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml @@ -76,5 +76,50 @@ QtObject { property var layer2Networks: networksModule.layer2 property var testNetworks: networksModule.test property var enabledNetworks: networksModule.enabled - property var allNetworks: networksModule.all + property var allNetworks: networksModule.all + + function getChainName(chainId) { + // TODO: MOCKED now + return "Goerli" + } + + function getChainIcon(chainId) { + // TODO: MOCKED now + return "network/Network=Custom" + } + + // Token holders model: MOCKED DATA -> TODO: Update with real data + readonly property var holdersModel: ListModel { + + readonly property string image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/ + nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC" + + Component.onCompleted: + append([ + { + ensName: "carmen.eth", + walletAddress: "0xb794f5450ba39494ce839613fffba74279579268", + imageSource:image, + amount: 3 + }, + { + ensName: "chris.eth", + walletAddress: "0xb794f5ea0ba39494ce839613fffba74279579268", + imageSource: image, + amount: 2 + }, + { + ensName: "emily.eth", + walletAddress: "0xb794f5ea0ba39494ce839613fffba74279579268", + imageSource: image, + amount: 2 + }, + { + ensName: "", + walletAddress: "0xb794f5ea0ba39494ce839613fffba74279579268", + imageSource: "", + amount: 1 + } + ]) + } } diff --git a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml index 1c815a6f08..b68a6d9d40 100644 --- a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml @@ -173,7 +173,6 @@ StatusSectionLayout { centerPanel: Loader { id: centerPanelContentLoader anchors.fill: parent - anchors.bottomMargin: 16 active: root.community sourceComponent: StackLayout { currentIndex: d.currentIndex diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityCollectibleView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityCollectibleView.qml new file mode 100644 index 0000000000..64eb7b1ac5 --- /dev/null +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityCollectibleView.qml @@ -0,0 +1,255 @@ +import QtQuick 2.14 +import QtQuick.Layouts 1.14 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Components 0.1 + +import utils 1.0 +import shared.panels 1.0 + +import AppLayouts.Chat.panels.communities 1.0 + +StatusScrollView { + id: root + + property int viewWidth: 560 // by design + property bool preview: false + property var holdersModel + + // Collectible object properties: + property alias artworkSource: image.source + property alias symbol: symbolBox.value + property alias description: descriptionItem.text + property alias chainName: chainText.text + property string name + property string supplyText + property bool infiniteSupply + property bool transferable + property bool selfDestruct + property int chainId + property string chainIcon + property int deployState + + signal mintCollectible(url artworkSource, + string name, + string symbol, + string description, + int supply, + bool infiniteSupply, + bool transferable, + bool selfDestruct, + int chainId) + + QtObject { + id: d + + readonly property int imageSelectorRectSize: 280 + readonly property int iconSize: 20 + } + + enum DeployState { + Failed, + InProgress, + Deployed + } + + contentWidth: mainLayout.width + contentHeight: mainLayout.height + padding: 0 + + ColumnLayout { + id: mainLayout + + width: root.viewWidth + spacing: Style.current.padding + + RowLayout { + visible: !root.preview && (root.deployState === CommunityCollectibleView.DeployState.InProgress) + spacing: Style.current.halfPadding + + StatusDotsLoadingIndicator {} + + StatusBaseText { + elide: Text.ElideRight + font.pixelSize: Theme.primaryTextFontSize + text: qsTr("Collectible is being minted") + } + } + + Rectangle { + Layout.preferredHeight: d.imageSelectorRectSize + Layout.preferredWidth: Layout.preferredHeight + radius: 8 + color: Theme.palette.baseColor2 + + Image { + id: image + + anchors.fill: parent + fillMode: Image.PreserveAspectFit + } + } + + StatusBaseText { + id: descriptionItem + + Layout.fillWidth: true + wrapMode: TextEdit.WordWrap + font.pixelSize: Theme.primaryTextFontSize + lineHeight: 1.2 + } + + Flow { + spacing: Style.current.halfPadding + Layout.fillWidth: true + + component CustomPreviewBox: Rectangle { + id: previewBox + + property string label + property string value + property bool leftAlignment: true + + radius: 8 + border.color: Theme.palette.baseColor2 + implicitWidth: Math.min(boxContent.implicitWidth + Style.current.padding, mainLayout.width) + implicitHeight: boxContent.implicitHeight + Style.current.padding + + ColumnLayout { + id: boxContent + anchors.centerIn: parent + spacing: 2 + + StatusBaseText { + Layout.fillWidth: true + text: previewBox.label + elide: Text.ElideRight + font.pixelSize: 13 + color: Theme.palette.baseColor1 + horizontalAlignment: Text.AlignHCenter + } + + StatusBaseText { + Layout.maximumWidth: mainLayout.width - Style.current.padding + Layout.alignment: previewBox.leftAlignment ? Qt.AlignLeft : Qt.AlignHCenter + text: previewBox.value + elide: Text.ElideRight + font.pixelSize: Theme.primaryTextFontSize + color: Theme.palette.directColor1 + horizontalAlignment: previewBox.leftAlignment ? Text.AlignLeft : Text.AlignHCenter + } + } + } + + CustomPreviewBox { + label: root.infiniteSupply ? qsTr("Infinite supply") : qsTr("Total") + value: root.infiniteSupply ? qsTr("Yes") : root.supplyText + leftAlignment: root.infiniteSupply + } + + CustomPreviewBox { + label: qsTr("Transferable") + value: root.transferable ? qsTr("Yes") : qsTr("No") + } + + CustomPreviewBox { + label: qsTr("Remote self-destruct") + value: root.selfDestruct ? qsTr("Yes") : qsTr("No") + } + + CustomPreviewBox { + id: symbolBox + + label: qsTr("Symbol") + leftAlignment: false + } + + Rectangle { + height: symbolBox.height + width: rowChain.implicitWidth + 2 * Style.current.padding + border.width: 1 + radius: 8 + border.color: Theme.palette.baseColor2 + color: "transparent" + + RowLayout { + id: rowChain + + anchors.centerIn: parent + spacing: Style.current.padding + + SVGImage { + id: chainIcon + + Layout.alignment: Qt.AlignVCenter + height: 24 + width: height + source: Style.svg(root.chainIcon) + } + + StatusBaseText { + id: chainText + + Layout.alignment: Qt.AlignVCenter + font.pixelSize: 13 + font.weight: Font.Medium + color: Theme.palette.baseColor1 + } + } + } + } + + RowLayout { + visible: root.preview + Layout.fillWidth: true + + StatusIcon { + Layout.preferredWidth: d.iconSize + Layout.preferredHeight: d.iconSize + Layout.alignment: Qt.AlignTop + color: Theme.palette.baseColor1 + icon: "info" + } + + StatusBaseText { + Layout.fillWidth: true + wrapMode: Text.Wrap + font.pixelSize: Style.current.primaryTextFontSize + color: Theme.palette.baseColor1 + text: qsTr("Make sure you’re happy with your collectible before minting it as it can’t be edited later") + } + } + + StatusButton { + visible: root.preview + Layout.preferredHeight: 44 + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.topMargin: Style.current.halfPadding + text: qsTr("Mint") + + onClicked: { + root.mintCollectible(root.artworkSource, + root.name, + root.symbol, + root.description, + parseInt(root.supplyText), + root.infiniteSupply, + root.transferable, + root.selfDestruct, + root.chainId) + } + } + + TokenHoldersPanel { + visible: !root.preview + tokenName: root.name + model: root.holdersModel + Layout.topMargin: Style.current.padding + Layout.fillWidth: true + Layout.fillHeight: true + } + } +} diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewCollectibleView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewCollectibleView.qml index be6eaf12e2..2a48e4522b 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewCollectibleView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewCollectibleView.qml @@ -15,37 +15,35 @@ StatusScrollView { id: root property var store - property var tokensModel // TEMPORARY property int viewWidth: 560 // by design + // Collectible properties + property alias name: nameInput.text + property alias symbol: symbolInput.text + property alias description: descriptionInput.text + property alias supplyText: supplyInput.text + property alias infiniteSupply: unlimitedSupplyChecker.checked + property alias transferable: transferableChecker.checked + property alias selfDestruct: selfDestructChecker.checked + property url artworkSource + property int chainId + property string chainName + property string chainIcon + signal chooseArtWork signal previewClicked - // TEMPORAL - signal mintCollectible(url artworkSource, - string name, - string symbol, - string description, - int supply, - bool infiniteSupply, - bool transferable, - bool selfDestruct, - int chainId) - QtObject { id: d - readonly property bool isFullyFilled: d.artworkSource.toString().length > 0 - && !!nameInput.text - && !!symbolInput.text - && !!descriptionInput.text - && (unlimitedSupplyItem.checked || (!unlimitedSupplyItem.checked && supplyInput.text.length > 0)) + readonly property bool isFullyFilled: root.artworkSource.toString().length > 0 + && !!root.name + && !!root.symbol + && !!root.description + && (root.infiniteSupply || (!root.infiniteSupply && root.supplyText.length > 0)) readonly property int imageSelectorRectWidth: 280 - - property url artworkSource - property int networkSelected } contentWidth: mainLayout.width @@ -65,8 +63,9 @@ StatusScrollView { uploadText: qsTr("Drag and Drop or Upload Artwork") additionalText: qsTr("Images only") acceptedImageExtensions: Constants.acceptedDragNDropImageExtensions + file: root.artworkSource - onFileSelected: d.artworkSource = file + onFileSelected: root.artworkSource = file } component CustomStatusInput: StatusInput { @@ -164,7 +163,11 @@ StatusScrollView { isChainVisible: false multiSelection: false - onSingleNetworkSelected: d.networkSelected = chainId + onSingleNetworkSelected: { + root.chainId = chainId + root.chainName = chainName + root.chainIcon = chainIcon + } } } @@ -176,7 +179,7 @@ StatusScrollView { } CustomRowComponent { - id: unlimitedSupplyItem + id: unlimitedSupplyChecker label: qsTr("Unlimited supply") description: qsTr("Enable to allow the minting of additional collectibles in the future. Disable to specify a finite supply") @@ -186,14 +189,14 @@ StatusScrollView { StatusInput { id: supplyInput - visible: !unlimitedSupplyItem.checked + visible: !unlimitedSupplyChecker.checked label: qsTr("Total finite supply") placeholderText: "1" validators: StatusIntValidator{bottom: 1; top: 999999999;} } CustomRowComponent { - id: transferibleChecker + id: transferableChecker label: qsTr("Not transferable (Soulbound)") description: qsTr("If enabled, the token is locked to the first address it is sent to and can never be transferred to another address. Useful for tokens that represent Admin permissions") @@ -216,47 +219,7 @@ StatusScrollView { text: qsTr("Preview") enabled: d.isFullyFilled - onClicked: { - root.previewClicked() - - // TEMPORAL - root.mintCollectible(d.artworkSource, - nameInput.text, - symbolInput.text, - descriptionInput.text, - parseInt(supplyInput.text), - unlimitedSupplyItem.checked, - transferibleChecker.checked, - selfDestructChecker.checked, - d.networkSelected) - } - } - - // TEMPORAL: - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: backendChecker.implicitHeight - color: "darkgrey" - radius: 8 - - ColumnLayout { - id: backendChecker - - StatusBaseText { - Layout.margins: 16 - text: "Backend checker - Minted collectibles" - font.bold: true - } - - ListView { - Layout.preferredWidth: 200 - Layout.preferredHeight: 100 - model: root.tokensModel - delegate: Text { - text: "name: " + name + ", descr: " + description + ", supply: " + supply + ", status: " + deployState - } - } - } + onClicked: root.previewClicked() } } } diff --git a/ui/app/AppLayouts/Chat/views/communities/qmldir b/ui/app/AppLayouts/Chat/views/communities/qmldir index 45db04c8ce..fd786f3c4c 100644 --- a/ui/app/AppLayouts/Chat/views/communities/qmldir +++ b/ui/app/AppLayouts/Chat/views/communities/qmldir @@ -1,7 +1,8 @@ ChannelsSelectionModel 1.0 ChannelsSelectionModel.qml +CommunityCollectibleView 1.0 CommunityCollectibleView.qml CommunityNewCollectibleView 1.0 CommunityNewCollectibleView.qml CommunityNewPermissionView 1.0 CommunityNewPermissionView.qml CommunityPermissionsView 1.0 CommunityPermissionsView.qml CommunityWelcomeSettingsView 1.0 CommunityWelcomeSettingsView.qml HoldingsSelectionModel 1.0 HoldingsSelectionModel.qml -JoinCommunityView 1.0 JoinCommunityView.qml +JoinCommunityView 1.0 JoinCommunityView.qml \ No newline at end of file diff --git a/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml b/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml index 70bbd3e20d..6922c1c729 100644 --- a/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml +++ b/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml @@ -20,7 +20,7 @@ Item { property bool isChainVisible: true property bool multiSelection: true - signal singleNetworkSelected(int chainId) + signal singleNetworkSelected(int chainId, string chainName, string chainIcon) QtObject { id: d @@ -105,7 +105,7 @@ Item { onSingleNetworkSelected: { d.selectedChainName = chainName d.selectedIconUrl = iconUrl - root.singleNetworkSelected(chainId) + root.singleNetworkSelected(chainId, chainName, iconUrl) } } }