mirror of
https://github.com/logos-blockchain/logos-execution-zone-wallet-ui.git
synced 2026-07-30 06:33:29 +00:00
151 lines
4.9 KiB
QML
151 lines
4.9 KiB
QML
|
|
import QtQuick
|
||
|
|
import QtQuick.Controls
|
||
|
|
import QtQuick.Layouts
|
||
|
|
|
||
|
|
import Logos.Theme
|
||
|
|
import Logos.Controls
|
||
|
|
|
||
|
|
import "../controls"
|
||
|
|
|
||
|
|
Popup {
|
||
|
|
id: root
|
||
|
|
|
||
|
|
// Context set by the parent right before open(). Only ever opened for an
|
||
|
|
// unlabeled account — the wallet core has no way to rename or remove a label
|
||
|
|
// once added, so there's no "current label" to prefill or compare against.
|
||
|
|
property string accountId: ""
|
||
|
|
property bool isPublic: true
|
||
|
|
|
||
|
|
// Debounced availability-check result. The parent owns the backend connection,
|
||
|
|
// so it drives these two properties in response to checkAvailabilityRequested.
|
||
|
|
property bool checkingAvailability: false
|
||
|
|
property bool labelAvailable: true
|
||
|
|
|
||
|
|
// Save round-trip state, likewise driven by the parent: saving stays true and the
|
||
|
|
// popup stays open until the parent reports success (closeOnSaveSuccess) or failure
|
||
|
|
// (reportSaveError) — so a failed save isn't silently swallowed by an immediate close.
|
||
|
|
property bool saving: false
|
||
|
|
property string saveError: ""
|
||
|
|
|
||
|
|
signal checkAvailabilityRequested(string label)
|
||
|
|
signal saveRequested(string accountId, bool isPublic, string label)
|
||
|
|
|
||
|
|
function closeOnSaveSuccess() {
|
||
|
|
root.saving = false
|
||
|
|
root.close()
|
||
|
|
}
|
||
|
|
|
||
|
|
function reportSaveError(message) {
|
||
|
|
root.saving = false
|
||
|
|
root.saveError = message
|
||
|
|
}
|
||
|
|
|
||
|
|
readonly property string trimmedText: labelField.text.trim()
|
||
|
|
readonly property bool saveEnabled: trimmedText.length > 0
|
||
|
|
&& root.labelAvailable && !root.checkingAvailability
|
||
|
|
|
||
|
|
modal: true
|
||
|
|
dim: true
|
||
|
|
padding: Theme.spacing.large
|
||
|
|
// No dismissal while a save is in flight — mirrors the disabled Cancel/Save
|
||
|
|
// buttons below, so a stale response can't land on a dialog the user thinks
|
||
|
|
// they already closed.
|
||
|
|
closePolicy: root.saving ? Popup.NoAutoClose : (Popup.CloseOnEscape | Popup.CloseOnPressOutside)
|
||
|
|
|
||
|
|
anchors.centerIn: parent
|
||
|
|
|
||
|
|
background: Rectangle {
|
||
|
|
color: Theme.palette.backgroundSecondary
|
||
|
|
radius: Theme.spacing.radiusXlarge
|
||
|
|
border.color: Theme.palette.backgroundElevated
|
||
|
|
}
|
||
|
|
|
||
|
|
onOpened: {
|
||
|
|
labelField.text = ""
|
||
|
|
root.labelAvailable = true
|
||
|
|
root.checkingAvailability = false
|
||
|
|
root.saving = false
|
||
|
|
root.saveError = ""
|
||
|
|
labelField.forceActiveFocus()
|
||
|
|
labelField.selectAll()
|
||
|
|
}
|
||
|
|
|
||
|
|
Timer {
|
||
|
|
id: debounce
|
||
|
|
interval: 400
|
||
|
|
onTriggered: {
|
||
|
|
if (root.trimmedText.length > 0) {
|
||
|
|
root.checkingAvailability = true
|
||
|
|
root.checkAvailabilityRequested(root.trimmedText)
|
||
|
|
} else {
|
||
|
|
root.checkingAvailability = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
contentItem: ColumnLayout {
|
||
|
|
width: 320
|
||
|
|
spacing: Theme.spacing.large
|
||
|
|
|
||
|
|
LogosText {
|
||
|
|
text: qsTr("Add label")
|
||
|
|
font.pixelSize: Theme.typography.titleText
|
||
|
|
font.weight: Theme.typography.weightBold
|
||
|
|
color: Theme.palette.text
|
||
|
|
}
|
||
|
|
|
||
|
|
LogosTextField {
|
||
|
|
id: labelField
|
||
|
|
Layout.fillWidth: true
|
||
|
|
enabled: !root.saving
|
||
|
|
onTextChanged: {
|
||
|
|
root.saveError = ""
|
||
|
|
// Mark as checking immediately so saveEnabled can't go true on stale
|
||
|
|
// (or no) availability data during the debounce window — the Timer
|
||
|
|
// below only confirms/updates the result once typing settles.
|
||
|
|
root.checkingAvailability = root.trimmedText.length > 0
|
||
|
|
debounce.restart()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
LogosText {
|
||
|
|
Layout.fillWidth: true
|
||
|
|
wrapMode: Text.WordWrap
|
||
|
|
font.pixelSize: Theme.typography.secondaryText
|
||
|
|
color: Theme.palette.error
|
||
|
|
visible: root.trimmedText.length > 0 && !root.checkingAvailability && !root.labelAvailable
|
||
|
|
text: qsTr("That label is already in use.")
|
||
|
|
}
|
||
|
|
|
||
|
|
LogosText {
|
||
|
|
Layout.fillWidth: true
|
||
|
|
wrapMode: Text.WordWrap
|
||
|
|
font.pixelSize: Theme.typography.secondaryText
|
||
|
|
color: Theme.palette.error
|
||
|
|
visible: root.saveError.length > 0
|
||
|
|
text: root.saveError
|
||
|
|
}
|
||
|
|
|
||
|
|
RowLayout {
|
||
|
|
Layout.topMargin: Theme.spacing.medium
|
||
|
|
spacing: Theme.spacing.medium
|
||
|
|
Layout.fillWidth: true
|
||
|
|
Item { Layout.fillWidth: true }
|
||
|
|
FeedbackButton {
|
||
|
|
text: qsTr("Cancel")
|
||
|
|
enabled: !root.saving
|
||
|
|
onClicked: root.close()
|
||
|
|
}
|
||
|
|
FeedbackButton {
|
||
|
|
text: root.saving ? qsTr("Saving…") : qsTr("Save")
|
||
|
|
enabled: root.saveEnabled && !root.saving
|
||
|
|
onClicked: {
|
||
|
|
root.saving = true
|
||
|
|
root.saveError = ""
|
||
|
|
root.saveRequested(root.accountId, root.isPublic, root.trimmedText)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|