mirror of
https://github.com/logos-blockchain/logos-execution-zone-wallet-ui.git
synced 2026-07-30 06:33:29 +00:00
feat: improve private account listing
This commit is contained in:
parent
275415f34c
commit
97bae8ad1f
@ -31,6 +31,7 @@ QVariant LEZWalletAccountModel::data(const QModelIndex& index, int role) const
|
||||
case SectionKeyRole: return e.sectionKey;
|
||||
case KeysJsonRole: return e.keysJson;
|
||||
case IsFirstInGroupRole: return e.isFirstInGroup;
|
||||
case IsFirstPrivateRole: return e.isFirstPrivate;
|
||||
case IsInitializedRole: return e.isInitialized;
|
||||
default: return QVariant();
|
||||
}
|
||||
@ -47,6 +48,7 @@ QHash<int, QByteArray> LEZWalletAccountModel::roleNames() const
|
||||
{ SectionKeyRole, "sectionKey" },
|
||||
{ KeysJsonRole, "keysJson" },
|
||||
{ IsFirstInGroupRole, "isFirstInGroup" },
|
||||
{ IsFirstPrivateRole, "isFirstPrivate" },
|
||||
{ IsInitializedRole, "isInitialized" }
|
||||
};
|
||||
}
|
||||
@ -100,8 +102,13 @@ void LEZWalletAccountModel::replaceFromVariantList(const QVariantList& list)
|
||||
if (a.isPublic != b.isPublic) return a.isPublic;
|
||||
return a.sectionKey < b.sectionKey;
|
||||
});
|
||||
for (int i = 0; i < m_entries.size(); ++i)
|
||||
for (int i = 0; i < m_entries.size(); ++i) {
|
||||
m_entries[i].isFirstInGroup = (i == 0) || (m_entries[i].sectionKey != m_entries[i - 1].sectionKey);
|
||||
// All private key-groups sit under a single "Private" title (unlike the public
|
||||
// section, they don't each get their own top-level header) — so only the very
|
||||
// first private row across all groups needs to flag it.
|
||||
m_entries[i].isFirstPrivate = !m_entries[i].isPublic && (i == 0 || m_entries[i - 1].isPublic);
|
||||
}
|
||||
endResetModel();
|
||||
if (oldCount != m_entries.size())
|
||||
emit countChanged();
|
||||
|
||||
@ -18,7 +18,8 @@ struct LEZWalletAccountEntry {
|
||||
bool isPublic = true;
|
||||
QString sectionKey;
|
||||
QString keysJson; // {nullifier_public_key, viewing_public_key} shared by the whole section; private only
|
||||
bool isFirstInGroup = false; // QML renders the section header above rows where this is true
|
||||
bool isFirstInGroup = false; // QML renders the per-key-set header (copy button) above rows where this is true
|
||||
bool isFirstPrivate = false; // QML renders the single "Private" section title above rows where this is true
|
||||
// Whether some program (in practice, the authenticated-transfer program) has claimed
|
||||
// this account yet. Defaults to false (shown as needing init) so an account whose
|
||||
// state we failed to enrich isn't silently mistaken for a usable one.
|
||||
@ -42,6 +43,7 @@ public:
|
||||
SectionKeyRole,
|
||||
KeysJsonRole,
|
||||
IsFirstInGroupRole,
|
||||
IsFirstPrivateRole,
|
||||
IsInitializedRole
|
||||
};
|
||||
Q_ENUM(Role)
|
||||
|
||||
@ -149,26 +149,124 @@ Rectangle {
|
||||
// row is created.
|
||||
property string keysJsonWarm: model.keysJson ?? ""
|
||||
|
||||
// "Public Accounts" title: the public section is a single group, so this
|
||||
// is equivalent to showing it once above the first public row.
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
visible: model.isFirstInGroup ?? false
|
||||
visible: model.isPublic && (model.isFirstInGroup ?? false)
|
||||
spacing: Theme.spacing.small
|
||||
|
||||
LogosText {
|
||||
text: model.isPublic
|
||||
? qsTr("Public Accounts")
|
||||
: qsTr("Private")
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
text: qsTr("Public Accounts")
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
font.bold: true
|
||||
color: Theme.palette.textSecondary
|
||||
color: Theme.palette.text
|
||||
}
|
||||
}
|
||||
|
||||
// "Private Accounts" title: shown once above the whole private section,
|
||||
// unlike the per-key-set row below which repeats for every private key
|
||||
// group. Wrapped the same way as the "Public Accounts" title above so
|
||||
// both line up identically.
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
visible: model.isFirstPrivate ?? false
|
||||
spacing: Theme.spacing.small
|
||||
|
||||
LogosText {
|
||||
text: qsTr("Private Accounts")
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
font.bold: true
|
||||
color: Theme.palette.text
|
||||
}
|
||||
}
|
||||
|
||||
// Per-key-set row: separates each private key group within the Private
|
||||
// section, naming the group by its Npk/Vpk pair, and holds the copy
|
||||
// button for that pair.
|
||||
RowLayout {
|
||||
id: keyGroupHeader
|
||||
Layout.fillWidth: true
|
||||
visible: !model.isPublic && (model.isFirstInGroup ?? false)
|
||||
spacing: Theme.spacing.small
|
||||
|
||||
property var groupKeys: {
|
||||
try { return JSON.parse(model.keysJson ?? "{}") } catch (e) { return {} }
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
function shortKey(key) {
|
||||
return key && key.length > 12 ? key.slice(0, 6) + "…" + key.slice(-4) : (key || "")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
|
||||
LogosText {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Accounts under keys")
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
}
|
||||
|
||||
// Each of Npk/Vpk gets its own bullet, aligned with "Private
|
||||
// Accounts"/"Accounts under keys" above. Labels share a fixed
|
||||
// width (the wider of the two) so the value column still lines
|
||||
// up between the two rows.
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Theme.spacing.small
|
||||
|
||||
LogosText {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
}
|
||||
LogosText {
|
||||
id: npkLabel
|
||||
Layout.preferredWidth: Math.max(npkLabel.implicitWidth, vpkLabel.implicitWidth)
|
||||
text: qsTr("Npk:")
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
}
|
||||
LogosText {
|
||||
Layout.fillWidth: true
|
||||
text: keyGroupHeader.shortKey(keyGroupHeader.groupKeys.nullifier_public_key)
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Theme.spacing.small
|
||||
|
||||
LogosText {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
}
|
||||
LogosText {
|
||||
id: vpkLabel
|
||||
Layout.preferredWidth: Math.max(npkLabel.implicitWidth, vpkLabel.implicitWidth)
|
||||
text: qsTr("Vpk:")
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
}
|
||||
LogosText {
|
||||
Layout.fillWidth: true
|
||||
text: keyGroupHeader.shortKey(keyGroupHeader.groupKeys.viewing_public_key)
|
||||
font.pixelSize: Theme.typography.secondaryText
|
||||
color: Theme.palette.textSecondary
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogosCopyButton {
|
||||
Layout.preferredHeight: 32
|
||||
Layout.preferredWidth: 32
|
||||
visible: !model.isPublic
|
||||
icon.color: Theme.palette.textMuted
|
||||
onCopyText: root.copyRequested(model.keysJson ?? "")
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user