2025-01-31 12:11:35 -03:00

366 lines
14 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import QtQuick 2.13
import QtQuick.Layouts 1.13
import StatusQ 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Backpressure 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Popups 0.1
import SortFilterProxyModel 0.2
import shared.panels 1.0
import utils 1.0
ColumnLayout {
id: root
property var network
property var rpcProviders
property var networksModule
property var networkRPCChanged
signal evaluateRpcEndPoint(string url, bool isMainUrl)
signal updateNetworkValues(int chainId, string newMainRpcInput, string newFailoverRpcUrl)
enum EvaluationState {
UnTouched,
Pending,
Verified,
InvalidURL,
PingUnsuccessful,
SameAsOther,
NotSameChain,
Empty,
RestartRequired
}
QtObject {
id: d
readonly property SortFilterProxyModel userRpcProvidersModel: SortFilterProxyModel {
sourceModel: root.rpcProviders
filters: [
ValueFilter { roleName: "chainId"; value: network.chainId },
ValueFilter { roleName: "providerType"; value: Constants.rpcProviderTypes.user }
]
}
readonly property int userRpcProvidersModelCount: d.userRpcProvidersModel.ModelCount.count ?? 0
property var mainRpcProvider
readonly property string mainRpcProviderUrl: !!d.mainRpcProvider ? d.mainRpcProvider.url : ""
property var fallbackRpcProvider
readonly property string fallbackRpcProviderUrl: !!d.fallbackRpcProvider ? d.fallbackRpcProvider.url : ""
function fetchProviders() {
mainRpcProvider = d.userRpcProvidersModelCount > 0 ? ModelUtils.get(d.userRpcProvidersModel, 0) : undefined
fallbackRpcProvider = d.userRpcProvidersModelCount > 1 ? ModelUtils.get(d.userRpcProvidersModel, 1) : undefined
}
onUserRpcProvidersModelCountChanged: d.fetchProviders()
Component.onCompleted: d.fetchProviders()
property int evaluationStatusMainRpc: EditNetworkForm.UnTouched
property int evaluationStatusFallBackRpc: EditNetworkForm.UnTouched
property var evaluateRpcEndPoint: Backpressure.debounce(root, 400, function (value, isMainUrl) {
if(!Utils.isURL(value)) {
if(isMainUrl)
d.evaluationStatusMainRpc = EditNetworkForm.InvalidURL
else
d.evaluationStatusFallBackRpc = EditNetworkForm.InvalidURL
return
}
root.evaluateRpcEndPoint(value, isMainUrl)
})
function getUrlStatusText(status, text) {
switch(status) {
case EditNetworkForm.Pending:
return qsTr("Checking RPC...")
case EditNetworkForm.InvalidURL:
return qsTr("What is %1? This isnt a URL 😒").arg(text)
case EditNetworkForm.PingUnsuccessful:
return qsTr("RPC appears to be either offline or this is not a valid JSON RPC endpoint URL")
case EditNetworkForm.Verified:
return qsTr("RPC successfully reached")
case EditNetworkForm.SameAsOther:
return qsTr("JSON RPC URLs are the same")
case EditNetworkForm.NotSameChain:
return qsTr("Chain ID returned from JSON RPC doesnt match %1").arg(network.chainName)
case EditNetworkForm.RestartRequired:
return qsTr("Restart required for changes to take effect")
default: return ""
}
}
function getErrorMessageColor(status) {
switch(status) {
case EditNetworkForm.Pending:
return Theme.palette.baseColor1
case EditNetworkForm.SameAsOther:
case EditNetworkForm.NotSameChain:
case EditNetworkForm.RestartRequired:
return Theme.palette.warningColor1
case EditNetworkForm.Verified:
return Theme.palette.successColor1
default: return Theme.palette.dangerColor1
}
}
function getErrorMessageAlignment(status) {
switch(status) {
case EditNetworkForm.Pending:
case EditNetworkForm.Verified:
case EditNetworkForm.SameAsOther:
case EditNetworkForm.NotSameChain:
case EditNetworkForm.RestartRequired:
return Text.AlignLeft
default: return Text.AlignRight
}
}
function save() {
if (d.evaluationStatusMainRpc == EditNetworkForm.UnTouched && d.evaluationStatusFallBackRpc == EditNetworkForm.UnTouched) {
return
}
let main = mainRpcInput.text
let fallback = failoverRpcUrlInput.text
root.updateNetworkValues(network.chainId, main, fallback)
root.networkRPCChanged[network.chainId] = true
}
}
Connections {
target: networksModule
function onChainIdFetchedForUrl(url, chainId, success, isMainUrl) {
let status = EditNetworkForm.PingUnsuccessful
if(success) {
if (network.chainId !== chainId) {
status = EditNetworkForm.NotSameChain
}
else if((isMainUrl && url === network.fallbackURL) ||
(!isMainUrl && url === network.rpcURL)) {
status = EditNetworkForm.SameAsOther
}
else
status = EditNetworkForm.Verified
}
if(isMainUrl)
d.evaluationStatusMainRpc = status
else
d.evaluationStatusFallBackRpc = status
}
}
spacing: 20
StatusInput {
Layout.fillWidth: true
label: qsTr("Network name")
input.edit.objectName: "editNetworkNameInput"
text: !!network ? network.chainName : ""
input.enabled: false
}
StatusInput {
Layout.fillWidth: true
label: qsTr("Short name")
input.edit.objectName: "editNetworkShortNameInput"
text: !!network ? network.shortName : ""
input.enabled: false
}
StatusInput {
Layout.fillWidth: true
input.edit.objectName: "editNetworkChainIdInput"
label: qsTr("Chain ID")
text: !!network ? network.chainId : ""
input.enabled: false
}
StatusInput {
Layout.fillWidth: true
input.edit.objectName: "editNetworkSymbolInput"
label: qsTr("Native Token Symbol")
text: !!network ? network.nativeCurrencySymbol : ""
input.enabled: false
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
StatusInput {
id: mainRpcInput
objectName: "mainRpcInputObject"
input.edit.objectName: "editNetworkMainRpcInput"
width: parent.width
label: qsTr("User JSON RPC URL #1")
text: d.mainRpcProviderUrl
onTextChanged: {
if (text === "") {
d.evaluationStatusMainRpc = EditNetworkForm.Empty
return
} else {
if (d.mainRpcProviderUrl === text) {
d.evaluationStatusMainRpc = EditNetworkForm.UnTouched
if (root.networkRPCChanged[network.chainId]) {
d.evaluationStatusMainRpc = EditNetworkForm.RestartRequired
}
} else {
d.evaluationStatusMainRpc = EditNetworkForm.Pending
Qt.callLater(d.evaluateRpcEndPoint, text, true);
}
}
}
errorMessageCmp.horizontalAlignment: d.getErrorMessageAlignment(d.evaluationStatusMainRpc)
errorMessageCmp.visible: d.evaluationStatusMainRpc !== EditNetworkForm.UnTouched
errorMessageCmp.color: d.getErrorMessageColor(d.evaluationStatusMainRpc)
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatusMainRpc, text)
}
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
StatusInput {
id: failoverRpcUrlInput
objectName: "failoverRpcUrlInputObject"
input.edit.objectName: "editNetworkFailoverRpcUrlInput"
width: parent.width
label: qsTr("User JSON RPC URL #2")
text: d.fallbackRpcProviderUrl
onTextChanged: {
if (text === "") {
d.evaluationStatusFallBackRpc = EditNetworkForm.Empty
return
}
if (d.fallbackRpcProviderUrl === text) {
d.evaluationStatusFallBackRpc = EditNetworkForm.UnTouched
if (root.networkRPCChanged[network.chainId]) {
d.evaluationStatusFallBackRpc = EditNetworkForm.RestartRequired
}
} else {
d.evaluationStatusFallBackRpc = EditNetworkForm.Pending
Qt.callLater(d.evaluateRpcEndPoint, text, false);
}
}
errorMessageCmp.horizontalAlignment: d.getErrorMessageAlignment(d.evaluationStatusFallBackRpc)
errorMessageCmp.visible: d.evaluationStatusFallBackRpc !== EditNetworkForm.UnTouched
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatusFallBackRpc, text)
errorMessageCmp.color: d.getErrorMessageColor(d.evaluationStatusFallBackRpc)
}
}
StatusInput {
input.edit.objectName: "editNetworkExplorerInput"
Layout.fillWidth: true
label: qsTr("Block Explorer")
text: !!network ? network.blockExplorerURL : ""
input.enabled: false
}
StatusCheckBox {
id: warningCheckbox
objectName: "editNetworkAknowledgmentCheckbox"
Layout.fillWidth: true
text: qsTr("I understand that changing network settings can cause unforeseen issues, errors, security risks and potentially even loss of funds.")
checkState: Qt.Unchecked
font.pixelSize: 15
}
Separator {}
Row {
Layout.alignment: Qt.AlignRight
StatusButton {
objectName: "editNetworkSaveButton"
text: qsTr("Save Changes")
enabled: (
d.evaluationStatusMainRpc === EditNetworkForm.Verified ||
d.evaluationStatusFallBackRpc === EditNetworkForm.Verified ||
d.evaluationStatusMainRpc === EditNetworkForm.SameAsOther ||
d.evaluationStatusFallBackRpc === EditNetworkForm.SameAsOther ||
d.evaluationStatusMainRpc === EditNetworkForm.Empty ||
d.evaluationStatusFallBackRpc === EditNetworkForm.Empty ||
d.evaluationStatusMainRpc === EditNetworkForm.NotSameChain ||
d.evaluationStatusFallBackRpc === EditNetworkForm.NotSameChain ||
d.evaluationStatusMainRpc === EditNetworkForm.RestartRequired ||
d.evaluationStatusFallBackRpc === EditNetworkForm.RestartRequired
) && warningCheckbox.checked
onClicked: {
Global.openPopup(confirmationDialogComponent)
}
}
}
Component {
id: confirmationDialogComponent
StatusModal {
headerSettings.title: qsTr("RPC URL change requires app restart")
contentItem: Item {
width: parent.width
implicitHeight: childrenRect.height
Column {
width: parent.width - 32
anchors.horizontalCenter: parent.horizontalCenter
Item {
width: parent.width
height: 16
}
StatusBaseText {
objectName: "mustBeRestartedText"
text: qsTr("For new JSON RPC URLs to take effect, Status must be restarted. Are you ready to do this now?")
font.pixelSize: 15
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
color: Theme.palette.directColor1
}
Item {
width: parent.width
height: 16
}
}
}
rightButtons: [
StatusFlatButton {
id: laterButton
objectName: "laterButton"
text: qsTr("Save and restart later")
type: StatusBaseButton.Type.Normal
onClicked: {
close()
d.save()
d.evaluationStatusMainRpc = EditNetworkForm.RestartRequired
}
},
StatusButton {
id: saveButton
objectName: "saveButton"
type: StatusBaseButton.Type.Normal
text: qsTr("Save and restart Status")
focus: true
Keys.onReturnPressed: function(event) {
saveButton.clicked()
}
onClicked: {
close()
d.save()
Qt.quit()
}
}
]
}
}
}