2023-06-22 21:24:30 +00:00
import QtQuick 2.15
import QtQuick . Controls 2.15
import QtQuick . Layouts 1.15
2023-03-09 11:12:49 +00:00
import QtQml 2.15
2023-03-07 11:32:45 +00:00
import StatusQ . Core . Theme 0.1
2023-05-22 13:00:40 +00:00
import StatusQ . Controls 0.1
2023-02-17 11:57:17 +00:00
2023-06-28 19:30:01 +00:00
import AppLayouts . Communities . controls 1.0
2023-06-23 06:17:04 +00:00
import AppLayouts . Communities . helpers 1.0
2023-06-28 22:11:58 +00:00
import AppLayouts . Communities . layouts 1.0
2023-06-28 19:30:01 +00:00
import AppLayouts . Communities . popups 1.0
import AppLayouts . Communities . views 1.0
2023-02-17 11:57:17 +00:00
import utils 1.0
2023-03-28 13:55:34 +00:00
import SortFilterProxyModel 0.2
2023-02-17 11:57:17 +00:00
2023-06-28 19:30:01 +00:00
StackView {
2023-02-17 11:57:17 +00:00
id: root
2023-06-01 10:38:56 +00:00
// General properties:
property string communityName
property int viewWidth: 560 // by design
2023-03-08 13:44:47 +00:00
// Models:
2023-02-17 11:57:17 +00:00
property var tokensModel
2023-06-20 10:12:56 +00:00
property var accounts // Expected roles: address, name, color, emoji, walletType
2023-04-13 08:09:06 +00:00
2023-06-01 10:38:56 +00:00
// Transaction related properties:
2023-03-23 13:17:07 +00:00
property string feeText
2023-04-03 11:29:36 +00:00
property string errorText
2023-03-23 13:17:07 +00:00
property bool isFeeLoading: true
2023-03-08 13:44:47 +00:00
// Network related properties:
property var layer1Networks
property var layer2Networks
property var testNetworks
property var enabledNetworks
property var allNetworks
2023-06-01 10:38:56 +00:00
signal mintCollectible ( var collectibleItem )
signal mintAsset ( var assetItem )
2023-06-28 19:30:01 +00:00
2023-06-14 07:50:54 +00:00
signal signMintTransactionOpened ( int chainId , string accountAddress , int tokenType )
2023-06-06 12:54:35 +00:00
2023-06-21 16:36:20 +00:00
signal signRemoteDestructTransactionOpened ( var remotelyDestructTokensList , // [key , amount]
string tokenKey )
signal remotelyDestructCollectibles ( var remotelyDestructTokensList , // [key , amount]
string tokenKey )
2023-06-06 12:54:35 +00:00
signal signBurnTransactionOpened ( string tokenKey , int amount )
2023-06-01 10:38:56 +00:00
signal burnToken ( string tokenKey , int amount )
2023-06-21 16:40:26 +00:00
signal airdropToken ( string tokenKey , int type , var addresses )
2023-05-30 15:18:45 +00:00
signal deleteToken ( string tokenKey )
2023-04-17 12:11:31 +00:00
function setFeeLoading ( ) {
root . isFeeLoading = true
root . feeText = ""
root . errorText = ""
}
2023-02-17 11:57:17 +00:00
function navigateBack ( ) {
2023-06-28 19:30:01 +00:00
pop ( StackView . Immediate )
2023-02-17 11:57:17 +00:00
}
2023-06-28 19:30:01 +00:00
function resetNavigation ( ) {
pop ( initialItem , StackView . Immediate )
2023-06-14 07:19:45 +00:00
}
2023-06-28 19:30:01 +00:00
function openNewTokenForm ( isAssetView ) {
resetNavigation ( )
const properties = { isAssetView }
root . push ( newTokenView , properties , StackView . Immediate )
2023-03-07 11:32:45 +00:00
}
2023-06-28 19:30:01 +00:00
property string previousPageName: depth > 1 ? qsTr ( "Back" ) : ""
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
initialItem: SettingsPage {
implicitWidth: 0
pageTitle: qsTr ( "Tokens" )
2023-06-22 21:24:30 +00:00
2023-06-28 19:30:01 +00:00
buttons: StatusButton {
text: qsTr ( "Mint token" )
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
onClicked: root . push ( newTokenView , StackView . Immediate )
}
2023-06-22 21:24:30 +00:00
2023-06-28 19:30:01 +00:00
contentItem: MintedTokensView {
model: root . tokensModel
2023-06-23 07:51:20 +00:00
2023-06-28 19:30:01 +00:00
onItemClicked: {
const properties = { preview: false , tokenKey }
root . push ( tokenView , properties , StackView . Immediate )
}
2023-06-09 11:50:22 +00:00
}
2023-05-30 15:18:45 +00:00
}
2023-06-28 19:30:01 +00:00
Component {
id: tokenObjectComponent
2023-03-09 11:12:49 +00:00
2023-06-28 19:30:01 +00:00
TokenObject { }
2023-03-09 11:12:49 +00:00
}
2023-02-17 11:57:17 +00:00
// Mint tokens possible view contents:
Component {
2023-05-22 13:00:40 +00:00
id: newTokenView
2023-02-17 11:57:17 +00:00
2023-06-28 19:30:01 +00:00
SettingsPage {
id: newTokenPage
2023-06-09 11:50:22 +00:00
2023-06-22 21:24:30 +00:00
property TokenObject asset: TokenObject {
type: TokenObject . Type . Asset
}
property TokenObject collectible: TokenObject {
type: TokenObject . Type . Collectible
}
2023-06-09 11:50:22 +00:00
property bool isAssetView: false
2023-06-09 16:42:35 +00:00
property int validationMode: StatusInput . ValidationMode . OnlyWhenDirty
property string referenceName: ""
property string referenceSymbol: ""
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
pageTitle: optionsTab . currentItem == assetsTab
? qsTr ( "Mint asset" ) : qsTr ( "Mint collectible" )
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
contentItem: ColumnLayout {
width: root . viewWidth
spacing: Style . current . padding
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
StatusSwitchTabBar {
id: optionsTab
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
Layout.preferredWidth: root . viewWidth
currentIndex: newTokenPage . isAssetView ? 1 : 0
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
StatusSwitchTabButton {
id: collectiblesTab
text: qsTr ( "Collectibles" )
}
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
StatusSwitchTabButton {
id: assetsTab
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
text: qsTr ( "Assets" )
}
2023-05-22 13:00:40 +00:00
}
2023-06-28 19:30:01 +00:00
StackLayout {
Layout.preferredWidth: root . viewWidth
Layout.fillHeight: true
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
currentIndex: optionsTab . currentItem == collectiblesTab ? 0 : 1
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
CustomEditCommunityTokenView {
id: newCollectibleView
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
isAssetView: false
validationMode: ! newTokenPage . isAssetView
? newTokenPage . validationMode
: StatusInput . ValidationMode . OnlyWhenDirty
collectible: newTokenPage . collectible
}
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
CustomEditCommunityTokenView {
id: newAssetView
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
isAssetView: true
validationMode: newTokenPage . isAssetView
? newTokenPage . validationMode
: StatusInput . ValidationMode . OnlyWhenDirty
asset: newTokenPage . asset
}
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
component CustomEditCommunityTokenView: EditCommunityTokenView {
viewWidth: root . viewWidth
layer1Networks: root . layer1Networks
layer2Networks: root . layer2Networks
testNetworks: root . testNetworks
enabledNetworks: root . testNetworks
allNetworks: root . allNetworks
accounts: root . accounts
tokensModel: root . tokensModel
referenceName: newTokenPage . referenceName
referenceSymbol: newTokenPage . referenceSymbol
onPreviewClicked: {
const properties = {
token: isAssetView ? asset : collectible
}
root . push ( previewTokenView , properties ,
StackView . Immediate )
2023-06-22 21:24:30 +00:00
}
2023-05-25 10:46:53 +00:00
}
2023-05-22 13:00:40 +00:00
}
2023-03-09 11:12:49 +00:00
}
2023-03-07 11:32:45 +00:00
}
}
Component {
2023-05-25 10:46:53 +00:00
id: previewTokenView
2023-03-07 11:32:45 +00:00
2023-06-28 19:30:01 +00:00
SettingsPage {
id: tokenPreviewPage
2023-03-07 11:32:45 +00:00
2023-06-28 19:30:01 +00:00
property alias token: preview . token
2023-03-23 13:17:07 +00:00
2023-06-28 19:30:01 +00:00
pageTitle: token . name
pageSubtitle: token . symbol
2023-05-15 12:49:26 +00:00
2023-06-28 19:30:01 +00:00
contentItem: CommunityTokenView {
id: preview
2023-03-23 13:17:07 +00:00
2023-06-28 19:30:01 +00:00
function signMintTransaction ( ) {
2023-04-03 11:29:36 +00:00
root . setFeeLoading ( )
2023-03-31 12:52:51 +00:00
2023-06-28 19:30:01 +00:00
if ( preview . isAssetView )
root . mintAsset ( token )
else
root . mintCollectible ( token )
2023-03-31 12:52:51 +00:00
2023-06-28 19:30:01 +00:00
root . resetNavigation ( )
2023-03-31 12:52:51 +00:00
}
2023-06-28 19:30:01 +00:00
viewWidth: root . viewWidth
preview: true
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
onMintClicked: signMintPopup . open ( )
2023-06-05 13:49:36 +00:00
2023-06-28 19:30:01 +00:00
SignTokenTransactionsPopup {
id: signMintPopup
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
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 . errorText
isFeeLoading: root . isFeeLoading
2023-03-31 12:52:51 +00:00
2023-06-28 19:30:01 +00:00
onOpened: {
root . setFeeLoading ( )
root . signMintTransactionOpened ( preview . chainId , preview . accountAddress ,
preview . isAssetView ? Constants . TokenType . ERC20
: Constants . TokenType . ERC721 )
2023-05-18 15:01:48 +00:00
}
2023-06-28 19:30:01 +00:00
onCancelClicked: close ( )
onSignTransactionClicked: preview . signMintTransaction ( )
2023-06-05 13:49:36 +00:00
}
}
2023-03-07 11:32:45 +00:00
}
}
2023-03-28 13:55:34 +00:00
Component {
2023-05-25 14:45:46 +00:00
id: tokenView
2023-03-28 13:55:34 +00:00
2023-06-28 19:30:01 +00:00
SettingsPage {
id: tokenViewPage
2023-03-28 13:55:34 +00:00
2023-06-28 19:30:01 +00:00
property string tokenKey
2023-03-28 13:55:34 +00:00
2023-06-28 19:30:01 +00:00
pageTitle: view . name
pageSubtitle: view . symbol
2023-06-22 21:24:30 +00:00
2023-06-28 19:30:01 +00:00
buttons: [
StatusButton {
text: qsTr ( "Delete" )
type: StatusBaseButton . Type . Danger
2023-03-28 13:55:34 +00:00
2023-06-28 19:30:01 +00:00
visible: view . deployState === Constants . ContractTransactionStatus . Failed
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
onClicked: deleteTokenAlertPopup . open ( )
} ,
StatusButton {
text: qsTr ( "Retry mint" )
2023-04-13 08:09:06 +00:00
2023-06-28 19:30:01 +00:00
visible: view . deployState === Constants . ContractTransactionStatus . Failed
2023-05-09 06:49:51 +00:00
2023-06-28 19:30:01 +00:00
onClicked: {
const isAssetView = view . isAssetView
2023-05-18 15:01:48 +00:00
2023-06-28 19:30:01 +00:00
// copy TokenObject
const tokenObject = tokenObjectComponent . createObject (
null , view . token )
2023-05-18 15:01:48 +00:00
2023-06-28 19:30:01 +00:00
// Then move on to the new token view, but token pre-filled:
const properties = {
isAssetView ,
referenceName: tokenObject . name ,
referenceSymbol: tokenObject . symbol ,
validationMode: StatusInput . ValidationMode . Always ,
[ isAssetView ? "asset" : "collectible" ] : tokenObject
}
2023-05-18 15:01:48 +00:00
2023-06-28 19:30:01 +00:00
const tokenView = root . push ( newTokenView , properties ,
StackView . Immediate )
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
// cleanup dynamically created TokenObject
tokenView . Component . destruction . connect ( ( ) = > tokenObject . destroy ( ) )
}
}
]
2023-06-09 11:50:22 +00:00
2023-03-28 13:55:34 +00:00
Instantiator {
id: instantiator
model: SortFilterProxyModel {
sourceModel: root . tokensModel
2023-05-26 15:00:51 +00:00
filters: ValueFilter {
roleName: "contractUniqueKey"
2023-06-28 19:30:01 +00:00
value: tokenViewPage . tokenKey
2023-03-28 13:55:34 +00:00
}
}
2023-06-28 19:30:01 +00:00
2023-03-28 13:55:34 +00:00
delegate: QtObject {
component Bind: Binding { target: view }
readonly property list < Binding > bindings: [
2023-05-25 14:45:46 +00:00
Bind { property: "tokenOwnersModel" ; value: model . tokenOwnersModel } ,
2023-06-01 10:38:56 +00:00
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
]
2023-06-22 21:24:30 +00:00
component BindToken: Binding { target: view . token }
2023-06-28 19:30:01 +00:00
readonly property list < Binding > tokenBindings: [
2023-06-22 21:24:30 +00:00
BindToken { property: "type" ; value: model . tokenType === Constants . TokenType . ERC20
? TokenObject.Type.Asset : TokenObject . Type . Collectible } ,
BindToken { property: "key" ; value: model . contractUniqueKey } ,
BindToken { property: "deployState" ; value: model . deployState } ,
BindToken { property: "burnState" ; value: model . burnState } ,
BindToken { property: "name" ; value: model . name } ,
BindToken { property: "artworkSource" ; value: model . image } ,
BindToken { property: "symbol" ; value: model . symbol } ,
BindToken { property: "description" ; value: model . description } ,
BindToken { property: "supply" ; value: model . supply } ,
BindToken { property: "infiniteSupply" ; value: model . infiniteSupply } ,
BindToken { property: "remainingTokens" ; value: model . remainingSupply } ,
BindToken { property: "chainId" ; value: model . chainId } ,
BindToken { property: "chainName" ; value: model . chainName } ,
BindToken { property: "chainIcon" ; value: model . chainIcon } ,
BindToken { property: "accountName" ; value: model . accountName } ,
BindToken { property: "accountAddress" ; value: model . accountAddress } , // TODO: Backend
BindToken { property: "transferable" ; value: model . transferable } ,
BindToken { property: "remotelyDestructState" ; value: model . remotelyDestructState } ,
BindToken { property: "remotelyDestruct" ; value: model . remoteSelfDestruct } ,
BindToken { property: "decimals" ; value: model . decimals }
2023-03-28 13:55:34 +00:00
]
}
}
2023-04-17 12:11:31 +00:00
2023-06-28 19:30:01 +00:00
contentItem: CommunityTokenView {
id: view
2023-06-05 13:49:36 +00:00
2023-06-28 19:30:01 +00:00
property string airdropKey // TO REMOVE: Temporal property until airdrop backend is not ready to use token key instead of symbol
property int tokenType
2023-06-05 13:49:36 +00:00
2023-06-28 19:30:01 +00:00
viewWidth: root . viewWidth
token: TokenObject { }
onGeneralAirdropRequested: {
root . airdropToken ( view . airdropKey , view . tokenType , [ ] ) // tokenKey instead when backend airdrop ready to use key instead of symbol
}
onAirdropRequested: {
root . airdropToken ( view . airdropKey , view . tokenType , [ address ] ) // tokenKey instead when backend airdrop ready to use key instead of symbol
}
onRemoteDestructRequested: {
remotelyDestructPopup . open ( )
// TODO: set the address selected in the popup's list
}
2023-06-05 13:49:36 +00:00
}
2023-06-28 19:30:01 +00:00
footer: MintTokensFooterPanel {
id: footer
readonly property TokenObject token: view . token
readonly property bool deployStateCompleted:
token . deployState === Constants . ContractTransactionStatus . Completed
function closePopups ( ) {
remotelyDestructPopup . close ( )
alertPopup . close ( )
signTransactionPopup . close ( )
burnTokensPopup . close ( )
}
airdropEnabled: deployStateCompleted &&
( token . infiniteSupply ||
token . remainingTokens !== 0 )
remotelyDestructEnabled: deployStateCompleted &&
! ! view . tokenOwnersModel &&
view . tokenOwnersModel . count > 0
burnEnabled: deployStateCompleted
remotelyDestructVisible: token . remotelyDestruct
burnVisible: ! token . infiniteSupply
onAirdropClicked: root . airdropToken ( view . airdropKey , // tokenKey instead when backend airdrop ready to use key instead of symbol
view . tokenType , [ ] )
onRemotelyDestructClicked: remotelyDestructPopup . open ( )
onBurnClicked: burnTokensPopup . open ( )
// helper properties to pass data through popups
property var remotelyDestructTokensList
property int burnAmount
RemotelyDestructPopup {
id: remotelyDestructPopup
collectibleName: view . token . name
model: view . tokenOwnersModel || null
destroyOnClose: false
onRemotelyDestructClicked: {
footer . remotelyDestructTokensList = remotelyDestructTokensList
alertPopup . tokenCount = tokenCount
alertPopup . open ( )
}
}
AlertPopup {
id: alertPopup
property int tokenCount
destroyOnClose: false
title: qsTr ( "Remotely destruct %n token(s)" , "" , tokenCount )
acceptBtnText: qsTr ( "Remotely destruct" )
alertText: qsTr ( "Continuing will destroy tokens held by members and revoke any permissions they are given. To undo you will have to issue them new tokens." )
onAcceptClicked: {
signTransactionPopup . isRemotelyDestructTransaction = true
signTransactionPopup . open ( )
}
}
SignTokenTransactionsPopup {
id: signTransactionPopup
property bool isRemotelyDestructTransaction
readonly property alias tokenKey: tokenViewPage . tokenKey
function signTransaction ( ) {
root . setFeeLoading ( )
if ( signTransactionPopup . isRemotelyDestructTransaction )
root . remotelyDestructCollectibles (
footer . remotelyDestructTokensList , tokenKey )
else
root . burnToken ( tokenKey , footer . burnAmount )
footerPanel . closePopups ( )
}
title: signTransactionPopup . isRemotelyDestructTransaction
? qsTr ( "Sign transaction - Self-destruct %1 tokens" ) . arg ( root . title )
: qsTr ( "Sign transaction - Burn %1 tokens" ) . arg ( root . title )
tokenName: footer . token . name
accountName: footer . token . accountName
networkName: footer . token . chainName
feeText: root . feeText
isFeeLoading: root . isFeeLoading
errorText: root . errorText
onOpened: {
root . setFeeLoading ( )
signTransactionPopup . isRemotelyDestructTransaction
? root . signRemoteDestructTransactionOpened ( footer . remotelyDestructTokensList , tokenKey )
: root . signBurnTransactionOpened ( tokenKey , footer . burnAmount )
}
onCancelClicked: close ( )
onSignTransactionClicked: signTransaction ( )
}
2023-04-17 12:11:31 +00:00
2023-06-28 19:30:01 +00:00
BurnTokensPopup {
id: burnTokensPopup
communityName: root . communityName
tokenName: footer . token . name
remainingTokens: footer . token . remainingTokens
tokenSource: footer . token . artworkSource
onBurnClicked: {
footer . burnAmount = burnAmount
signTransactionPopup . isRemotelyDestructTransaction = false
signTransactionPopup . open ( )
}
2023-04-17 12:11:31 +00:00
}
}
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
AlertPopup {
id: deleteTokenAlertPopup
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
readonly property alias tokenName: view . token . name
2023-05-30 15:18:45 +00:00
2023-06-28 19:30:01 +00:00
width: 521
title: qsTr ( "Delete %1" ) . arg ( tokenName )
acceptBtnText: qsTr ( "Delete %1 token" ) . arg ( tokenName )
alertText: qsTr ( "%1 is not yet minted, are you sure you want to delete it? All data associated with this token including its icon and description will be permanently deleted." ) . arg ( tokenName )
onAcceptClicked: {
root . deleteToken ( tokenViewPage . tokenKey )
root . navigateBack ( )
}
onCancelClicked: close ( )
}
2023-05-30 15:18:45 +00:00
}
}
2023-02-17 11:57:17 +00:00
}