mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +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/InputValidator.cc
|
||||||
src/Login.cc
|
src/Login.cc
|
||||||
src/LoginPage.cc
|
src/LoginPage.cc
|
||||||
src/LoginSettings.cc
|
|
||||||
src/LogoutDialog.cc
|
src/LogoutDialog.cc
|
||||||
src/MainWindow.cc
|
src/MainWindow.cc
|
||||||
src/MatrixClient.cc
|
src/MatrixClient.cc
|
||||||
|
@ -116,6 +115,7 @@ set(SRC_FILES
|
||||||
src/TrayIcon.cc
|
src/TrayIcon.cc
|
||||||
src/TopRoomBar.cc
|
src/TopRoomBar.cc
|
||||||
src/UserInfoWidget.cc
|
src/UserInfoWidget.cc
|
||||||
|
src/Versions.cc
|
||||||
src/WelcomePage.cc
|
src/WelcomePage.cc
|
||||||
src/main.cc
|
src/main.cc
|
||||||
|
|
||||||
|
@ -177,7 +177,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
include/TimelineView.h
|
include/TimelineView.h
|
||||||
include/TimelineViewManager.h
|
include/TimelineViewManager.h
|
||||||
include/LoginPage.h
|
include/LoginPage.h
|
||||||
include/LoginSettings.h
|
|
||||||
include/LogoutDialog.h
|
include/LogoutDialog.h
|
||||||
include/MainWindow.h
|
include/MainWindow.h
|
||||||
include/MatrixClient.h
|
include/MatrixClient.h
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "CircularProgress.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
#include "LoginSettings.h"
|
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "OverlayModal.h"
|
#include "OverlayModal.h"
|
||||||
#include "RaisedButton.h"
|
#include "RaisedButton.h"
|
||||||
|
@ -50,12 +50,20 @@ private slots:
|
||||||
// Callback for the login button.
|
// Callback for the login button.
|
||||||
void onLoginButtonClicked();
|
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.
|
// Displays errors produced during the login.
|
||||||
void loginError(QString error_message);
|
void loginError(QString error_message);
|
||||||
|
|
||||||
// Manipulate settings modal.
|
// Callback for errors produced during server probing
|
||||||
void showSettingsModal();
|
void versionError(QString error_message);
|
||||||
void closeSettingsModal(const QString &server);
|
|
||||||
|
// Callback for successful server probing
|
||||||
|
void versionSuccess();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVBoxLayout *top_layout_;
|
QVBoxLayout *top_layout_;
|
||||||
|
@ -67,8 +75,13 @@ private:
|
||||||
QLabel *logo_;
|
QLabel *logo_;
|
||||||
QLabel *error_label_;
|
QLabel *error_label_;
|
||||||
|
|
||||||
|
QHBoxLayout *serverLayout_;
|
||||||
|
QHBoxLayout *matrixidLayout_;
|
||||||
|
CircularProgress *spinner_;
|
||||||
|
QLabel *errorIcon_;
|
||||||
|
QString inferredServerAddress_;
|
||||||
|
|
||||||
FlatButton *back_button_;
|
FlatButton *back_button_;
|
||||||
FlatButton *advanced_settings_button_;
|
|
||||||
RaisedButton *login_button_;
|
RaisedButton *login_button_;
|
||||||
|
|
||||||
QWidget *form_widget_;
|
QWidget *form_widget_;
|
||||||
|
@ -77,10 +90,7 @@ private:
|
||||||
|
|
||||||
TextField *matrixid_input_;
|
TextField *matrixid_input_;
|
||||||
TextField *password_input_;
|
TextField *password_input_;
|
||||||
|
TextField *serverInput_;
|
||||||
OverlayModal *settings_modal_;
|
|
||||||
LoginSettings *login_settings_;
|
|
||||||
QString custom_domain_;
|
|
||||||
|
|
||||||
// Matrix client API provider.
|
// Matrix client API provider.
|
||||||
QSharedPointer<MatrixClient> client_;
|
QSharedPointer<MatrixClient> client_;
|
||||||
|
|
|
@ -63,11 +63,13 @@ public slots:
|
||||||
signals:
|
signals:
|
||||||
void loginError(const QString &error);
|
void loginError(const QString &error);
|
||||||
void registerError(const QString &error);
|
void registerError(const QString &error);
|
||||||
|
void versionError(const QString &error);
|
||||||
|
|
||||||
void loggedOut();
|
void loggedOut();
|
||||||
|
|
||||||
void loginSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
void loginSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
||||||
void registerSuccess(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 roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
|
||||||
void userAvatarRetrieved(const QString &userId, const QImage &img);
|
void userAvatarRetrieved(const QString &userId, const QImage &img);
|
||||||
|
|
|
@ -17,21 +17,26 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QFrame>
|
#include <QJsonDocument>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include "FlatButton.h"
|
#include "Deserializable.h"
|
||||||
#include "TextField.h"
|
|
||||||
|
|
||||||
class LoginSettings : public QFrame
|
|
||||||
|
class VersionsResponse : public Deserializable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
explicit LoginSettings(QWidget *parent = nullptr);
|
void deserialize(const QJsonDocument &data) override;
|
||||||
|
|
||||||
signals:
|
bool isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch);
|
||||||
void closing(const QString &server);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextField *input_;
|
struct Version_ {
|
||||||
FlatButton *submit_button_;
|
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/user-shape.png</file>
|
||||||
<file>icons/power-button-off.png</file>
|
<file>icons/power-button-off.png</file>
|
||||||
<file>icons/smile.png</file>
|
<file>icons/smile.png</file>
|
||||||
|
<file>icons/error.png</file>
|
||||||
|
|
||||||
<file>icons/emoji-categories/people.png</file>
|
<file>icons/emoji-categories/people.png</file>
|
||||||
<file>icons/emoji-categories/nature.png</file>
|
<file>icons/emoji-categories/nature.png</file>
|
||||||
|
|
174
src/LoginPage.cc
174
src/LoginPage.cc
|
@ -22,8 +22,7 @@
|
||||||
|
|
||||||
LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, settings_modal_{nullptr}
|
, inferredServerAddress_()
|
||||||
, login_settings_{nullptr}
|
|
||||||
, client_{client}
|
, client_{client}
|
||||||
{
|
{
|
||||||
setStyleSheet("background-color: #f9f9f9");
|
setStyleSheet("background-color: #f9f9f9");
|
||||||
|
@ -38,9 +37,8 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
back_button_->setMinimumSize(QSize(30, 30));
|
back_button_->setMinimumSize(QSize(30, 30));
|
||||||
back_button_->setForegroundColor("#333333");
|
back_button_->setForegroundColor("#333333");
|
||||||
|
|
||||||
advanced_settings_button_ = new FlatButton(this);
|
top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
advanced_settings_button_->setMinimumSize(QSize(30, 30));
|
top_bar_layout_->addStretch(1);
|
||||||
advanced_settings_button_->setForegroundColor("#333333");
|
|
||||||
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
|
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;
|
QIcon advanced_settings_icon;
|
||||||
advanced_settings_icon.addFile(":/icons/icons/cog.png", QSize(), QIcon::Normal, QIcon::Off);
|
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_ = new QLabel(this);
|
||||||
logo_->setPixmap(QPixmap(":/logos/nheko-128.png"));
|
logo_->setPixmap(QPixmap(":/logos/nheko-128.png"));
|
||||||
|
|
||||||
|
@ -85,6 +76,19 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
matrixid_input_->setBackgroundColor("#f9f9f9");
|
matrixid_input_->setBackgroundColor("#f9f9f9");
|
||||||
matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
|
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_ = new TextField(this);
|
||||||
password_input_->setTextColor("#333333");
|
password_input_->setTextColor("#333333");
|
||||||
password_input_->setLabel(tr("Password"));
|
password_input_->setLabel(tr("Password"));
|
||||||
|
@ -92,8 +96,20 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
password_input_->setBackgroundColor("#f9f9f9");
|
password_input_->setBackgroundColor("#f9f9f9");
|
||||||
password_input_->setEchoMode(QLineEdit::Password);
|
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_->addWidget(password_input_, Qt::AlignHCenter, 0);
|
||||||
|
form_layout_->addLayout(serverLayout_);
|
||||||
|
|
||||||
button_layout_ = new QHBoxLayout();
|
button_layout_ = new QHBoxLayout();
|
||||||
button_layout_->setSpacing(0);
|
button_layout_->setSpacing(0);
|
||||||
|
@ -128,8 +144,12 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
|
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
|
||||||
connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
|
connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
|
||||||
connect(password_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(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);
|
matrixid_input_->setValidator(&InputValidator::Id);
|
||||||
}
|
}
|
||||||
|
@ -139,63 +159,115 @@ void LoginPage::loginError(QString error)
|
||||||
error_label_->setText(error);
|
error_label_->setText(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginPage::onLoginButtonClicked()
|
void LoginPage::onMatrixIdEntered()
|
||||||
{
|
{
|
||||||
error_label_->setText("");
|
error_label_->setText("");
|
||||||
|
|
||||||
if (!matrixid_input_->hasAcceptableInput()) {
|
if (!matrixid_input_->hasAcceptableInput()) {
|
||||||
loginError(tr("Invalid Matrix ID"));
|
loginError(tr("Invalid Matrix ID"));
|
||||||
|
return;
|
||||||
} else if (password_input_->text().isEmpty()) {
|
} else if (password_input_->text().isEmpty()) {
|
||||||
loginError(tr("Empty password"));
|
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 {
|
} else {
|
||||||
QString user = matrixid_input_->text().split(":").at(0).split("@").at(1);
|
QString user = matrixid_input_->text().split(":").at(0).split("@").at(1);
|
||||||
QString password = password_input_->text();
|
QString password = password_input_->text();
|
||||||
|
client_->setServer(serverInput_->text());
|
||||||
QString home_server = custom_domain_.isEmpty()
|
|
||||||
? matrixid_input_->text().split(":").at(1)
|
|
||||||
: custom_domain_;
|
|
||||||
|
|
||||||
client_->setServer(home_server);
|
|
||||||
client_->login(user, password);
|
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()
|
void LoginPage::reset()
|
||||||
{
|
{
|
||||||
matrixid_input_->clear();
|
matrixid_input_->clear();
|
||||||
password_input_->clear();
|
password_input_->clear();
|
||||||
|
serverInput_->clear();
|
||||||
|
|
||||||
if (settings_modal_ != nullptr) {
|
spinner_->hide();
|
||||||
settings_modal_->deleteLater();
|
errorIcon_->hide();
|
||||||
settings_modal_ = nullptr;
|
serverLayout_->removeWidget(spinner_);
|
||||||
}
|
serverLayout_->removeWidget(errorIcon_);
|
||||||
|
matrixidLayout_->removeWidget(spinner_);
|
||||||
|
|
||||||
if (login_settings_ != nullptr) {
|
inferredServerAddress_.clear();
|
||||||
login_settings_->deleteLater();
|
|
||||||
login_settings_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginPage::onBackButtonClicked()
|
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 "MatrixClient.h"
|
||||||
#include "Profile.h"
|
#include "Profile.h"
|
||||||
#include "Register.h"
|
#include "Register.h"
|
||||||
|
#include "Versions.h"
|
||||||
|
|
||||||
MatrixClient::MatrixClient(QString server, QObject *parent)
|
MatrixClient::MatrixClient(QString server, QObject *parent)
|
||||||
: QNetworkAccessManager(parent)
|
: QNetworkAccessManager(parent)
|
||||||
|
@ -57,12 +58,34 @@ void MatrixClient::onVersionsResponse(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
reply->deleteLater();
|
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 data = reply->readAll();
|
||||||
auto json = QJsonDocument::fromJson(data);
|
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)
|
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