mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-26 06:31:19 +00:00
feat(wallet): humanize shared wallet experience
Consolidate wallet account decoding and portfolio handling around the shared Rust IDL decoder. Simplify AMM wallet integration, remove obsolete caches and network plumbing, and cover account selection and live flows.
This commit is contained in:
@@ -9,12 +9,21 @@ Popup {
|
||||
property string cancelText: qsTr("Cancel")
|
||||
property string confirmText: qsTr("Confirm")
|
||||
property bool busy: false
|
||||
property string busyText: qsTr("Submitting…")
|
||||
property bool activityBusy: false
|
||||
property string activityText: qsTr("Updating…")
|
||||
property bool showInlineBusyIndicator: true
|
||||
property var snapshot: ({})
|
||||
property Component summary: null
|
||||
property bool confirmationPending: false
|
||||
property bool confirmEnabled: true
|
||||
property bool roundedCancelButton: false
|
||||
property bool closeWhenSettled: true
|
||||
readonly property bool actionPending: root.busy || root.activityBusy
|
||||
|
||||
signal canceled
|
||||
signal confirmed(var snapshot)
|
||||
signal summaryEdited(var snapshot)
|
||||
|
||||
modal: true
|
||||
dim: true
|
||||
@@ -40,7 +49,14 @@ Popup {
|
||||
root.snapshot = root.cloneSnapshot(nextSnapshot)
|
||||
root.confirmationPending = false
|
||||
root.open()
|
||||
cancelButton.forceActiveFocus()
|
||||
Qt.callLater(function() {
|
||||
if (cancelButtonLoader.item)
|
||||
cancelButtonLoader.item.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
|
||||
function updateSnapshot(nextSnapshot) {
|
||||
root.snapshot = root.cloneSnapshot(nextSnapshot)
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
@@ -52,7 +68,7 @@ Popup {
|
||||
}
|
||||
|
||||
function confirm() {
|
||||
if (root.busy)
|
||||
if (root.actionPending || !root.confirmEnabled)
|
||||
return
|
||||
root.confirmationPending = true
|
||||
root.confirmed(root.snapshot)
|
||||
@@ -62,10 +78,21 @@ Popup {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: summaryLoader.item
|
||||
ignoreUnknownSignals: true
|
||||
|
||||
function onSnapshotEdited(snapshot) {
|
||||
root.updateSnapshot(snapshot)
|
||||
root.summaryEdited(root.snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
onBusyChanged: {
|
||||
if (!root.busy && root.confirmationPending) {
|
||||
root.confirmationPending = false
|
||||
root.close()
|
||||
if (root.closeWhenSettled)
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,26 +144,37 @@ Popup {
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
Item {
|
||||
id: inlineBusyIndicator
|
||||
|
||||
property bool active: root.showInlineBusyIndicator && root.actionPending
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: root.busy
|
||||
running: root.busy
|
||||
Accessible.name: qsTr("Submitting transaction")
|
||||
Layout.preferredWidth: active ? busySpinner.implicitWidth : 0
|
||||
Layout.preferredHeight: active ? busySpinner.implicitHeight : 0
|
||||
implicitWidth: busySpinner.implicitWidth
|
||||
implicitHeight: busySpinner.implicitHeight
|
||||
visible: active
|
||||
|
||||
BusyIndicator {
|
||||
id: busySpinner
|
||||
|
||||
anchors.centerIn: parent
|
||||
running: inlineBusyIndicator.active
|
||||
Accessible.name: root.busy ? root.busyText : root.activityText
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
|
||||
Button {
|
||||
id: cancelButton
|
||||
objectName: "transactionCancelButton"
|
||||
Loader {
|
||||
id: cancelButtonLoader
|
||||
objectName: "transactionCancelButtonLoader"
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 44
|
||||
text: root.cancelText
|
||||
enabled: !root.busy
|
||||
Accessible.name: text
|
||||
onClicked: root.cancel()
|
||||
Layout.preferredHeight: 44
|
||||
sourceComponent: root.roundedCancelButton
|
||||
? roundedCancelButtonComponent : defaultCancelButtonComponent
|
||||
}
|
||||
|
||||
Button {
|
||||
@@ -144,8 +182,8 @@ Popup {
|
||||
objectName: "transactionConfirmButton"
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 44
|
||||
text: root.busy ? qsTr("Submitting...") : root.confirmText
|
||||
enabled: !root.busy
|
||||
text: root.busy ? root.busyText : root.confirmText
|
||||
enabled: !root.actionPending && root.confirmEnabled
|
||||
Accessible.name: text
|
||||
onClicked: root.confirm()
|
||||
|
||||
@@ -166,4 +204,48 @@ Popup {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: defaultCancelButtonComponent
|
||||
|
||||
Button {
|
||||
objectName: "transactionCancelButton"
|
||||
anchors.fill: parent
|
||||
text: root.cancelText
|
||||
enabled: !root.busy
|
||||
Accessible.name: text
|
||||
onClicked: root.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: roundedCancelButtonComponent
|
||||
|
||||
Button {
|
||||
id: cancelButton
|
||||
|
||||
objectName: "transactionCancelButton"
|
||||
anchors.fill: parent
|
||||
text: root.cancelText
|
||||
enabled: !root.busy
|
||||
Accessible.name: text
|
||||
onClicked: root.cancel()
|
||||
|
||||
background: Rectangle {
|
||||
color: cancelButton.pressed ? "#3f3f46"
|
||||
: cancelButton.hovered ? "#27272a" : "#18181b"
|
||||
border.color: "#52525b"
|
||||
border.width: 1
|
||||
radius: 6
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
text: cancelButton.text
|
||||
color: "#f4f4f5"
|
||||
font.bold: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,53 +5,127 @@ import QtQuick.Layouts
|
||||
ItemDelegate {
|
||||
id: root
|
||||
|
||||
required property int index
|
||||
required property string name
|
||||
required property string alias
|
||||
required property string address
|
||||
required property string balance
|
||||
required property bool isPublic
|
||||
required property string displayAddress
|
||||
required property string kind
|
||||
required property string section
|
||||
required property string programName
|
||||
required property string accountType
|
||||
required property string decodedData
|
||||
required property string visibility
|
||||
required property bool canBePrimary
|
||||
required property bool isPrimary
|
||||
|
||||
signal copyRequested(string text)
|
||||
signal makePrimaryRequested(string address)
|
||||
signal renameRequested(string address, string alias)
|
||||
|
||||
leftPadding: 12
|
||||
rightPadding: 8
|
||||
topPadding: 10
|
||||
bottomPadding: 10
|
||||
enabled: root.section !== "hidden"
|
||||
Accessible.name: root.isPrimary
|
||||
? qsTr("%1, primary account").arg(root.name)
|
||||
: root.name
|
||||
|
||||
Accessible.name: qsTr("%1, balance %2").arg(root.name).arg(root.balance || "0")
|
||||
function kindLabel() {
|
||||
if (root.kind === "user")
|
||||
return qsTr("User")
|
||||
if (root.kind === "private")
|
||||
return qsTr("Account")
|
||||
if (root.accountType.length > 0)
|
||||
return root.accountType
|
||||
return root.kind === "unknown" ? qsTr("Unknown") : qsTr("Program")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: root.highlighted || root.hovered ? "#27272a" : "#18181b"
|
||||
radius: 6
|
||||
border.width: root.activeFocus ? 1 : 0
|
||||
border.color: "#f26a21"
|
||||
color: root.isPrimary || root.hovered ? "#27272a" : "#18181b"
|
||||
radius: 8
|
||||
border.width: root.activeFocus || root.isPrimary ? 1 : 0
|
||||
border.color: root.isPrimary ? "#f59e0b" : "#52525b"
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 6
|
||||
spacing: 7
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
spacing: 7
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: root.name
|
||||
color: "#f4f4f5"
|
||||
color: "#fafafa"
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: root.isPrimary
|
||||
text: qsTr("Primary")
|
||||
color: "#fbbf24"
|
||||
font.pixelSize: 11
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Label {
|
||||
text: root.isPublic ? qsTr("Public") : qsTr("Private")
|
||||
text: root.kindLabel()
|
||||
color: "#a1a1aa"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
Label {
|
||||
text: root.visibility === "private" ? qsTr("Private") : qsTr("Public")
|
||||
color: root.visibility === "private" ? "#c4b5fd" : "#93c5fd"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
objectName: "walletProgramName"
|
||||
visible: root.section === "advanced" && root.programName.length > 0
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Program: %1").arg(root.programName)
|
||||
color: "#a1a1aa"
|
||||
font.pixelSize: 11
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: root.section === "advanced" && root.decodedData.length > 0
|
||||
Layout.fillWidth: true
|
||||
spacing: 4
|
||||
|
||||
Label {
|
||||
text: root.balance.length > 0 ? root.balance : "-"
|
||||
color: "#f4f4f5"
|
||||
font.bold: true
|
||||
objectName: "walletDecodedDataLabel"
|
||||
text: qsTr("Decoded data")
|
||||
color: "#a1a1aa"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
objectName: "walletDecodedDataBox"
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: decodedDataText.implicitHeight + 16
|
||||
color: "#18181b"
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: "#3f3f46"
|
||||
|
||||
Text {
|
||||
id: decodedDataText
|
||||
objectName: "walletDecodedData"
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
text: root.decodedData
|
||||
color: "#d4d4d8"
|
||||
font.family: "monospace"
|
||||
font.pixelSize: 10
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,17 +135,45 @@ ItemDelegate {
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: root.address
|
||||
color: "#a1a1aa"
|
||||
text: root.displayAddress
|
||||
color: "#71717a"
|
||||
font.family: "monospace"
|
||||
font.pixelSize: 11
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
CopyButton {
|
||||
visible: root.address.length > 0
|
||||
onCopyRequested: root.copyRequested(root.address)
|
||||
visible: root.displayAddress.length > 0
|
||||
copyText: root.displayAddress
|
||||
copyLabel: qsTr("Copy address")
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 6
|
||||
|
||||
Button {
|
||||
objectName: "walletRenameButton"
|
||||
text: qsTr("Rename")
|
||||
flat: true
|
||||
onClicked: root.renameRequested(root.address, root.alias)
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Button {
|
||||
objectName: "walletMakePrimaryButton"
|
||||
visible: root.canBePrimary && !root.isPrimary
|
||||
text: qsTr("Make primary")
|
||||
flat: true
|
||||
onClicked: root.makePrimaryRequested(root.address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (root.canBePrimary && !root.isPrimary)
|
||||
root.makePrimaryRequested(root.address)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ WalletIconButton {
|
||||
|
||||
signal copyRequested
|
||||
|
||||
property string copyText: ""
|
||||
property string copyLabel: qsTr("Copy")
|
||||
property bool copied: false
|
||||
|
||||
accessibleName: root.copied ? qsTr("Copied") : qsTr("Copy")
|
||||
accessibleName: root.copied ? qsTr("Copied") : root.copyLabel
|
||||
iconSource: root.copied
|
||||
? Qt.resolvedUrl("icons/checkmark.svg")
|
||||
: Qt.resolvedUrl("icons/copy.svg")
|
||||
@@ -18,7 +20,24 @@ WalletIconButton {
|
||||
onTriggered: root.copied = false
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: clipboardProxy
|
||||
|
||||
visible: false
|
||||
}
|
||||
|
||||
function copyToClipboard() {
|
||||
if (root.copyText.length === 0)
|
||||
return
|
||||
clipboardProxy.text = root.copyText
|
||||
clipboardProxy.selectAll()
|
||||
clipboardProxy.copy()
|
||||
clipboardProxy.deselect()
|
||||
clipboardProxy.text = ""
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.copyToClipboard()
|
||||
root.copyRequested()
|
||||
root.copied = true
|
||||
resetTimer.restart()
|
||||
|
||||
@@ -16,9 +16,13 @@ Popup {
|
||||
x: parent ? Math.max(0, Math.round((parent.width - width) / 2)) : 0
|
||||
y: parent ? Math.max(0, Math.round((parent.height - height) / 2)) : 0
|
||||
padding: 20
|
||||
focus: true
|
||||
closePolicy: root.busy ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
onOpened: privateSwitch.checked = false
|
||||
onOpened: {
|
||||
privateSwitch.checked = false
|
||||
Qt.callLater(function() { privateSwitch.forceActiveFocus() })
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "#18181b"
|
||||
|
||||
@@ -20,6 +20,7 @@ Popup {
|
||||
x: parent ? Math.max(0, Math.round((parent.width - width) / 2)) : 0
|
||||
y: parent ? Math.max(0, Math.round((parent.height - height) / 2)) : 0
|
||||
padding: 20
|
||||
focus: true
|
||||
closePolicy: root.busy || root.mnemonic.length > 0
|
||||
? Popup.NoAutoClose
|
||||
: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
@@ -15,8 +15,11 @@ Popup {
|
||||
x: parent ? Math.max(0, Math.round((parent.width - width) / 2)) : 0
|
||||
y: parent ? Math.max(0, Math.round((parent.height - height) / 2)) : 0
|
||||
padding: 20
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
onOpened: Qt.callLater(function() { closeButton.forceActiveFocus() })
|
||||
|
||||
background: Rectangle {
|
||||
color: "#18181b"
|
||||
border.color: "#3f3f46"
|
||||
@@ -44,6 +47,8 @@ Popup {
|
||||
}
|
||||
|
||||
Button {
|
||||
id: closeButton
|
||||
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: qsTr("Close")
|
||||
onClicked: root.close()
|
||||
|
||||
Reference in New Issue
Block a user