Skip to content

Commit bbce6f3

Browse files
Add automatic wallet update checker
1 parent d2827d9 commit bbce6f3

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

src/qt/utilitydialog.cpp

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
#include <QTextCursor>
2727
#include <QTextTable>
2828
#include <QVBoxLayout>
29+
#include <QNetworkRequest>
30+
#include <QNetworkAccessManager>
31+
#include <QNetworkReply>
32+
#include <QJsonDocument>
33+
#include <QJsonObject>
34+
#include <QDesktopServices>
2935

3036
/** "Help message" or "About" dialog box */
3137
HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
@@ -135,6 +141,116 @@ void HelpMessageDialog::on_okButton_accepted()
135141
close();
136142
}
137143

144+
/** "Update wallet" dialog box */
145+
UpdateWalletDialog::UpdateWalletDialog(QWidget *parent) :
146+
QDialog(parent),
147+
ui(new Ui::HelpMessageDialog)
148+
{
149+
ui->setupUi(this);
150+
manager = new QNetworkAccessManager(this);
151+
152+
connect(manager, &QNetworkAccessManager::finished, [this]{ gotReply(); });
153+
connect(this, &QDialog::rejected, [this]{ on_okButton_accepted(); });
154+
155+
setWindowTitle(tr("%1 update available").arg(PACKAGE_NAME));
156+
157+
ui->aboutMessage->setTextFormat(Qt::RichText);
158+
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
159+
ui->aboutMessage->setText(getUpdateString());
160+
ui->aboutMessage->setWordWrap(true);
161+
ui->helpMessage->setVisible(false);
162+
163+
GUIUtil::handleCloseWindowShortcut(this);
164+
}
165+
166+
UpdateWalletDialog::~UpdateWalletDialog()
167+
{
168+
delete ui;
169+
delete manager;
170+
}
171+
172+
void UpdateWalletDialog::checkForUpdate()
173+
{
174+
const QString VERSION_URL = "https://raw.githubusercontent.com/ElectraProtocol/xep-ecosystem-versions/main/XEP-Core/latestversion.json";
175+
176+
const QNetworkRequest request(VERSION_URL);
177+
reply = manager->get(request);
178+
}
179+
180+
void UpdateWalletDialog::gotReply()
181+
{
182+
if (reply) {
183+
const QByteArray response_data = reply->readAll();
184+
delete reply;
185+
const QJsonDocument jsonAnswer = QJsonDocument::fromJson(response_data);
186+
const QJsonObject &responseObject = jsonAnswer.object();
187+
188+
const QString strVerMajor = "version_major";
189+
const QString strVerMinor = "version_minor";
190+
const QString strVerRev = "version_revision";
191+
const QString strVerBuild = "version_build";
192+
const QString strVerRC = "version_rc";
193+
const QString strMandatory = "mandatory";
194+
const QString strLastMandatory = "lastmandatory";
195+
196+
if (responseObject.size() == 7 && responseObject[strVerMajor].isDouble() && responseObject[strVerMinor].isDouble() &&
197+
responseObject[strVerRev].isDouble() && responseObject[strVerBuild].isDouble() && responseObject[strVerRC].isDouble() &&
198+
responseObject[strMandatory].isBool() && responseObject[strLastMandatory].isObject()) {
199+
const QJsonObject &lastMandatory = responseObject[strLastMandatory].toObject();
200+
if (lastMandatory.size() == 5 && lastMandatory[strVerMajor].isDouble() && lastMandatory[strVerMinor].isDouble() &&
201+
lastMandatory[strVerRev].isDouble() && lastMandatory[strVerBuild].isDouble() && lastMandatory[strVerRC].isDouble()) {
202+
bool outdated = true;
203+
mandatoryUpdate = true;
204+
205+
newVersionMajor = responseObject[strVerMajor].toInt();
206+
newVersionMinor = responseObject[strVerMinor].toInt();
207+
newVersionRevision = responseObject[strVerRev].toInt();
208+
newVersionBuild = responseObject[strVerBuild].toInt();
209+
newVersionRC = responseObject[strVerRC].toInt();
210+
if (lastMandatory[strVerMajor].toInt() <= CLIENT_VERSION_MAJOR && lastMandatory[strVerMinor].toInt() <= CLIENT_VERSION_MINOR && lastMandatory[strVerRev].toInt() <= CLIENT_VERSION_REVISION && lastMandatory[strVerBuild].toInt() <= CLIENT_VERSION_BUILD) {
211+
mandatoryUpdate = responseObject[strMandatory].toBool();
212+
if (newVersionMajor <= CLIENT_VERSION_MAJOR && newVersionMinor <= CLIENT_VERSION_MINOR && newVersionRevision <= CLIENT_VERSION_REVISION && newVersionBuild <= CLIENT_VERSION_BUILD) {
213+
outdated = false;
214+
}
215+
}
216+
217+
if (outdated) {
218+
ui->aboutMessage->setText(getUpdateString());
219+
exec();
220+
}
221+
}
222+
}
223+
}
224+
}
225+
226+
QString UpdateWalletDialog::getUpdateString()
227+
{
228+
229+
QString oldVersion = tr("Old version") + " - " + QString{PACKAGE_NAME} + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion());
230+
QString newVersion = tr("New version") + " - " + QString{PACKAGE_NAME} + " " + tr("version") + " v" + QString::number(newVersionMajor) + "." + QString::number(newVersionMinor) + "." + QString::number(newVersionRevision) + "." + QString::number(newVersionBuild) + (newVersionRC ? "rc" + QString::number(newVersionRC) : "");
231+
232+
/// HTML-format the license message from the core
233+
QString updateString = tr("There is a new version of %1 available for download from %2.").arg(PACKAGE_NAME, "<" PACKAGE_URL ">") + "\n\n" + tr("Please update your wallet at your earliest convenience.") + " " + (mandatoryUpdate ? tr("This is a mandatory update.") : tr("This is an optional update."));
234+
// Make URLs clickable
235+
QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2);
236+
uri.setMinimal(true); // use non-greedy matching
237+
updateString.replace(uri, "<a href=\"\\1\">\\1</a>");
238+
// Replace newlines with HTML breaks
239+
updateString.replace("\n", "<br>");
240+
241+
return (oldVersion + "<br>" + newVersion + "<br><br>" + updateString);
242+
}
243+
244+
void UpdateWalletDialog::on_okButton_accepted()
245+
{
246+
close();
247+
248+
if (mandatoryUpdate) {
249+
QDesktopServices::openUrl(QUrl(PACKAGE_URL));
250+
QApplication::quit();
251+
}
252+
}
253+
138254

