mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-21 18:50:47 +03:00
Improve login flow (#35)
* Validate both inferred and explicitly entered server addresses by attempting to call the /versions endpoint * If the domain from the mxid fails validation, try prefixing it with 'matrix' * Only show server address field if address validation ultimately fails
This commit is contained in:
parent
03437cc693
commit
f5ba63946b
10 changed files with 250 additions and 137 deletions
|
@ -98,7 +98,6 @@ set(SRC_FILES
|
|||
src/InputValidator.cc
|
||||
src/Login.cc
|
||||
src/LoginPage.cc
|
||||
src/LoginSettings.cc
|
||||
src/LogoutDialog.cc
|
||||
src/MainWindow.cc
|
||||
src/MatrixClient.cc
|
||||
|
@ -116,6 +115,7 @@ set(SRC_FILES
|
|||
src/TrayIcon.cc
|
||||
src/TopRoomBar.cc
|
||||
src/UserInfoWidget.cc
|
||||
src/Versions.cc
|
||||
src/WelcomePage.cc
|
||||
src/main.cc
|
||||
|
||||
|
@ -177,7 +177,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||
include/TimelineView.h
|
||||
include/TimelineViewManager.h
|
||||
include/LoginPage.h
|
||||
include/LoginSettings.h
|
||||
include/LogoutDialog.h
|
||||
include/MainWindow.h
|
||||
include/MatrixClient.h
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "CircularProgress.h"
|
||||
#include "FlatButton.h"
|
||||
#include "LoginSettings.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "OverlayModal.h"
|
||||
#include "RaisedButton.h"
|
||||
|
@ -50,12 +50,20 @@ private slots:
|
|||
// Callback for the login button.
|
||||
void onLoginButtonClicked();
|
||||
|
||||
// Callback for probing the server found in the mxid
|
||||
void onMatrixIdEntered();
|
||||
|
||||
// Callback for probing the manually entered server
|
||||
void onServerAddressEntered();
|
||||
|
||||
// Displays errors produced during the login.
|
||||
void loginError(QString error_message);
|
||||
|
||||
// Manipulate settings modal.
|
||||
void showSettingsModal();
|
||||
void closeSettingsModal(const QString &server);
|
||||
// Callback for errors produced during server probing
|
||||
void versionError(QString error_message);
|
||||
|
||||
// Callback for successful server probing
|
||||
void versionSuccess();
|
||||
|
||||
private:
|
||||
QVBoxLayout *top_layout_;
|
||||
|
@ -67,8 +75,13 @@ private:
|
|||
QLabel *logo_;
|
||||
QLabel *error_label_;
|
||||
|
||||
QHBoxLayout *serverLayout_;
|
||||
QHBoxLayout *matrixidLayout_;
|
||||
CircularProgress *spinner_;
|
||||
QLabel *errorIcon_;
|
||||
QString inferredServerAddress_;
|
||||
|
||||
FlatButton *back_button_;
|
||||
FlatButton *advanced_settings_button_;
|
||||
RaisedButton *login_button_;
|
||||
|
||||
QWidget *form_widget_;
|
||||
|
@ -77,10 +90,7 @@ private:
|
|||
|
||||
TextField *matrixid_input_;
|
||||
TextField *password_input_;
|
||||
|
||||
OverlayModal *settings_modal_;
|
||||
LoginSettings *login_settings_;
|
||||
QString custom_domain_;
|
||||
TextField *serverInput_;
|
||||
|
||||
// Matrix client API provider.
|
||||
QSharedPointer<MatrixClient> client_;
|
||||
|
|
|
@ -63,11 +63,13 @@ public slots:
|
|||
signals:
|
||||
void loginError(const QString &error);
|
||||
void registerError(const QString &error);
|
||||
void versionError(const QString &error);
|
||||
|
||||
void loggedOut();
|
||||
|
||||
void loginSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
||||
void registerSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
||||
void versionSuccess();
|
||||
|
||||
void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
|
||||
void userAvatarRetrieved(const QString &userId, const QImage &img);
|
||||
|
|
|
@ -17,21 +17,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QJsonDocument>
|
||||
#include <QVector>
|
||||
|
||||
#include "FlatButton.h"
|
||||
#include "TextField.h"
|
||||
#include "Deserializable.h"
|
||||
|
||||
class LoginSettings : public QFrame
|
||||
|
||||
class VersionsResponse : public Deserializable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LoginSettings(QWidget *parent = nullptr);
|
||||
void deserialize(const QJsonDocument &data) override;
|
||||
|
||||
signals:
|
||||
void closing(const QString &server);
|
||||
bool isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch);
|
||||
|
||||
private:
|
||||
TextField *input_;
|
||||
FlatButton *submit_button_;
|
||||
struct Version_ {
|
||||
unsigned int major_;
|
||||
unsigned int minor_;
|
||||
unsigned int patch_;
|
||||
};
|
||||
|
||||
QVector<Version_> supported_versions_;
|
||||
|
||||
};
|
BIN
resources/icons/error.png
Normal file
BIN
resources/icons/error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 621 B |
|
@ -12,6 +12,7 @@
|
|||
<file>icons/user-shape.png</file>
|
||||
<file>icons/power-button-off.png</file>
|
||||
<file>icons/smile.png</file>
|
||||
<file>icons/error.png</file>
|
||||
|
||||
<file>icons/emoji-categories/people.png</file>
|
||||
<file>icons/emoji-categories/nature.png</file>
|
||||
|
|
178
src/LoginPage.cc
178
src/LoginPage.cc
|
@ -21,10 +21,9 @@
|
|||
#include "LoginPage.h"
|
||||
|
||||
LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, settings_modal_{nullptr}
|
||||
, login_settings_{nullptr}
|
||||
, client_{client}
|
||||
: QWidget(parent)
|
||||
, inferredServerAddress_()
|
||||
, client_{client}
|
||||
{
|
||||
setStyleSheet("background-color: #f9f9f9");
|
||||
|
||||
|
@ -38,9 +37,8 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
back_button_->setMinimumSize(QSize(30, 30));
|
||||
back_button_->setForegroundColor("#333333");
|
||||
|
||||
advanced_settings_button_ = new FlatButton(this);
|
||||
advanced_settings_button_->setMinimumSize(QSize(30, 30));
|
||||
advanced_settings_button_->setForegroundColor("#333333");
|
||||
top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
top_bar_layout_->addStretch(1);
|
||||
|
||||
QIcon icon;
|
||||
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||
|
@ -51,13 +49,6 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
QIcon advanced_settings_icon;
|
||||
advanced_settings_icon.addFile(":/icons/icons/cog.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||
|
||||
advanced_settings_button_->setIcon(advanced_settings_icon);
|
||||
advanced_settings_button_->setIconSize(QSize(24, 24));
|
||||
|
||||
top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
top_bar_layout_->addStretch(1);
|
||||
top_bar_layout_->addWidget(advanced_settings_button_, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
|
||||
logo_ = new QLabel(this);
|
||||
logo_->setPixmap(QPixmap(":/logos/nheko-128.png"));
|
||||
|
||||
|
@ -85,6 +76,19 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
matrixid_input_->setBackgroundColor("#f9f9f9");
|
||||
matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
|
||||
|
||||
spinner_ = new CircularProgress(this);
|
||||
spinner_->setColor("#acc7dc");
|
||||
spinner_->setSize(32);
|
||||
spinner_->setMaximumWidth(spinner_->width());
|
||||
spinner_->hide();
|
||||
|
||||
errorIcon_ = new QLabel(this);
|
||||
errorIcon_->setPixmap(QPixmap(":/icons/icons/error.png"));
|
||||
errorIcon_->hide();
|
||||
|
||||
matrixidLayout_ = new QHBoxLayout();
|
||||
matrixidLayout_->addWidget(matrixid_input_, 0, Qt::AlignVCenter);
|
||||
|
||||
password_input_ = new TextField(this);
|
||||
password_input_->setTextColor("#333333");
|
||||
password_input_->setLabel(tr("Password"));
|
||||
|
@ -92,8 +96,20 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
password_input_->setBackgroundColor("#f9f9f9");
|
||||
password_input_->setEchoMode(QLineEdit::Password);
|
||||
|
||||
form_layout_->addWidget(matrixid_input_, Qt::AlignHCenter, 0);
|
||||
serverInput_ = new TextField(this);
|
||||
serverInput_->setTextColor("#333333");
|
||||
serverInput_->setLabel("Homeserver address");
|
||||
serverInput_->setInkColor("#555459");
|
||||
serverInput_->setBackgroundColor("#f9f9f9");
|
||||
serverInput_->setPlaceholderText("matrix.org");
|
||||
serverInput_->hide();
|
||||
|
||||
serverLayout_ = new QHBoxLayout();
|
||||
serverLayout_->addWidget(serverInput_, 0, Qt::AlignVCenter);
|
||||
|
||||
form_layout_->addLayout(matrixidLayout_);
|
||||
form_layout_->addWidget(password_input_, Qt::AlignHCenter, 0);
|
||||
form_layout_->addLayout(serverLayout_);
|
||||
|
||||
button_layout_ = new QHBoxLayout();
|
||||
button_layout_->setSpacing(0);
|
||||
|
@ -128,8 +144,12 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
|
||||
connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
|
||||
connect(password_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
|
||||
connect(serverInput_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
|
||||
connect(client_.data(), SIGNAL(loginError(QString)), this, SLOT(loginError(QString)));
|
||||
connect(advanced_settings_button_, SIGNAL(clicked()), this, SLOT(showSettingsModal()));
|
||||
connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
|
||||
connect(client_.data(), SIGNAL(versionError(QString)), this, SLOT(versionError(QString)));
|
||||
connect(client_.data(), SIGNAL(versionSuccess()), this, SLOT(versionSuccess()));
|
||||
connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered()));
|
||||
|
||||
matrixid_input_->setValidator(&InputValidator::Id);
|
||||
}
|
||||
|
@ -139,63 +159,115 @@ void LoginPage::loginError(QString error)
|
|||
error_label_->setText(error);
|
||||
}
|
||||
|
||||
void LoginPage::onLoginButtonClicked()
|
||||
void LoginPage::onMatrixIdEntered()
|
||||
{
|
||||
error_label_->setText("");
|
||||
|
||||
if (!matrixid_input_->hasAcceptableInput()) {
|
||||
loginError(tr("Invalid Matrix ID"));
|
||||
return;
|
||||
} else if (password_input_->text().isEmpty()) {
|
||||
loginError(tr("Empty password"));
|
||||
}
|
||||
|
||||
QString homeServer = matrixid_input_->text().split(":").at(1);
|
||||
if (homeServer != inferredServerAddress_) {
|
||||
serverInput_->hide();
|
||||
serverLayout_->removeWidget(errorIcon_);
|
||||
errorIcon_->hide();
|
||||
if (serverInput_->isVisible()) {
|
||||
matrixidLayout_->removeWidget(spinner_);
|
||||
serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
|
||||
spinner_->show();
|
||||
} else {
|
||||
serverLayout_->removeWidget(spinner_);
|
||||
matrixidLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
|
||||
spinner_->show();
|
||||
}
|
||||
|
||||
inferredServerAddress_ = homeServer;
|
||||
serverInput_->setText(homeServer);
|
||||
client_->setServer(homeServer);
|
||||
client_->versions();
|
||||
}
|
||||
}
|
||||
|
||||
void LoginPage::onServerAddressEntered()
|
||||
{
|
||||
error_label_->setText("");
|
||||
client_->setServer(serverInput_->text());
|
||||
client_->versions();
|
||||
|
||||
serverLayout_->removeWidget(errorIcon_);
|
||||
errorIcon_->hide();
|
||||
serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
|
||||
spinner_->show();
|
||||
}
|
||||
|
||||
void LoginPage::versionError(QString error)
|
||||
{
|
||||
// Matrix homeservers are often kept on a subdomain called 'matrix'
|
||||
// so let's try that next, unless the address was set explicitly or the domain part of the username already points to this subdomain
|
||||
QUrl currentServer = client_->getHomeServer();
|
||||
QString mxidAddress = matrixid_input_->text().split(":").at(1);
|
||||
if (currentServer.host() == inferredServerAddress_ && !currentServer.host().startsWith("matrix")) {
|
||||
error_label_->setText("");
|
||||
currentServer.setHost(QString("matrix.")+currentServer.host());
|
||||
serverInput_->setText(currentServer.host());
|
||||
client_->setServer(currentServer.host());
|
||||
client_->versions();
|
||||
return;
|
||||
}
|
||||
|
||||
error_label_->setText(error);
|
||||
serverInput_->show();
|
||||
|
||||
spinner_->hide();
|
||||
serverLayout_->removeWidget(spinner_);
|
||||
serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight);
|
||||
errorIcon_->show();
|
||||
matrixidLayout_->removeWidget(spinner_);
|
||||
}
|
||||
|
||||
void LoginPage::versionSuccess()
|
||||
{
|
||||
serverLayout_->removeWidget(spinner_);
|
||||
matrixidLayout_->removeWidget(spinner_);
|
||||
spinner_->hide();
|
||||
|
||||
if (serverInput_->isVisible())
|
||||
serverInput_->hide();
|
||||
}
|
||||
|
||||
void LoginPage::onLoginButtonClicked()
|
||||
{
|
||||
error_label_->setText("");
|
||||
|
||||
if (!matrixid_input_->hasAcceptableInput()) {
|
||||
loginError("Invalid Matrix ID");
|
||||
} else if (password_input_->text().isEmpty()) {
|
||||
loginError("Empty password");
|
||||
} else {
|
||||
QString user = matrixid_input_->text().split(":").at(0).split("@").at(1);
|
||||
QString password = password_input_->text();
|
||||
|
||||
QString home_server = custom_domain_.isEmpty()
|
||||
? matrixid_input_->text().split(":").at(1)
|
||||
: custom_domain_;
|
||||
|
||||
client_->setServer(home_server);
|
||||
client_->setServer(serverInput_->text());
|
||||
client_->login(user, password);
|
||||
}
|
||||
}
|
||||
|
||||
void LoginPage::showSettingsModal()
|
||||
{
|
||||
if (login_settings_ == nullptr) {
|
||||
login_settings_ = new LoginSettings(this);
|
||||
connect(login_settings_, &LoginSettings::closing, this, &LoginPage::closeSettingsModal);
|
||||
}
|
||||
|
||||
if (settings_modal_ == nullptr) {
|
||||
settings_modal_ = new OverlayModal(this, login_settings_);
|
||||
settings_modal_->setDuration(100);
|
||||
settings_modal_->setColor(QColor(55, 55, 55, 170));
|
||||
}
|
||||
|
||||
settings_modal_->fadeIn();
|
||||
}
|
||||
|
||||
void LoginPage::closeSettingsModal(const QString &server)
|
||||
{
|
||||
custom_domain_ = server;
|
||||
settings_modal_->fadeOut();
|
||||
}
|
||||
|
||||
void LoginPage::reset()
|
||||
{
|
||||
matrixid_input_->clear();
|
||||
password_input_->clear();
|
||||
serverInput_->clear();
|
||||
|
||||
if (settings_modal_ != nullptr) {
|
||||
settings_modal_->deleteLater();
|
||||
settings_modal_ = nullptr;
|
||||
}
|
||||
spinner_->hide();
|
||||
errorIcon_->hide();
|
||||
serverLayout_->removeWidget(spinner_);
|
||||
serverLayout_->removeWidget(errorIcon_);
|
||||
matrixidLayout_->removeWidget(spinner_);
|
||||
|
||||
if (login_settings_ != nullptr) {
|
||||
login_settings_->deleteLater();
|
||||
login_settings_ = nullptr;
|
||||
}
|
||||
inferredServerAddress_.clear();
|
||||
}
|
||||
|
||||
void LoginPage::onBackButtonClicked()
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "LoginSettings.h"
|
||||
|
||||
LoginSettings::LoginSettings(QWidget *parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
setMaximumSize(400, 400);
|
||||
setStyleSheet("background-color: #f9f9f9");
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(30);
|
||||
layout->setContentsMargins(20, 20, 20, 10);
|
||||
|
||||
input_ = new TextField(this);
|
||||
input_->setTextColor("#555459");
|
||||
input_->setLabel("Homeserver's domain");
|
||||
input_->setInkColor("#333333");
|
||||
input_->setBackgroundColor("#f9f9f9");
|
||||
input_->setPlaceholderText("e.g matrix.domain.org:3434");
|
||||
|
||||
submit_button_ = new FlatButton("OK", this);
|
||||
submit_button_->setBackgroundColor("black");
|
||||
submit_button_->setForegroundColor("black");
|
||||
submit_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
||||
submit_button_->setFontSize(15);
|
||||
submit_button_->setFixedHeight(50);
|
||||
submit_button_->setCornerRadius(3);
|
||||
|
||||
auto label = new QLabel("Advanced Settings", this);
|
||||
label->setStyleSheet("color: #333333");
|
||||
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(input_);
|
||||
layout->addWidget(submit_button_);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
connect(input_, SIGNAL(returnPressed()), submit_button_, SIGNAL(clicked()));
|
||||
connect(submit_button_, &QPushButton::clicked, [=]() {
|
||||
emit closing(input_->text());
|
||||
});
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
#include "MatrixClient.h"
|
||||
#include "Profile.h"
|
||||
#include "Register.h"
|
||||
#include "Versions.h"
|
||||
|
||||
MatrixClient::MatrixClient(QString server, QObject *parent)
|
||||
: QNetworkAccessManager(parent)
|
||||
|
@ -57,12 +58,34 @@ void MatrixClient::onVersionsResponse(QNetworkReply *reply)
|
|||
{
|
||||
reply->deleteLater();
|
||||
|
||||
qDebug() << "Handling the versions response";
|
||||
int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (status_code == 404) {
|
||||
emit versionError("Versions endpoint was not found on the server. Possibly not a Matrix server");
|
||||
return;
|
||||
}
|
||||
|
||||
if (status_code >= 400) {
|
||||
qWarning() << "API version error: " << reply->errorString();
|
||||
emit versionError("An unknown error occured. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = reply->readAll();
|
||||
auto json = QJsonDocument::fromJson(data);
|
||||
|
||||
qDebug() << json;
|
||||
VersionsResponse response;
|
||||
|
||||
try {
|
||||
response.deserialize(json);
|
||||
if (!response.isVersionSupported(0, 2, 0))
|
||||
emit versionError("Server does not support required API version.");
|
||||
else
|
||||
emit versionSuccess();
|
||||
} catch (DeserializationException &e) {
|
||||
qWarning() << "Malformed JSON response" << e.what();
|
||||
emit versionError("Malformed response. Possibly not a Matrix server");
|
||||
}
|
||||
}
|
||||
|
||||
void MatrixClient::onLoginResponse(QNetworkReply *reply)
|
||||
|
|
62
src/Versions.cc
Normal file
62
src/Versions.cc
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* nheko Copyright (C) 2017 Jan Solanti <jhs@psonet.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QRegExp>
|
||||
|
||||
#include "Deserializable.h"
|
||||
#include "Versions.h"
|
||||
|
||||
void VersionsResponse::deserialize(const QJsonDocument &data)
|
||||
{
|
||||
if (!data.isObject())
|
||||
throw DeserializationException("Versions response is not a JSON object");
|
||||
|
||||
QJsonObject object = data.object();
|
||||
|
||||
if (object.value("versions") == QJsonValue::Undefined)
|
||||
throw DeserializationException("Versions: missing version list");
|
||||
|
||||
auto versions = object.value("versions").toArray();
|
||||
for (auto const &elem: versions) {
|
||||
QString str = elem.toString();
|
||||
QRegExp rx("r(\\d+)\\.(\\d+)\\.(\\d+)");
|
||||
|
||||
if (rx.indexIn(str) == -1)
|
||||
throw DeserializationException("Invalid version string in versions response");
|
||||
|
||||
struct Version_ v;
|
||||
v.major_ = rx.cap(1).toUInt();
|
||||
v.minor_ = rx.cap(2).toUInt();
|
||||
v.patch_ = rx.cap(3).toUInt();
|
||||
|
||||
supported_versions_.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
bool VersionsResponse::isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch)
|
||||
{
|
||||
for (auto &v: supported_versions_) {
|
||||
if (v.major_ == major && v.minor_ == minor && v.patch_ >= patch)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
Loading…
Reference in a new issue