mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-10-30 09:30:47 +03:00
parent
39a8150fae
commit
4659d0efc2
17 changed files with 212 additions and 137 deletions
|
@ -144,6 +144,7 @@ set(SRC_FILES
|
||||||
src/dialogs/LeaveRoom.cc
|
src/dialogs/LeaveRoom.cc
|
||||||
src/dialogs/Logout.cc
|
src/dialogs/Logout.cc
|
||||||
src/dialogs/ReadReceipts.cc
|
src/dialogs/ReadReceipts.cc
|
||||||
|
src/dialogs/ReCaptcha.cpp
|
||||||
|
|
||||||
# Emoji
|
# Emoji
|
||||||
src/emoji/Category.cc
|
src/emoji/Category.cc
|
||||||
|
@ -192,7 +193,6 @@ set(SRC_FILES
|
||||||
src/MainWindow.cc
|
src/MainWindow.cc
|
||||||
src/MatrixClient.cc
|
src/MatrixClient.cc
|
||||||
src/QuickSwitcher.cc
|
src/QuickSwitcher.cc
|
||||||
src/Register.cc
|
|
||||||
src/RegisterPage.cc
|
src/RegisterPage.cc
|
||||||
src/RoomInfoListItem.cc
|
src/RoomInfoListItem.cc
|
||||||
src/RoomList.cc
|
src/RoomList.cc
|
||||||
|
@ -238,6 +238,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
include/dialogs/LeaveRoom.h
|
include/dialogs/LeaveRoom.h
|
||||||
include/dialogs/Logout.h
|
include/dialogs/Logout.h
|
||||||
include/dialogs/ReadReceipts.h
|
include/dialogs/ReadReceipts.h
|
||||||
|
include/dialogs/ReCaptcha.hpp
|
||||||
|
|
||||||
# Emoji
|
# Emoji
|
||||||
include/emoji/Category.h
|
include/emoji/Category.h
|
||||||
|
|
|
@ -5,6 +5,7 @@ nheko
|
||||||
[![Latest Release](https://img.shields.io/github/release/mujx/nheko.svg)](https://github.com/mujx/nheko/releases)
|
[![Latest Release](https://img.shields.io/github/release/mujx/nheko.svg)](https://github.com/mujx/nheko/releases)
|
||||||
[![Chat on Matrix](https://img.shields.io/badge/chat-on%20matrix-blue.svg)](https://matrix.to/#/#nheko:matrix.org)
|
[![Chat on Matrix](https://img.shields.io/badge/chat-on%20matrix-blue.svg)](https://matrix.to/#/#nheko:matrix.org)
|
||||||
[![AUR: nheko-git](https://img.shields.io/badge/AUR-nheko--git-blue.svg)](https://aur.archlinux.org/packages/nheko-git)
|
[![AUR: nheko-git](https://img.shields.io/badge/AUR-nheko--git-blue.svg)](https://aur.archlinux.org/packages/nheko-git)
|
||||||
|
[![AUR: nheko](https://img.shields.io/badge/AUR-nheko-blue.svg)](https://aur.archlinux.org/packages/nheko)
|
||||||
|
|
||||||
The motivation behind the project is to provide a native desktop app for [Matrix] that
|
The motivation behind the project is to provide a native desktop app for [Matrix] that
|
||||||
feels more like a mainstream chat app ([Riot], Telegram etc) and less like an IRC client.
|
feels more like a mainstream chat app ([Riot], Telegram etc) and less like an IRC client.
|
||||||
|
@ -14,6 +15,7 @@ feels more like a mainstream chat app ([Riot], Telegram etc) and less like an IR
|
||||||
Most of the features you would expect from a chat application are missing right now
|
Most of the features you would expect from a chat application are missing right now
|
||||||
but we are getting close to a more feature complete client.
|
but we are getting close to a more feature complete client.
|
||||||
Specifically there is support for:
|
Specifically there is support for:
|
||||||
|
- User registration.
|
||||||
- Creating, joining & leaving rooms.
|
- Creating, joining & leaving rooms.
|
||||||
- Sending & receiving invites.
|
- Sending & receiving invites.
|
||||||
- Sending & receiving files and emoji (inline widgets for images, audio and file messages).
|
- Sending & receiving files and emoji (inline widgets for images, audio and file messages).
|
||||||
|
|
|
@ -23,7 +23,7 @@ ExternalProject_Add(
|
||||||
MatrixStructs
|
MatrixStructs
|
||||||
|
|
||||||
GIT_REPOSITORY https://github.com/mujx/matrix-structs
|
GIT_REPOSITORY https://github.com/mujx/matrix-structs
|
||||||
GIT_TAG a1beea3b115f037e26c15f22ed911341b3893411
|
GIT_TAG 850100c0ac2b5a04720b2a1f09270749bf99f7dd
|
||||||
|
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
SOURCE_DIR ${MATRIX_STRUCTS_ROOT}
|
SOURCE_DIR ${MATRIX_STRUCTS_ROOT}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void backButtonClicked();
|
void backButtonClicked();
|
||||||
void loggingIn();
|
void loggingIn();
|
||||||
void errorOccured();
|
void errorOccurred();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
|
@ -49,6 +49,7 @@ class InviteUsers;
|
||||||
class JoinRoom;
|
class JoinRoom;
|
||||||
class LeaveRoom;
|
class LeaveRoom;
|
||||||
class Logout;
|
class Logout;
|
||||||
|
class ReCaptcha;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
|
|
|
@ -54,7 +54,8 @@ public:
|
||||||
void login(const QString &username, const QString &password) noexcept;
|
void login(const QString &username, const QString &password) noexcept;
|
||||||
void registerUser(const QString &username,
|
void registerUser(const QString &username,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
const QString &server) noexcept;
|
const QString &server,
|
||||||
|
const QString &session = "") noexcept;
|
||||||
void versions() noexcept;
|
void versions() noexcept;
|
||||||
void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
|
void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
|
||||||
//! Download user's avatar.
|
//! Download user's avatar.
|
||||||
|
@ -109,6 +110,10 @@ 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 registrationFlow(const QString &user,
|
||||||
|
const QString &pass,
|
||||||
|
const QString &server,
|
||||||
|
const QString &session);
|
||||||
void versionError(const QString &error);
|
void versionError(const QString &error);
|
||||||
|
|
||||||
void loggedOut();
|
void loggedOut();
|
||||||
|
|
|
@ -1,52 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Deserializable.h"
|
|
||||||
#include <QJsonDocument>
|
|
||||||
|
|
||||||
class RegisterRequest
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RegisterRequest();
|
|
||||||
RegisterRequest(const QString &username, const QString &password);
|
|
||||||
|
|
||||||
QByteArray serialize() noexcept;
|
|
||||||
|
|
||||||
void setPassword(QString password) { password_ = password; };
|
|
||||||
void setUser(QString username) { user_ = username; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString user_;
|
|
||||||
QString password_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegisterResponse : public Deserializable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void deserialize(const QJsonDocument &data) override;
|
|
||||||
|
|
||||||
QString getAccessToken() { return access_token_; };
|
|
||||||
QString getHomeServer() { return home_server_; };
|
|
||||||
QString getUserId() { return user_id_; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString access_token_;
|
|
||||||
QString home_server_;
|
|
||||||
QString user_id_;
|
|
||||||
};
|
|
|
@ -20,12 +20,17 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class FlatButton;
|
class FlatButton;
|
||||||
class MatrixClient;
|
class MatrixClient;
|
||||||
class RaisedButton;
|
class RaisedButton;
|
||||||
class TextField;
|
class TextField;
|
||||||
|
|
||||||
|
namespace dialogs {
|
||||||
|
class ReCaptcha;
|
||||||
|
}
|
||||||
|
|
||||||
class RegisterPage : public QWidget
|
class RegisterPage : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -38,6 +43,8 @@ protected:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void backButtonClicked();
|
void backButtonClicked();
|
||||||
|
void errorOccurred();
|
||||||
|
void registering();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onBackButtonClicked();
|
void onBackButtonClicked();
|
||||||
|
@ -70,4 +77,6 @@ private:
|
||||||
|
|
||||||
// Matrix client API provider.
|
// Matrix client API provider.
|
||||||
QSharedPointer<MatrixClient> client_;
|
QSharedPointer<MatrixClient> client_;
|
||||||
|
//! ReCaptcha dialog.
|
||||||
|
std::shared_ptr<dialogs::ReCaptcha> captchaDialog_;
|
||||||
};
|
};
|
||||||
|
|
28
include/dialogs/ReCaptcha.hpp
Normal file
28
include/dialogs/ReCaptcha.hpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class FlatButton;
|
||||||
|
class RaisedButton;
|
||||||
|
|
||||||
|
namespace dialogs {
|
||||||
|
|
||||||
|
class ReCaptcha : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReCaptcha(const QString &server, const QString &session, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void closing();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FlatButton *openCaptchaBtn_;
|
||||||
|
RaisedButton *confirmBtn_;
|
||||||
|
RaisedButton *cancelBtn_;
|
||||||
|
};
|
||||||
|
} // dialogs
|
|
@ -101,6 +101,7 @@ Avatar {
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogs--Logout,
|
dialogs--Logout,
|
||||||
|
dialogs--ReCaptcha,
|
||||||
dialogs--LeaveRoom,
|
dialogs--LeaveRoom,
|
||||||
dialogs--CreateRoom,
|
dialogs--CreateRoom,
|
||||||
dialogs--InviteUsers,
|
dialogs--InviteUsers,
|
||||||
|
|
|
@ -104,6 +104,7 @@ Avatar {
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogs--Logout,
|
dialogs--Logout,
|
||||||
|
dialogs--ReCaptcha,
|
||||||
dialogs--LeaveRoom,
|
dialogs--LeaveRoom,
|
||||||
dialogs--CreateRoom,
|
dialogs--CreateRoom,
|
||||||
dialogs--InviteUsers,
|
dialogs--InviteUsers,
|
||||||
|
|
|
@ -144,7 +144,7 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
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(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(client_.data(), SIGNAL(loginError(QString)), this, SIGNAL(errorOccured()));
|
connect(client_.data(), SIGNAL(loginError(QString)), this, SIGNAL(errorOccurred()));
|
||||||
connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
|
connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
|
||||||
connect(client_.data(), SIGNAL(versionError(QString)), this, SLOT(versionError(QString)));
|
connect(client_.data(), SIGNAL(versionError(QString)), this, SLOT(versionError(QString)));
|
||||||
connect(client_.data(), SIGNAL(versionSuccess()), this, SLOT(versionSuccess()));
|
connect(client_.data(), SIGNAL(versionSuccess()), this, SLOT(versionSuccess()));
|
||||||
|
|
|
@ -85,7 +85,12 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
connect(login_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
|
connect(login_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
|
||||||
connect(login_page_, &LoginPage::loggingIn, this, &MainWindow::showOverlayProgressBar);
|
connect(login_page_, &LoginPage::loggingIn, this, &MainWindow::showOverlayProgressBar);
|
||||||
connect(
|
connect(
|
||||||
login_page_, &LoginPage::errorOccured, this, [this]() { removeOverlayProgressBar(); });
|
register_page_, &RegisterPage::registering, this, &MainWindow::showOverlayProgressBar);
|
||||||
|
connect(
|
||||||
|
login_page_, &LoginPage::errorOccurred, this, [this]() { removeOverlayProgressBar(); });
|
||||||
|
connect(register_page_, &RegisterPage::errorOccurred, this, [this]() {
|
||||||
|
removeOverlayProgressBar();
|
||||||
|
});
|
||||||
connect(register_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
|
connect(register_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
|
||||||
|
|
||||||
connect(chat_page_, SIGNAL(close()), this, SLOT(showWelcomePage()));
|
connect(chat_page_, SIGNAL(close()), this, SLOT(showWelcomePage()));
|
||||||
|
@ -120,6 +125,11 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
this,
|
this,
|
||||||
SLOT(showChatPage(QString, QString, QString)));
|
SLOT(showChatPage(QString, QString, QString)));
|
||||||
|
|
||||||
|
connect(client_.data(),
|
||||||
|
SIGNAL(registerSuccess(QString, QString, QString)),
|
||||||
|
this,
|
||||||
|
SLOT(showChatPage(QString, QString, QString)));
|
||||||
|
|
||||||
QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
|
QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
|
||||||
connect(quitShortcut, &QShortcut::activated, this, QApplication::quit);
|
connect(quitShortcut, &QShortcut::activated, this, QApplication::quit);
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,10 @@
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
#include <mtx/errors.hpp>
|
||||||
|
|
||||||
|
#include "Deserializable.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "Register.h"
|
|
||||||
|
|
||||||
MatrixClient::MatrixClient(QString server, QObject *parent)
|
MatrixClient::MatrixClient(QString server, QObject *parent)
|
||||||
: QNetworkAccessManager(parent)
|
: QNetworkAccessManager(parent)
|
||||||
|
@ -193,50 +194,66 @@ MatrixClient::logout() noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MatrixClient::registerUser(const QString &user, const QString &pass, const QString &server) noexcept
|
MatrixClient::registerUser(const QString &user,
|
||||||
|
const QString &pass,
|
||||||
|
const QString &server,
|
||||||
|
const QString &session) noexcept
|
||||||
{
|
{
|
||||||
setServer(server);
|
setServer(server);
|
||||||
|
|
||||||
QUrlQuery query;
|
|
||||||
query.addQueryItem("kind", "user");
|
|
||||||
|
|
||||||
QUrl endpoint(server_);
|
QUrl endpoint(server_);
|
||||||
endpoint.setPath(clientApiUrl_ + "/register");
|
endpoint.setPath(clientApiUrl_ + "/register");
|
||||||
endpoint.setQuery(query);
|
|
||||||
|
|
||||||
QNetworkRequest request(QString(endpoint.toEncoded()));
|
QNetworkRequest request(QString(endpoint.toEncoded()));
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
RegisterRequest body(user, pass);
|
QJsonObject body{{"username", user}, {"password", pass}};
|
||||||
auto reply = post(request, body.serialize());
|
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
// We trying to register using the response from the recaptcha.
|
||||||
|
if (!session.isEmpty())
|
||||||
|
body = QJsonObject{
|
||||||
|
{"username", user},
|
||||||
|
{"password", pass},
|
||||||
|
{"auth", QJsonObject{{"type", "m.login.recaptcha"}, {"session", session}}}};
|
||||||
|
|
||||||
|
auto reply = post(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, reply, user, pass, server]() {
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
auto data = reply->readAll();
|
auto data = reply->readAll();
|
||||||
auto json = QJsonDocument::fromJson(data);
|
|
||||||
|
|
||||||
if (status == 0 || status >= 400) {
|
// Try to parse a regular register response.
|
||||||
if (json.isObject() && json.object().contains("error"))
|
try {
|
||||||
emit registerError(json.object().value("error").toString());
|
mtx::responses::Register res = nlohmann::json::parse(data);
|
||||||
else
|
emit registerSuccess(QString::fromStdString(res.user_id.toString()),
|
||||||
emit registerError(reply->errorString());
|
QString::fromStdString(res.user_id.hostname()),
|
||||||
|
QString::fromStdString(res.access_token));
|
||||||
return;
|
} catch (const std::exception &e) {
|
||||||
|
qWarning() << "Register" << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterResponse response;
|
// Check if the server requires a registration flow.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response.deserialize(json);
|
mtx::responses::RegistrationFlows res = nlohmann::json::parse(data);
|
||||||
emit registerSuccess(response.getUserId(),
|
emit registrationFlow(
|
||||||
response.getHomeServer(),
|
user, pass, server, QString::fromStdString(res.session));
|
||||||
response.getAccessToken());
|
return;
|
||||||
} catch (DeserializationException &e) {
|
} catch (const std::exception &) {
|
||||||
qWarning() << "Register" << e.what();
|
}
|
||||||
emit registerError("Received malformed response.");
|
|
||||||
|
// We encountered an unknown error.
|
||||||
|
if (status == 0 || status >= 400) {
|
||||||
|
try {
|
||||||
|
mtx::errors::Error res = nlohmann::json::parse(data);
|
||||||
|
emit registerError(QString::fromStdString(res.error));
|
||||||
|
return;
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
}
|
||||||
|
|
||||||
|
emit registerError(reply->errorString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +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 "Register.h"
|
|
||||||
|
|
||||||
RegisterRequest::RegisterRequest(const QString &username, const QString &password)
|
|
||||||
: user_(username)
|
|
||||||
, password_(password)
|
|
||||||
{}
|
|
||||||
|
|
||||||
QByteArray
|
|
||||||
RegisterRequest::serialize() noexcept
|
|
||||||
{
|
|
||||||
QJsonObject body{{"username", user_}, {"password", password_}};
|
|
||||||
|
|
||||||
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RegisterResponse::deserialize(const QJsonDocument &data)
|
|
||||||
{
|
|
||||||
if (!data.isObject())
|
|
||||||
throw DeserializationException("Response is not a JSON object");
|
|
||||||
|
|
||||||
QJsonObject object = data.object();
|
|
||||||
|
|
||||||
if (!object.contains("access_token"))
|
|
||||||
throw DeserializationException("Missing access_token param");
|
|
||||||
|
|
||||||
if (!object.contains("home_server"))
|
|
||||||
throw DeserializationException("Missing home_server param");
|
|
||||||
|
|
||||||
if (!object.contains("user_id"))
|
|
||||||
throw DeserializationException("Missing user_id param");
|
|
||||||
|
|
||||||
access_token_ = object.value("access_token").toString();
|
|
||||||
home_server_ = object.value("home_server").toString();
|
|
||||||
user_id_ = object.value("user_id").toString();
|
|
||||||
}
|
|
|
@ -16,14 +16,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "RaisedButton.h"
|
#include "RaisedButton.h"
|
||||||
#include "RegisterPage.h"
|
#include "RegisterPage.h"
|
||||||
#include "TextField.h"
|
#include "TextField.h"
|
||||||
|
|
||||||
|
#include "dialogs/ReCaptcha.hpp"
|
||||||
|
|
||||||
RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, client_(client)
|
, client_(client)
|
||||||
|
@ -126,6 +130,30 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
SIGNAL(registerError(const QString &)),
|
SIGNAL(registerError(const QString &)),
|
||||||
this,
|
this,
|
||||||
SLOT(registerError(const QString &)));
|
SLOT(registerError(const QString &)));
|
||||||
|
connect(client_.data(),
|
||||||
|
&MatrixClient::registrationFlow,
|
||||||
|
this,
|
||||||
|
[this](const QString &user,
|
||||||
|
const QString &pass,
|
||||||
|
const QString &server,
|
||||||
|
const QString &session) {
|
||||||
|
emit errorOccurred();
|
||||||
|
|
||||||
|
if (!captchaDialog_) {
|
||||||
|
captchaDialog_ =
|
||||||
|
std::make_shared<dialogs::ReCaptcha>(server, session, this);
|
||||||
|
connect(captchaDialog_.get(),
|
||||||
|
&dialogs::ReCaptcha::closing,
|
||||||
|
this,
|
||||||
|
[this, user, pass, server, session]() {
|
||||||
|
captchaDialog_->close();
|
||||||
|
emit registering();
|
||||||
|
client_->registerUser(user, pass, server, session);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimer::singleShot(1000, this, [this]() { captchaDialog_->show(); });
|
||||||
|
});
|
||||||
|
|
||||||
setLayout(top_layout_);
|
setLayout(top_layout_);
|
||||||
}
|
}
|
||||||
|
@ -139,6 +167,7 @@ RegisterPage::onBackButtonClicked()
|
||||||
void
|
void
|
||||||
RegisterPage::registerError(const QString &msg)
|
RegisterPage::registerError(const QString &msg)
|
||||||
{
|
{
|
||||||
|
emit errorOccurred();
|
||||||
error_label_->setText(msg);
|
error_label_->setText(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +190,7 @@ RegisterPage::onRegisterButtonClicked()
|
||||||
QString server = server_input_->text();
|
QString server = server_input_->text();
|
||||||
|
|
||||||
client_->registerUser(username, password, server);
|
client_->registerUser(username, password, server);
|
||||||
|
emit registering();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
src/dialogs/ReCaptcha.cpp
Normal file
75
src/dialogs/ReCaptcha.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "FlatButton.h"
|
||||||
|
#include "RaisedButton.h"
|
||||||
|
#include "Theme.h"
|
||||||
|
|
||||||
|
#include "dialogs/ReCaptcha.hpp"
|
||||||
|
|
||||||
|
using namespace dialogs;
|
||||||
|
|
||||||
|
ReCaptcha::ReCaptcha(const QString &server, const QString &session, QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
setAutoFillBackground(true);
|
||||||
|
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
|
||||||
|
setWindowModality(Qt::WindowModal);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
layout->setSpacing(30);
|
||||||
|
layout->setMargin(20);
|
||||||
|
|
||||||
|
auto buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->setSpacing(8);
|
||||||
|
buttonLayout->setMargin(0);
|
||||||
|
|
||||||
|
openCaptchaBtn_ = new FlatButton("OPEN reCAPTCHA", this);
|
||||||
|
openCaptchaBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
confirmBtn_ = new RaisedButton(tr("CONFIRM"), this);
|
||||||
|
confirmBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
cancelBtn_ = new RaisedButton(tr("CANCEL"), this);
|
||||||
|
cancelBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
buttonLayout->addStretch(1);
|
||||||
|
buttonLayout->addWidget(openCaptchaBtn_);
|
||||||
|
buttonLayout->addWidget(confirmBtn_);
|
||||||
|
buttonLayout->addWidget(cancelBtn_);
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPixelSize(conf::headerFontSize);
|
||||||
|
|
||||||
|
auto label = new QLabel(tr("Solve the reCAPTCHA and press the confirm button"), this);
|
||||||
|
label->setFont(font);
|
||||||
|
|
||||||
|
layout->addWidget(label);
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
connect(openCaptchaBtn_, &QPushButton::clicked, [server, session, this]() {
|
||||||
|
const auto url =
|
||||||
|
QString(
|
||||||
|
"https://%1/_matrix/client/r0/auth/m.login.recaptcha/fallback/web?session=%2")
|
||||||
|
.arg(server)
|
||||||
|
.arg(session);
|
||||||
|
|
||||||
|
QDesktopServices::openUrl(url);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(confirmBtn_, &QPushButton::clicked, this, &dialogs::ReCaptcha::closing);
|
||||||
|
connect(cancelBtn_, &QPushButton::clicked, this, &dialogs::ReCaptcha::close);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReCaptcha::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QStyleOption opt;
|
||||||
|
opt.init(this);
|
||||||
|
QPainter p(this);
|
||||||
|
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||||
|
}
|
Loading…
Reference in a new issue