diff --git a/storybook/pages/CommunityMintTokensSettingsPanelPage.qml b/storybook/pages/CommunityMintTokensSettingsPanelPage.qml index 6dcedc20c3..c1efa140dd 100644 --- a/storybook/pages/CommunityMintTokensSettingsPanelPage.qml +++ b/storybook/pages/CommunityMintTokensSettingsPanelPage.qml @@ -45,7 +45,6 @@ SplitView { onMintCollectible: logs.logEvent("CommunityMintTokensSettingsPanel::mintCollectible") onMintAsset: logs.logEvent("CommunityMintTokensSettingsPanel::mintAssets") onDeleteToken: logs.logEvent("CommunityMintTokensSettingsPanel::deleteToken: " + key) - onRetryMintToken: logs.logEvent("CommunityMintTokensSettingsPanel::retryMintToken: " + key) } } diff --git a/storybook/pages/CommunityMintedTokensViewPage.qml b/storybook/pages/CommunityMintedTokensViewPage.qml index d95ea76c3e..bc5dc24537 100644 --- a/storybook/pages/CommunityMintedTokensViewPage.qml +++ b/storybook/pages/CommunityMintedTokensViewPage.qml @@ -28,7 +28,7 @@ SplitView { anchors.fill: parent anchors.margins: 50 model: MintedTokensModel.mintedTokensModel - onItemClicked: logs.logEvent("CommunityMintedTokensView::itemClicked --> " + contractUniqueKey) + onItemClicked: logs.logEvent("CommunityMintedTokensView::itemClicked --> " + tokenKey) } } diff --git a/storybook/pages/CommunityTokenViewPage.qml b/storybook/pages/CommunityTokenViewPage.qml index 211b31a14a..aaab7a8233 100644 --- a/storybook/pages/CommunityTokenViewPage.qml +++ b/storybook/pages/CommunityTokenViewPage.qml @@ -3,6 +3,7 @@ import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import AppLayouts.Chat.views.communities 1.0 +import AppLayouts.Chat.helpers 1.0 import StatusQ.Core 0.1 @@ -23,59 +24,59 @@ SplitView { SplitView.fillWidth: true SplitView.fillHeight: true - CommunityTokenView { - id: view + CollectibleObject { + id: collectibleObj - anchors.fill: parent - anchors.margins: 50 artworkSource: ModelsData.icons.superRare - preview: previewBox.checked - isAssetView: isAssetBox.checked remotelyDestructState: remotelyDestructStateBox.checked ? 1 /*In progress*/ : 2 /*Completed*/ burnState: burnDestructStateBox.checked ? 1 /*In progress*/ : 2 /*Completed*/ name: nameText.text symbol: symbolText.text description: descriptionText.text - supplyAmount: parseInt(supplyText.text) + supply: parseInt(supplyText.text) infiniteSupply: unlimitedSupplyChecker.checked - assetDecimals: parseInt(decimalText.text) remainingTokens: parseInt(remainingText.text) transferable: transferibleChecker.checked - selfDestruct: selfdestructChecker.checked + remotelyDestruct: selfdestructChecker.checked chainId: 1 chainName: "Ethereum Mainnet" chainIcon: ModelsData.networks.ethereum accountName: "helloworld" - - tokenOwnersModel: TokenHoldersModel { - - } - - onMintCollectible: logs.logEvent("CommunityTokenView::onMintCollectible: \n" - + "artworkSource: " + artworkSource + "\n" - + "name: " + name + "\n" - + "symbol: " + symbol + "\n" - + "description: " + description + "\n" - + "supply: " + supply + "\n" - + "infiniteSupply: " + infiniteSupply + "\n" - + "transferable: " + transferable + "\n" - + "selfDestruct: " + selfDestruct + "\n" - + "chainId: " + chainId + "\n" - + "accountName: " + accountName) - - onMintAsset: logs.logEvent("CommunityTokenView::onMintAsset: \n" - + "artworkSource: " + artworkSource + "\n" - + "name: " + name + "\n" - + "symbol: " + symbol + "\n" - + "description: " + description + "\n" - + "supply: " + supply + "\n" - + "infiniteSupply: " + infiniteSupply + "\n" - + "decimals: " + decimals + "\n" - + "chainId: " + chainId + "\n" - + "accountName: " + accountName) } + + AssetObject { + id: assetObj + + artworkSource: ModelsData.icons.superRare + burnState: burnDestructStateBox.checked ? 1 /*In progress*/ : 2 /*Completed*/ + name: nameText.text + symbol: symbolText.text + description: descriptionText.text + supply: parseInt(supplyText.text) + infiniteSupply: unlimitedSupplyChecker.checked + decimals: parseInt(decimalText.text) + remainingTokens: parseInt(remainingText.text) + chainId: 1 + chainName: "Ethereum Mainnet" + chainIcon: ModelsData.networks.ethereum + accountName: "helloworld" + } + + CommunityTokenView { + id: view + + anchors.fill: parent + anchors.margins: 50 + preview: previewBox.checked + isAssetView: isAssetBox.checked + collectible: collectibleObj + asset: assetObj + tokenOwnersModel: TokenHoldersModel {} + + onMintClicked: logs.logEvent("CommunityTokenView::onMintClicked") } + } LogsAndControlsPanel { id: logsAndControlsPanel @@ -119,20 +120,29 @@ SplitView { RadioButton { id: mintingInProgress text: "In progress" - onCheckedChanged: if(checked) view.deployState = Constants.ContractTransactionStatus.InProgress + onCheckedChanged: { + if(view.isAssetView) assetObj.deployState = Constants.ContractTransactionStatus.InProgress + else collectibleObj.deployState = Constants.ContractTransactionStatus.InProgress + } } RadioButton { id: mintingFailed text: "Failed" - onCheckedChanged: if(checked) view.deployState = Constants.ContractTransactionStatus.Failed + onCheckedChanged: { + if(view.isAssetView) assetObj.deployState = Constants.ContractTransactionStatus.Failed + else collectibleObj.deployState = Constants.ContractTransactionStatus.Failed + } } RadioButton { id: mintingCompleted text: "Completed" checked: true - onCheckedChanged: if(checked) view.deployState = Constants.ContractTransactionStatus.Completed + onCheckedChanged: { + if(view.isAssetView) assetObj.deployState = Constants.ContractTransactionStatus.Completed + else collectibleObj.deployState = Constants.ContractTransactionStatus.Completed + } } } @@ -158,17 +168,26 @@ SplitView { RadioButton { text: "Small" checked: true - onCheckedChanged: view.artworkSource = ModelsData.icons.superRare + onCheckedChanged: { + if(view.isAssetView) assetObj.artworkSource = ModelsData.icons.superRare + else collectibleObj.artworkSource = ModelsData.icons.superRare + } } RadioButton { text: "Medium" - onCheckedChanged: view.artworkSource = ModelsData.collectibles.kitty2Big + onCheckedChanged: { + if(view.isAssetView) assetObj.artworkSource = ModelsData.collectibles.kitty2Big + else collectibleObj.artworkSource = ModelsData.collectibles.kitty2Big + } } RadioButton { text: "Large" - onCheckedChanged: view.artworkSource = ModelsData.banners.superRare + onCheckedChanged: { + if(view.isAssetView) assetObj.artworkSource = ModelsData.banners.superRare + else collectibleObj.artworkSource = ModelsData.banners.superRare + } } Label { @@ -280,9 +299,15 @@ SplitView { text: "Ethereum Mainnet" checked: true onCheckedChanged: { - view.chainName = text - view.chainIcon = ModelsData.networks.ethereum - view.chainId = 1 + if(view.isAssetView) { + assetObj.chainName = text + assetObj.chainIcon = ModelsData.networks.ethereum + assetObj.chainId = 1 + } else { + collectibleObj.chainName = text + collectibleObj.chainIcon = ModelsData.networks.ethereum + collectibleObj.chainId = 1 + } } } @@ -290,9 +315,15 @@ SplitView { id: opt text: "Optimism" onCheckedChanged: { - view.chainName = text - view.chainIcon = ModelsData.networks.optimism - view.chainId = 2 + if(view.isAssetView) { + assetObj.chainName = text + assetObj.chainIcon = ModelsData.networks.optimism + assetObj.chainId = 2 + } else { + collectibleObj.chainName = text + collectibleObj.chainIcon = ModelsData.networks.optimism + collectibleObj.chainId = 2 + } } } @@ -300,9 +331,15 @@ SplitView { id: arb text: "Arbitrum" onCheckedChanged: { - view.chainName = text - view.chainIcon = ModelsData.networks.arbitrum - view.chainId = 3 + if(view.isAssetView) { + assetObj.chainName = text + assetObj.chainIcon = ModelsData.networks.arbitrum + assetObj.chainId = 3 + } else { + collectibleObj.chainName = text + collectibleObj.chainIcon = ModelsData.networks.arbitrum + collectibleObj.chainId = 3 + } } } } diff --git a/ui/app/AppLayouts/Chat/helpers/AssetObject.qml b/ui/app/AppLayouts/Chat/helpers/AssetObject.qml new file mode 100644 index 0000000000..e6b8ef99e1 --- /dev/null +++ b/ui/app/AppLayouts/Chat/helpers/AssetObject.qml @@ -0,0 +1,15 @@ +import QtQuick 2.15 + +/*! + \qmltype AssetObject + \inherits TokenObject + \brief ERC20 token object properties definition (also known as asset). +*/ +TokenObject { + property int decimals: 2 // Default value + + function copyAsset(tokenObject) { + copyToken(tokenObject) + decimals = tokenObject.decimals + } +} diff --git a/ui/app/AppLayouts/Chat/helpers/CollectibleObject.qml b/ui/app/AppLayouts/Chat/helpers/CollectibleObject.qml new file mode 100644 index 0000000000..618d03ad93 --- /dev/null +++ b/ui/app/AppLayouts/Chat/helpers/CollectibleObject.qml @@ -0,0 +1,21 @@ +import QtQuick 2.15 + +import utils 1.0 + +/*! + \qmltype CollectibleObject + \inherits TokenObject + \brief ERC721 token object properties definition (also known as collectible). +*/ +TokenObject { + property bool transferable: false + property bool remotelyDestruct: true + property int remotelyDestructState: Constants.ContractTransactionStatus.None + + function copyCollectible(tokenObject) { + copyToken(tokenObject) + transferable = tokenObject.transferable + remotelyDestruct = tokenObject.remotelyDestruct + remotelyDestructState = tokenObject.remotelyDestructState + } +} diff --git a/ui/app/AppLayouts/Chat/helpers/TokenObject.qml b/ui/app/AppLayouts/Chat/helpers/TokenObject.qml new file mode 100644 index 0000000000..d69d940191 --- /dev/null +++ b/ui/app/AppLayouts/Chat/helpers/TokenObject.qml @@ -0,0 +1,57 @@ +import QtQuick 2.15 + +import utils 1.0 + +/*! + \qmltype TokenObject + \inherits QtObject + \brief Token object properties definition. +*/ +QtObject { + // Unique identifier: + property string key + + // General descriptive properties: + property string name + property string symbol + property string description + property bool infiniteSupply: true + property int supply: 1 + property int remainingTokens + + // Artwork related properties: + property url artworkSource + property rect artworkCropRect: Qt.rect(0, 0, 0, 0) + + // Network related properties: + property int chainId + property string chainName + property string chainIcon + + // Account related properties (from where they will be / have been deployed): + property string accountAddress + property string accountName + + // Contract transactions states: + property int deployState: Constants.ContractTransactionStatus.None + property int burnState: Constants.ContractTransactionStatus.None + + function copyToken(tokenObject) { + key = tokenObject.key + name = tokenObject.name + symbol = tokenObject.symbol + description = tokenObject.description + infiniteSupply = tokenObject.infiniteSupply + supply = tokenObject.supply + remainingTokens = tokenObject.remainingTokens + artworkSource = tokenObject.artworkSource + artworkCropRect = tokenObject.artworkCropRect + chainId = tokenObject.chainId + chainName = tokenObject.chainName + chainIcon = tokenObject.chainIcon + accountAddress = tokenObject.accountAddress + accountName = tokenObject.accountName + deployState = tokenObject.deployState + burnState = tokenObject.burnState + } +} diff --git a/ui/app/AppLayouts/Chat/helpers/qmldir b/ui/app/AppLayouts/Chat/helpers/qmldir index 224cd3d4b9..98ef325335 100644 --- a/ui/app/AppLayouts/Chat/helpers/qmldir +++ b/ui/app/AppLayouts/Chat/helpers/qmldir @@ -1 +1,4 @@ singleton CommunityPermissionsHelpers 1.0 CommunityPermissionsHelpers.qml +AssetObject 1.0 AssetObject.qml +CollectibleObject 1.0 CollectibleObject.qml +TokenObject 1.0 TokenObject.qml diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml index edf76b7d31..77ac24f80c 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml @@ -29,8 +29,8 @@ SettingsPageLayout { stackManager.pop(StackView.Immediate) } - function selectCollectible(key, amount) { - d.selectCollectible(key, amount) + function selectToken(key, amount, type) { + d.selectToken(key, amount, type) } function addAddresses(addresses) { @@ -46,7 +46,7 @@ SettingsPageLayout { readonly property string welcomePageTitle: qsTr("Airdrops") readonly property string newAirdropViewPageTitle: qsTr("New airdrop") - signal selectCollectible(string key, int amount) + signal selectToken(string key, int amount, int type) signal addAddresses(var addresses) } @@ -116,7 +116,7 @@ SettingsPageLayout { onNavigateToMintTokenSettings: root.navigateToMintTokenSettings() Component.onCompleted: { - d.selectCollectible.connect(view.selectCollectible) + d.selectToken.connect(view.selectToken) d.addAddresses.connect(view.addAddresses) } } diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml index 7abe3c8a0e..a8b4545800 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityMintTokensSettingsPanel.qml @@ -12,6 +12,7 @@ import StatusQ.Controls 0.1 import AppLayouts.Chat.layouts 1.0 import AppLayouts.Chat.views.communities 1.0 import AppLayouts.Chat.popups.community 1.0 +import AppLayouts.Chat.helpers 1.0 import utils 1.0 import SortFilterProxyModel 0.2 @@ -19,9 +20,15 @@ import SortFilterProxyModel 0.2 SettingsPageLayout { id: root + // General properties: + property string communityName + property int viewWidth: 560 // by design + // Models: property var tokensModel + property var accounts // Expected roles: address, name, color, emoji + // Transaction related properties: property string feeText property string errorText property bool isFeeLoading: true @@ -33,57 +40,18 @@ SettingsPageLayout { property var enabledNetworks property var allNetworks - // Account expected roles: address, name, color, emoji - property var accounts - - property string communityName - - property int viewWidth: 560 // by design - - signal mintCollectible(url artworkSource, - string name, - string symbol, - string description, - int supply, - bool infiniteSupply, - bool transferable, - bool selfDestruct, - int chainId, - string accountName, - string accountAddress, - var artworkCropRect) - - signal mintAsset(url artworkSource, - string name, - string symbol, - string description, - int supply, - bool infiniteSupply, - int decimals, - int chainId, - string accountName, - string accountAddress, - var artworkCropRect) - + signal mintCollectible(var collectibleItem) + signal mintAsset(var assetItem) signal signMintTransactionOpened(int chainId, string accountAddress) - - signal signSelfDestructTransactionOpened(var selfDestructTokensList, // [key , amount] - string tokenKey) - - signal remoteSelfDestructCollectibles(var selfDestructTokensList, // [key , amount] - string tokenKey) - + signal signRemoteDestructTransactionOpened(var remotelyDestructTokensList, // [key , amount] + string tokenKey) + signal remotelyDestructCollectibles(var remotelyDestructTokensList, // [key , amount] + string tokenKey) signal signBurnTransactionOpened(int chainId) - - signal burnCollectibles(string tokenKey, - int amount) - - signal airdropCollectible(string tokenKey, var addresses) - + signal burnToken(string tokenKey, int amount) + signal airdropToken(string tokenKey, int type, var addresses) signal deleteToken(string tokenKey) - signal retryMintToken(string tokenKey) - function setFeeLoading() { root.isFeeLoading = true root.feeText = "" @@ -108,15 +76,13 @@ SettingsPageLayout { readonly property string newTokenButtonText: qsTr("Mint token") readonly property string backButtonText: qsTr("Back") - property string accountAddress property string accountName property int chainId property string chainName - property string contractUniqueKey property var tokenOwnersModel - property var selfDestructTokensList - property bool selfDestruct + property var remotelyDestructTokensList + property bool remotelyDestruct property bool burnEnabled property string tokenKey property int burnAmount @@ -124,11 +90,9 @@ SettingsPageLayout { property url artworkSource readonly property var initialItem: (root.tokensModel && root.tokensModel.count > 0) ? mintedTokensView : welcomeView - onInitialItemChanged: updateInitialStackView() signal airdropClicked() signal remoteDestructAddressClicked(string address) - signal retryMintClicked() function updateInitialStackView() { @@ -139,6 +103,8 @@ SettingsPageLayout { stackManager.stackView.replace(welcomeView, mintedTokensView, StackView.Immediate) } } + + onInitialItemChanged: updateInitialStackView() } secondaryHeaderButton.type: StatusBaseButton.Type.Danger @@ -244,7 +210,7 @@ SettingsPageLayout { Binding { target: root property: "title" - value: optionsTab.currentItem === collectiblesTab ? d.newCollectiblePageTitle : d.newAssetPageTitle + value: optionsTab.currentItem == collectiblesTab ? d.newCollectiblePageTitle : d.newAssetPageTitle } } @@ -252,9 +218,14 @@ SettingsPageLayout { Layout.preferredWidth: root.viewWidth Layout.fillHeight: true - currentIndex: optionsTab.currentItem === collectiblesTab ? 0 : 1 + currentIndex: optionsTab.currentItem == collectiblesTab ? 0 : 1 - CommunityNewTokenView { + CustomCommunityNewTokenView {} + + CustomCommunityNewTokenView { isAssetView: true } + + component CustomCommunityNewTokenView: CommunityNewTokenView { + isAssetView: false viewWidth: root.viewWidth layer1Networks: root.layer1Networks layer2Networks: root.layer2Networks @@ -265,60 +236,13 @@ SettingsPageLayout { tokensModel: root.tokensModel onPreviewClicked: { - d.accountAddress = accountAddress stackManager.push(d.previewTokenViewState, previewTokenView, { - preview: true, - isAssetView: false, - name, - artworkSource, - artworkCropRect, - symbol, - description, - supplyAmount, - infiniteSupply, - transferable: !notTransferable, - selfDestruct, - chainId, - chainName, - chainIcon, - accountName - }, - StackView.Immediate) - } - } - - CommunityNewTokenView { - viewWidth: root.viewWidth - layer1Networks: root.layer1Networks - layer2Networks: root.layer2Networks - testNetworks: root.testNetworks - enabledNetworks: root.testNetworks - allNetworks: root.allNetworks - accounts: root.accounts - tokensModel: root.tokensModel - isAssetView: true - - onPreviewClicked: { - d.accountAddress = accountAddress - stackManager.push(d.previewTokenViewState, - previewTokenView, - { - preview: true, - isAssetView: true, - name, - artworkSource, - artworkCropRect, - symbol, - description, - supplyAmount, - infiniteSupply, - assetDecimals, - chainId, - chainName, - chainIcon, - accountName + preview : true, + isAssetView, + asset, + collectible }, StackView.Immediate) } @@ -335,40 +259,17 @@ SettingsPageLayout { function signMintTransaction() { root.setFeeLoading() - if(preview.isAssetView) { - root.mintAsset(artworkSource, - name, - symbol, - description, - supplyAmount, - infiniteSupply, - assetDecimals, - chainId, - accountName, - d.accountAddress, - artworkCropRect) - } else { - root.mintCollectible(artworkSource, - name, - symbol, - description, - supplyAmount, - infiniteSupply, - transferable, - selfDestruct, - chainId, - accountName, - d.accountAddress, - artworkCropRect) - } + if(preview.isAssetView) + root.mintAsset(asset) + else + root.mintCollectible(collectible) stackManager.clear(d.initialViewState, StackView.Immediate) } viewWidth: root.viewWidth - onMintCollectible: popup.open() - onMintAsset: popup.open() + onMintClicked: signMintPopup.open() Binding { target: root @@ -384,10 +285,10 @@ SettingsPageLayout { } SignTokenTransactionsPopup { - id: popup + id: signMintPopup anchors.centerIn: Overlay.overlay - title: qsTr("Sign transaction - Mint %1 token").arg(popup.tokenName) + title: qsTr("Sign transaction - Mint %1 token").arg(signMintPopup.tokenName) tokenName: preview.name accountName: preview.accountName networkName: preview.chainName @@ -397,7 +298,7 @@ SettingsPageLayout { onOpened: { root.setFeeLoading() - root.signMintTransactionOpened(preview.chainId, d.accountAddress) + root.signMintTransactionOpened(preview.chainId, preview.accountAddress) } onCancelClicked: close() onSignTransactionClicked: preview.signMintTransaction() @@ -419,7 +320,7 @@ SettingsPageLayout { airdropEnabled: true retailEnabled: false - remotelySelfDestructVisible: d.selfDestruct + remotelySelfDestructVisible: d.remotelyDestruct burnVisible: d.burnEnabled onAirdropClicked: d.airdropClicked() @@ -434,7 +335,7 @@ SettingsPageLayout { destroyOnClose: false onRemotelyDestructClicked: { - d.selfDestructTokensList = selfDestructTokensList + d.remotelyDestructTokensList = remotelyDestructTokensList alertPopup.tokenCount = tokenCount alertPopup.open() } @@ -465,9 +366,9 @@ SettingsPageLayout { function signTransaction() { root.setFeeLoading() if(signTransactionPopup.isRemotelyDestructTransaction) { - root.remoteSelfDestructCollectibles(d.selfDestructTokensList, d.tokenKey) + root.remotelyDestructCollectibles(d.remotelyDestructTokensList, d.tokenKey) } else { - root.burnCollectibles(d.tokenKey, d.burnAmount) + root.burnToken(d.tokenKey, d.burnAmount) } footerPanel.closePopups() @@ -484,7 +385,7 @@ SettingsPageLayout { onOpened: { root.setFeeLoading() - signTransactionPopup.isRemotelyDestructTransaction ? root.signSelfDestructTransactionOpened(d.selfDestructTokensList, d.tokenKey) : + signTransactionPopup.isRemotelyDestructTransaction ? root.signRemoteDestructTransactionOpened(d.remotelyDestructTokensList, d.tokenKey) : root.signBurnTransactionOpened(d.chainId) } onCancelClicked: close() @@ -524,28 +425,18 @@ SettingsPageLayout { viewWidth: root.viewWidth model: root.tokensModel onItemClicked: { - d.accountAddress = accountAddress d.chainId = chainId d.chainName = chainName d.accountName = accountName - d.tokenKey = contractUniqueKey + d.tokenKey = tokenKey stackManager.push(d.tokenViewState, tokenView, { preview: false, - contractUniqueKey + tokenKey }, StackView.Immediate) } - - Connections { - target: d - - function onRetryMintClicked() { - root.retryMintToken(d.tokenKey) - stackManager.clear(d.initialViewState, StackView.Immediate) - } - } } } @@ -555,9 +446,12 @@ SettingsPageLayout { CommunityTokenView { id: view - property string contractUniqueKey + property string airdropKey // TO REMOVE: Temporal property until airdrop backend is not ready to use token key instead of symbol + property int tokenType viewWidth: root.viewWidth + collectible: CollectibleObject{} + asset: AssetObject{} Binding { target: root @@ -604,8 +498,8 @@ SettingsPageLayout { Binding { target: d - property: "selfDestruct" - value: view.selfDestruct + property: "remotelyDestruct" + value: view.collectible.remotelyDestruct } Binding { @@ -634,40 +528,68 @@ SettingsPageLayout { sourceModel: root.tokensModel filters: ValueFilter { roleName: "contractUniqueKey" - value: view.contractUniqueKey + value: d.tokenKey } } delegate: QtObject { component Bind: Binding { target: view } readonly property list bindings: [ Bind { property: "isAssetView"; value: model.tokenType === Constants.TokenType.ERC20 }, - Bind { property: "deployState"; value: model.deployState }, - Bind { property: "remotelyDestructState"; value: model.remotelyDestructState }, - Bind { property: "burnState"; value: model.burnState }, - Bind { property: "name"; value: model.name }, - Bind { property: "artworkSource"; value: model.image }, - Bind { property: "symbol"; value: model.symbol }, - Bind { property: "description"; value: model.description }, - Bind { property: "supplyAmount"; value: model.supply }, - Bind { property: "infiniteSupply"; value: model.infiniteSupply }, - Bind { property: "remainingTokens"; value: model.remainingTokens }, - Bind { property: "selfDestruct"; value: model.remoteSelfDestruct }, - Bind { property: "chainId"; value: model.chainId }, - Bind { property: "chainName"; value: model.chainName }, - Bind { property: "chainIcon"; value: model.chainIcon }, - Bind { property: "accountName"; value: model.accountName }, Bind { property: "tokenOwnersModel"; value: model.tokenOwnersModel }, - Bind { property: "assetDecimals"; value: model.decimals } + Bind { property: "tokenType"; value: model.tokenType }, + Bind { property: "airdropKey"; value: model.symbol } // TO BE REMOVED: When airdrop backend is ready to use token key instead of symbol + ] + + component BindCollectible: Binding { target: view.collectible } + readonly property list collectibleBindings: [ + BindCollectible { property: "key"; value: model.contractUniqueKey }, + BindCollectible { property: "deployState"; value: model.deployState }, + BindCollectible { property: "burnState"; value: model.burnState }, + BindCollectible { property: "name"; value: model.name }, + BindCollectible { property: "artworkSource"; value: model.image }, + BindCollectible { property: "symbol"; value: model.symbol }, + BindCollectible { property: "description"; value: model.description }, + BindCollectible { property: "supply"; value: model.supply }, + BindCollectible { property: "infiniteSupply"; value: model.infiniteSupply }, + BindCollectible { property: "remainingTokens"; value: model.remainingTokens }, + BindCollectible { property: "chainId"; value: model.chainId }, + BindCollectible { property: "chainName"; value: model.chainName }, + BindCollectible { property: "chainIcon"; value: model.chainIcon }, + BindCollectible { property: "accountName"; value: model.accountName }, + BindCollectible { property: "accountAddress"; value: model.accountAddress }, // TODO: Backend + BindCollectible { property: "transferable"; value: model.transferable }, + BindCollectible { property: "remotelyDestructState"; value: model.remotelyDestructState }, + BindCollectible { property: "remotelyDestruct"; value: model.remoteSelfDestruct } + ] + + component BindAsset: Binding { target: view.asset } + readonly property list assetBindings: [ + BindAsset { property: "key"; value: model.contractUniqueKey }, + BindAsset { property: "deployState"; value: model.deployState }, + BindAsset { property: "burnState"; value: model.burnState }, + BindAsset { property: "name"; value: model.name }, + BindAsset { property: "artworkSource"; value: model.image }, + BindAsset { property: "symbol"; value: model.symbol }, + BindAsset { property: "description"; value: model.description }, + BindAsset { property: "supply"; value: model.supply }, + BindAsset { property: "infiniteSupply"; value: model.infiniteSupply }, + BindAsset { property: "remainingTokens"; value: model.remainingTokens }, + BindAsset { property: "chainId"; value: model.chainId }, + BindAsset { property: "chainName"; value: model.chainName }, + BindAsset { property: "chainIcon"; value: model.chainIcon }, + BindAsset { property: "accountName"; value: model.accountName }, + BindCollectible { property: "accountAddress"; value: model.accountAddress }, // TODO: Backend + BindAsset { property: "decimals"; value: model.decimals } ] } } onGeneralAirdropRequested: { - root.airdropCollectible(view.symbol, []) + root.airdropToken(view.airdropKey, view.tokenType, []) // d.tokenKey instead when backend airdrop ready to use key instead of symbol } onAirdropRequested: { - root.airdropCollectible(view.symbol, [address]) + root.airdropToken(view.airdropKey, view.tokenType, [address]) // d.tokenKey instead when backend airdrop ready to use key instead of symbol } onRemoteDestructRequested: { @@ -679,7 +601,9 @@ SettingsPageLayout { // handle airdrop request from the footer function onAirdropClicked() { - root.airdropCollectible(view.symbol, []) // TODO: Backend. It should just be the key (hash(chainId + contractAddress) + root.airdropToken(view.airdropKey, // d.tokenKey instead when backend airdrop ready to use key instead of symbol + view.tokenType, + []) } } } diff --git a/ui/app/AppLayouts/Chat/popups/community/RemotelyDestructPopup.qml b/ui/app/AppLayouts/Chat/popups/community/RemotelyDestructPopup.qml index 47dacdc469..5c4e49ada2 100644 --- a/ui/app/AppLayouts/Chat/popups/community/RemotelyDestructPopup.qml +++ b/ui/app/AppLayouts/Chat/popups/community/RemotelyDestructPopup.qml @@ -20,7 +20,7 @@ StatusDialog { property string collectibleName - signal remotelyDestructClicked(int tokenCount, var selfDestructTokensList) + signal remotelyDestructClicked(int tokenCount, var remotelyDestructTokensList) QtObject { id: d diff --git a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml index 3554c78b99..bc01506765 100644 --- a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml @@ -305,48 +305,18 @@ StatusSectionLayout { onPreviousPageNameChanged: root.backButtonName = previousPageName onSignMintTransactionOpened: communityTokensStore.computeDeployFee(chainId, accountAddress) - onMintCollectible: { - communityTokensStore.deployCollectible(root.community.id, - accountAddress, - name, - symbol, - description, - supply, - infiniteSupply, - transferable, - selfDestruct, - chainId, - artworkSource, - accountName, - artworkCropRect) - } - onMintAsset: { - communityTokensStore.deployAsset(root.community.id, - accountAddress, - name, - symbol, - description, - supply, - infiniteSupply, - decimals, - chainId, - artworkSource, - accountName, - artworkCropRect) - } - onSignSelfDestructTransactionOpened: communityTokensStore.computeSelfDestructFee(selfDestructTokensList, tokenKey) - onRemoteSelfDestructCollectibles: { + onMintCollectible: communityTokensStore.deployCollectible(root.community.id, collectibleItem) + onMintAsset: communityTokensStore.deployAsset(root.community.id, assetItem) + onSignRemoteDestructTransactionOpened: communityTokensStore.computeSelfDestructFee(remotelyDestructTokensList, tokenKey) + onRemotelyDestructCollectibles: { communityTokensStore.remoteSelfDestructCollectibles(root.community.id, - selfDestructTokensList, + remotelyDestructTokensList, tokenKey) } onSignBurnTransactionOpened: communityTokensStore.computeBurnFee(chainId) - onBurnCollectibles: communityTokensStore.burnCollectibles(tokenKey, amount) - onAirdropCollectible: { - root.goTo(Constants.CommunitySettingsSections.Airdrops) - } + onBurnToken: communityTokensStore.burnToken(tokenKey, amount) + onAirdropToken: root.goTo(Constants.CommunitySettingsSections.Airdrops) onDeleteToken: communityTokensStore.deleteToken(root.community.id, tokenKey) - onRetryMintToken: communityTokensStore.retryMintToken(root.community.id, tokenKey) Connections { target: rootStore.communityTokensStore @@ -480,13 +450,13 @@ StatusSectionLayout { Connections { target: mintPanel - function onAirdropCollectible(key, addresses) { + function onAirdropToken(tokenKey, type, addresses) { // Here it is forced a navigation to the new airdrop form, like if it was clicked the header button airdropPanel.primaryHeaderButtonClicked() // Force a token selection to be airdroped with default amount 1 - airdropPanel.selectCollectible(key, 1) - + airdropPanel.selectToken(tokenKey, 1, type) + // Set given addresses as recipients airdropPanel.addAddresses(addresses) } diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityMintedTokensView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityMintedTokensView.qml index dc22da6313..825a9d3ddd 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityMintedTokensView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityMintedTokensView.qml @@ -17,7 +17,7 @@ StatusScrollView { property int viewWidth: 560 // by design property var model - signal itemClicked(string contractUniqueKey, + signal itemClicked(string tokenKey, int chainId, string chainName, string accountName, diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml index 00ac091e24..baeaa41aad 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml @@ -37,11 +37,17 @@ StatusScrollView { signal airdropClicked(var airdropTokens, var addresses, var membersPubKeys) signal navigateToMintTokenSettings - function selectCollectible(key, amount) { - const modelItem = CommunityPermissionsHelpers.getTokenByKey( - root.collectiblesModel, key) + function selectToken(key, amount, type) { + var tokenModel = null + if(type === Constants.TokenType.ERC20) + tokenModel = root.assetsModel + else if (type === Constants.TokenType.ERC721) + tokenModel = root.collectiblesModel - const entry = d.prepareEntry(key, amount) + const modelItem = CommunityPermissionsHelpers.getTokenByKey( + tokenModel, key) + + const entry = d.prepareEntry(key, amount, type) entry.valid = true selectedHoldingsModel.append(entry) } @@ -57,9 +63,14 @@ StatusScrollView { readonly property int dropdownHorizontalOffset: 4 readonly property int dropdownVerticalOffset: 1 - function prepareEntry(key, amount) { - const modelItem = CommunityPermissionsHelpers.getTokenByKey( - root.collectiblesModel, key) + function prepareEntry(key, amount, type) { + var tokenModel = null + if(type === Constants.TokenType.ERC20) + tokenModel = root.assetsModel + else if (type === Constants.TokenType.ERC721) + tokenModel = root.collectiblesModel + + const modelItem = CommunityPermissionsHelpers.getTokenByKey(tokenModel, key) return { key, amount, @@ -170,7 +181,7 @@ StatusScrollView { } onAddCollectible: { - const entry = d.prepareEntry(key, amount) + const entry = d.prepareEntry(key, amount, Constants.TokenType.ERC721) entry.valid = true selectedHoldingsModel.append(entry) @@ -180,7 +191,7 @@ StatusScrollView { onUpdateCollectible: { const itemIndex = prepareUpdateIndex(key) - const entry = d.prepareEntry(key, amount) + const entry = d.prepareEntry(key, amount, Constants.TokenType.ERC721) const modelItem = CommunityPermissionsHelpers.getTokenByKey( root.collectiblesModel, key) diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewTokenView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewTokenView.qml index 692dcbc2f2..9a6869c8d5 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewTokenView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewTokenView.qml @@ -10,6 +10,7 @@ import StatusQ.Core.Utils 0.1 as SQUtils import utils 1.0 +import AppLayouts.Chat.helpers 1.0 import AppLayouts.Wallet.controls 1.0 import shared.panels 1.0 import shared.popups 1.0 @@ -21,26 +22,10 @@ StatusScrollView { property int viewWidth: 560 // by design property bool isAssetView: false - - // Token properties - readonly property alias name: nameInput.text - readonly property alias symbol: symbolInput.text - readonly property alias description: descriptionInput.text - readonly property alias infiniteSupply: unlimitedSupplyChecker.checked - readonly property int supplyAmount: supplyInput.text ? parseInt(supplyInput.text) : 0 - property alias artworkSource: dropAreaItem.artworkSource - property alias artworkCropRect: dropAreaItem.artworkCropRect - property int chainId - property string chainName - property string chainIcon property var tokensModel - // Collectible properties (ERC721) - readonly property alias notTransferable: transferableChecker.checked - readonly property alias selfDestruct: selfDestructChecker.checked - - // Asset properties (ERC20) - readonly property int assetDecimals: assetDecimalsInput.text ? parseInt(assetDecimalsInput.text) : 0 + property CollectibleObject collectible: CollectibleObject{} + property AssetObject asset: AssetObject{} // Network related properties: property var layer1Networks @@ -49,11 +34,8 @@ StatusScrollView { property var enabledNetworks property var allNetworks - // Account related properties: // Account expected roles: address, name, color, emoji property var accounts - readonly property string accountAddress: accountsComboBox.address - readonly property string accountName: accountsComboBox.control.displayText signal chooseArtWork signal previewClicked @@ -61,12 +43,12 @@ StatusScrollView { QtObject { id: d - readonly property bool isFullyFilled: root.artworkSource.toString().length > 0 + readonly property bool isFullyFilled: dropAreaItem.artworkSource.toString().length > 0 && nameInput.valid && descriptionInput.valid && symbolInput.valid - && (root.infiniteSupply || (!root.infiniteSupply && root.supplyAmount > 0)) - && (!root.isAssetView || (root.isAssetView&& assetDecimalsInput.valid)) + && (unlimitedSupplyChecker.checked || (!unlimitedSupplyChecker.checked && parseInt(supplyInput.text) > 0)) + && (!root.isAssetView || (root.isAssetView && assetDecimalsInput.valid)) readonly property int imageSelectorRectWidth: root.isAssetView ? 128 : 290 } @@ -87,8 +69,10 @@ StatusScrollView { DropAndEditImagePanel { id: dropAreaItem + Layout.fillWidth: true Layout.preferredHeight: d.imageSelectorRectWidth + artworkSource: root.isAssetView ? assetObj.artworkSource : collectibleObj.artworkSource editorAnchorLeft: !root.isAssetView editorRoundedImage: root.isAssetView uploadTextLabel.uploadText: root.isAssetView ? qsTr("Upload") : qsTr("Drag and Drop or Upload Artwork") @@ -96,24 +80,46 @@ StatusScrollView { uploadTextLabel.showAdditionalInfo: !root.isAssetView editorTitle: root.isAssetView ? qsTr("Asset icon") : qsTr("Collectible artwork") acceptButtonText: root.isAssetView ? qsTr("Upload asset icon") : qsTr("Upload collectible artwork") + + onArtworkSourceChanged: { + if(root.isAssetView) + asset.artworkSource = artworkSource + else + collectible.artworkSource = artworkSource + } + onArtworkCropRectChanged: { + if(root.isAssetView) + asset.artworkCropRect = artworkCropRect + else + collectible.artworkCropRect = artworkCropRect + } } CustomStatusInput { id: nameInput label: qsTr("Name") + text: root.isAssetView ? asset.name : collectible.name charLimit: 15 placeholderText: qsTr("Name") minLengthValidator.errorMessage: qsTr("Please name your token name (use A-Z and 0-9, hyphens and underscores only)") regexValidator.errorMessage: qsTr("Your token name contains invalid characters (use A-Z and 0-9, hyphens and underscores only)") extraValidator.validate: function (value) { return !SQUtils.ModelUtils.contains(root.tokensModel, "name", nameInput.text) } extraValidator.errorMessage: qsTr("You have used this token name before") + + onTextChanged: { + if(root.isAssetView) + asset.name = text + else + collectible.name = text + } } CustomStatusInput { id: descriptionInput label: qsTr("Description") + text: root.isAssetView ? asset.description : collectible.description charLimit: 280 placeholderText: root.isAssetView ? qsTr("Describe your asset") : qsTr("Describe your collectible") input.multiline: true @@ -124,12 +130,20 @@ StatusScrollView { minLengthValidator.errorMessage: qsTr("Please enter a token description") regexValidator.regularExpression: Constants.regularExpressions.asciiPrintable regexValidator.errorMessage: qsTr("Only A-Z, 0-9 and standard punctuation allowed") + + onTextChanged: { + if(root.isAssetView) + asset.description = text + else + collectible.description = text + } } CustomStatusInput { id: symbolInput label: qsTr("Symbol") + text: root.isAssetView ? asset.symbol : collectible.symbol charLimit: 6 placeholderText: qsTr("e.g. DOODLE") minLengthValidator.errorMessage: qsTr("Please enter your token symbol (use A-Z only)") @@ -137,6 +151,13 @@ StatusScrollView { regexValidator.regularExpression: Constants.regularExpressions.capitalOnly extraValidator.validate: function (value) { return !SQUtils.ModelUtils.contains(root.tokensModel, "symbol", symbolInput.text) } extraValidator.errorMessage: qsTr("You have used this token symbol before") + + onTextChanged: { + if(root.isAssetView) + asset.symbol = text + else + collectible.symbol = text + } } CustomLabelDescriptionComponent { @@ -146,11 +167,15 @@ StatusScrollView { } StatusEmojiAndColorComboBox { - id: accountsComboBox + id: accountBox readonly property string address: SQUtils.ModelUtils.get(root.accounts, currentIndex, "address") + readonly property string initAccountName: root.isAssetView ? asset.accountName : collectible.accountName + readonly property int initIndex: SQUtils.ModelUtils.indexOf(root.accounts, "name", initAccountName) Layout.fillWidth: true + + currentIndex: (initIndex !== -1) ? initIndex : 0 model: SortFilterProxyModel { sourceModel: root.accounts proxyRoles: [ @@ -171,6 +196,19 @@ StatusScrollView { size: StatusComboBox.Size.Small implicitHeight: 44 defaultAssetName: "filled-account" + + onAddressChanged: { + if(root.isAssetView) + asset.accountAddress = address + else + collectible.accountAddress = address + } + control.onDisplayTextChanged: { + if(root.isAssetView) + asset.accountName = control.displayText + else + collectible.accountName = control.displayText + } } CustomNetworkFilterRowComponent { @@ -183,9 +221,16 @@ StatusScrollView { label: qsTr("Unlimited supply") description: qsTr("Enable to allow the minting of additional tokens in the future. Disable to specify a finite supply") - checked: true + checked: root.isAssetView ? asset.infiniteSupply : collectible.infiniteSupply - onCheckedChanged: if(!checked) supplyInput.forceActiveFocus() + onCheckedChanged: { + if(!checked) supplyInput.forceActiveFocus() + + if(root.isAssetView) + asset.infiniteSupply = checked + else + collectible.infiniteSupply = checked + } } CustomStatusInput { @@ -193,12 +238,20 @@ StatusScrollView { visible: !unlimitedSupplyChecker.checked label: qsTr("Total finite supply") + text: root.isAssetView ? asset.supply : collectible.supply placeholderText: qsTr("e.g. 300") minLengthValidator.errorMessage: qsTr("Please enter a total finite supply") regexValidator.errorMessage: qsTr("Your total finite supply contains invalid characters (use 0-9 only)") regexValidator.regularExpression: Constants.regularExpressions.numerical extraValidator.validate: function (value) { return parseInt(value) > 0 && parseInt(value) <= 999999999 } extraValidator.errorMessage: qsTr("Enter a number between 0 and 999,999,999") + + onTextChanged: { + if(root.isAssetView) + asset.supply = parseInt(text) + else + collectible.supply = parseInt(text) + } } CustomSwitchRowComponent { @@ -207,16 +260,19 @@ StatusScrollView { visible: !root.isAssetView label: checked ? qsTr("Not transferable (Soulbound)") : qsTr("Transferable") 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") - checked: true + checked: !collectible.transferable + + onCheckedChanged: collectible.transferable = !checked } CustomSwitchRowComponent { - id: selfDestructChecker + id: remotelyDestructChecker visible: !root.isAssetView label: qsTr("Remotely destructible") description: qsTr("Enable to allow you to destroy tokens remotely. Useful for revoking permissions from individuals") - checked: true + checked: !!collectible ? collectible.remotelyDestruct : true + onCheckedChanged: collectible.remotelyDestruct = checked } CustomStatusInput { @@ -227,11 +283,13 @@ StatusScrollView { charLimit: 2 charLimitLabel: qsTr("Max 10") placeholderText: "2" - text: "2" // Default value + text: !!asset ? asset.decimals : "" validationMode: StatusInput.ValidationMode.Always minLengthValidator.errorMessage: qsTr("Please enter how many decimals your token should have") regexValidator.errorMessage: qsTr("Your decimal amount contains invalid characters (use 0-9 only)") regexValidator.regularExpression: Constants.regularExpressions.numerical + + onTextChanged: asset.decimals = parseInt(text) } StatusButton { @@ -345,9 +403,15 @@ StatusScrollView { onToggleNetwork: (network) => { - root.chainId = network.chainId - root.chainName = network.chainName - root.chainIcon = network.iconUrl + if(root.isAssetView) { + asset.chainId = network.chainId + asset.chainName = network.chainName + asset.chainIcon = network.iconUrl + } else { + collectible.chainId = network.chainId + collectible.chainName = network.chainName + collectible.chainIcon = network.iconUrl + } } } } diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityTokenView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityTokenView.qml index b03b830061..0fdc3a1d19 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityTokenView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityTokenView.qml @@ -11,6 +11,7 @@ import StatusQ.Core.Utils 0.1 as StatusQUtils import utils 1.0 import shared.panels 1.0 +import AppLayouts.Chat.helpers 1.0 import AppLayouts.Chat.panels.communities 1.0 StatusScrollView { @@ -20,54 +21,24 @@ StatusScrollView { property bool preview: false property bool isAssetView: false - // Token properties - property alias artworkSource: image.source - property rect artworkCropRect - property string name - property alias symbol: symbolBox.value - property alias description: descriptionItem.text - property int supplyAmount - property int remainingTokens - property bool infiniteSupply + property CollectibleObject collectible + property AssetObject asset - property alias accountName: accountBox.value - property int chainId - property string chainIcon - property alias chainName: chainText.text + readonly property string name: root.isAssetView ? asset.name : collectible.name + readonly property string symbol: root.isAssetView ? asset.symbol : collectible.symbol + readonly property url artworkSource: root.isAssetView ? asset.artworkSource : collectible.artworkSource + readonly property bool infiniteSupply: root.isAssetView ? asset.infiniteSupply : collectible.infiniteSupply + readonly property int remainingTokens: root.isAssetView ? asset.remainingTokens : collectible.remainingTokens + readonly property int deployState: root.isAssetView ? asset.deployState : collectible.deployState + readonly property string accountName: root.isAssetView ? asset.accountName : collectible.accountName + readonly property string chainName: root.isAssetView ? asset.chainName : collectible.chainName + readonly property string chainId: root.isAssetView ? asset.chainId : collectible.chainId + readonly property string accountAddress: root.isAssetView ? asset.accountAddress : collectible.accountAddress + // Models: property var tokenOwnersModel - property int deployState: Constants.ContractTransactionStatus.None - property int burnState: Constants.ContractTransactionStatus.None - - // Collectible object properties (ERC721) - property bool transferable - property bool selfDestruct - property int remotelyDestructState: Constants.ContractTransactionStatus.None - - // Asset properties (ERC20) - property alias assetDecimals: decimalsBox.value - - signal mintCollectible(url artworkSource, - string name, - string symbol, - string description, - int supply, - bool infiniteSupply, - bool transferable, - bool selfDestruct, - int chainId, - string accountName) - - signal mintAsset(url artworkSource, - string name, - string symbol, - string description, - int supply, - bool infiniteSupply, - int decimals, - int chainId, - string accountName) + signal mintClicked() signal airdropRequested(string address) signal generalAirdropRequested @@ -80,6 +51,7 @@ StatusScrollView { readonly property int imageSelectorRectSize: root.isAssetView ? 104 : 280 readonly property int iconSize: 20 readonly property string infiniteSymbol: "∞" + readonly property int burnState: root.isAssetView ? asset.burnState : collectible.burnState function startAnimation(isBurn) { totalbox.highlighted = true @@ -87,13 +59,12 @@ StatusScrollView { if(isBurn) remainingBox.highlighted = true } + + onBurnStateChanged: if(burnState === Constants.ContractTransactionStatus.Completed) d.startAnimation(true) } padding: 0 - onRemotelyDestructStateChanged: if(remotelyDestructState === Constants.ContractTransactionStatus.Completed) d.startAnimation(false) - onBurnStateChanged: if(burnState === Constants.ContractTransactionStatus.Completed) d.startAnimation(true) - ColumnLayout { id: mainLayout @@ -105,9 +76,7 @@ StatusScrollView { (root.deployState === Constants.ContractTransactionStatus.Failed)) spacing: Style.current.halfPadding - StatusDotsLoadingIndicator { - visible: (root.deployState === Constants.ContractTransactionStatus.InProgress) - } + StatusDotsLoadingIndicator { visible: (root.deployState === Constants.ContractTransactionStatus.InProgress) } StatusIcon { visible: (root.deployState === Constants.ContractTransactionStatus.Failed) @@ -138,10 +107,13 @@ StatusScrollView { Image { id: image + property rect imageCropRect: root.isAssetView ? asset.artworkCropRect : collectible.artworkCropRect + anchors.fill: parent fillMode: Image.PreserveAspectFit visible: false - sourceClipRect: root.artworkCropRect ? root.artworkCropRect : undefined + source: root.artworkSource + sourceClipRect: imageCropRect ? imageCropRect : undefined } OpacityMask { @@ -234,16 +206,19 @@ StatusScrollView { id: symbolBox label: qsTr("Symbol") + value: root.symbol } CustomPreviewBox { id: totalbox + property int supply: root.isAssetView ? asset.supply : collectible.supply + label: qsTr("Total") - value: root.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(root.supplyAmount) + value: root.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(supply) isLoading: !root.infiniteSupply && - ((root.remotelyDestructState === Constants.ContractTransactionStatus.InProgress) || - (root.burnState === Constants.ContractTransactionStatus.InProgress)) + ((!root.isAssetView && collectible.remotelyDestructState === Constants.ContractTransactionStatus.InProgress) || + (d.burnState === Constants.ContractTransactionStatus.InProgress)) } CustomPreviewBox { @@ -251,32 +226,30 @@ StatusScrollView { label: qsTr("Remaining") value: root.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(root.remainingTokens) - isLoading: !root.infiniteSupply && (root.burnState === Constants.ContractTransactionStatus.InProgress) + isLoading: !root.infiniteSupply && (d.burnState === Constants.ContractTransactionStatus.InProgress) } CustomPreviewBox { - id: decimalsBox - visible: root.isAssetView label: qsTr("DP") + value: asset.decimals } CustomPreviewBox { visible: !root.isAssetView label: qsTr("Transferable") - value: root.transferable ? qsTr("Yes") : qsTr("No") + value: collectible.transferable ? qsTr("Yes") : qsTr("No") } CustomPreviewBox { visible: !root.isAssetView label: qsTr("Remotely destructible") - value: root.selfDestruct ? qsTr("Yes") : qsTr("No") + value: collectible.remotelyDestruct ? qsTr("Yes") : qsTr("No") } CustomPreviewBox { - id: accountBox - label: qsTr("Account") + value: root.accountName } Rectangle { @@ -294,18 +267,17 @@ StatusScrollView { spacing: Style.current.padding SVGImage { - id: chainIcon - Layout.alignment: Qt.AlignVCenter + height: 24 width: height - source: Style.svg(root.chainIcon) + source: Style.svg(root.isAssetView ? asset.chainIcon : collectible.chainIcon) } StatusBaseText { - id: chainText - Layout.alignment: Qt.AlignVCenter + + text: root.chainName font.pixelSize: 13 font.weight: Font.Medium color: Theme.palette.baseColor1 @@ -315,9 +287,9 @@ StatusScrollView { } StatusBaseText { - id: descriptionItem - Layout.fillWidth: true + + text: root.isAssetView ? asset.description : collectible.description wrapMode: TextEdit.WordWrap font.pixelSize: Theme.primaryTextFontSize lineHeight: 1.2 @@ -352,30 +324,7 @@ StatusScrollView { Layout.topMargin: Style.current.halfPadding text: qsTr("Mint") - onClicked: { - if(root.isAssetView) { - root.mintAsset(root.artworkSource, - root.name, - root.symbol, - root.description, - root.supplyAmount, - root.infiniteSupply, - root.assetDecimals, - root.chainId, - root.accountName) - } else { - root.mintCollectible(root.artworkSource, - root.name, - root.symbol, - root.description, - root.supplyAmount, - root.infiniteSupply, - root.transferable, - root.selfDestruct, - root.chainId, - root.accountName) - } - } + onClicked: root.mintClicked() } SortableTokenHoldersPanel { @@ -383,7 +332,7 @@ StatusScrollView { model: root.tokenOwnersModel tokenName: root.name - showRemotelyDestructMenuItem: !root.isAssetView && root.selfDestruct + showRemotelyDestructMenuItem: !root.isAssetView && collectible.remotelyDestruct Layout.topMargin: Style.current.padding Layout.fillWidth: true @@ -393,4 +342,12 @@ StatusScrollView { onRemoteDestructRequested: root.remoteDestructRequested(address) } } + + Connections { + target: collectible + + function onRemotelyDestructStateChanged() { + if(collectible.remotelyDestructState === Constants.ContractTransactionStatus.Completed) d.startAnimation(false) + } + } } diff --git a/ui/imports/shared/stores/CommunityTokensStore.qml b/ui/imports/shared/stores/CommunityTokensStore.qml index 9190c417d8..13ac337bdd 100644 --- a/ui/imports/shared/stores/CommunityTokensStore.qml +++ b/ui/imports/shared/stores/CommunityTokensStore.qml @@ -23,22 +23,26 @@ QtObject { signal remoteDestructStateChanged(string communityId, string tokenName, int status, string url) // Minting tokens: - function deployCollectible(communityId, accountAddress, name, symbol, description, supply, - infiniteSupply, transferable, selfDestruct, chainId, artworkSource, accountName, artworkCropRect) - { + function deployCollectible(communityId, collectibleItem) + { // TODO: Backend needs to create new role `accountName` and update this call accordingly + // TODO: Backend will need to check if the collectibleItem has a valid tokenKey, so it means a deployment retry, + // otherwise, it is a new deployment. // TODO: Backend needs to modify the call to expect an image JSON file with cropped artwork information: - const jsonArtworkFile = Utils.getImageAndCropInfoJson(artworkSource, artworkCropRect) - communityTokensModuleInst.deployCollectible(communityId, accountAddress, name, symbol, description, supply, - infiniteSupply, transferable, selfDestruct, chainId, artworkSource/*instead: jsonArtworkFile*/) + const jsonArtworkFile = Utils.getImageAndCropInfoJson(collectibleItem.artworkSource, collectibleItem.artworkCropRect) + communityTokensModuleInst.deployCollectible(communityId, collectibleItem.accountAddress, collectibleItem.name, + collectibleItem.symbol, collectibleItem.description, collectibleItem.supply, + collectibleItem.infiniteSupply, collectibleItem.transferable, collectibleItem.remotelyDestruct, + collectibleItem.chainId, collectibleItem.artworkSource/*instead: jsonArtworkFile*/) } - function deployAsset(communityId, accountAddress, name, symbol, description, supply, - infiniteSupply, decimals, chainId, artworkSource, accountName, artworkCropRect) + function deployAsset(communityId, assetItem) { // TODO: Backend needs to create new role `accountName` and update this call accordingly + // TODO: Backend will need to check if the collectibleItem has a valid tokenKey, so it means a deployment retry, + // otherwise, it is a new deployment. // TODO: Backend needs to modify the call to expect an image JSON file with cropped artwork information: - const jsonArtworkFile = Utils.getImageAndCropInfoJson(artworkSource, artworkCropRect) + const jsonArtworkFile = Utils.getImageAndCropInfoJson(assetItem.artworkSource, assetItem.artworkCropRect) console.log("TODO: Deploy Asset backend!") } @@ -46,10 +50,6 @@ QtObject { console.log("TODO: Delete token bakend!") } - function retryMintToken(communityId, contractUniqueKey) { - console.log("TODO: Retry mint token bakend!") - } - readonly property Connections connections: Connections { target: communityTokensModuleInst function onDeployFeeUpdated(ethCurrency, fiatCurrency, errorCode) { @@ -85,7 +85,7 @@ QtObject { console.warn("TODO: Compute burn fee backend") } - function burnCollectibles(tokenKey, burnAmount) { + function burnToken(tokenKey, burnAmount) { // TODO BACKEND console.warn("TODO: Burn collectible backend") }