summary refs log tree commit diff
path: root/src/LoginPage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/LoginPage.cpp')
-rw-r--r--src/LoginPage.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/LoginPage.cpp b/src/LoginPage.cpp
new file mode 100644

index 00000000..dbf9d470 --- /dev/null +++ b/src/LoginPage.cpp
@@ -0,0 +1,318 @@ +/* + * 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 <QStyleOption> + +#include <mtx/identifiers.hpp> + +#include "Config.h" +#include "LoginPage.h" +#include "MatrixClient.h" +#include "ui/FlatButton.h" +#include "ui/LoadingIndicator.h" +#include "ui/OverlayModal.h" +#include "ui/RaisedButton.h" +#include "ui/TextField.h" + +using namespace mtx::identifiers; + +LoginPage::LoginPage(QWidget *parent) + : QWidget(parent) + , inferredServerAddress_() +{ + top_layout_ = new QVBoxLayout(); + + top_bar_layout_ = new QHBoxLayout(); + top_bar_layout_->setSpacing(0); + top_bar_layout_->setMargin(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(":/icons/icons/ui/angle-pointing-to-left.png"); + + back_button_->setIcon(icon); + back_button_->setIconSize(QSize(32, 32)); + + QIcon logo; + logo.addFile(":/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_->setPlaceholderText(tr("e.g @joe:matrix.org")); + + spinner_ = new LoadingIndicator(this); + spinner_->setFixedHeight(40); + spinner_->setFixedWidth(40); + 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_->setLabel(tr("Password")); + password_input_->setEchoMode(QLineEdit::Password); + + serverInput_ = new TextField(this); + serverInput_->setLabel("Homeserver address"); + 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); + button_layout_->setContentsMargins(0, 0, 0, 30); + + login_button_ = new RaisedButton(tr("LOGIN"), this); + login_button_->setMinimumSize(350, 65); + login_button_->setFontSize(20); + login_button_->setCornerRadius(3); + + button_layout_->addStretch(1); + button_layout_->addWidget(login_button_); + button_layout_->addStretch(1); + + QFont font; + font.setPixelSize(conf::fontSize); + + error_label_ = new QLabel(this); + error_label_->setFont(font); + + 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_); + + connect(this, &LoginPage::versionOkCb, this, &LoginPage::versionOk); + connect(this, &LoginPage::versionErrorCb, this, &LoginPage::versionError); + connect(this, &LoginPage::loginErrorCb, this, &LoginPage::loginError); + + connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked())); + 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(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered())); + connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered())); +} + +void +LoginPage::onMatrixIdEntered() +{ + error_label_->setText(""); + + User user; + + try { + user = parse<User>(matrixid_input_->text().toStdString()); + } catch (const std::exception &e) { + return loginError("You have entered an invalid Matrix ID e.g @joe:matrix.org"); + } + + 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(); + } + + inferredServerAddress_ = homeServer; + serverInput_->setText(homeServer); + + http::client()->set_server(user.hostname()); + checkHomeserverVersion(); + } +} + +void +LoginPage::checkHomeserverVersion() +{ + http::client()->versions( + [this](const mtx::responses::Versions &, mtx::http::RequestErr err) { + if (err) { + using namespace boost::beast::http; + + if (err->status_code == status::not_found) { + emit versionErrorCb(tr("The required endpoints were not found. " + "Possibly not a Matrix server.")); + return; + } + + if (!err->parse_error.empty()) { + emit versionErrorCb(tr("Received malformed response. Make sure " + "the homeserver domain is valid.")); + return; + } + + emit versionErrorCb(tr( + "An unknown error occured. Make sure the homeserver domain is valid.")); + return; + } + + emit versionOkCb(); + }); +} + +void +LoginPage::onServerAddressEntered() +{ + error_label_->setText(""); + 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) +{ + error_label_->setText(error); + serverInput_->show(); + + spinner_->stop(); + serverLayout_->removeWidget(spinner_); + serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight); + errorIcon_->show(); + matrixidLayout_->removeWidget(spinner_); +} + +void +LoginPage::versionOk() +{ + serverLayout_->removeWidget(spinner_); + matrixidLayout_->removeWidget(spinner_); + spinner_->stop(); + + if (serverInput_->isVisible()) + serverInput_->hide(); +} + +void +LoginPage::onLoginButtonClicked() +{ + error_label_->setText(""); + + User user; + + try { + user = parse<User>(matrixid_input_->text().toStdString()); + } catch (const std::exception &e) { + return loginError("You have entered an invalid Matrix ID e.g @joe:matrix.org"); + } + + if (password_input_->text().isEmpty()) + return loginError(tr("Empty password")); + + http::client()->set_server(serverInput_->text().toStdString()); + http::client()->login(user.localpart(), + password_input_->text().toStdString(), + initialDeviceName(), + [this](const mtx::responses::Login &res, mtx::http::RequestErr err) { + if (err) { + emit loginError( + QString::fromStdString(err->matrix_error.error)); + emit errorOccurred(); + return; + } + + emit loginOk(res); + }); + + emit loggingIn(); +} + +void +LoginPage::reset() +{ + matrixid_input_->clear(); + password_input_->clear(); + 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.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); +}