summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--resources/qml/Root.qml22
-rw-r--r--resources/qml/dialogs/ReCaptchaDialog.qml63
-rw-r--r--src/MainWindow.h1
-rw-r--r--src/ReCaptcha.cpp29
-rw-r--r--src/ReCaptcha.h32
-rw-r--r--src/dialogs/ReCaptcha.cpp74
-rw-r--r--src/dialogs/ReCaptcha.h29
-rw-r--r--src/ui/UIA.cpp28
-rw-r--r--src/ui/UIA.h5
10 files changed, 154 insertions, 134 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1d43cfe6..2bc6806b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -353,8 +353,6 @@ set(SRC_FILES
 	# Dialogs
 	src/dialogs/FallbackAuth.cpp
 	src/dialogs/FallbackAuth.h
-	src/dialogs/ReCaptcha.cpp
-	src/dialogs/ReCaptcha.h
 
 	# Emoji
 	src/emoji/Provider.cpp
@@ -487,6 +485,8 @@ set(SRC_FILES
 	src/PowerlevelsEditModels.h
 	src/ReadReceiptsModel.cpp
 	src/ReadReceiptsModel.h
+	src/ReCaptcha.cpp
+	src/ReCaptcha.h
 	src/RegisterPage.cpp
 	src/RegisterPage.h
 	src/RoomDirectoryModel.cpp
@@ -779,6 +779,7 @@ set(QML_SOURCES
         resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml
         resources/qml/dialogs/RawMessageDialog.qml
         resources/qml/dialogs/ReadReceipts.qml
+        resources/qml/dialogs/ReCaptchaDialog.qml
         resources/qml/dialogs/RoomDirectory.qml
         resources/qml/dialogs/RoomMembers.qml
         resources/qml/dialogs/AllowedRoomsSettingsDialog.qml
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index e26b386a..fb0c6036 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -348,11 +348,6 @@ Pane {
         }
     }
     Platform.MessageDialog {
-        id: uiaErrorDialog
-
-        buttons: Platform.MessageDialog.Ok
-    }
-    Platform.MessageDialog {
         id: uiaConfirmationLinkDialog
 
         buttons: Platform.MessageDialog.Ok
@@ -360,6 +355,7 @@ Pane {
 
         onAccepted: UIA.continue3pidReceived()
     }
+
     Connections {
         function onConfirm3pidToken() {
             uiaConfirmationLinkDialog.open();
@@ -367,10 +363,6 @@ Pane {
         function onEmail() {
             uiaEmailPrompt.show();
         }
-        function onError(msg) {
-            uiaErrorDialog.text = msg;
-            uiaErrorDialog.open();
-        }
         function onPassword() {
             console.log("UIA: password needed");
             uiaPassPrompt.show();
@@ -381,6 +373,18 @@ Pane {
         function onPrompt3pidToken() {
             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
     }
diff --git a/resources/qml/dialogs/ReCaptchaDialog.qml b/resources/qml/dialogs/ReCaptchaDialog.qml
new file mode 100644
index 00000000..0da62cbc
--- /dev/null
+++ b/resources/qml/dialogs/ReCaptchaDialog.qml
@@ -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
+        }
+    }
+
+}
diff --git a/src/MainWindow.h b/src/MainWindow.h
index 20e81efc..fc06e183 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -34,7 +34,6 @@ namespace dialogs {
 class CreateRoom;
 class InviteUsers;
 class MemberList;
-class ReCaptcha;
 }
 
 class NhekoFixupPaletteEventFilter final : public QObject
diff --git a/src/ReCaptcha.cpp b/src/ReCaptcha.cpp
new file mode 100644
index 00000000..ab9db8cc
--- /dev/null
+++ b/src/ReCaptcha.cpp
@@ -0,0 +1,29 @@
+// 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);
+}
diff --git a/src/ReCaptcha.h b/src/ReCaptcha.h
new file mode 100644
index 00000000..84d65478
--- /dev/null
+++ b/src/ReCaptcha.h
@@ -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;
+};
diff --git a/src/dialogs/ReCaptcha.cpp b/src/dialogs/ReCaptcha.cpp
deleted file mode 100644
index 2abf7c07..00000000
--- a/src/dialogs/ReCaptcha.cpp
+++ /dev/null
@@ -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();
-    });
-}
diff --git a/src/dialogs/ReCaptcha.h b/src/dialogs/ReCaptcha.h
deleted file mode 100644
index 53c7453e..00000000
--- a/src/dialogs/ReCaptcha.h
+++ /dev/null
@@ -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
diff --git a/src/ui/UIA.cpp b/src/ui/UIA.cpp
index 2b6b059a..9654c9aa 100644
--- a/src/ui/UIA.cpp
+++ b/src/ui/UIA.cpp
@@ -13,13 +13,13 @@
 
 #include "Logging.h"
 #include "MatrixClient.h"
