feat(Communities): Add fee box and updated sign popup to standard minting flow

Closes: #11303
This commit is contained in:
Michał Cieślak 2023-07-27 22:29:31 +02:00 committed by Michał
parent f4d66a244e
commit 190a3b775e
5 changed files with 242 additions and 92 deletions

View File

@ -62,6 +62,8 @@ SplitView {
token: tokenObject
tokenOwnersModel: TokenHoldersModel {}
accounts: WalletAccountsModel {}
onMintClicked: logs.logEvent("CommunityTokenView::onMintClicked")
}

View File

@ -363,6 +363,10 @@ StackView {
referenceName: newTokenPage.referenceName
referenceSymbol: newTokenPage.referenceSymbol
feeText: root.feeText
feeErrorText: root.feeErrorText
isFeeLoading: root.isFeeLoading
onPreviewClicked: {
const properties = {
token: isAssetView ? asset : collectible
@ -371,6 +375,17 @@ StackView {
root.push(previewTokenViewComponent, properties,
StackView.Immediate)
}
onDeployFeesRequested: {
if (isAssetView)
root.deployFeesRequested(asset.chainId,
asset.accountAddress,
Constants.TokenType.ERC20)
else
root.deployFeesRequested(collectible.chainId,
collectible.accountAddress,
Constants.TokenType.ERC721)
}
}
}
}
@ -391,6 +406,20 @@ StackView {
contentItem: CommunityTokenView {
id: preview
viewWidth: root.viewWidth
preview: true
feeText: root.feeText
feeErrorText: root.feeErrorText
isFeeLoading: root.isFeeLoading
accounts: root.accounts
onDeployFeesRequested: root.deployFeesRequested(
token.chainId, token.accountAddress,
token.type)
onMintClicked: signMintPopup.open()
function signMintTransaction() {
root.setFeeLoading()
@ -402,32 +431,20 @@ StackView {
root.resetNavigation()
}
viewWidth: root.viewWidth
preview: true
onMintClicked: signMintPopup.open()
SignTokenTransactionsPopup {
SignMultiTokenTransactionsPopup {
id: signMintPopup
anchors.centerIn: Overlay.overlay
title: qsTr("Sign transaction - Mint %1 token").arg(
signMintPopup.tokenName)
tokenName: preview.name
accountName: preview.accountName
networkName: preview.chainName
feeText: root.feeText
errorText: root.feeErrorText
isFeeLoading: root.isFeeLoading
preview.token.name)
totalFeeText: root.isFeeLoading ? "" : root.feeText
accountName: preview.token.accountName
onOpened: {
root.setFeeLoading()
root.signMintTransactionOpened(
preview.chainId, preview.accountAddress,
preview.isAssetView ? Constants.TokenType.ERC20
: Constants.TokenType.ERC721)
model: QtObject {
readonly property string title: preview.feeLabel
readonly property string feeText: signMintPopup.totalFeeText
readonly property bool error: root.feeErrorText !== ""
}
onCancelClicked: close()
onSignTransactionClicked: preview.signMintTransaction()
}
}

View File

@ -347,9 +347,14 @@ StatusSectionLayout {
allNetworks: communityTokensStore.allNetworks
accounts: root.rootStore.accounts
onDeployFeesRequested:
onDeployFeesRequested: {
feeText = ""
feeErrorText = ""
isFeeLoading = true
communityTokensStore.computeDeployFee(
chainId, accountAddress, tokenType)
}
onMintCollectible:
communityTokensStore.deployCollectible(

View File

@ -14,6 +14,8 @@ import shared.panels 1.0
import AppLayouts.Communities.helpers 1.0
import AppLayouts.Communities.panels 1.0
import SortFilterProxyModel 0.2
StatusScrollView {
id: root
@ -47,9 +49,19 @@ StatusScrollView {
readonly property bool deploymentCompleted:
deployState === Constants.ContractTransactionStatus.Completed
readonly property string feeLabel:
isAssetView ? qsTr("Mint asset on %1").arg(token.chainName)
: qsTr("Mint collectible on %1").arg(token.chainName)
// Models:
property var tokenOwnersModel
// Required for preview mode:
property var accounts
property string feeText
property string feeErrorText
property bool isFeeLoading
signal mintClicked()
signal airdropRequested(string address)
@ -57,6 +69,8 @@ StatusScrollView {
signal remoteDestructRequested(string address)
signal deployFeesRequested
QtObject {
id: d
@ -124,12 +138,79 @@ StatusScrollView {
}
}
StatusButton {
FeesBox {
id: feesBox
Layout.fillWidth: true
Layout.topMargin: Style.current.padding
implicitWidth: 0
visible: root.preview
accountErrorText: root.feeErrorText
model: QtObject {
id: singleFeeModel
readonly property string title: root.feeLabel
readonly property string feeText: root.isFeeLoading ?
"" : root.feeText
readonly property bool error: root.feeErrorText !== ""
}
accountsSelector.model: SortFilterProxyModel {
sourceModel: root.accounts
proxyRoles: [
ExpressionRole {
name: "color"
function getColor(colorId) {
return Utils.getColorForId(colorId)
}
// Direct call for singleton function is not handled properly by
// SortFilterProxyModel that's why helper function is used instead.
expression: { return getColor(model.colorId) }
}
]
filters: ValueFilter {
roleName: "walletType"
value: Constants.watchWalletType
inverted: true
}
}
Component.onCompleted: {
const initIndex = StatusQUtils.ModelUtils.indexOf(
accountsSelector.model, "name",
token.accountName)
accountsSelector.currentIndex = (initIndex !== -1) ? initIndex : 0
accountsSelector.currentIndexChanged.connect(() => {
if (accountsSelector.currentIndex < 0)
return
const item = StatusQUtils.ModelUtils.get(
accountsSelector.model,
accountsSelector.currentIndex)
token.accountAddress = item.address
token.accountName = item.name
root.deployFeesRequested()
})
}
}
StatusButton {
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.topMargin: Style.current.halfPadding
visible: root.preview
enabled: !root.isFeeLoading && root.feeErrorText === ""
text: qsTr("Mint")
onClicked: root.mintClicked()

View File

@ -11,6 +11,7 @@ import StatusQ.Core.Utils 0.1 as SQUtils
import utils 1.0
import AppLayouts.Communities.helpers 1.0
import AppLayouts.Communities.panels 1.0
import AppLayouts.Wallet.controls 1.0
import shared.panels 1.0
import shared.popups 1.0
@ -26,7 +27,6 @@ StatusScrollView {
property var tokensModel
property var tokensModelWallet
property TokenObject collectible: TokenObject {
type: Constants.TokenType.ERC721
}
@ -49,8 +49,17 @@ StatusScrollView {
// Account expected roles: address, name, color, emoji, walletType
property var accounts
property string feeText
property string feeErrorText
property bool isFeeLoading
readonly property string feeLabel:
isAssetView ? qsTr("Mint asset on %1").arg(asset.chainName)
: qsTr("Mint collectible on %1").arg(collectible.chainName)
signal chooseArtWork
signal previewClicked
signal deployFeesRequested
QtObject {
id: d
@ -61,6 +70,7 @@ StatusScrollView {
&& symbolInput.valid
&& (unlimitedSupplyChecker.checked || (!unlimitedSupplyChecker.checked && parseInt(supplyInput.text) > 0))
&& (!root.isAssetView || (root.isAssetView && assetDecimalsInput.valid))
&& !root.isFeeLoading && root.feeErrorText === "" && !requestFeeDelayTimer.running
readonly property int imageSelectorRectWidth: root.isAssetView ? 128 : 290
@ -216,62 +226,6 @@ StatusScrollView {
}
}
CustomLabelDescriptionComponent {
Layout.topMargin: Style.current.padding
label: qsTr("Select account")
description: qsTr("Account will be required for all subsequent interactions with this token. Remember everybody in your community will be able to see this address.")
}
StatusEmojiAndColorComboBox {
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: [
ExpressionRole {
name: "color"
function getColor(colorId) {
return Utils.getColorForId(colorId)
}
// Direct call for singleton function is not handled properly by
// SortFilterProxyModel that's why helper function is used instead.
expression: { return getColor(model.colorId) }
}
]
filters: ValueFilter {
roleName: "walletType"
value: Constants.watchWalletType
inverted: true
}
}
type: StatusComboBox.Type.Secondary
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 {
id: networkSelector
@ -362,6 +316,98 @@ StatusScrollView {
onTextChanged: asset.decimals = parseInt(text)
}
FeesBox {
id: feesBox
Layout.fillWidth: true
Layout.topMargin: Style.current.padding
accountErrorText: root.feeErrorText
implicitWidth: 0
model: QtObject {
id: singleFeeModel
readonly property string title: root.feeLabel
readonly property string feeText: root.isFeeLoading ?
"" : root.feeText
readonly property bool error: root.feeErrorText !== ""
}
Timer {
id: requestFeeDelayTimer
interval: 500
onTriggered: root.deployFeesRequested()
}
readonly property bool triggerFeeReevaluation: {
dropAreaItem.artworkSource
nameInput.text
descriptionInput.text
symbolInput.text
supplyInput.text
unlimitedSupplyChecker.checked
transferableChecker.checked
remotelyDestructChecker.checked
feesBox.accountsSelector.currentIndex
asset.chainId
collectible.chainId
requestFeeDelayTimer.restart()
return true
}
accountsSelector.model: SortFilterProxyModel {
sourceModel: root.accounts
proxyRoles: [
ExpressionRole {
name: "color"
function getColor(colorId) {
return Utils.getColorForId(colorId)
}
// Direct call for singleton function is not handled properly by
// SortFilterProxyModel that's why helper function is used instead.
expression: { return getColor(model.colorId) }
}
]
filters: ValueFilter {
roleName: "walletType"
value: Constants.watchWalletType
inverted: true
}
}
readonly property TokenObject token: root.isAssetView ? root.asset
: root.collectible
// account can be changed also on preview page and it should be
// reflected in the form after navigating back
Connections {
target: feesBox.token
function onAccountAddressChanged() {
const idx = SQUtils.ModelUtils.indexOf(
feesBox.accountsSelector.model, "address",
feesBox.token.accountAddress)
feesBox.accountsSelector.currentIndex = idx
}
}
accountsSelector.onCurrentIndexChanged: {
if (accountsSelector.currentIndex < 0)
return
const item = SQUtils.ModelUtils.get(
accountsSelector.model, accountsSelector.currentIndex)
token.accountAddress = item.address
token.accountName = item.name
}
}
StatusButton {
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignHCenter
@ -481,18 +527,17 @@ StatusScrollView {
multiSelection: false
onToggleNetwork: (network) =>
{
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
}
}
onToggleNetwork: (network) => {
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
}
}
}
}
}