mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Port the reCAPTCHA dialog to QML
This commit is contained in:
parent
ff4c16c34f
commit
fedc178827
9 changed files with 153 additions and 124 deletions
|
@ -353,8 +353,6 @@ set(SRC_FILES
|
||||||
# Dialogs
|
# Dialogs
|
||||||
src/dialogs/FallbackAuth.cpp
|
src/dialogs/FallbackAuth.cpp
|
||||||
src/dialogs/FallbackAuth.h
|
src/dialogs/FallbackAuth.h
|
||||||
src/dialogs/ReCaptcha.cpp
|
|
||||||
src/dialogs/ReCaptcha.h
|
|
||||||
|
|
||||||
# Emoji
|
# Emoji
|
||||||
src/emoji/Provider.cpp
|
src/emoji/Provider.cpp
|
||||||
|
@ -485,6 +483,8 @@ set(SRC_FILES
|
||||||
src/PowerlevelsEditModels.h
|
src/PowerlevelsEditModels.h
|
||||||
src/ReadReceiptsModel.cpp
|
src/ReadReceiptsModel.cpp
|
||||||
src/ReadReceiptsModel.h
|
src/ReadReceiptsModel.h
|
||||||
|
src/ReCaptcha.cpp
|
||||||
|
src/ReCaptcha.h
|
||||||
src/RegisterPage.cpp
|
src/RegisterPage.cpp
|
||||||
src/RegisterPage.h
|
src/RegisterPage.h
|
||||||
src/RoomDirectoryModel.cpp
|
src/RoomDirectoryModel.cpp
|
||||||
|
@ -776,6 +776,7 @@ set(QML_SOURCES
|
||||||
resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml
|
resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml
|
||||||
resources/qml/dialogs/RawMessageDialog.qml
|
resources/qml/dialogs/RawMessageDialog.qml
|
||||||
resources/qml/dialogs/ReadReceipts.qml
|
resources/qml/dialogs/ReadReceipts.qml
|
||||||
|
resources/qml/dialogs/ReCaptchaDialog.qml
|
||||||
resources/qml/dialogs/RoomDirectory.qml
|
resources/qml/dialogs/RoomDirectory.qml
|
||||||
resources/qml/dialogs/RoomMembers.qml
|
resources/qml/dialogs/RoomMembers.qml
|
||||||
resources/qml/dialogs/AllowedRoomsSettingsDialog.qml
|
resources/qml/dialogs/AllowedRoomsSettingsDialog.qml
|
||||||
|
|
|
@ -360,6 +360,7 @@ Pane {
|
||||||
|
|
||||||
onAccepted: UIA.continue3pidReceived()
|
onAccepted: UIA.continue3pidReceived()
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onConfirm3pidToken() {
|
function onConfirm3pidToken() {
|
||||||
uiaConfirmationLinkDialog.open();
|
uiaConfirmationLinkDialog.open();
|
||||||
|
@ -381,6 +382,18 @@ Pane {
|
||||||
function onPrompt3pidToken() {
|
function onPrompt3pidToken() {
|
||||||
uiaTokenPrompt.show();
|
uiaTokenPrompt.show();
|
||||||
}
|
}
|
||||||
|
function onReCaptcha(recaptcha) {
|
||||||
|
var component = Qt.createComponent("qrc:/resources/qml/dialogs/ReCaptchaDialog.qml");
|
||||||
|
if (component.status == Component.Ready) {
|
||||||
|
var dialog = component.createObject(timelineRoot, {
|
||||||
|
"recaptcha": recaptcha
|
||||||
|
});
|
||||||
|
dialog.show();
|
||||||
|
destroyOnClose(dialog);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to create component: " + component.errorString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
target: UIA
|
target: UIA
|
||||||
}
|
}
|
||||||
|
|
63
resources/qml/dialogs/ReCaptchaDialog.qml
Normal file
63
resources/qml/dialogs/ReCaptchaDialog.qml
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// SPDX-FileCopyrightText: Nheko Contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import im.nheko
|
||||||
|
|
||||||
|
ApplicationWindow {
|
||||||
|
id: recaptchaRoot
|
||||||
|
|
||||||
|
required property ReCaptcha recaptcha
|
||||||
|
|
||||||
|
function accept() {
|
||||||
|
recaptcha.confirm();
|
||||||
|
recaptchaRoot.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function reject() {
|
||||||
|
recaptcha.cancel();
|
||||||
|
recaptchaRoot.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
color: palette.window
|
||||||
|
title: recaptcha.context
|
||||||
|
flags: Qt.Tool | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
|
||||||
|
height: msg.implicitHeight + footer.implicitHeight
|
||||||
|
width: Math.max(msg.implicitWidth, footer.implicitWidth)
|
||||||
|
|
||||||
|
Shortcut {
|
||||||
|
sequence: StandardKey.Cancel
|
||||||
|
onActivated: recaptchaRoot.reject()
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: msg
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
padding: 8
|
||||||
|
text: qsTr("Solve the reCAPTCHA and press the confirm button")
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: DialogButtonBox {
|
||||||
|
onAccepted: recaptchaRoot.accept()
|
||||||
|
onRejected: recaptchaRoot.reject()
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Open reCAPTCHA")
|
||||||
|
onClicked: recaptcha.openReCaptcha()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr("Confirm")
|
||||||
|
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/ReCaptcha.cpp
Normal file
28
src/ReCaptcha.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// SPDX-FileCopyrightText: Nheko Contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "ReCaptcha.h"
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "MatrixClient.h"
|
||||||
|
|
||||||
|
ReCaptcha::ReCaptcha(const QString &session, const QString &context, QObject *parent)
|
||||||
|
: QObject{parent},
|
||||||
|
m_session{session},
|
||||||
|
m_context{context}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReCaptcha::openReCaptcha()
|
||||||
|
{
|
||||||
|
const auto url = QString("https://%1:%2/_matrix/client/r0/auth/m.login.recaptcha/"
|
||||||
|
"fallback/web?session=%3")
|
||||||
|
.arg(QString::fromStdString(http::client()->server()))
|
||||||
|
.arg(http::client()->port())
|
||||||
|
.arg(m_session);
|
||||||
|
|
||||||
|
QDesktopServices::openUrl(url);
|
||||||
|
}
|
32
src/ReCaptcha.h
Normal file
32
src/ReCaptcha.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// SPDX-FileCopyrightText: Nheko Contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
class ReCaptcha : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
QML_UNCREATABLE("")
|
||||||
|
|
||||||
|
Q_PROPERTY(QString context MEMBER m_context CONSTANT)
|
||||||
|
Q_PROPERTY(QString session MEMBER m_session CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReCaptcha(const QString &session, const QString &context, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Q_INVOKABLE void openReCaptcha();
|
||||||
|
Q_INVOKABLE void confirm() { emit confirmation(); }
|
||||||
|
Q_INVOKABLE void cancel() { emit cancelled(); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void confirmation();
|
||||||
|
void cancelled();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_session;
|
||||||
|
QString m_context;
|
||||||
|
};
|
|
@ -1,74 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "dialogs/ReCaptcha.h"
|
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
#include "MatrixClient.h"
|
|
||||||
|
|
||||||
using namespace dialogs;
|
|
||||||
|
|
||||||
ReCaptcha::ReCaptcha(const QString &session, QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
setAutoFillBackground(true);
|
|
||||||
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
|
|
||||||
setWindowModality(Qt::WindowModal);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
layout->setSpacing(conf::modals::WIDGET_SPACING);
|
|
||||||
layout->setContentsMargins(conf::modals::WIDGET_MARGIN,
|
|
||||||
conf::modals::WIDGET_MARGIN,
|
|
||||||
conf::modals::WIDGET_MARGIN,
|
|
||||||
conf::modals::WIDGET_MARGIN);
|
|
||||||
|
|
||||||
auto buttonLayout = new QHBoxLayout();
|
|
||||||
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
buttonLayout->setSpacing(8);
|
|
||||||
|
|
||||||
openCaptchaBtn_ = new QPushButton(tr("Open reCAPTCHA"), this);
|
|
||||||
cancelBtn_ = new QPushButton(tr("Cancel"), this);
|
|
||||||
confirmBtn_ = new QPushButton(tr("Confirm"), this);
|
|
||||||
confirmBtn_->setDefault(true);
|
|
||||||
|
|
||||||
buttonLayout->addStretch(1);
|
|
||||||
buttonLayout->addWidget(openCaptchaBtn_);
|
|
||||||
buttonLayout->addWidget(cancelBtn_);
|
|
||||||
buttonLayout->addWidget(confirmBtn_);
|
|
||||||
|
|
||||||
QFont font;
|
|
||||||
font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
|
|
||||||
|
|
||||||
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, [session]() {
|
|
||||||
const auto url = QString("https://%1:%2/_matrix/client/r0/auth/m.login.recaptcha/"
|
|
||||||
"fallback/web?session=%3")
|
|
||||||
.arg(QString::fromStdString(http::client()->server()))
|
|
||||||
.arg(http::client()->port())
|
|
||||||
.arg(session);
|
|
||||||
|
|
||||||
QDesktopServices::openUrl(url);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
|
|
||||||
emit confirmation();
|
|
||||||
close();
|
|
||||||
});
|
|
||||||
connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
|
|
||||||
emit cancel();
|
|
||||||
close();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class QPushButton;
|
|
||||||
|
|
||||||
namespace dialogs {
|
|
||||||
|
|
||||||
class ReCaptcha final : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ReCaptcha(const QString &session, QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void confirmation();
|
|
||||||
void cancel();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QPushButton *openCaptchaBtn_;
|
|
||||||
QPushButton *confirmBtn_;
|
|
||||||
QPushButton *cancelBtn_;
|
|
||||||
};
|
|
||||||
} // dialogs
|
|
|
@ -14,12 +14,12 @@
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "dialogs/FallbackAuth.h"
|
#include "dialogs/FallbackAuth.h"
|
||||||
#include "dialogs/ReCaptcha.h"
|
#include "ReCaptcha.h"
|
||||||
|
|
||||||
UIA *
|
UIA *
|
||||||
UIA::instance()
|
UIA::instance()
|
||||||
{
|
{
|
||||||
static UIA uia;
|
static UIA uia{nullptr};
|
||||||
return &uia;
|
return &uia;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,24 +99,16 @@ UIA::genericHandler(QString context)
|
||||||
} else if (current_stage == mtx::user_interactive::auth_types::msisdn) {
|
} else if (current_stage == mtx::user_interactive::auth_types::msisdn) {
|
||||||
emit phoneNumber();
|
emit phoneNumber();
|
||||||
} else if (current_stage == mtx::user_interactive::auth_types::recaptcha) {
|
} else if (current_stage == mtx::user_interactive::auth_types::recaptcha) {
|
||||||
auto captchaDialog =
|
auto captcha = new ReCaptcha(QString::fromStdString(u.session), context, nullptr);
|
||||||
new dialogs::ReCaptcha(QString::fromStdString(u.session), nullptr);
|
QQmlEngine::setObjectOwnership(captcha, QQmlEngine::JavaScriptOwnership);
|
||||||
captchaDialog->setWindowTitle(context);
|
connect(captcha, &ReCaptcha::confirmation, this, [h, u]() {
|
||||||
|
|
||||||
connect(
|
|
||||||
captchaDialog, &dialogs::ReCaptcha::confirmation, this, [captchaDialog, h, u]() {
|
|
||||||
captchaDialog->close();
|
|
||||||
captchaDialog->deleteLater();
|
|
||||||
h.next(mtx::user_interactive::Auth{u.session,
|
h.next(mtx::user_interactive::Auth{u.session,
|
||||||
mtx::user_interactive::auth::Fallback{}});
|
mtx::user_interactive::auth::Fallback{}});
|
||||||
});
|
});
|
||||||
|
connect(captcha, &ReCaptcha::cancelled, this, [this]() {
|
||||||
connect(captchaDialog, &dialogs::ReCaptcha::cancel, this, [this]() {
|
|
||||||
emit error(tr("Registration aborted"));
|
emit error(tr("Registration aborted"));
|
||||||
});
|
});
|
||||||
|
emit reCaptcha(captcha);
|
||||||
QTimer::singleShot(0, this, [captchaDialog]() { captchaDialog->show(); });
|
|
||||||
|
|
||||||
} else if (current_stage == mtx::user_interactive::auth_types::dummy) {
|
} else if (current_stage == mtx::user_interactive::auth_types::dummy) {
|
||||||
h.next(
|
h.next(
|
||||||
mtx::user_interactive::Auth{u.session, mtx::user_interactive::auth::Dummy{}});
|
mtx::user_interactive::Auth{u.session, mtx::user_interactive::auth::Dummy{}});
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <mtxclient/http/client.hpp>
|
#include <mtxclient/http/client.hpp>
|
||||||
|
|
||||||
|
#include "ReCaptcha.h"
|
||||||
|
|
||||||
class UIA final : public QObject
|
class UIA final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -39,7 +41,7 @@ public:
|
||||||
return instance();
|
return instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
UIA(QObject *parent = nullptr)
|
UIA(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -59,6 +61,7 @@ signals:
|
||||||
void password();
|
void password();
|
||||||
void email();
|
void email();
|
||||||
void phoneNumber();
|
void phoneNumber();
|
||||||
|
void reCaptcha(ReCaptcha *recaptcha);
|
||||||
|
|
||||||
void confirm3pidToken();
|
void confirm3pidToken();
|
||||||
void prompt3pidToken();
|
void prompt3pidToken();
|
||||||
|
|
Loading…
Reference in a new issue