Skip to content

Commit 3ca75a4

Browse files
committed
qml: Introduce UI Flow for Loading Snapshot
This introduce the UI flow to load a AssumeUTXO snapshot into the Bitcoin Core App. It modifies the connection seetings and adds a SnapshotSettings file, Icon, and modified profress bar.
1 parent 7b056a0 commit 3ca75a4

17 files changed

+368
-1
lines changed

src/Makefile.qt.include

+5
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,14 @@ QML_RES_ICONS = \
337337
qml/res/icons/caret-left.png \
338338
qml/res/icons/caret-right.png \
339339
qml/res/icons/check.png \
340+
qml/res/icons/circle-file.png \
341+
qml/res/icons/circle-green-check.png \
340342
qml/res/icons/cross.png \
341343
qml/res/icons/error.png \
342344
qml/res/icons/export.png \
343345
qml/res/icons/gear.png \
344346
qml/res/icons/gear-outline.png \
347+
qml/res/icons/green-check.png \
345348
qml/res/icons/hidden.png \
346349
qml/res/icons/info.png \
347350
qml/res/icons/network-dark.png \
@@ -372,6 +375,7 @@ QML_RES_QML = \
372375
qml/components/NetworkIndicator.qml \
373376
qml/components/ProxySettings.qml \
374377
qml/components/Separator.qml \
378+
qml/components/SnapshotSettings.qml \
375379
qml/components/StorageLocations.qml \
376380
qml/components/StorageOptions.qml \
377381
qml/components/StorageSettings.qml \
@@ -425,6 +429,7 @@ QML_RES_QML = \
425429
qml/pages/settings/SettingsDeveloper.qml \
426430
qml/pages/settings/SettingsDisplay.qml \
427431
qml/pages/settings/SettingsProxy.qml \
432+
qml/pages/settings/SettingsSnapshot.qml \
428433
qml/pages/settings/SettingsStorage.qml \
429434
qml/pages/settings/SettingsTheme.qml \
430435
qml/pages/wallet/AddWallet.qml \

src/qml/bitcoin_qml.qrc

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<file>components/ProxySettings.qml</file>
1616
<file>components/StorageLocations.qml</file>
1717
<file>components/Separator.qml</file>
18+
<file>components/SnapshotSettings.qml</file>
1819
<file>components/StorageOptions.qml</file>
1920
<file>components/StorageSettings.qml</file>
2021
<file>components/ThemeSettings.qml</file>
@@ -25,6 +26,7 @@
2526
<file>controls/CoreTextField.qml</file>
2627
<file>controls/ExternalLink.qml</file>
2728
<file>controls/FocusBorder.qml</file>
29+
<file>controls/GreenCheckIcon.qml</file>
2830
<file>controls/Header.qml</file>
2931
<file>controls/Icon.qml</file>
3032
<file>controls/InformationPage.qml</file>
@@ -66,6 +68,7 @@
6668
<file>pages/settings/SettingsDeveloper.qml</file>
6769
<file>pages/settings/SettingsDisplay.qml</file>
6870
<file>pages/settings/SettingsProxy.qml</file>
71+
<file>pages/settings/SettingsSnapshot.qml</file>
6972
<file>pages/settings/SettingsStorage.qml</file>
7073
<file>pages/settings/SettingsTheme.qml</file>
7174
<file>pages/wallet/AddWallet.qml</file>
@@ -91,11 +94,14 @@
9194
<file alias="caret-left">res/icons/caret-left.png</file>
9295
<file alias="caret-right">res/icons/caret-right.png</file>
9396
<file alias="check">res/icons/check.png</file>
97+
<file alias="circle-file">res/icons/circle-file.png</file>
98+
<file alias="circle-green-check">res/icons/circle-green-check.png</file>
9499
<file alias="cross">res/icons/cross.png</file>
95100
<file alias="error">res/icons/error.png</file>
96101
<file alias="export">res/icons/export.png</file>
97102
<file alias="gear">res/icons/gear.png</file>
98103
<file alias="gear-outline">res/icons/gear-outline.png</file>
104+
<file alias="green-check">res/icons/green-check.png</file>
99105
<file alias="hidden">res/icons/hidden.png</file>
100106
<file alias="info">res/icons/info.png</file>
101107
<file alias="minus">res/icons/minus.png</file>

src/qml/components/ConnectionSettings.qml

+29
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,36 @@ import QtQuick.Layouts 1.15
88
import "../controls"
99

