From 0634d3f09c6e427e0b5091ebd9ba770099057951 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Thu, 13 Jul 2023 12:53:51 -0400 Subject: [PATCH] QML the fallback auth dialog --- CMakeLists.txt | 9 ++- resources/qml/Root.qml | 12 ++++ resources/qml/dialogs/FallbackAuthDialog.qml | 63 ++++++++++++++++ src/FallbackAuth.cpp | 29 ++++++++ src/FallbackAuth.h | 32 +++++++++ src/dialogs/FallbackAuth.cpp | 75 -------------------- src/dialogs/FallbackAuth.h | 30 -------- src/ui/UIA.cpp | 21 ++---- src/ui/UIA.h | 2 + 9 files changed, 149 insertions(+), 124 deletions(-) create mode 100644 resources/qml/dialogs/FallbackAuthDialog.qml create mode 100644 src/FallbackAuth.cpp create mode 100644 src/FallbackAuth.h delete mode 100644 src/dialogs/FallbackAuth.cpp delete mode 100644 src/dialogs/FallbackAuth.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bc6806b..d05bd111 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -350,10 +350,6 @@ configure_file(cmake/nheko.h config/nheko.h) # Declare source and header files. # set(SRC_FILES - # Dialogs - src/dialogs/FallbackAuth.cpp - src/dialogs/FallbackAuth.h - # Emoji src/emoji/Provider.cpp src/emoji/Provider.h @@ -463,6 +459,8 @@ set(SRC_FILES src/Config.h src/EventAccessors.cpp src/EventAccessors.h + src/FallbackAuth.cpp + src/FallbackAuth.h src/ImagePackListModel.cpp src/ImagePackListModel.h src/InviteesModel.cpp @@ -764,8 +762,9 @@ set(QML_SOURCES resources/qml/dialogs/ConfirmJoinRoomDialog.qml resources/qml/dialogs/CreateDirect.qml resources/qml/dialogs/CreateRoom.qml + resources/qml/dialogs/FallbackAuthDialog.qml resources/qml/dialogs/HiddenEventsDialog.qml - resources/qml/dialogs/EventExpirationDialog.qml + resources/qml/dialogs/EventExpirationDialog.qml resources/qml/dialogs/ImageOverlay.qml resources/qml/dialogs/ImagePackEditorDialog.qml resources/qml/dialogs/ImagePackSettingsDialog.qml diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml index fb0c6036..1e8a6a27 100644 --- a/resources/qml/Root.qml +++ b/resources/qml/Root.qml @@ -385,6 +385,18 @@ Pane { console.error("Failed to create component: " + component.errorString()); } } + function onFallbackAuth(fallback) { + var component = Qt.createComponent("qrc:/resources/qml/dialogs/FallbackAuthDialog.qml"); + if (component.status == Component.Ready) { + var dialog = component.createObject(timelineRoot, { + "fallback": fallback + }); + dialog.show(); + destroyOnClose(dialog); + } else { + console.error("Failed to create component: " + component.errorString()); + } + } target: UIA } diff --git a/resources/qml/dialogs/FallbackAuthDialog.qml b/resources/qml/dialogs/FallbackAuthDialog.qml new file mode 100644 index 00000000..d9a7ac8f --- /dev/null +++ b/resources/qml/dialogs/FallbackAuthDialog.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: fallbackRoot + + required property FallbackAuth fallback + + function accept() { + fallback.confirm(); + fallbackRoot.close(); + } + + function reject() { + fallback.cancel(); + fallbackRoot.close(); + } + + color: palette.window + title: qsTr("Fallback authentication") + 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: fallbackRoot.reject() + } + + Label { + id: msg + + anchors.fill: parent + padding: 8 + text: qsTr("Open the fallback, follow the steps, and confirm after completing them.") + } + + footer: DialogButtonBox { + onAccepted: fallbackRoot.accept() + onRejected: fallbackRoot.reject() + + Button { + text: qsTr("Open Fallback in Browser") + onClicked: fallback.openFallbackAuth() + } + + Button { + text: qsTr("Cancel") + DialogButtonBox.buttonRole: DialogButtonBox.RejectRole + } + + Button { + text: qsTr("Confirm") + DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole + } + } + +} diff --git a/src/FallbackAuth.cpp b/src/FallbackAuth.cpp new file mode 100644 index 00000000..5b668310 --- /dev/null +++ b/src/FallbackAuth.cpp @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "FallbackAuth.h" + +#include +#include + +#include "MatrixClient.h" + +FallbackAuth::FallbackAuth(const QString &session, const QString &authType, QObject *parent) + : QObject{parent} + , m_session{session} + , m_authType{authType} +{ +} + +void +FallbackAuth::openFallbackAuth() +{ + const auto url = QString("https://%1:%2/_matrix/client/r0/auth/%4/" + "fallback/web?session=%3") + .arg(QString::fromStdString(http::client()->server())) + .arg(http::client()->port()) + .arg(m_session, m_authType); + + QDesktopServices::openUrl(url); +} diff --git a/src/FallbackAuth.h b/src/FallbackAuth.h new file mode 100644 index 00000000..c3b042ce --- /dev/null +++ b/src/FallbackAuth.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +class FallbackAuth : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("") + + Q_PROPERTY(QString authType MEMBER m_authType CONSTANT) + Q_PROPERTY(QString session MEMBER m_session CONSTANT) + +public: + FallbackAuth(const QString &session, const QString &authType, QObject *parent = nullptr); + + Q_INVOKABLE void openFallbackAuth(); + Q_INVOKABLE void confirm() { emit confirmation(); } + Q_INVOKABLE void cancel() { emit cancelled(); } + +signals: + void confirmation(); + void cancelled(); + +private: + const QString m_session; + const QString m_authType; +}; diff --git a/src/dialogs/FallbackAuth.cpp b/src/dialogs/FallbackAuth.cpp deleted file mode 100644 index 9d59fc97..00000000 --- a/src/dialogs/FallbackAuth.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include -#include -#include -#include -#include - -#include "dialogs/FallbackAuth.h" - -#include "Config.h" -#include "MatrixClient.h" - -using namespace dialogs; - -FallbackAuth::FallbackAuth(const QString &authType, 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->setSpacing(8); - buttonLayout->setContentsMargins(0, 0, 0, 0); - - openBtn_ = new QPushButton(tr("Open Fallback in Browser"), this); - cancelBtn_ = new QPushButton(tr("Cancel"), this); - confirmBtn_ = new QPushButton(tr("Confirm"), this); - confirmBtn_->setDefault(true); - - buttonLayout->addStretch(1); - buttonLayout->addWidget(openBtn_); - buttonLayout->addWidget(cancelBtn_); - buttonLayout->addWidget(confirmBtn_); - - QFont font; - font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO); - - auto label = new QLabel( - tr("Open the fallback, follow the steps, and confirm after completing them."), this); - label->setFont(font); - - layout->addWidget(label); - layout->addLayout(buttonLayout); - - connect(openBtn_, &QPushButton::clicked, [session, authType]() { - const auto url = QString("https://%1:%2/_matrix/client/r0/auth/%4/" - "fallback/web?session=%3") - .arg(QString::fromStdString(http::client()->server())) - .arg(http::client()->port()) - .arg(session, authType); - - QDesktopServices::openUrl(url); - }); - - connect(confirmBtn_, &QPushButton::clicked, this, [this]() { - emit confirmation(); - emit close(); - }); - connect(cancelBtn_, &QPushButton::clicked, this, [this]() { - emit cancel(); - emit close(); - }); -} diff --git a/src/dialogs/FallbackAuth.h b/src/dialogs/FallbackAuth.h deleted file mode 100644 index 62092b08..00000000 --- a/src/dialogs/FallbackAuth.h +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include - -class QPushButton; -class QLabel; - -namespace dialogs { - -class FallbackAuth final : public QWidget -{ - Q_OBJECT - -public: - FallbackAuth(const QString &authType, const QString &session, QWidget *parent = nullptr); - -signals: - void confirmation(); - void cancel(); - -private: - QPushButton *openBtn_; - QPushButton *confirmBtn_; - QPushButton *cancelBtn_; -}; -} // dialogs diff --git a/src/ui/UIA.cpp b/src/ui/UIA.cpp index 9654c9aa..4c1d35b9 100644 --- a/src/ui/UIA.cpp +++ b/src/ui/UIA.cpp @@ -13,8 +13,6 @@ #include "Logging.h" #include "MatrixClient.h" -#include "ReCaptcha.h" -#include "dialogs/FallbackAuth.h" UIA * UIA::instance() @@ -132,23 +130,18 @@ UIA::genericHandler(QString context) } } else { // use fallback - auto dialog = new dialogs::FallbackAuth(QString::fromStdString(current_stage), - QString::fromStdString(u.session), - nullptr); - dialog->setWindowTitle(context); - - connect(dialog, &dialogs::FallbackAuth::confirmation, this, [h, u, dialog]() { - dialog->close(); - dialog->deleteLater(); + auto fallback = new FallbackAuth(QString::fromStdString(u.session), + QString::fromStdString(current_stage), + nullptr); + QQmlEngine::setObjectOwnership(fallback, QQmlEngine::JavaScriptOwnership); + connect(fallback, &FallbackAuth::confirmation, this, [h, u]() { h.next(mtx::user_interactive::Auth{u.session, mtx::user_interactive::auth::Fallback{}}); }); - - connect(dialog, &dialogs::FallbackAuth::cancel, this, [this]() { + connect(fallback, &FallbackAuth::cancelled, this, [this]() { emit error(tr("Registration aborted")); }); - - dialog->show(); + emit fallbackAuth(fallback); } }); }); diff --git a/src/ui/UIA.h b/src/ui/UIA.h index 5b5eb9f4..2bff6948 100644 --- a/src/ui/UIA.h +++ b/src/ui/UIA.h @@ -9,6 +9,7 @@ #include +#include "FallbackAuth.h" #include "ReCaptcha.h" class UIA final : public QObject @@ -62,6 +63,7 @@ signals: void email(); void phoneNumber(); void reCaptcha(ReCaptcha *recaptcha); + void fallbackAuth(FallbackAuth *fallback); void confirm3pidToken(); void prompt3pidToken();