139255
/** "Shutdown" window */
140256
ShutdownWindow::ShutdownWindow(QWidget *parent, Qt::WindowFlags f):

src/qt/utilitydialog.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include <QDialog>
99
#include <QWidget>
10+
#include <QNetworkAccessManager>
11+
#include <QNetworkReply>
1012

1113
QT_BEGIN_NAMESPACE
1214
class QMainWindow;
@@ -36,6 +38,35 @@ private Q_SLOTS:
3638
void on_okButton_accepted();
3739
};
3840

41+
/** "Update wallet" dialog box */
42+
class UpdateWalletDialog : public QDialog
43+
{
44+
Q_OBJECT
45+
46+
public:
47+
explicit UpdateWalletDialog(QWidget *parent);
48+
~UpdateWalletDialog();
49+
50+
void checkForUpdate();
51+
52+
private:
53+
Ui::HelpMessageDialog *ui;
54+
QNetworkAccessManager *manager = nullptr;
55+
QNetworkReply *reply = nullptr;
56+
bool mandatoryUpdate = false;
57+
unsigned int newVersionMajor = 0;
58+
unsigned int newVersionMinor = 0;
59+
unsigned int newVersionRevision = 0;
60+
unsigned int newVersionBuild = 0;
61+
unsigned int newVersionRC = 0;
62+
63+
void gotReply();
64+
QString getUpdateString();
65+
66+
private Q_SLOTS:
67+
void on_okButton_accepted();
68+
};
69+
3970

4071
/** "Shutdown" window */
4172
class ShutdownWindow : public QWidget

src/qt/xepgui.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ XEPGUI::XEPGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, cons
9696

9797
rpcConsole = new RPCConsole(node, _platformStyle, nullptr);
9898
helpMessageDialog = new HelpMessageDialog(this, false);
99+
updateWalletDialog = new UpdateWalletDialog(this);
99100
#ifdef ENABLE_WALLET
100101
if(enableWallet)
101102
{
@@ -215,6 +216,8 @@ XEPGUI::XEPGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, cons
215216
m_app_nap_inhibitor = new CAppNapInhibitor;
216217
#endif
217218

219+
updateWalletDialog->checkForUpdate();
220+
218221
GUIUtil::handleCloseWindowShortcut(this);
219222
}
220223

src/qt/xepgui.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class WalletController;
3737
class WalletFrame;
3838
class WalletModel;
3939
class HelpMessageDialog;
40+
class UpdateWalletDialog;
4041
class ModalOverlay;
4142
enum class SynchronizationState;
4243

@@ -173,6 +174,7 @@ class XEPGUI : public QMainWindow
173174
Notificator* notificator = nullptr;
174175
RPCConsole* rpcConsole = nullptr;
175176
HelpMessageDialog* helpMessageDialog = nullptr;
177+
UpdateWalletDialog* updateWalletDialog = nullptr;
176178
ModalOverlay* modalOverlay = nullptr;
177179

178180
#ifdef Q_OS_MAC

0 commit comments

Comments
 (0)