1010
ColumnLayout {
11+
property bool snapshotImported: false
12+
function setSnapshotImported(imported) {
13+
snapshotImported = imported
14+
}
1115
spacing: 4
16+
Setting {
17+
id: gotoSnapshot
18+
Layout.fillWidth: true
19+
header: qsTr("Load snapshot")
20+
description: qsTr("Instant use with background sync")
21+
actionItem: Item {
22+
width: 26
23+
height: 26
24+
CaretRightIcon {
25+
anchors.centerIn: parent
26+
visible: !snapshotImported
27+
color: gotoSnapshot.stateColor
28+
}
29+
GreenCheckIcon {
30+
anchors.centerIn: parent
31+
visible: snapshotImported
32+
color: Theme.color.transparent
33+
}
34+
}
35+
onClicked: {
36+
connectionSwipe.incrementCurrentIndex()
37+
connectionSwipe.incrementCurrentIndex()
38+
}
39+
}
40+
Separator { Layout.fillWidth: true }
1241
Setting {
1342
Layout.fillWidth: true
1443
header: qsTr("Enable listening")
+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// Copyright (c) 2023-present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
import QtQuick 2.15
6+
import QtQuick.Controls 2.15
7+
import QtQuick.Layouts 1.15
8+
9+
import "../controls"
10+
11+
ColumnLayout {
12+
signal snapshotImportCompleted()
13+
property int snapshotVerificationCycles: 0
14+
property real snapshotVerificationProgress: 0
15+
property bool snapshotVerified: false
16+
17+
id: columnLayout
18+
width: Math.min(parent.width, 450)
19+
anchors.horizontalCenter: parent.horizontalCenter
20+
21+
22+
Timer {
23+
id: snapshotSimulationTimer
24+
interval: 50 // Update every 50ms
25+
running: false
26+
repeat: true
27+
onTriggered: {
28+
if (snapshotVerificationProgress < 1) {
29+
snapshotVerificationProgress += 0.01
30+
} else {
31+
snapshotVerificationCycles++
32+
if (snapshotVerificationCycles < 1) {
33+
snapshotVerificationProgress = 0
34+
} else {
35+
running = false
36+
snapshotVerified = true
37+
settingsStack.currentIndex = 2
38+
}
39+
}
40+
}
41+
}
42+
43+
StackLayout {
44+
id: settingsStack
45+
currentIndex: 0
46+
47+
ColumnLayout {
48+
Layout.alignment: Qt.AlignHCenter
49+
Layout.preferredWidth: Math.min(parent.width, 450)
50+
51+
Image {
52+
Layout.alignment: Qt.AlignCenter
53+
source: "image://images/circle-file"
54+
55+
sourceSize.width: 200
56+
sourceSize.height: 200
57+
}
58+
59+
Header {
60+
Layout.fillWidth: true
61+
Layout.topMargin: 20
62+
headerBold: true
63+
header: qsTr("Load snapshot")
64+
descriptionBold: false
65+
descriptionColor: Theme.color.neutral6
66+
descriptionSize: 17
67+
descriptionLineHeight: 1.1
68+
description: qsTr("You can start using the application more quickly by loading a recent transaction snapshot." +
69+
" It will be automatically verified in the background.")
70+
}
71+
72+
ContinueButton {
73+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
74+
Layout.topMargin: 40
75+
Layout.leftMargin: 20
76+
Layout.rightMargin: Layout.leftMargin
77+
Layout.bottomMargin: 20
78+
Layout.alignment: Qt.AlignCenter
79+
text: qsTr("Choose snapshot file")
80+
onClicked: {
81+
settingsStack.currentIndex = 1
82+
snapshotSimulationTimer.start()
83+
}
84+
}
85+
}
86+
87+
ColumnLayout {
88+
Layout.alignment: Qt.AlignHCenter
89+
Layout.preferredWidth: Math.min(parent.width, 450)
90+
91+
Image {
92+
Layout.alignment: Qt.AlignCenter
93+
source: "image://images/circle-file"
94+
95+
sourceSize.width: 200
96+
sourceSize.height: 200
97+
}
98+
99+
Header {
100+
Layout.fillWidth: true
101+
Layout.topMargin: 20
102+
Layout.leftMargin: 20
103+
Layout.rightMargin: 20
104+
header: qsTr("Loading Snapshot")
105+
}
106+
107+
ProgressIndicator {
108+
id: progressIndicator
109+
Layout.topMargin: 20
110+
width: 200
111+
height: 20
112+
progress: snapshotVerificationProgress
113+
Layout.alignment: Qt.AlignCenter
114+
progressColor: Theme.color.blue
115+
}
116+
}
117+
118+
ColumnLayout {
119+
id: loadedSnapshotColumn
120+
Layout.alignment: Qt.AlignHCenter
121+
Layout.preferredWidth: Math.min(parent.width, 450)
122+
123+
Image {
124+
Layout.alignment: Qt.AlignCenter
125+
source: "image://images/circle-green-check"
126+
127+
sourceSize.width: 60
128+
sourceSize.height: 60
129+
}
130+
131+
Header {
132+
Layout.fillWidth: true
133+
Layout.topMargin: 20
134+
headerBold: true
135+
header: qsTr("Snapshot Loaded")
136+
descriptionBold: false
137+
descriptionColor: Theme.color.neutral6
138+
descriptionSize: 17
139+
descriptionLineHeight: 1.1
140+
description: qsTr("It contains transactions up to January 12, 2024. Newer transactions still need to be downloaded." +
141+
" The data will be verified in the background.")
142+
}
143+
144+
ContinueButton {
145+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
146+
Layout.topMargin: 40
147+
Layout.alignment: Qt.AlignCenter
148+
text: qsTr("Done")
149+
onClicked: {
150+
snapshotImportCompleted()
151+
connectionSwipe.decrementCurrentIndex()
152+
connectionSwipe.decrementCurrentIndex()
153+
}
154+
}
155+
156+
Setting {
157+
id: viewDetails
158+
Layout.alignment: Qt.AlignCenter
159+
header: qsTr("View details")
160+
actionItem: CaretRightIcon {
161+
id: caretIcon
162+
color: viewDetails.stateColor
163+
rotation: viewDetails.expanded ? 90 : 0
164+
Behavior on rotation { NumberAnimation { duration: 200 } }
165+
}
166+
167+
property bool expanded: false
168+
169+
onClicked: {
170+
expanded = !expanded
171+
}
172+
}
173+
174+
ColumnLayout {
175+
id: detailsContent
176+
visible: viewDetails.expanded
177+
Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin)
178+
Layout.alignment: Qt.AlignCenter
179+
Layout.leftMargin: 80
180+
Layout.rightMargin: 80
181+
Layout.topMargin: 10
182+
spacing: 10
183+
// TODO: make sure the block height number aligns right
184+
RowLayout {
185+
CoreText {
186+
text: qsTr("Block Height:")
187+
Layout.alignment: Qt.AlignLeft
188+
font.pixelSize: 14
189+
}
190+
CoreText {
191+
text: qsTr("200,000")
192+
Layout.alignment: Qt.AlignRight
193+
font.pixelSize: 14
194+
}
195+
}
196+
Separator { Layout.fillWidth: true }
197+
CoreText {
198+
text: qsTr("Hash: 0x1234567890abcdef...")
199+
font.pixelSize: 14
200+
}
201+
}
202+
}
203+
}
204+
}

src/qml/controls/GreenCheckIcon.qml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) 2023 - present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
import QtQuick 2.15
6+
import QtQuick.Controls 2.15
7+
8+
Icon {
9+
source: "image://images/green-check"
10+
size: 26
11+
}

