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 importedAccounts: walletSectionAccounts.imported
|
||||||
property var generatedAccounts: walletSectionAccounts.generated
|
property var generatedAccounts: walletSectionAccounts.generated
|
||||||
property var watchOnlyAccounts: walletSectionAccounts.watchOnly
|
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 "../../stores"
|
||||||
import "../../controls"
|
import "../../controls"
|
||||||
|
import "../../popups"
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
||||||
|
@ -34,7 +34,18 @@ Column {
|
||||||
StatusSettingsLineButton {
|
StatusSettingsLineButton {
|
||||||
text: qsTr("Manage Assets & List")
|
text: qsTr("Manage Assets & List")
|
||||||
height: 64
|
height: 64
|
||||||
onClicked: goToNetworksView()
|
onClicked: Global.openPopup(tokenSettingsModalComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: tokenSettingsModalComponent
|
||||||
|
TokenSettingsModal {
|
||||||
|
walletStore: root.walletStore
|
||||||
|
onClosed: {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator {
|
Separator {
|
||||||
|
|
Loading…
Reference in New Issue