From 9289a1fd131f32c7c370c4cea3119adc2235f0ed Mon Sep 17 00:00:00 2001
From: johnny9 <985648+johnny9@users.noreply.github.com>
Date: Sat, 18 May 2024 23:40:27 -0400
Subject: [PATCH] qml: Introduce the WalletBadge component
The WalletBadge is an Item that shows a wallet's name, type and
balance. The WalletBadge balance shows all of the decimal places
for a whole bitcoin and highlights the satoshis available. The
component can be configured to not show the Icon or the Balance.
---
src/Makefile.qt.include | 3 +-
src/qml/bitcoin_qml.qrc | 1 +
src/qml/pages/wallet/DesktopWallets.qml | 25 +---
src/qml/pages/wallet/WalletBadge.qml | 151 ++++++++++++++++++++++++
4 files changed, 158 insertions(+), 22 deletions(-)
create mode 100644 src/qml/pages/wallet/WalletBadge.qml
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 29c329028f..d7e7d5b8d0 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -423,7 +423,8 @@ QML_RES_QML = \
qml/pages/wallet/CreateIntro.qml \
qml/pages/wallet/CreateName.qml \
qml/pages/wallet/CreatePassword.qml \
- qml/pages/wallet/DesktopWallets.qml
+ qml/pages/wallet/DesktopWallets.qml \
+ qml/pages/wallet/WalletBadge.qml
if TARGET_ANDROID
BITCOIN_QT_H += qml/androidnotifier.h
diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc
index 2f36fe8776..e7ae19417f 100644
--- a/src/qml/bitcoin_qml.qrc
+++ b/src/qml/bitcoin_qml.qrc
@@ -73,6 +73,7 @@
pages/wallet/CreateName.qml
pages/wallet/CreatePassword.qml
pages/wallet/DesktopWallets.qml
+ pages/wallet/WalletBadge.qml
res/icons/add-wallet-dark.png
diff --git a/src/qml/pages/wallet/DesktopWallets.qml b/src/qml/pages/wallet/DesktopWallets.qml
index 87b90e0166..50281453ce 100644
--- a/src/qml/pages/wallet/DesktopWallets.qml
+++ b/src/qml/pages/wallet/DesktopWallets.qml
@@ -21,27 +21,10 @@ Page {
header: NavigationBar2 {
id: navBar
- leftItem: RowLayout {
- spacing: 5
- Icon {
- source: "image://images/singlesig-wallet"
- color: Theme.color.neutral8
- Layout.preferredWidth: 30
- Layout.preferredHeight: 30
- Layout.leftMargin: 10
- }
- Column {
- spacing: 2
- CoreText {
- text: "Singlesig Wallet"
- color: Theme.color.neutral7
- bold: true
- }
- CoreText {
- text: "₿ 0.00 167 599"
- color: Theme.color.neutral7
- }
- }
+ leftItem: WalletBadge {
+ implicitWidth: 164
+ implicitHeight: 60
+ text: qsTr("Singlesig Wallet")
}
centerItem: RowLayout {
NavigationTab {
diff --git a/src/qml/pages/wallet/WalletBadge.qml b/src/qml/pages/wallet/WalletBadge.qml
new file mode 100644
index 0000000000..14f9392fb8
--- /dev/null
+++ b/src/qml/pages/wallet/WalletBadge.qml
@@ -0,0 +1,151 @@
+// Copyright (c) 2024 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+
+import org.bitcoincore.qt 1.0
+
+import "../../controls"
+
+Button {
+ id: root
+
+ function formatSatoshis(satoshis) {
+ // Convert satoshis to bitcoins
+ var bitcoins = satoshis / 100000000;
+
+ // Format bitcoins to a fixed 8 decimal places string
+ var bitcoinStr = bitcoins.toFixed(8);
+
+ // Split the bitcoin string into integer and fractional parts
+ var parts = bitcoinStr.split('.');
+
+ // Add spaces for every 3 digits in the integer part
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
+
+ // Highlight the first significant digit and all following digits in the integer part
+ var significantFound = false;
+ parts[0] = parts[0].replace(/(\d)/g, function(match) {
+ if (!significantFound && match !== '0') {
+ significantFound = true;
+ }
+ if (significantFound) {
+ return '' + match + '';
+ }
+ return match;
+ });
+
+ // Add spaces for every 3 digits in the decimal part
+ parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
+ if (significantFound) {
+ parts[1] = '' + parts[1] + '';
+ } else {
+ // Highlight the first significant digit and all following digits in the fractional part
+ significantFound = false;
+ parts[1] = parts[1].replace(/(\d)/g, function(match) {
+ if (!significantFound && match !== '0') {
+ significantFound = true;
+ }
+ if (significantFound) {
+ return '' + match + '';
+ }
+ return match;
+ });
+ }
+
+ // Concatenate the parts back together
+ var formattedBitcoins = parts.join('.');
+
+ // Format the text with the Bitcoin symbol
+ var formattedText = `₿ ${formattedBitcoins}`;
+
+ // Highlight zero in a different color if satoshis are zero
+ if (satoshis === 0) {
+ formattedText = `₿ 0.00`;
+ }
+
+ return formattedText;
+ }
+
+ property color bgActiveColor: Theme.color.neutral2
+ property color textColor: Theme.color.neutral7
+ property color textHoverColor: Theme.color.neutral9
+ property color textActiveColor: Theme.color.orange
+ property color iconColor: "transparent"
+ property string iconSource: ""
+ property bool showBalance: true
+ property bool showIcon: true
+
+ checkable: true
+ hoverEnabled: AppMode.isDesktop
+ implicitHeight: 60
+ implicitWidth: 220
+ bottomPadding: 0
+ topPadding: 0
+
+ contentItem: RowLayout {
+ anchors.fill: parent
+ anchors.leftMargin: 10
+ spacing: 5
+ Icon {
+ id: icon
+ visible: root.showIcon
+ source: "image://images/singlesig-wallet"
+ color: Theme.color.neutral8
+ Layout.preferredWidth: 30
+ Layout.preferredHeight: 30
+ }
+ Column {
+ Layout.fillWidth: true
+ spacing: 2
+ CoreText {
+ id: buttonText
+ font.pixelSize: 13
+ text: root.text
+ color: root.textColor
+ bold: true
+ visible: root.text !== ""
+ }
+ CoreText {
+ id: balanceText
+ visible: root.showBalance
+ text: formatSatoshis(12300)
+ color: Theme.color.neutral7
+ }
+ }
+ }
+
+ background: Rectangle {
+ id: bg
+ height: root.height
+ width: root.width
+ radius: 5
+ color: Theme.color.neutral3
+ visible: root.hovered || root.checked
+
+ FocusBorder {
+ visible: root.visualFocus
+ }
+
+ Behavior on color {
+ ColorAnimation { duration: 150 }
+ }
+ }
+
+ states: [
+ State {
+ name: "CHECKED"; when: root.checked
+ PropertyChanges { target: buttonText; color: root.textActiveColor }
+ PropertyChanges { target: icon; color: root.textActiveColor }
+ },
+ State {
+ name: "HOVER"; when: root.hovered
+ PropertyChanges { target: buttonText; color: root.textHoverColor }
+ PropertyChanges { target: icon; color: root.textHoverColor }
+ PropertyChanges { target: balanceText; color: root.textHoverColor }
+ }
+ ]
+}
\ No newline at end of file