src/qml/controls/Header.qml

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ColumnLayout {
2525
property int subtextSize: 15
2626
property color subtextColor: Theme.color.neutral9
2727
property bool wrap: true
28+
property real descriptionLineHeight: 1
2829

2930
spacing: 0
3031
Loader {
@@ -60,6 +61,7 @@ ColumnLayout {
6061
text: root.description
6162
horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft
6263
wrapMode: wrap ? Text.WordWrap : Text.NoWrap
64+
lineHeight: root.descriptionLineHeight
6365

6466
Behavior on color {
6567
ColorAnimation { duration: 150 }

src/qml/controls/ProgressIndicator.qml

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import QtQuick.Controls 2.15
77

88
Control {
99
property real progress: 0
10+
property color progressColor: Theme.color.orange
1011
Behavior on progress {
1112
NumberAnimation {
1213
easing.type: Easing.Bezier
@@ -26,7 +27,7 @@ Control {
2627
width: contentItem.width
2728
height: contentItem.height
2829
radius: contentItem.radius
29-
color: Theme.color.orange
30+
color: progressColor
3031
}
3132
}
3233
}

src/qml/controls/Theme.qml

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Control {
2727
required property color blue
2828
required property color amber
2929
required property color purple
30+
required property color transparent
3031
required property color neutral0
3132
required property color neutral1
3233
required property color neutral2
@@ -59,6 +60,7 @@ Control {
5960
blue: "#3CA3DE"
6061
amber: "#C9B500"
6162
purple: "#C075DC"
63+
transparent: "#00000000"
6264
neutral0: "#000000"
6365
neutral1: "#1A1A1A"
6466
neutral2: "#2D2D2D"
@@ -91,6 +93,7 @@ Control {
9193
blue: "#2D9CDB"
9294
amber: "#C9B500"
9395
purple: "#BB6BD9"
96+
transparent: "#00000000"
9497
neutral0: "#FFFFFF"
9598
neutral1: "#F8F8F8"
9699
neutral2: "#F4F4F4"

0 commit comments

Comments
 (0)