From ed5f034676a97a3d1cb5d16a6d4ed82765ac8dfa Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Tue, 20 May 2025 19:47:08 -0400 Subject: [PATCH 1/6] qml: Add initialized property to WalletQmlController --- src/qml/walletqmlcontroller.cpp | 3 +++ src/qml/walletqmlcontroller.h | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/qml/walletqmlcontroller.cpp b/src/qml/walletqmlcontroller.cpp index d4a443d6c2..a9eed57d0d 100644 --- a/src/qml/walletqmlcontroller.cpp +++ b/src/qml/walletqmlcontroller.cpp @@ -120,4 +120,7 @@ void WalletQmlController::initialize() m_selected_wallet = m_wallets.front(); Q_EMIT selectedWalletChanged(); } + + m_initialized = true; + Q_EMIT initializedChanged(); } diff --git a/src/qml/walletqmlcontroller.h b/src/qml/walletqmlcontroller.h index 476800cfaa..4dd5acb211 100644 --- a/src/qml/walletqmlcontroller.h +++ b/src/qml/walletqmlcontroller.h @@ -6,19 +6,22 @@ #define BITCOIN_QML_WALLETQMLCONTROLLER_H #include + #include #include #include +#include + #include #include #include -#include class WalletQmlController : public QObject { Q_OBJECT Q_PROPERTY(WalletQmlModel* selectedWallet READ selectedWallet NOTIFY selectedWalletChanged) + Q_PROPERTY(bool initialized READ initialized NOTIFY initializedChanged) public: explicit WalletQmlController(interfaces::Node& node, QObject *parent = nullptr); @@ -29,9 +32,11 @@ class WalletQmlController : public QObject WalletQmlModel* selectedWallet() const; void unloadWallets(); + bool initialized() const { return m_initialized; } Q_SIGNALS: void selectedWalletChanged(); + void initializedChanged(); public Q_SLOTS: void initialize(); @@ -39,6 +44,7 @@ public Q_SLOTS: private: void handleLoadWallet(std::unique_ptr wallet); + bool m_initialized{false}; interfaces::Node& m_node; WalletQmlModel* m_selected_wallet; QObject* m_worker; From bad0648b86adcb1ccb2ba1937a60fddb27a36120 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Tue, 20 May 2025 19:47:30 -0400 Subject: [PATCH 2/6] qml: Fix walletqmlmodel.cpp include order --- src/qml/models/walletqmlmodel.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qml/models/walletqmlmodel.cpp b/src/qml/models/walletqmlmodel.cpp index 55df50c8da..cdce215608 100644 --- a/src/qml/models/walletqmlmodel.cpp +++ b/src/qml/models/walletqmlmodel.cpp @@ -4,13 +4,14 @@ #include +#include +#include +#include + #include #include #include #include -#include -#include -#include #include #include #include From 6bbd72d91ca419748bc19f723a356a229250bb89 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Tue, 20 May 2025 23:47:43 -0400 Subject: [PATCH 3/6] qml: Introduce Skeleton.qml --- src/Makefile.qt.include | 3 +- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/Skeleton.qml | 62 +++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/qml/controls/Skeleton.qml diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index c52728fce2..c727260533 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -440,8 +440,9 @@ QML_RES_QML = \ qml/controls/PageStack.qml \ qml/controls/ProgressIndicator.qml \ qml/controls/qmldir \ - qml/controls/Setting.qml \ qml/controls/SendOptionsPopup.qml \ + qml/controls/Setting.qml \ + qml/controls/Skeleton.qml \ qml/controls/TextButton.qml \ qml/controls/Theme.qml \ qml/controls/ToggleButton.qml \ diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 8c4b231ef9..13044f30f7 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -50,6 +50,7 @@ controls/qmldir controls/SendOptionsPopup.qml controls/Setting.qml + controls/Skeleton.qml controls/TextButton.qml controls/Theme.qml controls/ToggleButton.qml diff --git a/src/qml/controls/Skeleton.qml b/src/qml/controls/Skeleton.qml new file mode 100644 index 0000000000..34a89faba5 --- /dev/null +++ b/src/qml/controls/Skeleton.qml @@ -0,0 +1,62 @@ +// Copyright (c) 2025 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 + +Rectangle { + id: root + property color baseColor: Theme.color.neutral1 + property color highlightColor: Theme.color.neutral2 + property int shimmerDuration: 2500 + + radius: 3 + + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { + id: stop1 + position: 0.0 + color: root.baseColor + } + GradientStop { + id: stop2 + position: 0.5 + color: root.highlightColor + } + GradientStop { + id: stop3; + position: 1 + color: root.baseColor + } + } + + ParallelAnimation { + running: true + loops: Animation.Infinite + NumberAnimation { + target: stop1 + property: "position" + from: -1.0 + to: 1.0 + duration: root.shimmerDuration + easing.type: Easing.Linear + } + NumberAnimation { + target: stop2 + property: "position" + from: -0.5 + to: 1.5 + duration: root.shimmerDuration; + easing.type: Easing.Linear + } + NumberAnimation { + target: stop3 + property: "position" + from: 0.0 + to: 2.0 + duration: root.shimmerDuration + easing.type: Easing.Linear + } + } +} From 2ba51482bb73ed8e85462322903a7b2e44b82209 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Tue, 20 May 2025 23:52:11 -0400 Subject: [PATCH 4/6] qml: Add Skeleton loading animation to WalletBadge --- src/qml/pages/wallet/DesktopWallets.qml | 1 + src/qml/pages/wallet/WalletBadge.qml | 96 +++++++++++++++++-------- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/src/qml/pages/wallet/DesktopWallets.qml b/src/qml/pages/wallet/DesktopWallets.qml index c63dd9f7bb..c9fe742993 100644 --- a/src/qml/pages/wallet/DesktopWallets.qml +++ b/src/qml/pages/wallet/DesktopWallets.qml @@ -29,6 +29,7 @@ Page { implicitHeight: 46 text: walletController.selectedWallet.name balance: walletController.selectedWallet.balance + loading: !walletController.initialized MouseArea { anchors.fill: parent diff --git a/src/qml/pages/wallet/WalletBadge.qml b/src/qml/pages/wallet/WalletBadge.qml index befc49eddf..9d3bb31039 100644 --- a/src/qml/pages/wallet/WalletBadge.qml +++ b/src/qml/pages/wallet/WalletBadge.qml @@ -22,6 +22,7 @@ Button { property bool showBalance: true property bool showIcon: true property string balance: "0.0 000 000" + property bool loading: false checkable: true hoverEnabled: AppMode.isDesktop @@ -31,39 +32,72 @@ Button { topPadding: 0 clip: true - contentItem: RowLayout { - anchors.leftMargin: 5 - anchors.rightMargin: 5 - clip: true - spacing: 5 - Icon { - id: icon - visible: root.showIcon - source: "image://images/singlesig-wallet" - color: Theme.color.neutral8 - size: 30 - Layout.minimumWidth: 30 - Layout.preferredWidth: 30 - Layout.maximumWidth: 30 - } - ColumnLayout { - spacing: 2 - CoreText { - horizontalAlignment: Text.AlignLeft + contentItem: Item { + RowLayout { + visible: root.loading + anchors.leftMargin: 5 + anchors.rightMargin: 5 + anchors.centerIn: parent + spacing: 5 + + Skeleton { + Layout.preferredHeight: 30 + Layout.preferredWidth: 30 + } + ColumnLayout { + spacing: 2 + Layout.preferredHeight: 30 Layout.fillWidth: true - wrap: false - id: buttonText - font.pixelSize: 13 - text: root.text - color: root.textColor - bold: true - visible: root.text !== "" + + Skeleton { + Layout.preferredHeight: 15 + Layout.preferredWidth: 50 + } + + Skeleton { + Layout.preferredHeight: 15 + Layout.preferredWidth: 114 + } + } + } + + RowLayout { + visible: !root.loading + + anchors.leftMargin: 5 + anchors.rightMargin: 5 + anchors.centerIn: parent + clip: true + spacing: 5 + Icon { + id: icon + visible: root.showIcon + source: "image://images/singlesig-wallet" + color: Theme.color.neutral8 + size: 30 + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 } - CoreText { - id: balanceText - visible: root.showBalance - text: "₿ " + root.balance - color: Theme.color.neutral7 + ColumnLayout { + spacing: 2 + CoreText { + horizontalAlignment: Text.AlignLeft + Layout.fillWidth: true + wrap: false + id: buttonText + font.pixelSize: 13 + text: root.text + color: root.textColor + bold: true + visible: root.text !== "" + } + CoreText { + id: balanceText + visible: root.showBalance + text: "₿ " + root.balance + color: Theme.color.neutral7 + } } } } From 99ca9fde8032177fb54c662cb929bc2ade790d94 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Tue, 20 May 2025 23:52:54 -0400 Subject: [PATCH 5/6] qml: Add fade-in animation to WalletBadge --- src/qml/pages/wallet/WalletBadge.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qml/pages/wallet/WalletBadge.qml b/src/qml/pages/wallet/WalletBadge.qml index 9d3bb31039..b7bcf7f781 100644 --- a/src/qml/pages/wallet/WalletBadge.qml +++ b/src/qml/pages/wallet/WalletBadge.qml @@ -64,6 +64,12 @@ Button { RowLayout { visible: !root.loading + opacity: visible ? 1 : 0 + + Behavior on opacity { + NumberAnimation { duration: 400 } + } + anchors.leftMargin: 5 anchors.rightMargin: 5 anchors.centerIn: parent From bb95aa796977e6374059af67ccabb884548efb62 Mon Sep 17 00:00:00 2001 From: johnny9 <985648+johnny9@users.noreply.github.com> Date: Thu, 22 May 2025 09:30:35 -0400 Subject: [PATCH 6/6] qml: Explicitly stop Skeleton Animation when not loading --- src/qml/controls/Skeleton.qml | 3 ++- src/qml/pages/wallet/WalletBadge.qml | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qml/controls/Skeleton.qml b/src/qml/controls/Skeleton.qml index 34a89faba5..36277c1cc0 100644 --- a/src/qml/controls/Skeleton.qml +++ b/src/qml/controls/Skeleton.qml @@ -9,6 +9,7 @@ Rectangle { property color baseColor: Theme.color.neutral1 property color highlightColor: Theme.color.neutral2 property int shimmerDuration: 2500 + property bool loading: true radius: 3 @@ -32,7 +33,7 @@ Rectangle { } ParallelAnimation { - running: true + running: loading loops: Animation.Infinite NumberAnimation { target: stop1 diff --git a/src/qml/pages/wallet/WalletBadge.qml b/src/qml/pages/wallet/WalletBadge.qml index b7bcf7f781..1fca0b7105 100644 --- a/src/qml/pages/wallet/WalletBadge.qml +++ b/src/qml/pages/wallet/WalletBadge.qml @@ -43,6 +43,7 @@ Button { Skeleton { Layout.preferredHeight: 30 Layout.preferredWidth: 30 + loading: root.loading } ColumnLayout { spacing: 2 @@ -52,11 +53,13 @@ Button { Skeleton { Layout.preferredHeight: 15 Layout.preferredWidth: 50 + loading: root.loading } Skeleton { Layout.preferredHeight: 15 Layout.preferredWidth: 114 + loading: root.loading } } }