feat(@settings): copy assets popup to settings
This commit is contained in:
parent
f8aebda0dd
commit
e7ece14346
|
@ -0,0 +1,150 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import shared.panels 1.0
|
||||
import shared.controls 1.0
|
||||
|
||||
Item {
|
||||
id: modalBody
|
||||
|
||||
property var defaultTokenList
|
||||
property var customTokenList
|
||||
signal toggleVisibleClicked(int chainId, string symbol)
|
||||
signal removeCustomTokenTriggered(int chainId, string address)
|
||||
signal showTokenDetailsTriggered(int chainId, string address, string name, string symbol, string decimals)
|
||||
|
||||
Component {
|
||||
id: tokenComponent
|
||||
|
||||
StatusListItem {
|
||||
id: assetSymbol
|
||||
title: symbol
|
||||
subTitle: name || ""
|
||||
image.source: Style.png("tokens/" + (hasIcon ? symbol : "DEFAULT-TOKEN@3x"))
|
||||
image.height: 36
|
||||
components: [StatusCheckBox {
|
||||
id: assetCheck
|
||||
checked: model.isVisible
|
||||
onClicked: toggleVisibleClicked(chainId, symbol)
|
||||
}]
|
||||
visible: symbol && (searchBox.text == "" || name.toLowerCase().includes(searchBox.text.toLowerCase()) || symbol.toLowerCase().includes(searchBox.text.toLowerCase()))
|
||||
MouseArea {
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: function (event) {
|
||||
if (event.button === Qt.RightButton) {
|
||||
return contextMenu.popup(mouseX, mouseY)
|
||||
}
|
||||
assetCheck.checked = !assetCheck.checked
|
||||
toggleVisibleClicked(chainId, symbol)
|
||||
}
|
||||
|
||||
StatusPopupMenu {
|
||||
id: contextMenu
|
||||
Action {
|
||||
icon.source: Style.svg("make-admin")
|
||||
//% "Token details"
|
||||
text: qsTrId("token-details")
|
||||
onTriggered: {
|
||||
modalBody.showTokenDetailsTriggered(chainId, address, name, symbol, decimals);
|
||||
}
|
||||
}
|
||||
Action {
|
||||
icon.source: Style.svg("remove-from-group")
|
||||
icon.color: Style.current.red
|
||||
enabled: isCustom
|
||||
//% "Remove token"
|
||||
text: qsTrId("remove-token")
|
||||
onTriggered: removeCustomTokenTriggered(chainId, address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SearchBox {
|
||||
id: searchBox
|
||||
customHeight: 36
|
||||
fontPixelSize: 12
|
||||
anchors.top: modalBody.top
|
||||
anchors.topMargin: Style.current.padding
|
||||
}
|
||||
|
||||
|
||||
ScrollView {
|
||||
id: sview
|
||||
clip: true
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
|
||||
contentHeight: tokenList.height
|
||||
|
||||
anchors.top: searchBox.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
|
||||
Item {
|
||||
id: tokenList
|
||||
height: childrenRect.height
|
||||
|
||||
Column {
|
||||
id: customTokens
|
||||
spacing: Style.current.halfPadding
|
||||
visible: { modalBody.customTokenList.count > 0 }
|
||||
|
||||
StyledText {
|
||||
id: customLbl
|
||||
//% "Custom"
|
||||
text: qsTrId("custom")
|
||||
font.pixelSize: 13
|
||||
color: Style.current.secondaryText
|
||||
height: 20
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: customTokensRepeater
|
||||
model: modalBody.customTokenList
|
||||
delegate: tokenComponent
|
||||
anchors.top: customLbl.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.top: customTokens.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
id: defaultTokens
|
||||
spacing: Style.current.halfPadding
|
||||
|
||||
StyledText {
|
||||
id: defaultLbl
|
||||
//% "Default"
|
||||
text: qsTrId("default")
|
||||
font.pixelSize: 13
|
||||
color: Style.current.secondaryText
|
||||
height: 20
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: modalBody.defaultTokenList
|
||||
delegate: tokenComponent
|
||||
anchors.top: defaultLbl.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
import "../stores"
|
||||
|
||||
StatusModal {
|
||||
id: popup
|
||||
|
||||
property bool editable: true
|
||||
property int marginBetweenInputs: 35
|
||||
property string validationError: ""
|
||||
property WalletStore walletStore
|
||||
|
||||
header.title: editable ?
|
||||
//% "Add custom token"
|
||||
qsTrId("add-custom-token")
|
||||
: nameInput.text
|
||||
|
||||
x: Math.round(((parent ? parent.width : 0) - width) / 2)
|
||||
y: Math.round(((parent ? parent.height : 0) - height) / 2)
|
||||
|
||||
height: editable ? 450 : 380
|
||||
|
||||
onOpened: {
|
||||
addressInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
function openEditable(){
|
||||
addressInput.text = "";
|
||||
nameInput.text = "";
|
||||
symbolInput.text = "";
|
||||
decimalsInput.text = "";
|
||||
editable = true;
|
||||
open();
|
||||
}
|
||||
|
||||
function openWithData(address, name, symbol, decimals){
|
||||
addressInput.text = address;
|
||||
nameInput.text = name;
|
||||
symbolInput.text = symbol;
|
||||
decimalsInput.text = decimals;
|
||||
editable = false;
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
function validate() {
|
||||
if (addressInput.text !== "" && !Utils.isAddress(addressInput.text)) {
|
||||
//% "This needs to be a valid address"
|
||||
validationError = qsTrId("this-needs-to-be-a-valid-address");
|
||||
}
|
||||
return validationError === ""
|
||||
}
|
||||
|
||||
property var getTokenDetails: Backpressure.debounce(popup, 500, function (tokenAddress){
|
||||
popup.walletStore.walletTokensModule.getTokenDetails(tokenAddress)
|
||||
});
|
||||
|
||||
function onKeyReleased(){
|
||||
validationError = "";
|
||||
if (!validate() || addressInput.text === "") {
|
||||
return;
|
||||
}
|
||||
Qt.callLater(getTokenDetails, addressInput.text)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: popup.walletStore.walletTokensModule
|
||||
onTokenDetailsWereResolved: {
|
||||
const jsonObj = JSON.parse(tokenDetails)
|
||||
if (jsonObj.error) {
|
||||
validationError = jsonObj.error
|
||||
return
|
||||
}
|
||||
if (jsonObj.name === "" && jsonObj.symbol === "" && jsonObj.decimals === "") {
|
||||
//% "Invalid ERC20 address"
|
||||
validationError = qsTrId("invalid-erc20-address")
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressInput.text.toLowerCase() === jsonObj.address.toLowerCase()) {
|
||||
symbolInput.text = jsonObj.symbol;
|
||||
decimalsInput.text = jsonObj.decimals;
|
||||
nameInput.text = jsonObj.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
Input {
|
||||
id: addressInput
|
||||
readOnly: !editable
|
||||
textField.maximumLength: 42
|
||||
//% "Enter contract address..."
|
||||
placeholderText: qsTrId("enter-contract-address...")
|
||||
//% "Contract address"
|
||||
label: qsTrId("contract-address")
|
||||
validationError: popup.validationError
|
||||
Keys.onReleased: onKeyReleased()
|
||||
}
|
||||
|
||||
Input {
|
||||
id: nameInput
|
||||
readOnly: !editable
|
||||
anchors.top: addressInput.bottom
|
||||
anchors.topMargin: marginBetweenInputs
|
||||
//% "The name of your token..."
|
||||
placeholderText: qsTrId("the-name-of-your-token...")
|
||||
//% "Name"
|
||||
label: qsTrId("name")
|
||||
}
|
||||
|
||||
Input {
|
||||
id: symbolInput
|
||||
readOnly: !editable
|
||||
//% "ABC"
|
||||
placeholderText: qsTrId("abc")
|
||||
//% "Symbol"
|
||||
label: qsTrId("symbol")
|
||||
anchors.top: nameInput.bottom
|
||||
anchors.topMargin: marginBetweenInputs
|
||||
anchors.left: parent.left
|
||||
anchors.right: undefined
|
||||
width: parent.width / 2 - 20
|
||||
}
|
||||
|
||||
Input {
|
||||
id: decimalsInput
|
||||
readOnly: !editable
|
||||
placeholderText: "18"
|
||||
//% "Decimals"
|
||||
label: qsTrId("decimals")
|
||||
text: "18"
|
||||
anchors.top: nameInput.bottom
|
||||
anchors.topMargin: marginBetweenInputs
|
||||
anchors.right: parent.right
|
||||
anchors.left: undefined
|
||||
width: parent.width / 2 - 20
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: changeError
|
||||
title: qsTr("Changing settings failed")
|
||||
icon: StandardIcon.Critical
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
//% "Add"
|
||||
text: qsTrId("add")
|
||||
enabled: validationError === "" && addressInput.text !== "" && nameInput.text !== "" && symbolInput.text !== "" && decimalsInput.text !== ""
|
||||
visible: editable
|
||||
onClicked: {
|
||||
const error = popup.walletStore.addCustomToken(0, addressInput.text, nameInput.text, symbolInput.text, decimalsInput.text);
|
||||
|
||||
if (error) {
|
||||
Global.playErrorSound();
|
||||
changeError.text = error;
|
||||
changeError.open();
|
||||
return;
|
||||
}
|
||||
popup.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import "../panels"
|
||||
import "../stores"
|
||||
|
||||
StatusModal {
|
||||
id: popup
|
||||
x: Math.round(((parent ? parent.width : 0) - width) / 2)
|
||||
y: Math.round(((parent ? parent.height : 0) - height) / 2)
|
||||
height: 480
|
||||
property WalletStore walletStore
|
||||
//% "Manage Assets"
|
||||
header.title: qsTrId("manage-assets")
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
//% "Add custom token"
|
||||
text: qsTrId("add-custom-token")
|
||||
onClicked: {
|
||||
addShowTokenModal.openEditable();
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
contentItem: TokenSettingsModalContent {
|
||||
id: settingsModalContent
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
defaultTokenList: walletStore.defaultTokenList
|
||||
customTokenList: walletStore.customTokenList
|
||||
|
||||
onToggleVisibleClicked: {
|
||||
walletStore.toggleVisible(chainId, symbol)
|
||||
}
|
||||
onRemoveCustomTokenTriggered: {
|
||||
walletStore.removeCustomToken(chainId, address)
|
||||
}
|
||||
onShowTokenDetailsTriggered: {
|
||||
addShowTokenModal.openWithData(chainId, address, name, symbol, decimals);
|
||||
}
|
||||
|
||||
AddShowTokenModal{
|
||||
id: addShowTokenModal
|
||||
walletStore: root.walletStore
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,4 +11,19 @@ QtObject {
|
|||
property var importedAccounts: walletSectionAccounts.imported
|
||||
property var generatedAccounts: walletSectionAccounts.generated
|
||||
property var watchOnlyAccounts: walletSectionAccounts.watchOnly
|
||||
}
|
||||
property var walletTokensModule: walletSectionAllTokens
|
||||
property var defaultTokenList: walletSectionAllTokens.default
|
||||
property var customTokenList: walletSectionAllTokens.custom
|
||||
|
||||
function addCustomToken(chainId, address, name, symbol, decimals) {
|
||||
return walletSectionAllTokens.addCustomToken(chainId, address, name, symbol, decimals)
|
||||
}
|
||||
|
||||
function toggleVisible(chainId, symbol) {
|
||||
walletSectionAllTokens.toggleVisible(chainId, symbol)
|
||||
}
|
||||
|
||||
function removeCustomToken(chainId, address) {
|
||||
walletSectionAllTokens.removeCustomToken(chainId, address)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import StatusQ.Core 0.1
|
|||
|
||||
import "../../stores"
|
||||
import "../../controls"
|
||||
|
||||
import "../../popups"
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
@ -34,7 +34,18 @@ Column {
|
|||
StatusSettingsLineButton {
|
||||
text: qsTr("Manage Assets & List")
|
||||
height: 64
|
||||
onClicked: goToNetworksView()
|
||||
onClicked: Global.openPopup(tokenSettingsModalComponent)
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: tokenSettingsModalComponent
|
||||
TokenSettingsModal {
|
||||
walletStore: root.walletStore
|
||||
onClosed: {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Separator {
|
||||
|
|
Loading…
Reference in New Issue