Skip to content

Commit 029b3a5

Browse files
committed
qml: Introduce UI Flow for Loading Snapshot
- This introduce the UI flow to load a AssumeUTXO snapshot - It modifies the connection settings - Adds a SnapshotLoadSettings file, Icon, and modified progress bar. - Also it adds error page on snapshotloading failure
1 parent 04b2a1f commit 029b3a5

21 files changed

+605
-5
lines changed

bitcoin

Submodule bitcoin updated 301 files

qml/bitcoin_qml.qrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<file>components/ProxySettings.qml</file>
1717
<file>components/StorageLocations.qml</file>
1818
<file>components/Separator.qml</file>
19+
<file>components/SnapshotLoadSettings.qml</file>
1920
<file>components/StorageOptions.qml</file>
2021
<file>components/StorageSettings.qml</file>
2122
<file>components/ThemeSettings.qml</file>
@@ -29,6 +30,7 @@
2930
<file>controls/CoreTextField.qml</file>
3031
<file>controls/ExternalLink.qml</file>
3132
<file>controls/FocusBorder.qml</file>
33+
<file>controls/GreenCheckIcon.qml</file>
3234
<file>controls/Header.qml</file>
3335
<file>controls/Icon.qml</file>
3436
<file>controls/IconButton.qml</file>
@@ -79,6 +81,7 @@
7981
<file>pages/settings/SettingsDeveloper.qml</file>
8082
<file>pages/settings/SettingsDisplay.qml</file>
8183
<file>pages/settings/SettingsProxy.qml</file>
84+
<file>pages/settings/SettingsSnapshotLoad.qml</file>
8285
<file>pages/settings/SettingsStorage.qml</file>
8386
<file>pages/settings/SettingsTheme.qml</file>
8487
<file>pages/wallet/Activity.qml</file>
@@ -115,13 +118,17 @@
115118
<file alias="check">res/icons/check.png</file>
116119
<file alias="copy">res/icons/copy.png</file>
117120
<file alias="coinbase">res/icons/coinbase.png</file>
121+
<file alias="circle-file">res/icons/circle-file.png</file>
122+
<file alias="circle-green-check">res/icons/circle-green-check.png</file>
123+
<file alias="circle-red-cross">res/icons/circle-red-cross.png</file>
118124
<file alias="cross">res/icons/cross.png</file>
119125
<file alias="ellipsis">res/icons/ellipsis.png</file>
120126
<file alias="error">res/icons/error.png</file>
121127
<file alias="export">res/icons/export.png</file>
122128
<file alias="flip-vertical">res/icons/flip-vertical.png</file>
123129
<file alias="gear">res/icons/gear.png</file>
124130
<file alias="gear-outline">res/icons/gear-outline.png</file>
131+
<file alias="green-check">res/icons/green-check.png</file>
125132
<file alias="hidden">res/icons/hidden.png</file>
126133
<file alias="info">res/icons/info.png</file>
127134
<file alias="lock">res/icons/lock.png</file>

