From 37679ac57ec79d112a76bd8afb0dfea7e433da80 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Tue, 9 Feb 2021 23:11:39 +0530 Subject: [PATCH 01/14] added room settings qml --- resources/qml/RoomSettings.qml | 157 +++++++++++++++++++++++++++ resources/qml/TimelineView.qml | 16 +++ resources/res.qrc | 1 + src/timeline/TimelineViewManager.cpp | 3 +- src/timeline/TimelineViewManager.h | 4 +- 5 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 resources/qml/RoomSettings.qml diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml new file mode 100644 index 00000000..106c9119 --- /dev/null +++ b/resources/qml/RoomSettings.qml @@ -0,0 +1,157 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.2 +import QtQuick.Window 2.3 +import im.nheko 1.0 + +ApplicationWindow { + id: roomSettingsDialog + + property var roomSettings + + x: MainWindow.x + (MainWindow.width / 2) - (width / 2) + y: MainWindow.y + (MainWindow.height / 2) - (height / 2) + height: 600 + width: 420 + minimumHeight: 420 + palette: colors + color: colors.window + title: "Room Settings" + modality: Qt.Modal + + Shortcut { + sequence: StandardKey.Cancel + onActivated: roomSettingsDialog.close() + } + + ColumnLayout { + id: contentLayout + + anchors.fill: parent + anchors.margins: 10 + spacing: 10 + + Avatar { + url: "" + height: 130 + width: 130 + displayName: "" + userid: "" + Layout.alignment: Qt.AlignHCenter + } + + ColumnLayout { + Layout.alignment: Qt.AlignHCenter + + MatrixText { + text: "room name" + font.pixelSize: 24 + Layout.alignment: Qt.AlignHCenter + } + + MatrixText { + text: "1 member" + Layout.alignment: Qt.AlignHCenter + } + } + + ImageButton { + Layout.alignment: Qt.AlignHCenter + image: ":/icons/icons/ui/edit.png" + } + + MatrixText { + text: "SETTINGS" + } + + RowLayout { + MatrixText { + text: "Notifications" + } + + Item { + Layout.fillWidth: true + } + + ComboBox { + model: [ "Muted", "Mentions only", "All messages" ] + } + } + + RowLayout { + MatrixText { + text: "Room access" + } + + ComboBox { + Layout.fillWidth: true + model: [ "Anyone and guests", "Anyone", "Invited users" ] + } + } + + RowLayout { + MatrixText { + text: "Encryption" + } + + Item { + Layout.fillWidth: true + } + + Switch { + } + } + + RowLayout { + MatrixText { + text: "Respond to key requests" + } + + Item { + Layout.fillWidth: true + } + + Switch { + } + } + + MatrixText { + text: "INFO" + } + + RowLayout { + MatrixText { + text: "Internal ID" + } + + Item { + Layout.fillWidth: true + } + + MatrixText { + text: "asdajdhasjkdhaskjdhasjdks" + font.pixelSize: 12 + } + } + + RowLayout { + MatrixText { + text: "Room Version" + } + + Item { + Layout.fillWidth: true + } + + MatrixText { + text: "6" + font.pixelSize: 12 + } + } + + Button { + Layout.alignment: Qt.AlignRight + text: "Ok" + } + } +} \ No newline at end of file diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index c03e8d31..c6c1e2b2 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -52,6 +52,14 @@ Page { } + Component { + id: roomSettingsComponent + + RoomSettings { + } + + } + Component { id: mobileCallInviteDialog @@ -166,6 +174,14 @@ Page { } } + Connections { + target: TimelineManager + onOpenRoomSettingsDialog: { + var roomSettings = roomSettingsComponent.createObject(timelineRoot); + roomSettings.show(); + } + } + Connections { target: CallManager onNewInviteState: { diff --git a/resources/res.qrc b/resources/res.qrc index 308d81a6..24b41179 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -139,6 +139,7 @@ qml/TimelineRow.qml qml/TopBar.qml qml/TypingIndicator.qml + qml/RoomSettings.qml qml/emoji/EmojiButton.qml qml/emoji/EmojiPicker.qml qml/UserProfile.qml diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 93451976..d7d06386 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -390,9 +390,10 @@ TimelineViewManager::openLeaveRoomDialog() const MainWindow::instance()->openLeaveRoomDialog(timeline_->roomId()); } void -TimelineViewManager::openRoomSettings() const +TimelineViewManager::openRoomSettings() { MainWindow::instance()->openRoomSettings(timeline_->roomId()); + emit openRoomSettingsDialog(); } void diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 74128865..841e0bcb 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -18,6 +18,7 @@ #include "WebRTCSession.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" +#include "dialogs/RoomSettings.h" class MxcImageProvider; class BlurhashProvider; @@ -69,7 +70,7 @@ public: Q_INVOKABLE void openInviteUsersDialog(); Q_INVOKABLE void openMemberListDialog() const; Q_INVOKABLE void openLeaveRoomDialog() const; - Q_INVOKABLE void openRoomSettings() const; + Q_INVOKABLE void openRoomSettings(); Q_INVOKABLE void removeVerificationFlow(DeviceVerificationFlow *flow); void verifyUser(QString userid); @@ -87,6 +88,7 @@ signals: void showRoomList(); void narrowViewChanged(); void focusChanged(); + void openRoomSettingsDialog(); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); From b70f37194fd968950c920b1c39388154aa46cdc1 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Wed, 10 Feb 2021 21:22:42 +0530 Subject: [PATCH 02/14] ui almost looks the same, midway between transition from old room settings to new room settings --- CMakeLists.txt | 6 ++- resources/qml/RoomSettings.qml | 2 +- resources/qml/TimelineView.qml | 4 +- resources/qml/ToggleButton.qml | 10 ++++ src/MainWindow.cpp | 4 +- src/MainWindow.h | 2 +- .../{RoomSettings.cpp => RoomSettingsOld.cpp} | 50 +++++++++---------- .../{RoomSettings.h => RoomSettingsOld.h} | 4 +- src/timeline/TimelineViewManager.cpp | 4 +- src/timeline/TimelineViewManager.h | 5 +- src/ui/RoomSettings.cpp | 33 ++++++++++++ src/ui/RoomSettings.h | 25 ++++++++++ 12 files changed, 112 insertions(+), 37 deletions(-) create mode 100644 resources/qml/ToggleButton.qml rename src/dialogs/{RoomSettings.cpp => RoomSettingsOld.cpp} (96%) rename src/dialogs/{RoomSettings.h => RoomSettingsOld.h} (97%) create mode 100644 src/ui/RoomSettings.cpp create mode 100644 src/ui/RoomSettings.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c9e29998..505a59f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,7 +257,7 @@ set(SRC_FILES src/dialogs/PreviewUploadOverlay.cpp src/dialogs/ReCaptcha.cpp src/dialogs/ReadReceipts.cpp - src/dialogs/RoomSettings.cpp + src/dialogs/RoomSettingsOld.cpp # Emoji src/emoji/EmojiModel.cpp @@ -294,6 +294,7 @@ set(SRC_FILES src/ui/ThemeManager.cpp src/ui/ToggleButton.cpp src/ui/UserProfile.cpp + src/ui/RoomSettings.cpp src/AvatarProvider.cpp src/BlurhashProvider.cpp @@ -471,7 +472,7 @@ qt5_wrap_cpp(MOC_HEADERS src/dialogs/RawMessage.h src/dialogs/ReCaptcha.h src/dialogs/ReadReceipts.h - src/dialogs/RoomSettings.h + src/dialogs/RoomSettingsOld.h # Emoji src/emoji/EmojiModel.h @@ -506,6 +507,7 @@ qt5_wrap_cpp(MOC_HEADERS src/ui/Theme.h src/ui/ThemeManager.h src/ui/UserProfile.h + src/ui/RoomSettings.h src/notifications/Manager.h diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index 106c9119..d6f3fe7b 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -16,7 +16,7 @@ ApplicationWindow { minimumHeight: 420 palette: colors color: colors.window - title: "Room Settings" + title: roomSettings.roomName modality: Qt.Modal Shortcut { diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index c6c1e2b2..6b34f2ab 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -177,7 +177,9 @@ Page { Connections { target: TimelineManager onOpenRoomSettingsDialog: { - var roomSettings = roomSettingsComponent.createObject(timelineRoot); + var roomSettings = roomSettingsComponent.createObject(timelineRoot, { + "roomSettings": roomSettings + }); roomSettings.show(); } } diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml new file mode 100644 index 00000000..584fc693 --- /dev/null +++ b/resources/qml/ToggleButton.qml @@ -0,0 +1,10 @@ +import QtQuick 2.5 +import QtQuick.Controls 2.3 +import im.nheko 1.0 + +Switch { + property color activeColor + property color disabledColor + property color inactiveColor + property color trackColor +} \ No newline at end of file diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index ab3c2cf2..b1635c94 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -51,7 +51,7 @@ #include "dialogs/Logout.h" #include "dialogs/MemberList.h" #include "dialogs/ReadReceipts.h" -#include "dialogs/RoomSettings.h" +#include "dialogs/RoomSettingsOld.h" MainWindow *MainWindow::instance_ = nullptr; @@ -366,7 +366,7 @@ MainWindow::hasActiveUser() void MainWindow::openRoomSettings(const QString &room_id) { - auto dialog = new dialogs::RoomSettings(room_id, this); + auto dialog = new dialogs::RoomSettingsOld(room_id, this); showDialog(dialog); } diff --git a/src/MainWindow.h b/src/MainWindow.h index bb219813..b3983d72 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -54,7 +54,7 @@ class LeaveRoom; class Logout; class MemberList; class ReCaptcha; -class RoomSettings; +class RoomSettingsOld; } class MainWindow : public QMainWindow diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettingsOld.cpp similarity index 96% rename from src/dialogs/RoomSettings.cpp rename to src/dialogs/RoomSettingsOld.cpp index bd3cc26f..7eb34c20 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettingsOld.cpp @@ -1,4 +1,4 @@ -#include "dialogs/RoomSettings.h" +#include "dialogs/RoomSettingsOld.h" #include #include #include @@ -195,7 +195,7 @@ EditModal::setFields(const QString &roomName, const QString &roomTopic) topicInput_->setText(roomTopic); } -RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) +RoomSettingsOld::RoomSettingsOld(const QString &room_id, QWidget *parent) : QFrame(parent) , room_id_{std::move(room_id)} { @@ -253,7 +253,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) notifCombo->addItem(tr("Mentions only")); // {"actions":["dont_notify"]} notifCombo->addItem(tr("All messages")); // delete rule - connect(this, &RoomSettings::notifChanged, notifCombo, &QComboBox::setCurrentIndex); + connect(this, &RoomSettingsOld::notifChanged, notifCombo, &QComboBox::setCurrentIndex); http::client()->get_pushrules( "global", "override", @@ -487,7 +487,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) auto filter = new ClickableFilter(this); avatar_->installEventFilter(filter); avatar_->setCursor(Qt::PointingHandCursor); - connect(filter, &ClickableFilter::clicked, this, &RoomSettings::updateAvatar); + connect(filter, &ClickableFilter::clicked, this, &RoomSettingsOld::updateAvatar); } roomNameLabel_ = new QLabel(QString::fromStdString(info_.name), this); @@ -542,7 +542,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) layout->addLayout(spinnerLayout); layout->addStretch(1); - connect(this, &RoomSettings::enableEncryptionError, this, [this](const QString &msg) { + connect(this, &RoomSettingsOld::enableEncryptionError, this, [this](const QString &msg) { encryptionToggle_->setState(false); keyRequestsToggle_->setState(false); keyRequestsToggle_->setEnabled(false); @@ -551,7 +551,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) emit ChatPage::instance()->showNotification(msg); }); - connect(this, &RoomSettings::showErrorMessage, this, [this](const QString &msg) { + connect(this, &RoomSettingsOld::showErrorMessage, this, [this](const QString &msg) { if (!errorLabel_) return; @@ -561,18 +561,18 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) errorLabel_->setText(msg); }); - connect(this, &RoomSettings::accessRulesUpdated, this, [this]() { + connect(this, &RoomSettingsOld::accessRulesUpdated, this, [this]() { stopLoadingSpinner(); resetErrorLabel(); }); auto closeShortcut = new QShortcut(QKeySequence(QKeySequence::Cancel), this); - connect(closeShortcut, &QShortcut::activated, this, &RoomSettings::close); - connect(okBtn, &QPushButton::clicked, this, &RoomSettings::close); + connect(closeShortcut, &QShortcut::activated, this, &RoomSettingsOld::close); + connect(okBtn, &QPushButton::clicked, this, &RoomSettingsOld::close); } void -RoomSettings::setupEditButton() +RoomSettingsOld::setupEditButton() { btnLayout_ = new QHBoxLayout; btnLayout_->setSpacing(BUTTON_SPACING); @@ -610,7 +610,7 @@ RoomSettings::setupEditButton() } void -RoomSettings::retrieveRoomInfo() +RoomSettingsOld::retrieveRoomInfo() { try { usesEncryption_ = cache::isRoomEncrypted(room_id_.toStdString()); @@ -623,7 +623,7 @@ RoomSettings::retrieveRoomInfo() } void -RoomSettings::enableEncryption() +RoomSettingsOld::enableEncryption() { const auto room_id = room_id_.toStdString(); http::client()->enable_encryption( @@ -645,7 +645,7 @@ RoomSettings::enableEncryption() } void -RoomSettings::showEvent(QShowEvent *event) +RoomSettingsOld::showEvent(QShowEvent *event) { resetErrorLabel(); stopLoadingSpinner(); @@ -654,7 +654,7 @@ RoomSettings::showEvent(QShowEvent *event) } bool -RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const +RoomSettingsOld::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const { try { return cache::hasEnoughPowerLevel({EventType::RoomJoinRules}, room_id, user_id); @@ -666,7 +666,7 @@ RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string & } bool -RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const +RoomSettingsOld::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const { try { return cache::hasEnoughPowerLevel( @@ -679,7 +679,7 @@ RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::strin } bool -RoomSettings::canChangeAvatar(const std::string &room_id, const std::string &user_id) const +RoomSettingsOld::canChangeAvatar(const std::string &room_id, const std::string &user_id) const { try { return cache::hasEnoughPowerLevel({EventType::RoomAvatar}, room_id, user_id); @@ -691,7 +691,7 @@ RoomSettings::canChangeAvatar(const std::string &room_id, const std::string &use } void -RoomSettings::updateAccessRules(const std::string &room_id, +RoomSettingsOld::updateAccessRules(const std::string &room_id, const mtx::events::state::JoinRules &join_rule, const mtx::events::state::GuestAccess &guest_access) { @@ -732,7 +732,7 @@ RoomSettings::updateAccessRules(const std::string &room_id, } void -RoomSettings::stopLoadingSpinner() +RoomSettingsOld::stopLoadingSpinner() { if (spinner_) { spinner_->stop(); @@ -741,7 +741,7 @@ RoomSettings::stopLoadingSpinner() } void -RoomSettings::startLoadingSpinner() +RoomSettingsOld::startLoadingSpinner() { if (spinner_) { spinner_->start(); @@ -750,7 +750,7 @@ RoomSettings::startLoadingSpinner() } void -RoomSettings::displayErrorMessage(const QString &msg) +RoomSettingsOld::displayErrorMessage(const QString &msg) { stopLoadingSpinner(); @@ -759,7 +759,7 @@ RoomSettings::displayErrorMessage(const QString &msg) } void -RoomSettings::setAvatar() +RoomSettingsOld::setAvatar() { stopLoadingSpinner(); @@ -768,7 +768,7 @@ RoomSettings::setAvatar() } void -RoomSettings::resetErrorLabel() +RoomSettingsOld::resetErrorLabel() { if (errorLabel_) { errorLabel_->hide(); @@ -777,7 +777,7 @@ RoomSettings::resetErrorLabel() } void -RoomSettings::updateAvatar() +RoomSettingsOld::updateAvatar() { const QString picturesFolder = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); @@ -811,8 +811,8 @@ RoomSettings::updateAvatar() // Events emitted from the http callbacks (different threads) will // be queued back into the UI thread through this proxy object. auto proxy = std::make_shared(); - connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayErrorMessage); - connect(proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettings::setAvatar); + connect(proxy.get(), &ThreadProxy::error, this, &RoomSettingsOld::displayErrorMessage); + connect(proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettingsOld::setAvatar); const auto bin = file.peek(file.size()); const auto payload = std::string(bin.data(), bin.size()); diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettingsOld.h similarity index 97% rename from src/dialogs/RoomSettings.h rename to src/dialogs/RoomSettingsOld.h index e0918afd..e517676a 100644 --- a/src/dialogs/RoomSettings.h +++ b/src/dialogs/RoomSettingsOld.h @@ -86,11 +86,11 @@ private: namespace dialogs { -class RoomSettings : public QFrame +class RoomSettingsOld : public QFrame { Q_OBJECT public: - RoomSettings(const QString &room_id, QWidget *parent = nullptr); + RoomSettingsOld(const QString &room_id, QWidget *parent = nullptr); signals: void enableEncryptionError(const QString &msg); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index d7d06386..7c1922d7 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -393,7 +393,9 @@ void TimelineViewManager::openRoomSettings() { MainWindow::instance()->openRoomSettings(timeline_->roomId()); - emit openRoomSettingsDialog(); + + RoomSettings *roomSettings = new RoomSettings(timeline_->roomId(), this); + emit openRoomSettingsDialog(roomSettings); } void diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 841e0bcb..dca133ce 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -18,7 +18,8 @@ #include "WebRTCSession.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" -#include "dialogs/RoomSettings.h" +#include "dialogs/RoomSettingsOld.h" +#include "ui/RoomSettings.h" class MxcImageProvider; class BlurhashProvider; @@ -88,7 +89,7 @@ signals: void showRoomList(); void narrowViewChanged(); void focusChanged(); - void openRoomSettingsDialog(); + void openRoomSettingsDialog(RoomSettings *roomSettings); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp new file mode 100644 index 00000000..e8317024 --- /dev/null +++ b/src/ui/RoomSettings.cpp @@ -0,0 +1,33 @@ +#include "RoomSettings.h" + +#include +#include + +#include "Cache.h" +#include "Logging.h" + +RoomSettings::RoomSettings(QString roomid, QObject *parent) + : roomid_{std::move(roomid)} + , QObject(parent) +{ + retrieveRoomInfo(); +} + +QString +RoomSettings::roomName() const +{ + return QString(info_.name.c_str()); +} + +void +RoomSettings::retrieveRoomInfo() +{ + try { + usesEncryption_ = cache::isRoomEncrypted(roomid_.toStdString()); + info_ = cache::singleRoomInfo(roomid_.toStdString()); + //setAvatar(); + } catch (const lmdb::error &) { + nhlog::db()->warn("failed to retrieve room info from cache: {}", + roomid_.toStdString()); + } +} \ No newline at end of file diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h new file mode 100644 index 00000000..98e64b74 --- /dev/null +++ b/src/ui/RoomSettings.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "CacheStructs.h" + +class RoomSettings : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString roomName READ roomName CONSTANT) + +public: + RoomSettings(QString roomid, QObject *parent = nullptr); + + QString roomName() const; + +private: + void retrieveRoomInfo(); + +private: + QString roomid_; + bool usesEncryption_ = false; + RoomInfo info_; +}; \ No newline at end of file From 7401bd13b272bbe9a0415c2e523f8ec0fa7f3e11 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Thu, 11 Feb 2021 19:54:09 +0530 Subject: [PATCH 03/14] added notifications and encryption for the new roomsettings --- resources/qml/RoomSettings.qml | 58 +++++- resources/qml/TimelineView.qml | 2 +- src/timeline/TimelineViewManager.cpp | 10 +- src/timeline/TimelineViewManager.h | 2 +- src/ui/RoomSettings.cpp | 257 ++++++++++++++++++++++++++- src/ui/RoomSettings.h | 29 +++ 6 files changed, 352 insertions(+), 6 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index d6f3fe7b..4b03e08b 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -2,6 +2,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.3 +import QtQuick.Dialogs 1.2 import im.nheko 1.0 ApplicationWindow { @@ -17,7 +18,8 @@ ApplicationWindow { palette: colors color: colors.window title: roomSettings.roomName - modality: Qt.Modal + modality: Qt.WindowModal + flags: Qt.WindowStaysOnTopHint Shortcut { sequence: StandardKey.Cancel @@ -75,6 +77,10 @@ ApplicationWindow { ComboBox { model: [ "Muted", "Mentions only", "All messages" ] + currentIndex: roomSettings.notifications + onActivated: { + roomSettings.changeNotifications(index) + } } } @@ -85,7 +91,12 @@ ApplicationWindow { ComboBox { Layout.fillWidth: true + enabled: roomSettings.canChangeJoinRules model: [ "Anyone and guests", "Anyone", "Invited users" ] + currentIndex: roomSettings.accessJoinRules + onActivated: { + roomSettings.changeAccessRules(index) + } } } @@ -99,10 +110,46 @@ ApplicationWindow { } Switch { + id: encryptionSwitch + + checked: roomSettings.isEncryptionEnabled + onToggled: { + if(roomSettings.isEncryptionEnabled) { + checked=true; + return; + } + + confirmEncryptionDialog.open(); + } + } + + MessageDialog { + id: confirmEncryptionDialog + title: qsTr("End-to-End Encryption") + text: qsTr("Encryption is currently experimental and things might break unexpectedly.
+ Please take note that it can't be disabled afterwards.") + modality: Qt.WindowModal + icon: StandardIcon.Question + + onAccepted: { + if(roomSettings.isEncryptionEnabled) { + return; + } + + roomSettings.enableEncryption(); + } + + onRejected: { + encryptionSwitch.checked = false + } + + standardButtons: Dialog.Ok | Dialog.Cancel } } RowLayout { + visible: roomSettings.isEncryptionEnabled + MatrixText { text: "Respond to key requests" } @@ -112,6 +159,15 @@ ApplicationWindow { } Switch { + ToolTip.text: qsTr("Whether or not the client should respond automatically with the session keys + upon request. Use with caution, this is a temporary measure to test the + E2E implementation until device verification is completed.") + + checked: roomSettings.respondsToKeyRequests + + onToggled: { + roomSettings.changeKeyRequestsPreference(checked) + } } } diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 6b34f2ab..0c32effd 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -178,7 +178,7 @@ Page { target: TimelineManager onOpenRoomSettingsDialog: { var roomSettings = roomSettingsComponent.createObject(timelineRoot, { - "roomSettings": roomSettings + "roomSettings": settings }); roomSettings.show(); } diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 7c1922d7..4edc3369 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -126,6 +126,12 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par 0, "UserProfileModel", "UserProfile needs to be instantiated on the C++ side"); + qmlRegisterUncreatableType( + "im.nheko", + 1, + 0, + "RoomSettingsModel", + "Room Settings needs to be instantiated on the C++ side"); static auto self = this; qmlRegisterSingletonType( @@ -394,8 +400,8 @@ TimelineViewManager::openRoomSettings() { MainWindow::instance()->openRoomSettings(timeline_->roomId()); - RoomSettings *roomSettings = new RoomSettings(timeline_->roomId(), this); - emit openRoomSettingsDialog(roomSettings); + RoomSettings *settings = new RoomSettings(timeline_->roomId(), this); + emit openRoomSettingsDialog(settings); } void diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index dca133ce..10708033 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -89,7 +89,7 @@ signals: void showRoomList(); void narrowViewChanged(); void focusChanged(); - void openRoomSettingsDialog(RoomSettings *roomSettings); + void openRoomSettingsDialog(RoomSettings *settings); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index e8317024..785452d0 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -5,12 +5,65 @@ #include "Cache.h" #include "Logging.h" +#include "MatrixClient.h" +#include "Utils.h" + +using namespace mtx::events; RoomSettings::RoomSettings(QString roomid, QObject *parent) : roomid_{std::move(roomid)} , QObject(parent) { retrieveRoomInfo(); + + // get room setting notifications + http::client()->get_pushrules( + "global", + "override", + roomid_.toStdString(), + [this](const mtx::pushrules::PushRule &rule, mtx::http::RequestErr &err) { + if (err) { + if (err->status_code == boost::beast::http::status::not_found) + http::client()->get_pushrules( + "global", + "room", + roomid_.toStdString(), + [this](const mtx::pushrules::PushRule &rule, + mtx::http::RequestErr &err) { + if (err) { + notifications_ = 2; // all messages + emit notificationsChanged(); + return; + } + + if (rule.enabled) { + notifications_ = 1; // mentions only + emit notificationsChanged(); + } + }); + return; + } + + if (rule.enabled) { + notifications_ = 0; // muted + emit notificationsChanged(); + } else { + notifications_ = 2; // all messages + emit notificationsChanged(); + } + }); + + // access rules + if (info_.join_rule == state::JoinRule::Public) { + if (info_.guest_access) { + accessRules_ = 0; + } else { + accessRules_ = 1; + } + } else { + accessRules_ = 2; + } + emit accessJoinRulesChanged(); } QString @@ -25,9 +78,211 @@ RoomSettings::retrieveRoomInfo() try { usesEncryption_ = cache::isRoomEncrypted(roomid_.toStdString()); info_ = cache::singleRoomInfo(roomid_.toStdString()); - //setAvatar(); + // setAvatar(); } catch (const lmdb::error &) { nhlog::db()->warn("failed to retrieve room info from cache: {}", roomid_.toStdString()); } +} + +int +RoomSettings::notifications() +{ + return notifications_; +} + +int +RoomSettings::accessJoinRules() +{ + return accessRules_; +} + +bool +RoomSettings::respondsToKeyRequests() +{ + return usesEncryption_ && utils::respondsToKeyRequests(roomid_); +} + +void +RoomSettings::changeKeyRequestsPreference(bool isOn) +{ + utils::setKeyRequestsPreference(roomid_, isOn); + emit keyRequestsChanged(); +} + +void +RoomSettings::enableEncryption() +{ + if (usesEncryption_) + return; + + const auto room_id = roomid_.toStdString(); + http::client()->enable_encryption( + room_id, [room_id, this](const mtx::responses::EventId &, mtx::http::RequestErr err) { + if (err) { + int status_code = static_cast(err->status_code); + nhlog::net()->warn("failed to enable encryption in room ({}): {} {}", + room_id, + err->matrix_error.error, + status_code); + //emit enableEncryptionError( + // tr("Failed to enable encryption: %1") + // .arg(QString::fromStdString(err->matrix_error.error))); + usesEncryption_ = false; + emit encryptionChanged(); + return; + } + + nhlog::net()->info("enabled encryption on room ({})", room_id); + }); + + usesEncryption_ = true; + emit encryptionChanged(); +} + +bool +RoomSettings::canChangeJoinRules() const +{ + try { + return cache::hasEnoughPowerLevel({EventType::RoomJoinRules}, + roomid_.toStdString(), + utils::localUser().toStdString()); + } catch (const lmdb::error &e) { + nhlog::db()->warn("lmdb error: {}", e.what()); + } + + return false; +} + +bool +RoomSettings::isEncryptionEnabled() const +{ + return usesEncryption_; +} + +void +RoomSettings::changeNotifications(int currentIndex) +{ + notifications_ = currentIndex; + + std::string room_id = roomid_.toStdString(); + if (notifications_ == 0) { + // mute room + // delete old rule first, then add new rule + mtx::pushrules::PushRule rule; + rule.actions = {mtx::pushrules::actions::dont_notify{}}; + mtx::pushrules::PushCondition condition; + condition.kind = "event_match"; + condition.key = "room_id"; + condition.pattern = room_id; + rule.conditions = {condition}; + + http::client()->put_pushrules( + "global", "override", room_id, rule, [room_id](mtx::http::RequestErr &err) { + if (err) + nhlog::net()->error("failed to set pushrule for room {}: {} {}", + room_id, + static_cast(err->status_code), + err->matrix_error.error); + http::client()->delete_pushrules( + "global", "room", room_id, [room_id](mtx::http::RequestErr &) {}); + }); + } else if (notifications_ == 1) { + // mentions only + // delete old rule first, then add new rule + mtx::pushrules::PushRule rule; + rule.actions = {mtx::pushrules::actions::dont_notify{}}; + http::client()->put_pushrules( + "global", "room", room_id, rule, [room_id](mtx::http::RequestErr &err) { + if (err) + nhlog::net()->error("failed to set pushrule for room {}: {} {}", + room_id, + static_cast(err->status_code), + err->matrix_error.error); + http::client()->delete_pushrules( + "global", "override", room_id, [room_id](mtx::http::RequestErr &) {}); + }); + } else { + // all messages + http::client()->delete_pushrules( + "global", "override", room_id, [room_id](mtx::http::RequestErr &) { + http::client()->delete_pushrules( + "global", "room", room_id, [room_id](mtx::http::RequestErr &) {}); + }); + } +} + +void +RoomSettings::changeAccessRules(int index) +{ + using namespace mtx::events::state; + + auto guest_access = [](int index) -> state::GuestAccess { + state::GuestAccess event; + + if (index == 0) + event.guest_access = state::AccessState::CanJoin; + else + event.guest_access = state::AccessState::Forbidden; + + return event; + }(index); + + auto join_rule = [](int index) -> state::JoinRules { + state::JoinRules event; + + switch (index) { + case 0: + case 1: + event.join_rule = state::JoinRule::Public; + break; + default: + event.join_rule = state::JoinRule::Invite; + } + + return event; + }(index); + + updateAccessRules(roomid_.toStdString(), join_rule, guest_access); +} + +void +RoomSettings::updateAccessRules(const std::string &room_id, + const mtx::events::state::JoinRules &join_rule, + const mtx::events::state::GuestAccess &guest_access) +{ + // startLoadingSpinner(); + // resetErrorLabel(); + + http::client()->send_state_event( + room_id, + join_rule, + [this, room_id, guest_access](const mtx::responses::EventId &, + mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn("failed to send m.room.join_rule: {} {}", + static_cast(err->status_code), + err->matrix_error.error); + // emit showErrorMessage(QString::fromStdString(err->matrix_error.error)); + + return; + } + + http::client()->send_state_event( + room_id, + guest_access, + [this](const mtx::responses::EventId &, mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn("failed to send m.room.guest_access: {} {}", + static_cast(err->status_code), + err->matrix_error.error); + // emit showErrorMessage( + // QString::fromStdString(err->matrix_error.error)); + + return; + } + + // emit signal that stops loading spinner and reset error label + }); + }); } \ No newline at end of file diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 98e64b74..098e27ba 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -3,23 +3,52 @@ #include #include +#include + #include "CacheStructs.h" class RoomSettings : public QObject { Q_OBJECT Q_PROPERTY(QString roomName READ roomName CONSTANT) + Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged) + Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged) + Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT) + Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged) + Q_PROPERTY(bool respondsToKeyRequests READ respondsToKeyRequests NOTIFY keyRequestsChanged) public: RoomSettings(QString roomid, QObject *parent = nullptr); QString roomName() const; + int notifications(); + int accessJoinRules(); + bool respondsToKeyRequests(); + //! Whether the user has enough power level to send m.room.join_rules events. + bool canChangeJoinRules() const; + bool isEncryptionEnabled() const; + + Q_INVOKABLE void changeNotifications(int currentIndex); + Q_INVOKABLE void changeAccessRules(int index); + Q_INVOKABLE void changeKeyRequestsPreference(bool isOn); + Q_INVOKABLE void enableEncryption(); + +signals: + void notificationsChanged(); + void accessJoinRulesChanged(); + void keyRequestsChanged(); + void encryptionChanged(); private: void retrieveRoomInfo(); + void updateAccessRules(const std::string &room_id, + const mtx::events::state::JoinRules &, + const mtx::events::state::GuestAccess &); private: QString roomid_; bool usesEncryption_ = false; RoomInfo info_; + int notifications_ = 0; + int accessRules_ = 0; }; \ No newline at end of file From 473b14ed0f8053348000db370451cfff3ce3ac13 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Thu, 11 Feb 2021 21:23:33 +0530 Subject: [PATCH 04/14] added roomversion, roomid etc --- resources/qml/RoomSettings.qml | 9 ++++----- src/ui/RoomSettings.cpp | 18 ++++++++++++++++++ src/ui/RoomSettings.h | 6 ++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index 4b03e08b..ee824ba0 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -17,7 +17,6 @@ ApplicationWindow { minimumHeight: 420 palette: colors color: colors.window - title: roomSettings.roomName modality: Qt.WindowModal flags: Qt.WindowStaysOnTopHint @@ -46,13 +45,13 @@ ApplicationWindow { Layout.alignment: Qt.AlignHCenter MatrixText { - text: "room name" + text: roomSettings.roomName font.pixelSize: 24 Layout.alignment: Qt.AlignHCenter } MatrixText { - text: "1 member" + text: "%1 member(s)".arg(roomSettings.memberCount) Layout.alignment: Qt.AlignHCenter } } @@ -185,7 +184,7 @@ ApplicationWindow { } MatrixText { - text: "asdajdhasjkdhaskjdhasjdks" + text: roomSettings.roomId font.pixelSize: 12 } } @@ -200,7 +199,7 @@ ApplicationWindow { } MatrixText { - text: "6" + text: roomSettings.roomVersion font.pixelSize: 12 } } diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 785452d0..49e48e40 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -72,6 +72,24 @@ RoomSettings::roomName() const return QString(info_.name.c_str()); } +QString +RoomSettings::roomId() const +{ + return roomid_; +} + +QString +RoomSettings::roomVersion() const +{ + return QString::fromStdString(info_.version); +} + +int +RoomSettings::memberCount() const +{ + return info_.member_count; +} + void RoomSettings::retrieveRoomInfo() { diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 098e27ba..f5cc043c 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -11,6 +11,9 @@ class RoomSettings : public QObject { Q_OBJECT Q_PROPERTY(QString roomName READ roomName CONSTANT) + Q_PROPERTY(QString roomId READ roomId CONSTANT) + Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT) + Q_PROPERTY(int memberCount READ memberCount CONSTANT) Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged) Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged) Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT) @@ -21,6 +24,9 @@ public: RoomSettings(QString roomid, QObject *parent = nullptr); QString roomName() const; + QString roomId() const; + QString roomVersion() const; + int memberCount() const; int notifications(); int accessJoinRules(); bool respondsToKeyRequests(); From a7d7d18e92ec30977009e0947179dbc58ccb9e26 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Thu, 11 Feb 2021 23:39:11 +0530 Subject: [PATCH 05/14] shifted room avatar changing --- resources/qml/RoomSettings.qml | 47 ++++++++- src/dialogs/RoomSettingsOld.cpp | 14 +-- src/dialogs/RoomSettingsOld.h | 2 +- src/ui/RoomSettings.cpp | 167 +++++++++++++++++++++++++++++--- src/ui/RoomSettings.h | 35 ++++++- 5 files changed, 242 insertions(+), 23 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index ee824ba0..5d2baba1 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -33,12 +33,53 @@ ApplicationWindow { spacing: 10 Avatar { - url: "" + url: roomSettings.roomAvatarUrl.replace("mxc://", "image://MxcImage/") height: 130 width: 130 - displayName: "" - userid: "" Layout.alignment: Qt.AlignHCenter + onClicked: { + if(roomSettings.canChangeAvatar) { + roomSettings.updateAvatar(); + } + } + } + + BusyIndicator { + Layout.alignment: Qt.AlignHCenter + running: roomSettings.isLoading + visible: roomSettings.isLoading + } + + Text { + id: errorText + text: "Error Text" + color: "red" + visible: opacity > 0 + opacity: 0 + Layout.alignment: Qt.AlignHCenter + } + + SequentialAnimation { + id: hideErrorAnimation + running: false + PauseAnimation { + duration: 4000 + } + NumberAnimation { + target: errorText + property: 'opacity' + to: 0 + duration: 1000 + } + } + + Connections{ + target: roomSettings + onDisplayError: { + errorText.text = errorMessage + errorText.opacity = 1 + hideErrorAnimation.restart() + } } ColumnLayout { diff --git a/src/dialogs/RoomSettingsOld.cpp b/src/dialogs/RoomSettingsOld.cpp index 7eb34c20..bc34715e 100644 --- a/src/dialogs/RoomSettingsOld.cpp +++ b/src/dialogs/RoomSettingsOld.cpp @@ -143,10 +143,10 @@ EditModal::applyClicked() } using namespace mtx::events; - auto proxy = std::make_shared(); - connect(proxy.get(), &ThreadProxy::topicEventSent, this, &EditModal::topicEventSent); - connect(proxy.get(), &ThreadProxy::nameEventSent, this, &EditModal::nameEventSent); - connect(proxy.get(), &ThreadProxy::error, this, &EditModal::error); + auto proxy = std::make_shared(); + connect(proxy.get(), &ThreadProxya::topicEventSent, this, &EditModal::topicEventSent); + connect(proxy.get(), &ThreadProxya::nameEventSent, this, &EditModal::nameEventSent); + connect(proxy.get(), &ThreadProxya::error, this, &EditModal::error); if (newName != initialName_ && !newName.isEmpty()) { state::Name body; @@ -810,9 +810,9 @@ RoomSettingsOld::updateAvatar() // Events emitted from the http callbacks (different threads) will // be queued back into the UI thread through this proxy object. - auto proxy = std::make_shared(); - connect(proxy.get(), &ThreadProxy::error, this, &RoomSettingsOld::displayErrorMessage); - connect(proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettingsOld::setAvatar); + auto proxy = std::make_shared(); + connect(proxy.get(), &ThreadProxya::error, this, &RoomSettingsOld::displayErrorMessage); + connect(proxy.get(), &ThreadProxya::avatarChanged, this, &RoomSettingsOld::setAvatar); const auto bin = file.peek(file.size()); const auto payload = std::string(bin.data(), bin.size()); diff --git a/src/dialogs/RoomSettingsOld.h b/src/dialogs/RoomSettingsOld.h index e517676a..ad8dd5bd 100644 --- a/src/dialogs/RoomSettingsOld.h +++ b/src/dialogs/RoomSettingsOld.h @@ -40,7 +40,7 @@ protected: /// Convenience class which connects events emmited from threads /// outside of main with the UI code. -class ThreadProxy : public QObject +class ThreadProxya : public QObject { Q_OBJECT diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 49e48e40..3ff1d5d5 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -1,5 +1,9 @@ #include "RoomSettings.h" +#include +#include +#include +#include #include #include @@ -84,6 +88,18 @@ RoomSettings::roomVersion() const return QString::fromStdString(info_.version); } +bool +RoomSettings::isLoading() const +{ + return isLoading_; +} + +QString +RoomSettings::roomAvatarUrl() +{ + return QString::fromStdString(info_.avatar_url); +} + int RoomSettings::memberCount() const { @@ -96,7 +112,6 @@ RoomSettings::retrieveRoomInfo() try { usesEncryption_ = cache::isRoomEncrypted(roomid_.toStdString()); info_ = cache::singleRoomInfo(roomid_.toStdString()); - // setAvatar(); } catch (const lmdb::error &) { nhlog::db()->warn("failed to retrieve room info from cache: {}", roomid_.toStdString()); @@ -143,9 +158,9 @@ RoomSettings::enableEncryption() room_id, err->matrix_error.error, status_code); - //emit enableEncryptionError( - // tr("Failed to enable encryption: %1") - // .arg(QString::fromStdString(err->matrix_error.error))); + emit displayError( + tr("Failed to enable encryption: %1") + .arg(QString::fromStdString(err->matrix_error.error))); usesEncryption_ = false; emit encryptionChanged(); return; @@ -172,6 +187,33 @@ RoomSettings::canChangeJoinRules() const return false; } +bool +RoomSettings::canChangeNameAndTopic() const +{ + try { + return cache::hasEnoughPowerLevel({EventType::RoomName, EventType::RoomTopic}, + roomid_.toStdString(), + utils::localUser().toStdString()); + } catch (const lmdb::error &e) { + nhlog::db()->warn("lmdb error: {}", e.what()); + } + + return false; +} + +bool +RoomSettings::canChangeAvatar() const +{ + try { + return cache::hasEnoughPowerLevel( + {EventType::RoomAvatar}, roomid_.toStdString(), utils::localUser().toStdString()); + } catch (const lmdb::error &e) { + nhlog::db()->warn("lmdb error: {}", e.what()); + } + + return false; +} + bool RoomSettings::isEncryptionEnabled() const { @@ -269,8 +311,8 @@ RoomSettings::updateAccessRules(const std::string &room_id, const mtx::events::state::JoinRules &join_rule, const mtx::events::state::GuestAccess &guest_access) { - // startLoadingSpinner(); - // resetErrorLabel(); + isLoading_ = true; + emit loadingChanged(); http::client()->send_state_event( room_id, @@ -281,8 +323,9 @@ RoomSettings::updateAccessRules(const std::string &room_id, nhlog::net()->warn("failed to send m.room.join_rule: {} {}", static_cast(err->status_code), err->matrix_error.error); - // emit showErrorMessage(QString::fromStdString(err->matrix_error.error)); - + emit displayError(QString::fromStdString(err->matrix_error.error)); + isLoading_ = false; + emit loadingChanged(); return; } @@ -294,13 +337,115 @@ RoomSettings::updateAccessRules(const std::string &room_id, nhlog::net()->warn("failed to send m.room.guest_access: {} {}", static_cast(err->status_code), err->matrix_error.error); - // emit showErrorMessage( - // QString::fromStdString(err->matrix_error.error)); + emit displayError( + QString::fromStdString(err->matrix_error.error)); + } + isLoading_ = false; + emit loadingChanged(); + }); + }); +} + +void +RoomSettings::stopLoading() +{ + isLoading_ = false; + emit loadingChanged(); +} + +void +RoomSettings::avatarChanged() +{ + retrieveRoomInfo(); + emit avatarUrlChanged(); +} + +void +RoomSettings::updateAvatar() +{ + const QString picturesFolder = + QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + const QString fileName = QFileDialog::getOpenFileName( + nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)")); + + if (fileName.isEmpty()) + return; + + QMimeDatabase db; + QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent); + + const auto format = mime.name().split("/")[0]; + + QFile file{fileName, this}; + if (format != "image") { + emit displayError(tr("The selected file is not an image")); + return; + } + + if (!file.open(QIODevice::ReadOnly)) { + emit displayError(tr("Error while reading file: %1").arg(file.errorString())); + return; + } + + isLoading_ = true; + emit loadingChanged(); + + // Events emitted from the http callbacks (different threads) will + // be queued back into the UI thread through this proxy object. + auto proxy = std::make_shared(); + connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayError); + connect(proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettings::avatarChanged); + connect(proxy.get(), &ThreadProxy::stopLoading, this, &RoomSettings::stopLoading); + + const auto bin = file.peek(file.size()); + const auto payload = std::string(bin.data(), bin.size()); + const auto dimensions = QImageReader(&file).size(); + + // First we need to create a new mxc URI + // (i.e upload media to the Matrix content repository) for the new avatar. + http::client()->upload( + payload, + mime.name().toStdString(), + QFileInfo(fileName).fileName().toStdString(), + [proxy = std::move(proxy), + dimensions, + payload, + mimetype = mime.name().toStdString(), + size = payload.size(), + room_id = roomid_.toStdString(), + content = std::move(bin)](const mtx::responses::ContentURI &res, + mtx::http::RequestErr err) { + if (err) { + emit proxy->stopLoading(); + emit proxy->error( + tr("Failed to upload image: %s") + .arg(QString::fromStdString(err->matrix_error.error))); + return; + } + + using namespace mtx::events; + state::Avatar avatar_event; + avatar_event.image_info.w = dimensions.width(); + avatar_event.image_info.h = dimensions.height(); + avatar_event.image_info.mimetype = mimetype; + avatar_event.image_info.size = size; + avatar_event.url = res.content_uri; + + http::client()->send_state_event( + room_id, + avatar_event, + [content = std::move(content), proxy = std::move(proxy)]( + const mtx::responses::EventId &, mtx::http::RequestErr err) { + if (err) { + emit proxy->error( + tr("Failed to upload image: %s") + .arg(QString::fromStdString(err->matrix_error.error))); return; } - // emit signal that stops loading spinner and reset error label + emit proxy->stopLoading(); + emit proxy->avatarChanged(); }); }); } \ No newline at end of file diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index f5cc043c..09295a58 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -7,16 +7,34 @@ #include "CacheStructs.h" +/// Convenience class which connects events emmited from threads +/// outside of main with the UI code. +class ThreadProxy : public QObject +{ + Q_OBJECT + +signals: + void error(const QString &msg); + void avatarChanged(); + void nameEventSent(const QString &); + void topicEventSent(); + void stopLoading(); +}; + class RoomSettings : public QObject { - Q_OBJECT + Q_OBJECT Q_PROPERTY(QString roomName READ roomName CONSTANT) Q_PROPERTY(QString roomId READ roomId CONSTANT) Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT) + Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged) Q_PROPERTY(int memberCount READ memberCount CONSTANT) Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged) Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged) + Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged) Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT) + Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT) + Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT) Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged) Q_PROPERTY(bool respondsToKeyRequests READ respondsToKeyRequests NOTIFY keyRequestsChanged) @@ -26,24 +44,38 @@ public: QString roomName() const; QString roomId() const; QString roomVersion() const; + QString roomAvatarUrl(); int memberCount() const; int notifications(); int accessJoinRules(); bool respondsToKeyRequests(); + bool isLoading() const; //! Whether the user has enough power level to send m.room.join_rules events. bool canChangeJoinRules() const; + //! Whether the user has enough power level to send m.room.name & m.room.topic events. + bool canChangeNameAndTopic() const; + //! Whether the user has enough power level to send m.room.avatar event. + bool canChangeAvatar() const; bool isEncryptionEnabled() const; Q_INVOKABLE void changeNotifications(int currentIndex); Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeKeyRequestsPreference(bool isOn); Q_INVOKABLE void enableEncryption(); + Q_INVOKABLE void updateAvatar(); signals: void notificationsChanged(); void accessJoinRulesChanged(); void keyRequestsChanged(); void encryptionChanged(); + void avatarUrlChanged(); + void loadingChanged(); + void displayError(const QString &errorMessage); + +public slots: + void avatarChanged(); + void stopLoading(); private: void retrieveRoomInfo(); @@ -54,6 +86,7 @@ private: private: QString roomid_; bool usesEncryption_ = false; + bool isLoading_ = false; RoomInfo info_; int notifications_ = 0; int accessRules_ = 0; From f044e2d2a11150d026d5a523b518027154602d3a Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Thu, 11 Feb 2021 23:50:45 +0530 Subject: [PATCH 06/14] fix avatar update on timeline sync --- resources/qml/TimelineView.qml | 2 +- src/timeline/TimelineModel.cpp | 8 ++++++++ src/timeline/TimelineModel.h | 3 +++ src/timeline/TimelineViewManager.cpp | 4 +--- src/timeline/TimelineViewManager.h | 2 -- src/ui/RoomSettings.cpp | 2 -- src/ui/RoomSettings.h | 1 - 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 0c32effd..7a33f25f 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -175,7 +175,7 @@ Page { } Connections { - target: TimelineManager + target: TimelineManager.timeline onOpenRoomSettingsDialog: { var roomSettings = roomSettingsComponent.createObject(timelineRoot, { "roomSettings": settings diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 968ec3c7..29808fdd 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -807,6 +807,14 @@ TimelineModel::openUserProfile(QString userid, bool global) emit openProfile(userProfile); } +void +TimelineModel::openRoomSettings(QString roomid) +{ + RoomSettings *settings = new RoomSettings(roomid, this); + connect(this, &TimelineModel::roomAvatarUrlChanged, settings, &RoomSettings::avatarChanged); + openRoomSettingsDialog(settings); +} + void TimelineModel::replyAction(QString id) { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 51b8049e..1a12a8c3 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -12,6 +12,7 @@ #include "EventStore.h" #include "InputBar.h" #include "ui/UserProfile.h" +#include "ui/RoomSettings.h" namespace mtx::http { using RequestErr = const std::optional &; @@ -213,6 +214,7 @@ public: Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void viewDecryptedRawMessage(QString id) const; Q_INVOKABLE void openUserProfile(QString userid, bool global = false); + Q_INVOKABLE void openRoomSettings(QString roomid); Q_INVOKABLE void replyAction(QString id); Q_INVOKABLE void readReceiptsAction(QString id) const; Q_INVOKABLE void redactEvent(QString id); @@ -296,6 +298,7 @@ signals: void newCallEvent(const mtx::events::collections::TimelineEvents &event); void openProfile(UserProfile *profile); + void openRoomSettingsDialog(RoomSettings *settings); void newMessageToSend(mtx::events::collections::TimelineEvents event); void addPendingMessageToStore(mtx::events::collections::TimelineEvents event); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 4edc3369..99a2e388 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -399,9 +399,7 @@ void TimelineViewManager::openRoomSettings() { MainWindow::instance()->openRoomSettings(timeline_->roomId()); - - RoomSettings *settings = new RoomSettings(timeline_->roomId(), this); - emit openRoomSettingsDialog(settings); + timeline_->openRoomSettings(timeline_->roomId()); } void diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 10708033..a2d37342 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -19,7 +19,6 @@ #include "emoji/EmojiModel.h" #include "emoji/Provider.h" #include "dialogs/RoomSettingsOld.h" -#include "ui/RoomSettings.h" class MxcImageProvider; class BlurhashProvider; @@ -89,7 +88,6 @@ signals: void showRoomList(); void narrowViewChanged(); void focusChanged(); - void openRoomSettingsDialog(RoomSettings *settings); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 3ff1d5d5..adf8d8a7 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -395,7 +395,6 @@ RoomSettings::updateAvatar() // be queued back into the UI thread through this proxy object. auto proxy = std::make_shared(); connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayError); - connect(proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettings::avatarChanged); connect(proxy.get(), &ThreadProxy::stopLoading, this, &RoomSettings::stopLoading); const auto bin = file.peek(file.size()); @@ -445,7 +444,6 @@ RoomSettings::updateAvatar() } emit proxy->stopLoading(); - emit proxy->avatarChanged(); }); }); } \ No newline at end of file diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 09295a58..d31b38f2 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -15,7 +15,6 @@ class ThreadProxy : public QObject signals: void error(const QString &msg); - void avatarChanged(); void nameEventSent(const QString &); void topicEventSent(); void stopLoading(); From 35aa0126ac80d99aaf7f61d6eeba6c7d9eca96bc Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Fri, 12 Feb 2021 12:48:12 +0530 Subject: [PATCH 07/14] added changing of name through edit modal, removed old roomsettings --- CMakeLists.txt | 2 - resources/qml/RoomSettings.qml | 9 +- resources/qml/TopBar.qml | 4 +- resources/qml/UserProfile.qml | 1 - src/MainWindow.cpp | 9 - src/MainWindow.h | 1 - src/dialogs/RoomSettingsOld.cpp | 865 --------------------------- src/dialogs/RoomSettingsOld.h | 150 ----- src/timeline/TimelineModel.cpp | 4 +- src/timeline/TimelineModel.h | 2 +- src/timeline/TimelineViewManager.cpp | 6 - src/timeline/TimelineViewManager.h | 2 - src/ui/RoomSettings.cpp | 164 +++++ src/ui/RoomSettings.h | 41 +- 14 files changed, 214 insertions(+), 1046 deletions(-) delete mode 100644 src/dialogs/RoomSettingsOld.cpp delete mode 100644 src/dialogs/RoomSettingsOld.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 505a59f1..3e41ebc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,7 +257,6 @@ set(SRC_FILES src/dialogs/PreviewUploadOverlay.cpp src/dialogs/ReCaptcha.cpp src/dialogs/ReadReceipts.cpp - src/dialogs/RoomSettingsOld.cpp # Emoji src/emoji/EmojiModel.cpp @@ -472,7 +471,6 @@ qt5_wrap_cpp(MOC_HEADERS src/dialogs/RawMessage.h src/dialogs/ReCaptcha.h src/dialogs/ReadReceipts.h - src/dialogs/RoomSettingsOld.h # Emoji src/emoji/EmojiModel.h diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index 5d2baba1..eabe68f5 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -12,13 +12,11 @@ ApplicationWindow { x: MainWindow.x + (MainWindow.width / 2) - (width / 2) y: MainWindow.y + (MainWindow.height / 2) - (height / 2) - height: 600 - width: 420 - minimumHeight: 420 + minimumWidth: 340 + minimumHeight: 600 palette: colors color: colors.window modality: Qt.WindowModal - flags: Qt.WindowStaysOnTopHint Shortcut { sequence: StandardKey.Cancel @@ -100,6 +98,8 @@ ApplicationWindow { ImageButton { Layout.alignment: Qt.AlignHCenter image: ":/icons/icons/ui/edit.png" + visible: roomSettings.canChangeNameAndTopic + onClicked: roomSettings.openEditModal() } MatrixText { @@ -248,6 +248,7 @@ ApplicationWindow { Button { Layout.alignment: Qt.AlignRight text: "Ok" + onClicked: close() } } } \ No newline at end of file diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index 273ed8ab..c64eddd4 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -68,7 +68,7 @@ Rectangle { MouseArea { anchors.fill: parent - onClicked: TimelineManager.openRoomSettings() + onClicked: TimelineManager.timeline.openRoomSettings() } } @@ -114,7 +114,7 @@ Rectangle { MenuItem { text: qsTr("Settings") - onTriggered: TimelineManager.openRoomSettings() + onTriggered: TimelineManager.timeline.openRoomSettings() } } diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml index 37ae6de8..e8d41073 100644 --- a/resources/qml/UserProfile.qml +++ b/resources/qml/UserProfile.qml @@ -113,7 +113,6 @@ ApplicationWindow { } } } - } MatrixText { diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index b1635c94..ae532ef3 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -51,7 +51,6 @@ #include "dialogs/Logout.h" #include "dialogs/MemberList.h" #include "dialogs/ReadReceipts.h" -#include "dialogs/RoomSettingsOld.h" MainWindow *MainWindow::instance_ = nullptr; @@ -363,14 +362,6 @@ MainWindow::hasActiveUser() settings.contains(prefix + "auth/user_id"); } -void -MainWindow::openRoomSettings(const QString &room_id) -{ - auto dialog = new dialogs::RoomSettingsOld(room_id, this); - - showDialog(dialog); -} - void MainWindow::openMemberListDialog(const QString &room_id) { diff --git a/src/MainWindow.h b/src/MainWindow.h index b3983d72..5c2df8b6 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -78,7 +78,6 @@ public: std::function callback); void openJoinRoomDialog(std::function callback); void openLogoutDialog(); - void openRoomSettings(const QString &room_id); void openMemberListDialog(const QString &room_id); void openReadReceiptsDialog(const QString &event_id); diff --git a/src/dialogs/RoomSettingsOld.cpp b/src/dialogs/RoomSettingsOld.cpp deleted file mode 100644 index bc34715e..00000000 --- a/src/dialogs/RoomSettingsOld.cpp +++ /dev/null @@ -1,865 +0,0 @@ -#include "dialogs/RoomSettingsOld.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Cache.h" -#include "ChatPage.h" -#include "Config.h" -#include "Logging.h" -#include "MatrixClient.h" -#include "Utils.h" -#include "ui/Avatar.h" -#include "ui/FlatButton.h" -#include "ui/LoadingIndicator.h" -#include "ui/Painter.h" -#include "ui/TextField.h" -#include "ui/ToggleButton.h" - -using namespace dialogs; -using namespace mtx::events; - -constexpr int BUTTON_SIZE = 36; -constexpr int BUTTON_RADIUS = BUTTON_SIZE / 2; -constexpr int WIDGET_MARGIN = 20; -constexpr int TOP_WIDGET_MARGIN = 2 * WIDGET_MARGIN; -constexpr int WIDGET_SPACING = 15; -constexpr int TEXT_SPACING = 4; -constexpr int BUTTON_SPACING = 2 * TEXT_SPACING; - -bool -ClickableFilter::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::MouseButtonRelease) { - emit clicked(); - return true; - } - - return QObject::eventFilter(obj, event); -} - -EditModal::EditModal(const QString &roomId, QWidget *parent) - : QWidget(parent) - , roomId_{roomId} -{ - setAutoFillBackground(true); - setAttribute(Qt::WA_DeleteOnClose, true); - setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - setWindowModality(Qt::WindowModal); - - QFont largeFont; - largeFont.setPointSizeF(largeFont.pointSizeF() * 1.4); - setMinimumWidth(conf::window::minModalWidth); - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - - auto layout = new QVBoxLayout(this); - - applyBtn_ = new QPushButton(tr("Apply"), this); - cancelBtn_ = new QPushButton(tr("Cancel"), this); - cancelBtn_->setDefault(true); - - auto btnLayout = new QHBoxLayout; - btnLayout->addStretch(1); - btnLayout->setSpacing(15); - btnLayout->addWidget(cancelBtn_); - btnLayout->addWidget(applyBtn_); - - nameInput_ = new TextField(this); - nameInput_->setLabel(tr("Name").toUpper()); - topicInput_ = new TextField(this); - topicInput_->setLabel(tr("Topic").toUpper()); - - errorField_ = new QLabel(this); - errorField_->setWordWrap(true); - errorField_->hide(); - - layout->addWidget(nameInput_); - layout->addWidget(topicInput_); - layout->addLayout(btnLayout, 1); - - auto labelLayout = new QHBoxLayout; - labelLayout->setAlignment(Qt::AlignHCenter); - labelLayout->addWidget(errorField_); - layout->addLayout(labelLayout); - - connect(applyBtn_, &QPushButton::clicked, this, &EditModal::applyClicked); - connect(cancelBtn_, &QPushButton::clicked, this, &EditModal::close); - - auto window = QApplication::activeWindow(); - auto center = window->frameGeometry().center(); - move(center.x() - (width() * 0.5), center.y() - (height() * 0.5)); -} - -void -EditModal::topicEventSent() -{ - errorField_->hide(); - close(); -} - -void -EditModal::nameEventSent(const QString &name) -{ - errorField_->hide(); - emit nameChanged(name); - close(); -} - -void -EditModal::error(const QString &msg) -{ - errorField_->setText(msg); - errorField_->show(); -} - -void -EditModal::applyClicked() -{ - // Check if the values are changed from the originals. - auto newName = nameInput_->text().trimmed(); - auto newTopic = topicInput_->text().trimmed(); - - errorField_->hide(); - - if (newName == initialName_ && newTopic == initialTopic_) { - close(); - return; - } - - using namespace mtx::events; - auto proxy = std::make_shared(); - connect(proxy.get(), &ThreadProxya::topicEventSent, this, &EditModal::topicEventSent); - connect(proxy.get(), &ThreadProxya::nameEventSent, this, &EditModal::nameEventSent); - connect(proxy.get(), &ThreadProxya::error, this, &EditModal::error); - - if (newName != initialName_ && !newName.isEmpty()) { - state::Name body; - body.name = newName.toStdString(); - - http::client()->send_state_event( - roomId_.toStdString(), - body, - [proxy, newName](const mtx::responses::EventId &, mtx::http::RequestErr err) { - if (err) { - emit proxy->error( - QString::fromStdString(err->matrix_error.error)); - return; - } - - emit proxy->nameEventSent(newName); - }); - } - - if (newTopic != initialTopic_ && !newTopic.isEmpty()) { - state::Topic body; - body.topic = newTopic.toStdString(); - - http::client()->send_state_event( - roomId_.toStdString(), - body, - [proxy](const mtx::responses::EventId &, mtx::http::RequestErr err) { - if (err) { - emit proxy->error( - QString::fromStdString(err->matrix_error.error)); - return; - } - - emit proxy->topicEventSent(); - }); - } -} - -void -EditModal::setFields(const QString &roomName, const QString &roomTopic) -{ - initialName_ = roomName; - initialTopic_ = roomTopic; - - nameInput_->setText(roomName); - topicInput_->setText(roomTopic); -} - -RoomSettingsOld::RoomSettingsOld(const QString &room_id, QWidget *parent) - : QFrame(parent) - , room_id_{std::move(room_id)} -{ - retrieveRoomInfo(); - - setAutoFillBackground(true); - setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - setWindowModality(Qt::WindowModal); - setAttribute(Qt::WA_DeleteOnClose, true); - - QFont largeFont; - largeFont.setPointSizeF(largeFont.pointSizeF() * 1.5); - - setMinimumWidth(conf::window::minModalWidth); - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - - auto layout = new QVBoxLayout(this); - layout->setSpacing(WIDGET_SPACING); - layout->setContentsMargins(WIDGET_MARGIN, TOP_WIDGET_MARGIN, WIDGET_MARGIN, WIDGET_MARGIN); - - QFont font; - font.setWeight(QFont::Medium); - auto settingsLabel = new QLabel(tr("Settings").toUpper(), this); - settingsLabel->setFont(font); - - auto infoLabel = new QLabel(tr("Info").toUpper(), this); - infoLabel->setFont(font); - - QFont monospaceFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); - - auto roomIdLabel = new QLabel(room_id, this); - roomIdLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - roomIdLabel->setFont(monospaceFont); - - auto roomIdLayout = new QHBoxLayout; - roomIdLayout->setMargin(0); - roomIdLayout->addWidget(new QLabel(tr("Internal ID"), this), - Qt::AlignBottom | Qt::AlignLeft); - roomIdLayout->addWidget(roomIdLabel, 0, Qt::AlignBottom | Qt::AlignRight); - - auto roomVersionLabel = new QLabel(QString::fromStdString(info_.version), this); - roomVersionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - roomVersionLabel->setFont(monospaceFont); - - auto roomVersionLayout = new QHBoxLayout; - roomVersionLayout->setMargin(0); - roomVersionLayout->addWidget(new QLabel(tr("Room Version"), this), - Qt::AlignBottom | Qt::AlignLeft); - roomVersionLayout->addWidget(roomVersionLabel, 0, Qt::AlignBottom | Qt::AlignRight); - - auto notifLabel = new QLabel(tr("Notifications"), this); - notifCombo = new QComboBox(this); - notifCombo->addItem(tr( - "Muted")); //{"conditions":[{"kind":"event_match","key":"room_id","pattern":"!jxlRxnrZCsjpjDubDX:matrix.org"}],"actions":["dont_notify"]} - notifCombo->addItem(tr("Mentions only")); // {"actions":["dont_notify"]} - notifCombo->addItem(tr("All messages")); // delete rule - - connect(this, &RoomSettingsOld::notifChanged, notifCombo, &QComboBox::setCurrentIndex); - http::client()->get_pushrules( - "global", - "override", - room_id_.toStdString(), - [this](const mtx::pushrules::PushRule &rule, mtx::http::RequestErr &err) { - if (err) { - if (err->status_code == boost::beast::http::status::not_found) - http::client()->get_pushrules( - "global", - "room", - room_id_.toStdString(), - [this](const mtx::pushrules::PushRule &rule, - mtx::http::RequestErr &err) { - if (err) { - emit notifChanged(2); // all messages - return; - } - - if (rule.enabled) - emit notifChanged(1); // mentions only - }); - return; - } - - if (rule.enabled) - emit notifChanged(0); // muted - else - emit notifChanged(2); // all messages - }); - - connect(notifCombo, QOverload::of(&QComboBox::activated), [this](int index) { - std::string room_id = room_id_.toStdString(); - if (index == 0) { - // mute room - // delete old rule first, then add new rule - mtx::pushrules::PushRule rule; - rule.actions = {mtx::pushrules::actions::dont_notify{}}; - mtx::pushrules::PushCondition condition; - condition.kind = "event_match"; - condition.key = "room_id"; - condition.pattern = room_id; - rule.conditions = {condition}; - - http::client()->put_pushrules( - "global", - "override", - room_id, - rule, - [room_id](mtx::http::RequestErr &err) { - if (err) - nhlog::net()->error( - "failed to set pushrule for room {}: {} {}", - room_id, - static_cast(err->status_code), - err->matrix_error.error); - http::client()->delete_pushrules( - "global", "room", room_id, [room_id](mtx::http::RequestErr &) { - }); - }); - } else if (index == 1) { - // mentions only - // delete old rule first, then add new rule - mtx::pushrules::PushRule rule; - rule.actions = {mtx::pushrules::actions::dont_notify{}}; - http::client()->put_pushrules( - "global", "room", room_id, rule, [room_id](mtx::http::RequestErr &err) { - if (err) - nhlog::net()->error( - "failed to set pushrule for room {}: {} {}", - room_id, - static_cast(err->status_code), - err->matrix_error.error); - http::client()->delete_pushrules( - "global", - "override", - room_id, - [room_id](mtx::http::RequestErr &) {}); - }); - } else { - // all messages - http::client()->delete_pushrules( - "global", "override", room_id, [room_id](mtx::http::RequestErr &) { - http::client()->delete_pushrules( - "global", "room", room_id, [room_id](mtx::http::RequestErr &) { - }); - }); - } - }); - - auto notifOptionLayout_ = new QHBoxLayout; - notifOptionLayout_->setMargin(0); - notifOptionLayout_->addWidget(notifLabel, Qt::AlignBottom | Qt::AlignLeft); - notifOptionLayout_->addWidget(notifCombo, 0, Qt::AlignBottom | Qt::AlignRight); - - auto accessLabel = new QLabel(tr("Room access"), this); - accessCombo = new QComboBox(this); - accessCombo->addItem(tr("Anyone and guests")); - accessCombo->addItem(tr("Anyone")); - accessCombo->addItem(tr("Invited users")); - accessCombo->setDisabled( - !canChangeJoinRules(room_id_.toStdString(), utils::localUser().toStdString())); - connect(accessCombo, QOverload::of(&QComboBox::activated), [this](int index) { - using namespace mtx::events::state; - - auto guest_access = [](int index) -> state::GuestAccess { - state::GuestAccess event; - - if (index == 0) - event.guest_access = state::AccessState::CanJoin; - else - event.guest_access = state::AccessState::Forbidden; - - return event; - }(index); - - auto join_rule = [](int index) -> state::JoinRules { - state::JoinRules event; - - switch (index) { - case 0: - case 1: - event.join_rule = state::JoinRule::Public; - break; - default: - event.join_rule = state::JoinRule::Invite; - } - - return event; - }(index); - - updateAccessRules(room_id_.toStdString(), join_rule, guest_access); - }); - - if (info_.join_rule == state::JoinRule::Public) { - if (info_.guest_access) { - accessCombo->setCurrentIndex(0); - } else { - accessCombo->setCurrentIndex(1); - } - } else { - accessCombo->setCurrentIndex(2); - } - - auto accessOptionLayout = new QHBoxLayout(); - accessOptionLayout->setMargin(0); - accessOptionLayout->addWidget(accessLabel, Qt::AlignBottom | Qt::AlignLeft); - accessOptionLayout->addWidget(accessCombo, 0, Qt::AlignBottom | Qt::AlignRight); - - auto encryptionLabel = new QLabel(tr("Encryption"), this); - encryptionToggle_ = new Toggle(this); - - auto encryptionOptionLayout = new QHBoxLayout; - encryptionOptionLayout->setMargin(0); - encryptionOptionLayout->addWidget(encryptionLabel, Qt::AlignBottom | Qt::AlignLeft); - encryptionOptionLayout->addWidget(encryptionToggle_, 0, Qt::AlignBottom | Qt::AlignRight); - - auto keyRequestsLabel = new QLabel(tr("Respond to key requests"), this); - keyRequestsLabel->setToolTipDuration(6000); - keyRequestsLabel->setToolTip( - tr("Whether or not the client should respond automatically with the session keys\n" - " upon request. Use with caution, this is a temporary measure to test the\n" - " E2E implementation until device verification is completed.")); - keyRequestsToggle_ = new Toggle(this); - connect(keyRequestsToggle_, &Toggle::toggled, this, [this](bool isOn) { - utils::setKeyRequestsPreference(room_id_, isOn); - }); - - auto keyRequestsLayout = new QHBoxLayout; - keyRequestsLayout->setMargin(0); - keyRequestsLayout->setSpacing(0); - keyRequestsLayout->addWidget(keyRequestsLabel, Qt::AlignBottom | Qt::AlignLeft); - keyRequestsLayout->addWidget(keyRequestsToggle_, 0, Qt::AlignBottom | Qt::AlignRight); - - connect(encryptionToggle_, &Toggle::toggled, this, [this, keyRequestsLabel](bool isOn) { - if (!isOn || usesEncryption_) - return; - - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Question); - msgBox.setWindowTitle(tr("End-to-End Encryption")); - msgBox.setText(tr( - "Encryption is currently experimental and things might break unexpectedly.
" - "Please take note that it can't be disabled afterwards.")); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Save); - int ret = msgBox.exec(); - - switch (ret) { - case QMessageBox::Ok: { - encryptionToggle_->setState(true); - encryptionToggle_->setEnabled(false); - enableEncryption(); - keyRequestsToggle_->show(); - keyRequestsLabel->show(); - break; - } - default: { - break; - } - } - }); - - // Disable encryption button. - if (usesEncryption_) { - encryptionToggle_->setState(true); - encryptionToggle_->setEnabled(false); - - keyRequestsToggle_->setState(utils::respondsToKeyRequests(room_id_)); - } else { - encryptionToggle_->setState(false); - - keyRequestsLabel->hide(); - keyRequestsToggle_->hide(); - } - - // Hide encryption option for public rooms. - if (!usesEncryption_ && (info_.join_rule == state::JoinRule::Public)) { - encryptionToggle_->hide(); - encryptionLabel->hide(); - - keyRequestsLabel->hide(); - keyRequestsToggle_->hide(); - } - - avatar_ = new Avatar(this, 128); - avatar_->setLetter(utils::firstChar(QString::fromStdString(info_.name))); - if (!info_.avatar_url.empty()) - avatar_->setImage(QString::fromStdString(info_.avatar_url)); - - if (canChangeAvatar(room_id_.toStdString(), utils::localUser().toStdString())) { - auto filter = new ClickableFilter(this); - avatar_->installEventFilter(filter); - avatar_->setCursor(Qt::PointingHandCursor); - connect(filter, &ClickableFilter::clicked, this, &RoomSettingsOld::updateAvatar); - } - - roomNameLabel_ = new QLabel(QString::fromStdString(info_.name), this); - roomNameLabel_->setFont(largeFont); - - auto membersLabel = new QLabel(tr("%n member(s)", "", (int)info_.member_count), this); - - auto textLayout = new QVBoxLayout; - textLayout->addWidget(roomNameLabel_); - textLayout->addWidget(membersLabel); - textLayout->setAlignment(roomNameLabel_, Qt::AlignCenter | Qt::AlignTop); - textLayout->setAlignment(membersLabel, Qt::AlignCenter | Qt::AlignTop); - textLayout->setSpacing(TEXT_SPACING); - textLayout->setMargin(0); - - setupEditButton(); - - errorLabel_ = new QLabel(this); - errorLabel_->setAlignment(Qt::AlignCenter); - errorLabel_->hide(); - - spinner_ = new LoadingIndicator(this); - spinner_->setFixedHeight(30); - spinner_->setFixedWidth(30); - spinner_->hide(); - auto spinnerLayout = new QVBoxLayout; - spinnerLayout->addWidget(spinner_); - spinnerLayout->setAlignment(Qt::AlignCenter); - spinnerLayout->setMargin(0); - spinnerLayout->setSpacing(0); - - auto okBtn = new QPushButton("OK", this); - - auto buttonLayout = new QHBoxLayout(); - buttonLayout->setSpacing(15); - buttonLayout->addStretch(1); - buttonLayout->addWidget(okBtn); - - layout->addWidget(avatar_, Qt::AlignCenter | Qt::AlignTop); - layout->addLayout(textLayout); - layout->addLayout(btnLayout_); - layout->addWidget(settingsLabel, Qt::AlignLeft); - layout->addLayout(notifOptionLayout_); - layout->addLayout(accessOptionLayout); - layout->addLayout(encryptionOptionLayout); - layout->addLayout(keyRequestsLayout); - layout->addWidget(infoLabel, Qt::AlignLeft); - layout->addLayout(roomIdLayout); - layout->addLayout(roomVersionLayout); - layout->addWidget(errorLabel_); - layout->addLayout(buttonLayout); - layout->addLayout(spinnerLayout); - layout->addStretch(1); - - connect(this, &RoomSettingsOld::enableEncryptionError, this, [this](const QString &msg) { - encryptionToggle_->setState(false); - keyRequestsToggle_->setState(false); - keyRequestsToggle_->setEnabled(false); - keyRequestsToggle_->hide(); - - emit ChatPage::instance()->showNotification(msg); - }); - - connect(this, &RoomSettingsOld::showErrorMessage, this, [this](const QString &msg) { - if (!errorLabel_) - return; - - stopLoadingSpinner(); - - errorLabel_->show(); - errorLabel_->setText(msg); - }); - - connect(this, &RoomSettingsOld::accessRulesUpdated, this, [this]() { - stopLoadingSpinner(); - resetErrorLabel(); - }); - - auto closeShortcut = new QShortcut(QKeySequence(QKeySequence::Cancel), this); - connect(closeShortcut, &QShortcut::activated, this, &RoomSettingsOld::close); - connect(okBtn, &QPushButton::clicked, this, &RoomSettingsOld::close); -} - -void -RoomSettingsOld::setupEditButton() -{ - btnLayout_ = new QHBoxLayout; - btnLayout_->setSpacing(BUTTON_SPACING); - btnLayout_->setMargin(0); - - if (!canChangeNameAndTopic(room_id_.toStdString(), utils::localUser().toStdString())) - return; - - QIcon editIcon; - editIcon.addFile(":/icons/icons/ui/edit.png"); - editFieldsBtn_ = new FlatButton(this); - editFieldsBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE); - editFieldsBtn_->setCornerRadius(BUTTON_RADIUS); - editFieldsBtn_->setIcon(editIcon); - editFieldsBtn_->setIcon(editIcon); - editFieldsBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS)); - - connect(editFieldsBtn_, &QPushButton::clicked, this, [this]() { - retrieveRoomInfo(); - - auto modal = new EditModal(room_id_, this); - modal->setFields(QString::fromStdString(info_.name), - QString::fromStdString(info_.topic)); - modal->raise(); - modal->show(); - connect(modal, &EditModal::nameChanged, this, [this](const QString &newName) { - if (roomNameLabel_) - roomNameLabel_->setText(newName); - }); - }); - - btnLayout_->addStretch(1); - btnLayout_->addWidget(editFieldsBtn_); - btnLayout_->addStretch(1); -} - -void -RoomSettingsOld::retrieveRoomInfo() -{ - try { - usesEncryption_ = cache::isRoomEncrypted(room_id_.toStdString()); - info_ = cache::singleRoomInfo(room_id_.toStdString()); - setAvatar(); - } catch (const lmdb::error &) { - nhlog::db()->warn("failed to retrieve room info from cache: {}", - room_id_.toStdString()); - } -} - -void -RoomSettingsOld::enableEncryption() -{ - const auto room_id = room_id_.toStdString(); - http::client()->enable_encryption( - room_id, [room_id, this](const mtx::responses::EventId &, mtx::http::RequestErr err) { - if (err) { - int status_code = static_cast(err->status_code); - nhlog::net()->warn("failed to enable encryption in room ({}): {} {}", - room_id, - err->matrix_error.error, - status_code); - emit enableEncryptionError( - tr("Failed to enable encryption: %1") - .arg(QString::fromStdString(err->matrix_error.error))); - return; - } - - nhlog::net()->info("enabled encryption on room ({})", room_id); - }); -} - -void -RoomSettingsOld::showEvent(QShowEvent *event) -{ - resetErrorLabel(); - stopLoadingSpinner(); - - QWidget::showEvent(event); -} - -bool -RoomSettingsOld::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const -{ - try { - return cache::hasEnoughPowerLevel({EventType::RoomJoinRules}, room_id, user_id); - } catch (const lmdb::error &e) { - nhlog::db()->warn("lmdb error: {}", e.what()); - } - - return false; -} - -bool -RoomSettingsOld::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const -{ - try { - return cache::hasEnoughPowerLevel( - {EventType::RoomName, EventType::RoomTopic}, room_id, user_id); - } catch (const lmdb::error &e) { - nhlog::db()->warn("lmdb error: {}", e.what()); - } - - return false; -} - -bool -RoomSettingsOld::canChangeAvatar(const std::string &room_id, const std::string &user_id) const -{ - try { - return cache::hasEnoughPowerLevel({EventType::RoomAvatar}, room_id, user_id); - } catch (const lmdb::error &e) { - nhlog::db()->warn("lmdb error: {}", e.what()); - } - - return false; -} - -void -RoomSettingsOld::updateAccessRules(const std::string &room_id, - const mtx::events::state::JoinRules &join_rule, - const mtx::events::state::GuestAccess &guest_access) -{ - startLoadingSpinner(); - resetErrorLabel(); - - http::client()->send_state_event( - room_id, - join_rule, - [this, room_id, guest_access](const mtx::responses::EventId &, - mtx::http::RequestErr err) { - if (err) { - nhlog::net()->warn("failed to send m.room.join_rule: {} {}", - static_cast(err->status_code), - err->matrix_error.error); - emit showErrorMessage(QString::fromStdString(err->matrix_error.error)); - - return; - } - - http::client()->send_state_event( - room_id, - guest_access, - [this](const mtx::responses::EventId &, mtx::http::RequestErr err) { - if (err) { - nhlog::net()->warn("failed to send m.room.guest_access: {} {}", - static_cast(err->status_code), - err->matrix_error.error); - emit showErrorMessage( - QString::fromStdString(err->matrix_error.error)); - - return; - } - - emit accessRulesUpdated(); - }); - }); -} - -void -RoomSettingsOld::stopLoadingSpinner() -{ - if (spinner_) { - spinner_->stop(); - spinner_->hide(); - } -} - -void -RoomSettingsOld::startLoadingSpinner() -{ - if (spinner_) { - spinner_->start(); - spinner_->show(); - } -} - -void -RoomSettingsOld::displayErrorMessage(const QString &msg) -{ - stopLoadingSpinner(); - - errorLabel_->show(); - errorLabel_->setText(msg); -} - -void -RoomSettingsOld::setAvatar() -{ - stopLoadingSpinner(); - - if (avatar_) - avatar_->setImage(QString::fromStdString(info_.avatar_url)); -} - -void -RoomSettingsOld::resetErrorLabel() -{ - if (errorLabel_) { - errorLabel_->hide(); - errorLabel_->clear(); - } -} - -void -RoomSettingsOld::updateAvatar() -{ - const QString picturesFolder = - QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); - const QString fileName = QFileDialog::getOpenFileName( - this, tr("Select an avatar"), picturesFolder, tr("All Files (*)")); - - if (fileName.isEmpty()) - return; - - QMimeDatabase db; - QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent); - - const auto format = mime.name().split("/")[0]; - - QFile file{fileName, this}; - if (format != "image") { - displayErrorMessage(tr("The selected file is not an image")); - return; - } - - if (!file.open(QIODevice::ReadOnly)) { - displayErrorMessage(tr("Error while reading file: %1").arg(file.errorString())); - return; - } - - if (spinner_) { - startLoadingSpinner(); - resetErrorLabel(); - } - - // Events emitted from the http callbacks (different threads) will - // be queued back into the UI thread through this proxy object. - auto proxy = std::make_shared(); - connect(proxy.get(), &ThreadProxya::error, this, &RoomSettingsOld::displayErrorMessage); - connect(proxy.get(), &ThreadProxya::avatarChanged, this, &RoomSettingsOld::setAvatar); - - const auto bin = file.peek(file.size()); - const auto payload = std::string(bin.data(), bin.size()); - const auto dimensions = QImageReader(&file).size(); - - // First we need to create a new mxc URI - // (i.e upload media to the Matrix content repository) for the new avatar. - http::client()->upload( - payload, - mime.name().toStdString(), - QFileInfo(fileName).fileName().toStdString(), - [proxy = std::move(proxy), - dimensions, - payload, - mimetype = mime.name().toStdString(), - size = payload.size(), - room_id = room_id_.toStdString(), - content = std::move(bin)](const mtx::responses::ContentURI &res, - mtx::http::RequestErr err) { - if (err) { - emit proxy->error( - tr("Failed to upload image: %s") - .arg(QString::fromStdString(err->matrix_error.error))); - return; - } - - using namespace mtx::events; - state::Avatar avatar_event; - avatar_event.image_info.w = dimensions.width(); - avatar_event.image_info.h = dimensions.height(); - avatar_event.image_info.mimetype = mimetype; - avatar_event.image_info.size = size; - avatar_event.url = res.content_uri; - - http::client()->send_state_event( - room_id, - avatar_event, - [content = std::move(content), proxy = std::move(proxy)]( - const mtx::responses::EventId &, mtx::http::RequestErr err) { - if (err) { - emit proxy->error( - tr("Failed to upload image: %s") - .arg(QString::fromStdString(err->matrix_error.error))); - return; - } - - emit proxy->avatarChanged(); - }); - }); -} diff --git a/src/dialogs/RoomSettingsOld.h b/src/dialogs/RoomSettingsOld.h deleted file mode 100644 index ad8dd5bd..00000000 --- a/src/dialogs/RoomSettingsOld.h +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "CacheStructs.h" - -class Avatar; -class FlatButton; -class QPushButton; -class QComboBox; -class QHBoxLayout; -class QShowEvent; -class LoadingIndicator; -class QLayout; -class QPixmap; -class TextField; -class TextField; -class Toggle; -class QLabel; -class QEvent; - -class ClickableFilter : public QObject -{ - Q_OBJECT - -public: - explicit ClickableFilter(QWidget *parent) - : QObject(parent) - {} - -signals: - void clicked(); - -protected: - bool eventFilter(QObject *obj, QEvent *event) override; -}; - -/// Convenience class which connects events emmited from threads -/// outside of main with the UI code. -class ThreadProxya : public QObject -{ - Q_OBJECT - -signals: - void error(const QString &msg); - void avatarChanged(); - void nameEventSent(const QString &); - void topicEventSent(); -}; - -class EditModal : public QWidget -{ - Q_OBJECT - -public: - EditModal(const QString &roomId, QWidget *parent = nullptr); - - void setFields(const QString &roomName, const QString &roomTopic); - -signals: - void nameChanged(const QString &roomName); - -private slots: - void topicEventSent(); - void nameEventSent(const QString &name); - void error(const QString &msg); - - void applyClicked(); - -private: - QString roomId_; - QString initialName_; - QString initialTopic_; - - QLabel *errorField_; - - TextField *nameInput_; - TextField *topicInput_; - - QPushButton *applyBtn_; - QPushButton *cancelBtn_; -}; - -namespace dialogs { - -class RoomSettingsOld : public QFrame -{ - Q_OBJECT -public: - RoomSettingsOld(const QString &room_id, QWidget *parent = nullptr); - -signals: - void enableEncryptionError(const QString &msg); - void showErrorMessage(const QString &msg); - void accessRulesUpdated(); - void notifChanged(int index); - -protected: - void showEvent(QShowEvent *event) override; - -private slots: - //! The file dialog opens so the user can select and upload a new room avatar. - void updateAvatar(); - -private: - //! Whether the user has enough power level to send m.room.join_rules events. - bool canChangeJoinRules(const std::string &room_id, const std::string &user_id) const; - //! Whether the user has enough power level to send m.room.name & m.room.topic events. - bool canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const; - //! Whether the user has enough power level to send m.room.avatar event. - bool canChangeAvatar(const std::string &room_id, const std::string &user_id) const; - void updateAccessRules(const std::string &room_id, - const mtx::events::state::JoinRules &, - const mtx::events::state::GuestAccess &); - void stopLoadingSpinner(); - void startLoadingSpinner(); - void resetErrorLabel(); - void displayErrorMessage(const QString &msg); - - void setAvatar(); - void setupEditButton(); - //! Retrieve the current room information from cache. - void retrieveRoomInfo(); - void enableEncryption(); - - Avatar *avatar_ = nullptr; - - bool usesEncryption_ = false; - QHBoxLayout *btnLayout_; - - FlatButton *editFieldsBtn_ = nullptr; - - RoomInfo info_; - QString room_id_; - QImage avatarImg_; - - QLabel *roomNameLabel_ = nullptr; - QLabel *errorLabel_ = nullptr; - LoadingIndicator *spinner_ = nullptr; - - QComboBox *notifCombo = nullptr; - QComboBox *accessCombo = nullptr; - Toggle *encryptionToggle_ = nullptr; - Toggle *keyRequestsToggle_ = nullptr; -}; - -} // dialogs diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 29808fdd..efeba146 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -808,9 +808,9 @@ TimelineModel::openUserProfile(QString userid, bool global) } void -TimelineModel::openRoomSettings(QString roomid) +TimelineModel::openRoomSettings() { - RoomSettings *settings = new RoomSettings(roomid, this); + RoomSettings *settings = new RoomSettings(roomId(), this); connect(this, &TimelineModel::roomAvatarUrlChanged, settings, &RoomSettings::avatarChanged); openRoomSettingsDialog(settings); } diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 1a12a8c3..29207318 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -214,7 +214,7 @@ public: Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void viewDecryptedRawMessage(QString id) const; Q_INVOKABLE void openUserProfile(QString userid, bool global = false); - Q_INVOKABLE void openRoomSettings(QString roomid); + Q_INVOKABLE void openRoomSettings(); Q_INVOKABLE void replyAction(QString id); Q_INVOKABLE void readReceiptsAction(QString id) const; Q_INVOKABLE void redactEvent(QString id); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 99a2e388..0ed680f8 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -395,12 +395,6 @@ TimelineViewManager::openLeaveRoomDialog() const { MainWindow::instance()->openLeaveRoomDialog(timeline_->roomId()); } -void -TimelineViewManager::openRoomSettings() -{ - MainWindow::instance()->openRoomSettings(timeline_->roomId()); - timeline_->openRoomSettings(timeline_->roomId()); -} void TimelineViewManager::verifyUser(QString userid) diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index a2d37342..3e58bb43 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -18,7 +18,6 @@ #include "WebRTCSession.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" -#include "dialogs/RoomSettingsOld.h" class MxcImageProvider; class BlurhashProvider; @@ -70,7 +69,6 @@ public: Q_INVOKABLE void openInviteUsersDialog(); Q_INVOKABLE void openMemberListDialog() const; Q_INVOKABLE void openLeaveRoomDialog() const; - Q_INVOKABLE void openRoomSettings(); Q_INVOKABLE void removeVerificationFlow(DeviceVerificationFlow *flow); void verifyUser(QString userid); diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index adf8d8a7..c7f388d4 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -4,16 +4,165 @@ #include #include #include +#include +#include +#include #include #include #include "Cache.h" #include "Logging.h" +#include "Config.h" #include "MatrixClient.h" +#include "ui/TextField.h" #include "Utils.h" using namespace mtx::events; +EditModal::EditModal(const QString &roomId, QWidget *parent) + : QWidget(parent) + , roomId_{roomId} +{ + setAutoFillBackground(true); + setAttribute(Qt::WA_DeleteOnClose, true); + setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); + setWindowModality(Qt::WindowModal); + + QFont largeFont; + largeFont.setPointSizeF(largeFont.pointSizeF() * 1.4); + setMinimumWidth(conf::window::minModalWidth); + setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + + auto layout = new QVBoxLayout(this); + + applyBtn_ = new QPushButton(tr("Apply"), this); + cancelBtn_ = new QPushButton(tr("Cancel"), this); + cancelBtn_->setDefault(true); + + auto btnLayout = new QHBoxLayout; + btnLayout->addStretch(1); + btnLayout->setSpacing(15); + btnLayout->addWidget(cancelBtn_); + btnLayout->addWidget(applyBtn_); + + nameInput_ = new TextField(this); + nameInput_->setLabel(tr("Name").toUpper()); + topicInput_ = new TextField(this); + topicInput_->setLabel(tr("Topic").toUpper()); + + errorField_ = new QLabel(this); + errorField_->setWordWrap(true); + errorField_->hide(); + + layout->addWidget(nameInput_); + layout->addWidget(topicInput_); + layout->addLayout(btnLayout, 1); + + auto labelLayout = new QHBoxLayout; + labelLayout->setAlignment(Qt::AlignHCenter); + labelLayout->addWidget(errorField_); + layout->addLayout(labelLayout); + + connect(applyBtn_, &QPushButton::clicked, this, &EditModal::applyClicked); + connect(cancelBtn_, &QPushButton::clicked, this, &EditModal::close); + + auto window = QApplication::activeWindow(); + + if (window != nullptr) { + auto center = window->frameGeometry().center(); + move(center.x() - (width() * 0.5), center.y() - (height() * 0.5)); + } +} + +void +EditModal::topicEventSent() +{ + errorField_->hide(); + close(); +} + +void +EditModal::nameEventSent(const QString &name) +{ + errorField_->hide(); + emit nameChanged(name); + close(); +} + +void +EditModal::error(const QString &msg) +{ + errorField_->setText(msg); + errorField_->show(); +} + +void +EditModal::applyClicked() +{ + // Check if the values are changed from the originals. + auto newName = nameInput_->text().trimmed(); + auto newTopic = topicInput_->text().trimmed(); + + errorField_->hide(); + + if (newName == initialName_ && newTopic == initialTopic_) { + close(); + return; + } + + using namespace mtx::events; + auto proxy = std::make_shared(); + connect(proxy.get(), &ThreadProxy::topicEventSent, this, &EditModal::topicEventSent); + connect(proxy.get(), &ThreadProxy::nameEventSent, this, &EditModal::nameEventSent); + connect(proxy.get(), &ThreadProxy::error, this, &EditModal::error); + + if (newName != initialName_ && !newName.isEmpty()) { + state::Name body; + body.name = newName.toStdString(); + + http::client()->send_state_event( + roomId_.toStdString(), + body, + [proxy, newName](const mtx::responses::EventId &, mtx::http::RequestErr err) { + if (err) { + emit proxy->error( + QString::fromStdString(err->matrix_error.error)); + return; + } + + emit proxy->nameEventSent(newName); + }); + } + + if (newTopic != initialTopic_ && !newTopic.isEmpty()) { + state::Topic body; + body.topic = newTopic.toStdString(); + + http::client()->send_state_event( + roomId_.toStdString(), + body, + [proxy](const mtx::responses::EventId &, mtx::http::RequestErr err) { + if (err) { + emit proxy->error( + QString::fromStdString(err->matrix_error.error)); + return; + } + + emit proxy->topicEventSent(); + }); + } +} + +void +EditModal::setFields(const QString &roomName, const QString &roomTopic) +{ + initialName_ = roomName; + initialTopic_ = roomTopic; + + nameInput_->setText(roomName); + topicInput_->setText(roomTopic); +} + RoomSettings::RoomSettings(QString roomid, QObject *parent) : roomid_{std::move(roomid)} , QObject(parent) @@ -220,6 +369,21 @@ RoomSettings::isEncryptionEnabled() const return usesEncryption_; } +void +RoomSettings::openEditModal() +{ + retrieveRoomInfo(); + + auto modal = new EditModal(roomid_); + modal->setFields(QString::fromStdString(info_.name), QString::fromStdString(info_.topic)); + modal->raise(); + modal->show(); + connect(modal, &EditModal::nameChanged, this, [this](const QString &newName) { + info_.name = newName.toStdString(); + emit roomNameChanged(); + }); +} + void RoomSettings::changeNotifications(int currentIndex) { diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index d31b38f2..0d0b13f6 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -1,12 +1,16 @@ #pragma once +#include #include +#include #include #include #include "CacheStructs.h" +class TextField; + /// Convenience class which connects events emmited from threads /// outside of main with the UI code. class ThreadProxy : public QObject @@ -20,10 +24,43 @@ signals: void stopLoading(); }; +class EditModal : public QWidget +{ + Q_OBJECT + +public: + EditModal(const QString &roomId, QWidget *parent = nullptr); + + void setFields(const QString &roomName, const QString &roomTopic); + +signals: + void nameChanged(const QString &roomName); + +private slots: + void topicEventSent(); + void nameEventSent(const QString &name); + void error(const QString &msg); + + void applyClicked(); + +private: + QString roomId_; + QString initialName_; + QString initialTopic_; + + QLabel *errorField_; + + TextField *nameInput_; + TextField *topicInput_; + + QPushButton *applyBtn_; + QPushButton *cancelBtn_; +}; + class RoomSettings : public QObject { Q_OBJECT - Q_PROPERTY(QString roomName READ roomName CONSTANT) + Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) Q_PROPERTY(QString roomId READ roomId CONSTANT) Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged) @@ -62,6 +99,7 @@ public: Q_INVOKABLE void changeKeyRequestsPreference(bool isOn); Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void updateAvatar(); + Q_INVOKABLE void openEditModal(); signals: void notificationsChanged(); @@ -69,6 +107,7 @@ signals: void keyRequestsChanged(); void encryptionChanged(); void avatarUrlChanged(); + void roomNameChanged(); void loadingChanged(); void displayError(const QString &errorMessage); From f3596aed554feb848b3f3d09239e5cacf2155024 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Sat, 13 Feb 2021 19:08:52 +0530 Subject: [PATCH 08/14] added room topic --- resources/qml/RoomSettings.qml | 37 ++++++++++++++++++++++++++++++---- resources/qml/TopBar.qml | 2 +- src/ui/RoomSettings.cpp | 20 ++++++++++++++---- src/ui/RoomSettings.h | 32 ++++++++++++++++------------- 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index eabe68f5..2f6f1866 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -12,8 +12,8 @@ ApplicationWindow { x: MainWindow.x + (MainWindow.width / 2) - (width / 2) y: MainWindow.y + (MainWindow.height / 2) - (height / 2) - minimumWidth: 340 - minimumHeight: 600 + minimumWidth: 400 + minimumHeight: 650 palette: colors color: colors.window modality: Qt.WindowModal @@ -24,9 +24,12 @@ ApplicationWindow { } ColumnLayout { - id: contentLayout + id: contentLayout1 - anchors.fill: parent + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: undefined anchors.margins: 10 spacing: 10 @@ -101,6 +104,32 @@ ApplicationWindow { visible: roomSettings.canChangeNameAndTopic onClicked: roomSettings.openEditModal() } + } + + ScrollView { + id: topicScroll + anchors.left: parent.left + anchors.right: parent.right + anchors.top: contentLayout1.bottom + anchors.bottom: undefined + anchors.margins: 10 + height: 100 + + TextArea { + text: roomSettings.roomTopic + background: null + } + } + + ColumnLayout { + id: contentLayout2 + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: topicScroll.bottom + anchors.bottom: parent.bottom + anchors.margins: 10 + spacing: 10 MatrixText { text: "SETTINGS" diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index c64eddd4..967aa11e 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -15,7 +15,7 @@ Rectangle { MouseArea { anchors.fill: parent - onClicked: TimelineManager.openRoomSettings() + onClicked: TimelineManager.timeline.openRoomSettings() } GridLayout { diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index c7f388d4..d2b5a630 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -75,9 +75,10 @@ EditModal::EditModal(const QString &roomId, QWidget *parent) } void -EditModal::topicEventSent() +EditModal::topicEventSent(const QString &topic) { errorField_->hide(); + emit topicChanged(topic); close(); } @@ -141,14 +142,14 @@ EditModal::applyClicked() http::client()->send_state_event( roomId_.toStdString(), body, - [proxy](const mtx::responses::EventId &, mtx::http::RequestErr err) { + [proxy, newTopic](const mtx::responses::EventId &, mtx::http::RequestErr err) { if (err) { emit proxy->error( QString::fromStdString(err->matrix_error.error)); return; } - emit proxy->topicEventSent(); + emit proxy->topicEventSent(newTopic); }); } } @@ -222,7 +223,13 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent) QString RoomSettings::roomName() const { - return QString(info_.name.c_str()); + return QString::fromStdString(info_.name); +} + +QString +RoomSettings::roomTopic() const +{ + return QString::fromStdString(info_.topic); } QString @@ -382,6 +389,11 @@ RoomSettings::openEditModal() info_.name = newName.toStdString(); emit roomNameChanged(); }); + + connect(modal, &EditModal::topicChanged, this, [this](const QString &newTopic) { + info_.topic = newTopic.toStdString(); + emit roomTopicChanged(); + }); } void diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 0d0b13f6..25c6e588 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -20,7 +20,7 @@ class ThreadProxy : public QObject signals: void error(const QString &msg); void nameEventSent(const QString &); - void topicEventSent(); + void topicEventSent(const QString &); void stopLoading(); }; @@ -35,9 +35,10 @@ public: signals: void nameChanged(const QString &roomName); + void topicChanged(const QString &topic); private slots: - void topicEventSent(); + void topicEventSent(const QString &topic); void nameEventSent(const QString &name); void error(const QString &msg); @@ -60,25 +61,27 @@ private: class RoomSettings : public QObject { Q_OBJECT - Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) Q_PROPERTY(QString roomId READ roomId CONSTANT) Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT) + Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) + Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged) Q_PROPERTY(int memberCount READ memberCount CONSTANT) Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged) Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged) Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged) + Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT) Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT) Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT) - Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT) Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged) Q_PROPERTY(bool respondsToKeyRequests READ respondsToKeyRequests NOTIFY keyRequestsChanged) public: RoomSettings(QString roomid, QObject *parent = nullptr); - QString roomName() const; QString roomId() const; + QString roomName() const; + QString roomTopic() const; QString roomVersion() const; QString roomAvatarUrl(); int memberCount() const; @@ -94,26 +97,27 @@ public: bool canChangeAvatar() const; bool isEncryptionEnabled() const; - Q_INVOKABLE void changeNotifications(int currentIndex); - Q_INVOKABLE void changeAccessRules(int index); - Q_INVOKABLE void changeKeyRequestsPreference(bool isOn); Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void openEditModal(); + Q_INVOKABLE void changeAccessRules(int index); + Q_INVOKABLE void changeNotifications(int currentIndex); + Q_INVOKABLE void changeKeyRequestsPreference(bool isOn); signals: + void loadingChanged(); + void roomNameChanged(); + void roomTopicChanged(); + void avatarUrlChanged(); + void encryptionChanged(); + void keyRequestsChanged(); void notificationsChanged(); void accessJoinRulesChanged(); - void keyRequestsChanged(); - void encryptionChanged(); - void avatarUrlChanged(); - void roomNameChanged(); - void loadingChanged(); void displayError(const QString &errorMessage); public slots: - void avatarChanged(); void stopLoading(); + void avatarChanged(); private: void retrieveRoomInfo(); From 65403521239c202e7a3cdfb5a52fbcb700656474 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Sat, 13 Feb 2021 20:46:40 +0530 Subject: [PATCH 09/14] fix roomsetting layout --- resources/qml/RoomSettings.qml | 48 ++++++++++++---------------------- resources/res.qrc | 1 + 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index 2f6f1866..bc9406d4 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -26,10 +26,7 @@ ApplicationWindow { ColumnLayout { id: contentLayout1 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: undefined + anchors.fill: parent anchors.margins: 10 spacing: 10 @@ -104,32 +101,21 @@ ApplicationWindow { visible: roomSettings.canChangeNameAndTopic onClicked: roomSettings.openEditModal() } - } - ScrollView { - id: topicScroll - anchors.left: parent.left - anchors.right: parent.right - anchors.top: contentLayout1.bottom - anchors.bottom: undefined - anchors.margins: 10 - height: 100 + ScrollView { + Layout.maximumHeight: 75 + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true - TextArea { - text: roomSettings.roomTopic - background: null + TextArea { + text: roomSettings.roomTopic + wrapMode: TextEdit.WordWrap + readOnly: true + background: null + } } - } - - ColumnLayout { - id: contentLayout2 - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: topicScroll.bottom - anchors.bottom: parent.bottom - anchors.margins: 10 - spacing: 10 MatrixText { text: "SETTINGS" @@ -178,8 +164,8 @@ ApplicationWindow { Layout.fillWidth: true } - Switch { - id: encryptionSwitch + ToggleButton { + id: encryptionToggle checked: roomSettings.isEncryptionEnabled onToggled: { @@ -209,7 +195,7 @@ ApplicationWindow { } onRejected: { - encryptionSwitch.checked = false + encryptionToggle.checked = false } standardButtons: Dialog.Ok | Dialog.Cancel @@ -227,7 +213,7 @@ ApplicationWindow { Layout.fillWidth: true } - Switch { + ToggleButton { ToolTip.text: qsTr("Whether or not the client should respond automatically with the session keys upon request. Use with caution, this is a temporary measure to test the E2E implementation until device verification is completed.") diff --git a/resources/res.qrc b/resources/res.qrc index 24b41179..12d098c0 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -128,6 +128,7 @@ qml/EncryptionIndicator.qml qml/ImageButton.qml qml/MatrixText.qml + qml/ToggleButton.qml qml/MessageInput.qml qml/MessageView.qml qml/NhekoBusyIndicator.qml From 4996ae27a0f8cf2a9e2c3834cee3e546239a486a Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Sat, 13 Feb 2021 21:49:21 +0530 Subject: [PATCH 10/14] added togglebutton styling --- resources/qml/RoomSettings.qml | 5 ++--- resources/qml/ToggleButton.qml | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index bc9406d4..b3602a6a 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -105,7 +105,6 @@ ApplicationWindow { ScrollView { Layout.maximumHeight: 75 ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - ScrollBar.vertical.policy: ScrollBar.AlwaysOn Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true @@ -168,7 +167,7 @@ ApplicationWindow { id: encryptionToggle checked: roomSettings.isEncryptionEnabled - onToggled: { + onClicked: { if(roomSettings.isEncryptionEnabled) { checked=true; return; @@ -220,7 +219,7 @@ ApplicationWindow { checked: roomSettings.respondsToKeyRequests - onToggled: { + onClicked: { roomSettings.changeKeyRequestsPreference(checked) } } diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml index 584fc693..cf67c48c 100644 --- a/resources/qml/ToggleButton.qml +++ b/resources/qml/ToggleButton.qml @@ -1,10 +1,22 @@ import QtQuick 2.5 -import QtQuick.Controls 2.3 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 import im.nheko 1.0 Switch { - property color activeColor - property color disabledColor - property color inactiveColor - property color trackColor + style: SwitchStyle { + handle: Rectangle { + width: 20 + height: 20 + radius: 90 + color: "whitesmoke" + } + + groove: Rectangle { + implicitWidth: 40 + implicitHeight: 20 + radius: 90 + color: checked ? "skyblue" : "grey" + } + } } \ No newline at end of file From 1a406f79e6c7f673172c07da30ab958e980d919c Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Sat, 13 Feb 2021 23:59:42 +0530 Subject: [PATCH 11/14] replaced with togglebutton using qtquickcontrols2 --- resources/qml/ToggleButton.qml | 36 ++++++++++++++++++++++------------ src/MainWindow.h | 1 - src/timeline/TimelineModel.h | 2 +- src/ui/RoomSettings.cpp | 8 ++++---- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml index cf67c48c..01aef4c6 100644 --- a/resources/qml/ToggleButton.qml +++ b/resources/qml/ToggleButton.qml @@ -1,22 +1,32 @@ import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 +import QtQuick 2.12 +import QtQuick.Controls 2.12 import im.nheko 1.0 Switch { - style: SwitchStyle { - handle: Rectangle { - width: 20 - height: 20 - radius: 90 - color: "whitesmoke" + id: toggleButton + + indicator: Item { + implicitWidth: 48 + implicitHeight: 26 + + Rectangle { + height: parent.height/2 + radius: height/2 + width: parent.width - height + x: radius + y: parent.height / 2 - height / 2 + color: toggleButton.checked ? "skyblue" : "grey" + border.color: "#cccccc" } - groove: Rectangle { - implicitWidth: 40 - implicitHeight: 20 - radius: 90 - color: checked ? "skyblue" : "grey" + Rectangle { + x: toggleButton.checked ? parent.width - width : 0 + width: parent.height + height: width + radius: width/2 + color: toggleButton.down ? "whitesmoke" : "whitesmoke" + border.color: "#999999" } } } \ No newline at end of file diff --git a/src/MainWindow.h b/src/MainWindow.h index 5c2df8b6..4a8ea642 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -54,7 +54,6 @@ class LeaveRoom; class Logout; class MemberList; class ReCaptcha; -class RoomSettingsOld; } class MainWindow : public QMainWindow diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 29207318..df067fd4 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -11,8 +11,8 @@ #include "CacheCryptoStructs.h" #include "EventStore.h" #include "InputBar.h" -#include "ui/UserProfile.h" #include "ui/RoomSettings.h" +#include "ui/UserProfile.h" namespace mtx::http { using RequestErr = const std::optional &; diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index d2b5a630..b166332c 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -1,21 +1,21 @@ #include "RoomSettings.h" +#include #include +#include #include #include #include -#include #include -#include #include #include #include "Cache.h" -#include "Logging.h" #include "Config.h" +#include "Logging.h" #include "MatrixClient.h" -#include "ui/TextField.h" #include "Utils.h" +#include "ui/TextField.h" using namespace mtx::events; From b5e351ab025fe751cd230371714cdee24125bfc4 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Sun, 14 Feb 2021 11:26:10 +0530 Subject: [PATCH 12/14] Replace rowlayouts with gridlayout and fix room settings initializer list --- resources/qml/RoomSettings.qml | 61 ++++++++++++++-------------------- src/ui/RoomSettings.cpp | 4 +-- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index b3602a6a..eebecebb 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -12,7 +12,7 @@ ApplicationWindow { x: MainWindow.x + (MainWindow.width / 2) - (width / 2) y: MainWindow.y + (MainWindow.height / 2) - (height / 2) - minimumWidth: 400 + minimumWidth: 420 minimumHeight: 650 palette: colors color: colors.window @@ -113,56 +113,55 @@ ApplicationWindow { wrapMode: TextEdit.WordWrap readOnly: true background: null + horizontalAlignment: TextEdit.AlignHCenter + selectByMouse: true } } - MatrixText { - text: "SETTINGS" - } + GridLayout { + columns: 2 - RowLayout { MatrixText { - text: "Notifications" + text: "SETTINGS" } Item { Layout.fillWidth: true } + MatrixText { + text: "Notifications" + Layout.fillWidth: true + } + ComboBox { model: [ "Muted", "Mentions only", "All messages" ] currentIndex: roomSettings.notifications onActivated: { roomSettings.changeNotifications(index) } + Layout.fillWidth: true } - } - RowLayout { MatrixText { text: "Room access" + Layout.fillWidth: true } ComboBox { - Layout.fillWidth: true enabled: roomSettings.canChangeJoinRules model: [ "Anyone and guests", "Anyone", "Invited users" ] currentIndex: roomSettings.accessJoinRules onActivated: { roomSettings.changeAccessRules(index) } + Layout.fillWidth: true } - } - RowLayout { MatrixText { text: "Encryption" } - Item { - Layout.fillWidth: true - } - ToggleButton { id: encryptionToggle @@ -175,6 +174,7 @@ ApplicationWindow { confirmEncryptionDialog.open(); } + Layout.alignment: Qt.AlignRight } MessageDialog { @@ -199,20 +199,14 @@ ApplicationWindow { standardButtons: Dialog.Ok | Dialog.Cancel } - } - - RowLayout { - visible: roomSettings.isEncryptionEnabled MatrixText { + visible: roomSettings.isEncryptionEnabled text: "Respond to key requests" } - Item { - Layout.fillWidth: true - } - ToggleButton { + visible: roomSettings.isEncryptionEnabled ToolTip.text: qsTr("Whether or not the client should respond automatically with the session keys upon request. Use with caution, this is a temporary measure to test the E2E implementation until device verification is completed.") @@ -222,40 +216,35 @@ ApplicationWindow { onClicked: { roomSettings.changeKeyRequestsPreference(checked) } + Layout.alignment: Qt.AlignRight } - } - MatrixText { - text: "INFO" - } - - RowLayout { MatrixText { - text: "Internal ID" + text: "INFO" } Item { Layout.fillWidth: true } + MatrixText { + text: "Internal ID" + } + MatrixText { text: roomSettings.roomId font.pixelSize: 12 + Layout.alignment: Qt.AlignRight } - } - RowLayout { MatrixText { text: "Room Version" } - Item { - Layout.fillWidth: true - } - MatrixText { text: roomSettings.roomVersion font.pixelSize: 12 + Layout.alignment: Qt.AlignRight } } diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index b166332c..aa6f60a0 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -165,8 +165,8 @@ EditModal::setFields(const QString &roomName, const QString &roomTopic) } RoomSettings::RoomSettings(QString roomid, QObject *parent) - : roomid_{std::move(roomid)} - , QObject(parent) + : QObject(parent) + , roomid_{std::move(roomid)} { retrieveRoomInfo(); From 8c4f0a070e6e592e63726079bb43118614843fc3 Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Tue, 16 Feb 2021 11:52:03 +0530 Subject: [PATCH 13/14] change togglebutton size, set textarea color to colors.text --- resources/qml/RoomSettings.qml | 3 ++- resources/qml/ToggleButton.qml | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index eebecebb..dd5c85d3 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -113,8 +113,9 @@ ApplicationWindow { wrapMode: TextEdit.WordWrap readOnly: true background: null - horizontalAlignment: TextEdit.AlignHCenter selectByMouse: true + color: colors.text + horizontalAlignment: TextEdit.AlignHCenter } } diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml index 01aef4c6..59ec1a12 100644 --- a/resources/qml/ToggleButton.qml +++ b/resources/qml/ToggleButton.qml @@ -8,10 +8,11 @@ Switch { indicator: Item { implicitWidth: 48 - implicitHeight: 26 + implicitHeight: 24 + y: parent.height / 2 - height / 2 Rectangle { - height: parent.height/2 + height: 3 * parent.height/4 radius: height/2 width: parent.width - height x: radius @@ -22,11 +23,12 @@ Switch { Rectangle { x: toggleButton.checked ? parent.width - width : 0 + y: parent.height / 2 - height / 2 width: parent.height height: width radius: width/2 color: toggleButton.down ? "whitesmoke" : "whitesmoke" - border.color: "#999999" + border.color: "#ebebeb" } } } \ No newline at end of file From f76f7b7f8adaf6fd1727b30c0e1af5e5adacfe7b Mon Sep 17 00:00:00 2001 From: Jedi18 Date: Tue, 16 Feb 2021 22:22:55 +0530 Subject: [PATCH 14/14] fixed roomsettings spacing and toggle button right align bug --- resources/qml/RoomSettings.qml | 17 +++++++++++++++-- resources/qml/ToggleButton.qml | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml index dd5c85d3..898853e9 100644 --- a/resources/qml/RoomSettings.qml +++ b/resources/qml/RoomSettings.qml @@ -121,9 +121,11 @@ ApplicationWindow { GridLayout { columns: 2 + rowSpacing: 10 MatrixText { text: "SETTINGS" + font.bold: true } Item { @@ -220,8 +222,19 @@ ApplicationWindow { Layout.alignment: Qt.AlignRight } + Item { + // for adding extra space between sections + Layout.fillWidth: true + } + + Item { + // for adding extra space between sections + Layout.fillWidth: true + } + MatrixText { text: "INFO" + font.bold: true } Item { @@ -234,7 +247,7 @@ ApplicationWindow { MatrixText { text: roomSettings.roomId - font.pixelSize: 12 + font.pixelSize: 14 Layout.alignment: Qt.AlignRight } @@ -244,7 +257,7 @@ ApplicationWindow { MatrixText { text: roomSettings.roomVersion - font.pixelSize: 12 + font.pixelSize: 14 Layout.alignment: Qt.AlignRight } } diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml index 59ec1a12..dfef6207 100644 --- a/resources/qml/ToggleButton.qml +++ b/resources/qml/ToggleButton.qml @@ -5,8 +5,10 @@ import im.nheko 1.0 Switch { id: toggleButton + implicitWidth: indicatorItem.width indicator: Item { + id: indicatorItem implicitWidth: 48 implicitHeight: 24 y: parent.height / 2 - height / 2