+#include "ReCaptcha.h"
 #include "dialogs/FallbackAuth.h"
-#include "dialogs/ReCaptcha.h"
 
 UIA *
 UIA::instance()
 {
-    static UIA uia;
+    static UIA uia{nullptr};
     return &uia;
 }
 
@@ -99,24 +99,16 @@ UIA::genericHandler(QString context)
             } else if (current_stage == mtx::user_interactive::auth_types::msisdn) {
                 emit phoneNumber();
             } else if (current_stage == mtx::user_interactive::auth_types::recaptcha) {
-                auto captchaDialog =
-                  new dialogs::ReCaptcha(QString::fromStdString(u.session), nullptr);
-                captchaDialog->setWindowTitle(context);
-
-                connect(
-                  captchaDialog, &dialogs::ReCaptcha::confirmation, this, [captchaDialog, h, u]() {
-                      captchaDialog->close();
-                      captchaDialog->deleteLater();
-                      h.next(mtx::user_interactive::Auth{u.session,
-                                                         mtx::user_interactive::auth::Fallback{}});
-                  });
-
-                connect(captchaDialog, &dialogs::ReCaptcha::cancel, this, [this]() {
+                auto captcha = new ReCaptcha(QString::fromStdString(u.session), context, nullptr);
+                QQmlEngine::setObjectOwnership(captcha, QQmlEngine::JavaScriptOwnership);
+                connect(captcha, &ReCaptcha::confirmation, this, [h, u]() {
+                    h.next(mtx::user_interactive::Auth{u.session,
+                                                       mtx::user_interactive::auth::Fallback{}});
+                });
+                connect(captcha, &ReCaptcha::cancelled, this, [this]() {
                     emit error(tr("Registration aborted"));
                 });
-
-                QTimer::singleShot(0, this, [captchaDialog]() { captchaDialog->show(); });
-
+                emit reCaptcha(captcha);
             } else if (current_stage == mtx::user_interactive::auth_types::dummy) {
                 h.next(
                   mtx::user_interactive::Auth{u.session, mtx::user_interactive::auth::Dummy{}});
diff --git a/src/ui/UIA.h b/src/ui/UIA.h
index 414cb804..5b5eb9f4 100644
--- a/src/ui/UIA.h
+++ b/src/ui/UIA.h
@@ -9,6 +9,8 @@
 
 #include <mtxclient/http/client.hpp>
 
+#include "ReCaptcha.h"
+
 class UIA final : public QObject
 {
     Q_OBJECT
@@ -39,7 +41,7 @@ public:
         return instance();
     }
 
-    UIA(QObject *parent = nullptr)
+    UIA(QObject *parent)
       : QObject(parent)
     {
     }
@@ -59,6 +61,7 @@ signals:
     void password();
     void email();
     void phoneNumber();
+    void reCaptcha(ReCaptcha *recaptcha);
 
     void confirm3pidToken();
     void prompt3pidToken();