diff --git a/src/LoginPage.cpp b/src/LoginPage.cpp
index 4c28f364..cfc600ae 100644
--- a/src/LoginPage.cpp
+++ b/src/LoginPage.cpp
@@ -5,11 +5,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QDesktopServices>
-#include <QFontMetrics>
-#include <QLabel>
-#include <QPainter>
-#include <QStyleOption>
-#include <QtMath>
#include <mtx/identifiers.hpp>
#include <mtx/requests.hpp>
@@ -18,247 +13,94 @@
#include "Config.h"
#include "Logging.h"
#include "LoginPage.h"
+#include "MainWindow.h"
#include "MatrixClient.h"
#include "SSOHandler.h"
#include "UserSettingsPage.h"
-#include "ui/FlatButton.h"
-#include "ui/LoadingIndicator.h"
-#include "ui/OverlayModal.h"
-#include "ui/RaisedButton.h"
-#include "ui/TextField.h"
Q_DECLARE_METATYPE(LoginPage::LoginMethod)
using namespace mtx::identifiers;
-LoginPage::LoginPage(QWidget *parent)
- : QWidget(parent)
+LoginPage::LoginPage(QObject *parent)
+ : QObject(parent)
, inferredServerAddress_()
{
- qRegisterMetaType<LoginPage::LoginMethod>("LoginPage::LoginMethod");
-
- top_layout_ = new QVBoxLayout();
-
- top_bar_layout_ = new QHBoxLayout();
- top_bar_layout_->setSpacing(0);
- top_bar_layout_->setContentsMargins(0, 0, 0, 0);
-
- back_button_ = new FlatButton(this);
- back_button_->setMinimumSize(QSize(30, 30));
-
- top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
- top_bar_layout_->addStretch(1);
-
- QIcon icon;
- icon.addFile(QStringLiteral(":/icons/icons/ui/angle-arrow-left.svg"));
-
- back_button_->setIcon(icon);
- back_button_->setIconSize(QSize(32, 32));
-
- QIcon logo;
- logo.addFile(QStringLiteral(":/logos/login.png"));
-
- logo_ = new QLabel(this);
- logo_->setPixmap(logo.pixmap(128));
-
- logo_layout_ = new QHBoxLayout();
- logo_layout_->setContentsMargins(0, 0, 0, 20);
- logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
-
- form_wrapper_ = new QHBoxLayout();
- form_widget_ = new QWidget();
- form_widget_->setMinimumSize(QSize(350, 200));
-
- form_layout_ = new QVBoxLayout();
- form_layout_->setSpacing(20);
- form_layout_->setContentsMargins(0, 0, 0, 30);
- form_widget_->setLayout(form_layout_);
-
- form_wrapper_->addStretch(1);
- form_wrapper_->addWidget(form_widget_);
- form_wrapper_->addStretch(1);
-
- matrixid_input_ = new TextField(this);
- matrixid_input_->setLabel(tr("Matrix ID"));
- matrixid_input_->setRegexp(QRegularExpression(QStringLiteral("@.+?:.{3,}")));
- matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
- matrixid_input_->setToolTip(
- tr("Your login name. A mxid should start with @ followed by the user id. After the user "
- "id you need to include your server name after a :.\nYou can also put your homeserver "
- "address there, if your server doesn't support .well-known lookup.\nExample: "
- "@user:server.my\nIf Nheko fails to discover your homeserver, it will show you a "
- "field to enter the server manually."));
-
- spinner_ = new LoadingIndicator(this);
- spinner_->setFixedHeight(40);
- spinner_->setFixedWidth(40);
- spinner_->hide();
-
- errorIcon_ = new QLabel(this);
- errorIcon_->setPixmap(QPixmap(QStringLiteral(":/icons/icons/error.png")));
- errorIcon_->hide();
-
- matrixidLayout_ = new QHBoxLayout();
- matrixidLayout_->addWidget(matrixid_input_, 0, Qt::AlignVCenter);
-
- QFont font;
-
- error_matrixid_label_ = new QLabel(this);
- error_matrixid_label_->setFont(font);
- error_matrixid_label_->setWordWrap(true);
-
- password_input_ = new TextField(this);
- password_input_->setLabel(tr("Password"));
- password_input_->setEchoMode(QLineEdit::Password);
- password_input_->setToolTip(tr("Your password."));
-
- deviceName_ = new TextField(this);
- deviceName_->setLabel(tr("Device name"));
- deviceName_->setToolTip(
- tr("A name for this device, which will be shown to others, when verifying your devices. "
- "If none is provided a default is used."));
-
- serverInput_ = new TextField(this);
- serverInput_->setLabel(tr("Homeserver address"));
- serverInput_->setPlaceholderText(tr("server.my:8787"));
- serverInput_->setToolTip(tr("The address that can be used to contact you homeservers "
- "client API.\nExample: https://server.my:8787"));
- serverInput_->hide();
-
- serverLayout_ = new QHBoxLayout();
- serverLayout_->addWidget(serverInput_, 0, Qt::AlignVCenter);
-
- form_layout_->addLayout(matrixidLayout_);
- form_layout_->addWidget(error_matrixid_label_, 0, Qt::AlignHCenter);
- form_layout_->addWidget(password_input_);
- form_layout_->addWidget(deviceName_, Qt::AlignHCenter);
- form_layout_->addLayout(serverLayout_);
-
- error_matrixid_label_->hide();
-
- button_layout_ = new QHBoxLayout();
- button_layout_->setSpacing(20);
- button_layout_->setContentsMargins(0, 0, 0, 30);
-
- login_button_ = new RaisedButton(tr("LOGIN"), this);
- login_button_->setMinimumSize(150, 65);
- login_button_->setFontSize(20);
- login_button_->setCornerRadius(3);
-
- sso_login_button_ = new RaisedButton(tr("SSO LOGIN"), this);
- sso_login_button_->setMinimumSize(150, 65);
- sso_login_button_->setFontSize(20);
- sso_login_button_->setCornerRadius(3);
- sso_login_button_->setVisible(false);
-
- button_layout_->addStretch(1);
- button_layout_->addWidget(login_button_);
- button_layout_->addWidget(sso_login_button_);
- button_layout_->addStretch(1);
-
- error_label_ = new QLabel(this);
- error_label_->setFont(font);
- error_label_->setWordWrap(true);
-
- top_layout_->addLayout(top_bar_layout_);
- top_layout_->addStretch(1);
- top_layout_->addLayout(logo_layout_);
- top_layout_->addLayout(form_wrapper_);
- top_layout_->addStretch(1);
- top_layout_->addLayout(button_layout_);
- top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
- top_layout_->addStretch(1);
-
- setLayout(top_layout_);
+ [[maybe_unused]] static auto ignored =
+ qRegisterMetaType<LoginPage::LoginMethod>("LoginPage::LoginMethod");
connect(this, &LoginPage::versionOkCb, this, &LoginPage::versionOk, Qt::QueuedConnection);
connect(this, &LoginPage::versionErrorCb, this, &LoginPage::versionError, Qt::QueuedConnection);
+ connect(
+ this,
+ &LoginPage::loginOk,
+ this,
+ [this](const mtx::responses::Login &res) {
+ loggingIn_ = false;
+ emit loggingInChanged();
- connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
- connect(login_button_, &RaisedButton::clicked, this, [this]() {
- onLoginButtonClicked(passwordSupported ? LoginMethod::Password : LoginMethod::SSO);
- });
- connect(sso_login_button_, &RaisedButton::clicked, this, [this]() {
- onLoginButtonClicked(LoginMethod::SSO);
- });
- connect(this,
- &LoginPage::showErrorMessage,
- this,
- static_cast<void (LoginPage::*)(QLabel *, const QString &)>(&LoginPage::showError),
- Qt::QueuedConnection);
- connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
- connect(password_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
- connect(deviceName_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
- connect(serverInput_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
- connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
- connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered()));
+ http::client()->set_user(res.user_id);
+ MainWindow::instance()->showChatPage();
+ },
+ Qt::QueuedConnection);
}
void
LoginPage::showError(const QString &msg)
{
- auto rect = QFontMetrics(font()).boundingRect(msg);
- int width = rect.width();
- int height = rect.height();
- error_label_->setFixedHeight((int)qCeil(width / 200.0) * height);
- error_label_->setText(msg);
+ loggingIn_ = false;
+ emit loggingInChanged();
+
+ error_ = msg;
+ emit errorOccurred();
}
void
-LoginPage::showError(QLabel *label, const QString &msg)
+LoginPage::setHomeserver(QString hs)
{
- auto rect = QFontMetrics(font()).boundingRect(msg);
- int width = rect.width();
- int height = rect.height();
- label->setFixedHeight((int)qCeil(width / 200.0) * height);
- label->setText(msg);
+ if (hs != homeserver_) {
+ homeserver_ = hs;
+ homeserverValid_ = false;
+ emit homeserverChanged();
+ http::client()->set_server(hs.toStdString());
+ checkHomeserverVersion();
+ }
}
void
LoginPage::onMatrixIdEntered()
{
- error_label_->setText(QLatin1String(""));
-
- User user;
+ clearErrors();
- if (!matrixid_input_->isValid()) {
- error_matrixid_label_->show();
- showError(error_matrixid_label_,
- tr("You have entered an invalid Matrix ID e.g @joe:matrix.org"));
- return;
- } else {
- error_matrixid_label_->setText(QLatin1String(""));
- error_matrixid_label_->hide();
- }
+ homeserverValid_ = false;
+ emit homeserverChanged();
+ User user;
try {
- user = parse<User>(matrixid_input_->text().toStdString());
+ user = parse<User>(mxid_.toStdString());
} catch (const std::exception &) {
- showError(error_matrixid_label_,
- tr("You have entered an invalid Matrix ID e.g @joe:matrix.org"));
+ mxidError_ = tr("You have entered an invalid Matrix ID e.g @joe:matrix.org");
+ emit mxidErrorChanged();
return;
}
- QString homeServer = QString::fromStdString(user.hostname());
- 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_->start();
- } else {
- serverLayout_->removeWidget(spinner_);
- matrixidLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
- spinner_->start();
- }
+ if (user.hostname().empty() || user.localpart().empty()) {
+ mxidError_ = tr("You have entered an invalid Matrix ID e.g @joe:matrix.org");
+ emit mxidErrorChanged();
+ return;
+ } else {
+ nhlog::net()->debug("hostname: {}", user.hostname());
+ }
- inferredServerAddress_ = homeServer;
- serverInput_->setText(homeServer);
+ if (user.hostname() != inferredServerAddress_.toStdString()) {
+ homeserverNeeded_ = false;
+ lookingUpHs_ = true;
+ emit lookingUpHsChanged();
http::client()->set_server(user.hostname());
http::client()->verify_certificates(
!UserSettings::instance()->disableCertificateValidation());
+ homeserver_ = QString::fromStdString(user.hostname());
+ emit homeserverChanged();
http::client()->well_known(
[this](const mtx::responses::WellKnown &res, mtx::http::RequestErr err) {
@@ -286,6 +128,7 @@ LoginPage::onMatrixIdEntered()
nhlog::net()->info("Autodiscovery: Discovered '" + res.homeserver.base_url + "'");
http::client()->set_server(res.homeserver.base_url);
+ emit homeserverChanged();
checkHomeserverVersion();
});
}
@@ -294,6 +137,16 @@ LoginPage::onMatrixIdEntered()
void
LoginPage::checkHomeserverVersion()
{
+ clearErrors();
+
+ try {
+ User user = parse<User>(mxid_.toStdString());
+ } catch (const std::exception &) {
+ mxidError_ = tr("You have entered an invalid Matrix ID e.g @joe:matrix.org");
+ emit mxidErrorChanged();
+ return;
+ }
+
http::client()->versions([this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
if (err) {
if (err->status_code == 404) {
@@ -333,92 +186,63 @@ LoginPage::checkHomeserverVersion()
}
void
-LoginPage::onServerAddressEntered()
-{
- error_label_->setText(QLatin1String(""));
- http::client()->verify_certificates(!UserSettings::instance()->disableCertificateValidation());
- http::client()->set_server(serverInput_->text().toStdString());
- checkHomeserverVersion();
-
- serverLayout_->removeWidget(errorIcon_);
- errorIcon_->hide();
- serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
- spinner_->start();
-}
-
-void
LoginPage::versionError(const QString &error)
{
- showError(error_label_, error);
- serverInput_->show();
+ showError(error);
- spinner_->stop();
- serverLayout_->removeWidget(spinner_);
- serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight);
- errorIcon_->show();
- matrixidLayout_->removeWidget(spinner_);
+ homeserverNeeded_ = true;
+ lookingUpHs_ = false;
+ homeserverValid_ = false;
+ emit lookingUpHsChanged();
+ emit versionLookedUp();
}
void
-LoginPage::versionOk(bool passwordSupported_, bool ssoSupported_)
+LoginPage::versionOk(bool passwordSupported, bool ssoSupported)
{
- passwordSupported = passwordSupported_;
- ssoSupported = ssoSupported_;
-
- serverLayout_->removeWidget(spinner_);
- matrixidLayout_->removeWidget(spinner_);
- spinner_->stop();
-
- password_input_->setVisible(passwordSupported);
- password_input_->setEnabled(passwordSupported);
- sso_login_button_->setVisible(ssoSupported);
- login_button_->setVisible(passwordSupported);
+ passwordSupported_ = passwordSupported;
+ ssoSupported_ = ssoSupported;
- if (serverInput_->isVisible())
- serverInput_->hide();
+ lookingUpHs_ = false;
+ homeserverValid_ = true;
+ emit homeserverChanged();
+ emit lookingUpHsChanged();
+ emit versionLookedUp();
}
void
-LoginPage::onLoginButtonClicked(LoginMethod loginMethod)
+LoginPage::onLoginButtonClicked(LoginMethod loginMethod,
+ QString userid,
+ QString password,
+ QString deviceName)
{
- error_label_->setText(QLatin1String(""));
- User user;
+ clearErrors();
- if (!matrixid_input_->isValid()) {
- error_matrixid_label_->show();
- showError(error_matrixid_label_,
- tr("You have entered an invalid Matrix ID e.g @joe:matrix.org"));
- return;
- } else {
- error_matrixid_label_->setText(QLatin1String(""));
- error_matrixid_label_->hide();
- }
+ User user;
try {
- user = parse<User>(matrixid_input_->text().toStdString());
+ user = parse<User>(userid.toStdString());
} catch (const std::exception &) {
- showError(error_matrixid_label_,
- tr("You have entered an invalid Matrix ID e.g @joe:matrix.org"));
+ mxidError_ = tr("You have entered an invalid Matrix ID e.g @joe:matrix.org");
+ emit mxidErrorChanged();
return;
}
if (loginMethod == LoginMethod::Password) {
- if (password_input_->text().isEmpty())
- return showError(error_label_, tr("Empty password"));
+ if (password.isEmpty())
+ return showError(tr("Empty password"));
http::client()->login(
user.localpart(),
- password_input_->text().toStdString(),
- deviceName_->text().trimmed().isEmpty() ? initialDeviceName()
- : deviceName_->text().toStdString(),
+ password.toStdString(),
+ deviceName.trimmed().isEmpty() ? initialDeviceName_() : deviceName.toStdString(),
[this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
if (err) {
auto error = err->matrix_error.error;
if (error.empty())
error = err->parse_error;
- showErrorMessage(error_label_, QString::fromStdString(error));
- emit errorOccurred();
+ showError(QString::fromStdString(error));
return;
}
@@ -432,34 +256,33 @@ LoginPage::onLoginButtonClicked(LoginMethod loginMethod)
});
} else {
auto sso = new SSOHandler();
- connect(sso, &SSOHandler::ssoSuccess, this, [this, sso](std::string token) {
- mtx::requests::Login req{};
- req.token = token;
- req.type = mtx::user_interactive::auth_types::token;
- req.device_id = deviceName_->text().trimmed().isEmpty()
- ? initialDeviceName()
- : deviceName_->text().toStdString();
- http::client()->login(
- req, [this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
- if (err) {
- showErrorMessage(error_label_,
- QString::fromStdString(err->matrix_error.error));
- emit errorOccurred();
- return;
- }
+ connect(
+ sso, &SSOHandler::ssoSuccess, this, [this, sso, userid, deviceName](std::string token) {
+ mtx::requests::Login req{};
+ req.token = token;
+ req.type = mtx::user_interactive::auth_types::token;
+ req.device_id =
+ deviceName.trimmed().isEmpty() ? initialDeviceName_() : deviceName.toStdString();
+ http::client()->login(
+ req, [this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
+ if (err) {
+ showError(QString::fromStdString(err->matrix_error.error));
+ emit errorOccurred();
+ return;
+ }
- if (res.well_known) {
- http::client()->set_server(res.well_known->homeserver.base_url);
- nhlog::net()->info("Login requested to user server: " +
- res.well_known->homeserver.base_url);
- }
+ if (res.well_known) {
+ http::client()->set_server(res.well_known->homeserver.base_url);
+ nhlog::net()->info("Login requested to user server: " +
+ res.well_known->homeserver.base_url);
+ }
- emit loginOk(res);
- });
- sso->deleteLater();
- });
+ emit loginOk(res);
+ });
+ sso->deleteLater();
+ });
connect(sso, &SSOHandler::ssoFailed, this, [this, sso]() {
- showErrorMessage(error_label_, tr("SSO login failed"));
+ showError(tr("SSO login failed"));
emit errorOccurred();
sso->deleteLater();
});
@@ -468,37 +291,6 @@ LoginPage::onLoginButtonClicked(LoginMethod loginMethod)
QString::fromStdString(http::client()->login_sso_redirect(sso->url())));
}
- emit loggingIn();
-}
-
-void
-LoginPage::reset()
-{
- matrixid_input_->clear();
- password_input_->clear();
- password_input_->show();
- serverInput_->clear();
-
- spinner_->stop();
- errorIcon_->hide();
- serverLayout_->removeWidget(spinner_);
- serverLayout_->removeWidget(errorIcon_);
- matrixidLayout_->removeWidget(spinner_);
-
- inferredServerAddress_.clear();
-}
-
-void
-LoginPage::onBackButtonClicked()
-{
- emit backButtonClicked();
-}
-
-void
-LoginPage::paintEvent(QPaintEvent *)
-{
- QStyleOption opt;
- opt.initFrom(this);
- QPainter p(this);
- style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+ loggingIn_ = true;
+ emit loggingInChanged();
}
|