qml/components/ConnectionSettings.qml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,38 @@ import "../controls"
1010
ColumnLayout {
1111
id: root
1212
signal next
13+
signal gotoSnapshot
14+
property bool onboarding: false
15+
property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
16+
property bool isIBDCompleted: nodeModel.isIBDCompleted
1317
spacing: 4
18+
Setting {
19+
id: gotoSnapshot
20+
visible: !snapshotImportCompleted && !root.isIBDCompleted
21+
Layout.fillWidth: true
22+
header: qsTr("Load snapshot")
23+
description: qsTr("Instant use with background sync")
24+
actionItem: Item {
25+
width: 26
26+
height: 26
27+
CaretRightIcon {
28+
anchors.centerIn: parent
29+
visible: !snapshotImportCompleted
30+
color: gotoSnapshot.stateColor
31+
}
32+
GreenCheckIcon {
33+
anchors.centerIn: parent
34+
visible: snapshotImportCompleted
35+
color: Theme.color.transparent
36+
size: 30
37+
}
38+
}
39+
onClicked: root.gotoSnapshot()
40+
}
41+
Separator {
42+
visible: !snapshotImportCompleted && !root.isIBDCompleted
43+
Layout.fillWidth: true
44+
}
1445
Setting {
1546
Layout.fillWidth: true
1647
header: qsTr("Enable listening")
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
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+
import QtQuick.Dialogs
9+
10+
import "../controls"
11+
12+
ColumnLayout {
13+
id: columnLayout
14+
signal back
15+
property bool snapshotLoading: nodeModel.snapshotLoading
16+
property bool snapshotLoaded: nodeModel.isSnapshotLoaded
17+
property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
18+
property bool onboarding: false
19+
property bool snapshotVerified: onboarding ? false : chainModel.isSnapshotActive
20+
property string snapshotFileName: ""
21+
property var snapshotInfo: (snapshotVerified || snapshotLoaded) ? chainModel.getSnapshotInfo() : ({})
22+
property string selectedFile: ""
23+
property bool headersSynced: nodeModel.headersSynced
24+
property bool snapshotError: nodeModel.snapshotError
25+
26+
width: Math.min(parent.width, 450)
27+
anchors.horizontalCenter: parent.horizontalCenter
28+
29+
StackLayout {
30+
id: settingsStack
31+
currentIndex: onboarding ? 0 : snapshotLoaded ? 2 : snapshotVerified ? 2 : snapshotLoading ? 1 : snapshotError ? 3 : 0
32+
33+
ColumnLayout {
34+
Layout.alignment: Qt.AlignHCenter
35+
Layout.preferredWidth: Math.min(parent.width, 450)
36+
37+
Image {
38+
Layout.alignment: Qt.AlignCenter
39+
source: "image://images/circle-file"
40+
41+
sourceSize.width: 200
42+
sourceSize.height: 200
43+
}
44+
45+
Header {
46+
Layout.fillWidth: true
47+
Layout.topMargin: 20
48+
headerBold: true
49+
header: qsTr("Load snapshot")
50+
descriptionBold: false
51+
descriptionColor: Theme.color.neutral6
52+
descriptionSize: 17
53+
descriptionLineHeight: 1.1
54+
description: qsTr("You can start using the application more quickly by loading a recent transaction snapshot." +
55+
" It will be automatically verified in the background.")
56+
}
57+
58+
CoreText {
59+
Layout.fillWidth: true
60+
Layout.topMargin: 20
61+
color: Theme.color.neutral6
62+
font.pixelSize: 17
63+
visible: !headersSynced && !onboarding
64+
text: !headersSynced
65+
? qsTr("Please wait for headers to sync before loading a snapshot.")
66+
: qsTr("")
67+
wrap: true
68+
wrapMode: Text.WordWrap
69+
}
70+
71+
ContinueButton {
72+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
73+
Layout.topMargin: 40
74+
Layout.leftMargin: 20
75+
Layout.rightMargin: Layout.leftMargin
76+
Layout.bottomMargin: 20
77+
Layout.alignment: Qt.AlignCenter
78+
text: qsTr("Choose snapshot file")
79+
enabled: headersSynced || onboarding
80+
onClicked: fileDialog.open()
81+
}
82+
83+
FileDialog {
84+
id: fileDialog
85+
currentFolder: optionsModel.getDefaultDataDirectory
86+
nameFilters: ["Snapshot files (*.dat)", "All files (*)"]
87+
onAccepted: {
88+
snapshotFileName = selectedFile
89+
console.log("snapshotFileName", snapshotFileName)
90+
if (!onboarding) {
91+
nodeModel.snapshotLoadThread(snapshotFileName)
92+
} else {
93+
nodeModel.setSnapshotFilePath(snapshotFileName)
94+
back()
95+
}
96+
}
97+
}
98+
}
99+
100+
ColumnLayout {
101+
Layout.alignment: Qt.AlignHCenter
102+
Layout.preferredWidth: Math.min(parent.width, 450)
103+
104+
Image {
105+
Layout.alignment: Qt.AlignCenter
106+
source: "image://images/circle-file"
107+
108+
sourceSize.width: 200
109+
sourceSize.height: 200
110+
}
111+
112+
Header {
113+
Layout.fillWidth: true
114+
Layout.topMargin: 20
115+
Layout.leftMargin: 20
116+
Layout.rightMargin: 20
117+
header: qsTr("Loading Snapshot")
118+
description: qsTr("This might take a while...")
119+
}
120+
121+
ProgressIndicator {
122+
id: progressIndicator
123+
Layout.topMargin: 20
124+
width: 200
125+
height: 20
126+
progress: nodeModel.snapshotProgress
127+
Layout.alignment: Qt.AlignCenter
128+
progressColor: Theme.color.blue
129+
}
130+
}
131+
132+
ColumnLayout {
133+
id: loadedSnapshotColumn
134+
Layout.alignment: Qt.AlignHCenter
135+
Layout.preferredWidth: Math.min(parent.width, 450)
136+
137+
Image {
138+
Layout.alignment: Qt.AlignCenter
139+
source: "image://images/circle-green-check"
140+
141+
sourceSize.width: 60
142+
sourceSize.height: 60
143+
}
144+
145+
Header {
146+
Layout.fillWidth: true
147+
Layout.topMargin: 20
148+
headerBold: true
149+
header: qsTr("Snapshot Loaded")
150+
descriptionBold: false
151+
descriptionColor: Theme.color.neutral6
152+
descriptionSize: 17
153+
descriptionLineHeight: 1.1
154+
description: snapshotInfo && snapshotInfo["date"] ?
155+
qsTr("It contains unspent transactions up to %1. Next, transactions will be verified and newer transactions downloaded.").arg(snapshotInfo["date"]) :
156+
qsTr("It contains transactions up to DEBUG. Newer transactions still need to be downloaded." +
157+
" The data will be verified in the background.")
158+
}
159+
160+
ContinueButton {
161+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
162+
Layout.topMargin: 40
163+
Layout.alignment: Qt.AlignCenter
164+
text: qsTr("Done")
165+
onClicked: {
166+
chainModel.isSnapshotActiveChanged()
167+
back()
168+
}
169+
}
170+
171+
Setting {
172+
id: viewDetails
173+
Layout.alignment: Qt.AlignCenter
174+
header: qsTr("View details")
175+
actionItem: CaretRightIcon {
176+
id: caretIcon
177+
color: viewDetails.stateColor
178+
rotation: viewDetails.expanded ? 90 : 0
179+
Behavior on rotation { NumberAnimation { duration: 200 } }
180+
}
181+
182+
property bool expanded: false
183+
184+
onClicked: {
185+
expanded = !expanded
186+
}
187+
}
188+
189+
ColumnLayout {
190+
id: detailsContent
191+
visible: viewDetails.expanded
192+
Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin)
193+
Layout.alignment: Qt.AlignCenter
194+
Layout.leftMargin: 80
195+
Layout.rightMargin: 80
196+
Layout.topMargin: 10
197+
spacing: 10
198+
// TODO: make sure the block height number aligns right
199+
RowLayout {
200+
CoreText {
201+
text: qsTr("Block Height:")
202+
Layout.alignment: Qt.AlignLeft
203+
font.pixelSize: 14
204+
}
205+
CoreText {
206+
text: snapshotInfo && snapshotInfo["height"] ?
207+
snapshotInfo["height"] : qsTr("DEBUG")
208+
Layout.alignment: Qt.AlignRight
209+
font.pixelSize: 14
210+
}
211+
}
212+
Separator { Layout.fillWidth: true }
213+
ColumnLayout {
214+
Layout.fillWidth: true
215+
spacing: 5
216+
CoreText {
217+
text: qsTr("Hash:")
218+
font.pixelSize: 14
219+
}
220+
CoreText {
221+
text: snapshotInfo && snapshotInfo["hashSerializedFirstHalf"] ?
222+
snapshotInfo["hashSerializedFirstHalf"] + "\n" + snapshotInfo["hashSerializedSecondHalf"] :
223+
qsTr("DEBUG")
224+
Layout.fillWidth: true
225+
font.pixelSize: 14
226+
textFormat: Text.PlainText
227+
}
228+
}
229+
}
230+
}
231+
232+
ColumnLayout {
233+
id: snapshotErrorColumn
234+
Layout.alignment: Qt.AlignHCenter
235+
Layout.preferredWidth: Math.min(parent.width, 450)
236+
237+
Image {
238+
Layout.alignment: Qt.AlignCenter
239+
source: "image://images/circle-red-cross"
240+
241+
sourceSize.width: 60
242+
sourceSize.height: 60
243+
}
244+
245+
Header {
246+
Layout.fillWidth: true
247+
Layout.topMargin: 20
248+
headerBold: true
249+
header: qsTr("Snapshot Could Not Be Verified")
250+
descriptionBold: false
251+
descriptionColor: Theme.color.neutral6
252+
descriptionSize: 17
253+
descriptionLineHeight: 1.1
254+
description: qsTr("There was a problem with the transactions in the snapshot. Please try a different file.")
255+
}
256+
257+
ContinueButton {
258+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
259+
Layout.topMargin: 40
260+
Layout.alignment: Qt.AlignCenter
261+
text: qsTr("OK")
262+
onClicked: {
263+
nodeModel.setSnapshotError(false)
264+
back()
265+
}
266+
}
267+
}
268+
}
269+
}

qml/controls/GreenCheckIcon.qml

Lines changed: 11 additions & 0 deletions
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: 30
11+
}

qml/controls/Header.qml

Lines changed: 2 additions & 0 deletions
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 }

qml/controls/ProgressIndicator.qml

Lines changed: 2 additions & 1 deletion
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
}

0 commit comments

Comments
 (0)