summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/dialogs/RoomSettings.cpp205
-rw-r--r--src/dialogs/RoomSettings.h24
2 files changed, 188 insertions, 41 deletions
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp
index 8b450d7e..df4eaeee 100644
--- a/src/dialogs/RoomSettings.cpp
+++ b/src/dialogs/RoomSettings.cpp
@@ -5,6 +5,7 @@
 #include <QPainter>
 #include <QPixmap>
 #include <QSharedPointer>
+#include <QShowEvent>
 #include <QStyleOption>
 #include <QVBoxLayout>
 
@@ -17,6 +18,7 @@
 #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/Theme.h"
@@ -207,7 +209,39 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
         accessCombo->addItem(tr("Anyone and guests"));
         accessCombo->addItem(tr("Anyone"));
         accessCombo->addItem(tr("Invited users"));
-        accessCombo->setDisabled(true);
+        accessCombo->setDisabled(
+          !canChangeJoinRules(room_id_.toStdString(), utils::localUser().toStdString()));
+        connect(accessCombo, QOverload<int>::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 = JoinRule::Public;
+                                break;
+                        default:
+                                event.join_rule = JoinRule::Invite;
+                        }
+
+                        return event;
+                }(index);
+
+                updateAccessRules(room_id_.toStdString(), join_rule, guest_access);
+        });
 
         if (info_.join_rule == JoinRule::Public) {
                 if (info_.guest_access) {
@@ -321,6 +355,20 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
 
         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);
+
         layout->addWidget(avatar_, Qt::AlignCenter | Qt::AlignTop);
         layout->addLayout(textLayout);
         layout->addLayout(btnLayout_);
@@ -329,6 +377,8 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
         layout->addLayout(accessOptionLayout);
         layout->addLayout(encryptionOptionLayout);
         layout->addLayout(keyRequestsLayout);
+        layout->addWidget(errorLabel_);
+        layout->addLayout(spinnerLayout);
         layout->addStretch(1);
 
         connect(this, &RoomSettings::enableEncryptionError, this, [this](const QString &msg) {
@@ -337,6 +387,21 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
 
                 emit ChatPage::instance()->showNotification(msg);
         });
+
+        connect(this, &RoomSettings::showErrorMessage, this, [this](const QString &msg) {
+                if (!errorLabel_)
+                        return;
+
+                stopLoadingSpinner();
+
+                errorLabel_->show();
+                errorLabel_->setText(msg);
+        });
+
+        connect(this, &RoomSettings::accessRulesUpdated, this, [this]() {
+                stopLoadingSpinner();
+                resetErrorLabel();
+        });
 }
 
 void
@@ -346,16 +411,7 @@ RoomSettings::setupEditButton()
         btnLayout_->setSpacing(BUTTON_SPACING);
         btnLayout_->setMargin(0);
 
-        try {
-                auto userId = utils::localUser().toStdString();
-
-                hasEditRights_ = cache::client()->hasEnoughPowerLevel(
-                  {EventType::RoomName, EventType::RoomTopic}, room_id_.toStdString(), userId);
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn("lmdb error: {}", e.what());
-        }
-
-        if (!hasEditRights_)
+        if (!canChangeNameAndTopic(room_id_.toStdString(), utils::localUser().toStdString()))
                 return;
 
         QIcon editIcon;
@@ -398,30 +454,6 @@ RoomSettings::retrieveRoomInfo()
 }
 
 void
-RoomSettings::saveSettings()
-{
-        // TODO: Save access changes to the room
-        if (accessCombo->currentIndex() < 2) {
-                if (info_.join_rule != JoinRule::Public) {
-                        // Make join_rule Public
-                }
-                if (accessCombo->currentIndex() == 0) {
-                        if (!info_.guest_access) {
-                                // Make guest_access CanJoin
-                        }
-                }
-        } else {
-                if (info_.join_rule != JoinRule::Invite) {
-                        // Make join_rule invite
-                }
-                if (info_.guest_access) {
-                        // Make guest_access forbidden
-                }
-        }
-        closing();
-}
-
-void
 RoomSettings::enableEncryption()
 {
         const auto room_id = room_id_.toStdString();
@@ -444,6 +476,15 @@ RoomSettings::enableEncryption()
 }
 
 void
+RoomSettings::showEvent(QShowEvent *event)
+{
+        resetErrorLabel();
+        stopLoadingSpinner();
+
+        QWidget::showEvent(event);
+}
+
+void
 RoomSettings::paintEvent(QPaintEvent *)
 {
         QStyleOption opt;
@@ -451,3 +492,97 @@ RoomSettings::paintEvent(QPaintEvent *)
         QPainter p(this);
         style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }
+
+bool
+RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const
+{
+        try {
+                return cache::client()->hasEnoughPowerLevel(
+                  {EventType::RoomJoinRules}, room_id, user_id);
+        } catch (const lmdb::error &e) {
+                nhlog::db()->warn("lmdb error: {}", e.what());
+        }
+
+        return false;
+}
+
+bool
+RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const
+{
+        try {
+                return cache::client()->hasEnoughPowerLevel(
+                  {EventType::RoomName, EventType::RoomTopic}, room_id, user_id);
+        } catch (const lmdb::error &e) {
+                nhlog::db()->warn("lmdb error: {}", e.what());
+        }
+
+        return false;
+}
+
+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<state::JoinRules, EventType::RoomJoinRules>(
+          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<int>(err->status_code),
+                                             err->matrix_error.error);
+                          emit showErrorMessage(QString::fromStdString(err->matrix_error.error));
+
+                          return;
+                  }
+
+                  http::client()->send_state_event<state::GuestAccess, EventType::RoomGuestAccess>(
+                    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<int>(err->status_code),
+                                                       err->matrix_error.error);
+                                    emit showErrorMessage(
+                                      QString::fromStdString(err->matrix_error.error));
+
+                                    return;
+                            }
+
+                            emit accessRulesUpdated();
+                    });
+          });
+}
+
+void
+RoomSettings::stopLoadingSpinner()
+{
+        if (spinner_) {
+                spinner_->stop();
+                spinner_->hide();
+        }
+}
+
+void
+RoomSettings::startLoadingSpinner()
+{
+        if (spinner_) {
+                spinner_->start();
+                spinner_->show();
+        }
+}
+
+void
+RoomSettings::resetErrorLabel()
+{
+        if (errorLabel_) {
+                errorLabel_->hide();
+                errorLabel_->clear();
+        }
+}
diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettings.h
index 321ea551..192e922f 100644
--- a/src/dialogs/RoomSettings.h
+++ b/src/dialogs/RoomSettings.h
@@ -9,6 +9,8 @@ class Avatar;
 class FlatButton;
 class QComboBox;
 class QHBoxLayout;
+class QShowEvent;
+class LoadingIndicator;
 class QLabel;
 class QLabel;
 class QLayout;
@@ -60,15 +62,24 @@ public:
 signals:
         void closing();
         void enableEncryptionError(const QString &msg);
+        void showErrorMessage(const QString &msg);
+        void accessRulesUpdated();
 
 protected:
         void paintEvent(QPaintEvent *event) override;
-
-private slots:
-        void saveSettings();
+        void showEvent(QShowEvent *event) override;
 
 private:
-        static constexpr int AvatarSize = 64;
+        //! 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;
+        void updateAccessRules(const std::string &room_id,
+                               const mtx::events::state::JoinRules &,
+                               const mtx::events::state::GuestAccess &);
+        void stopLoadingSpinner();
+        void startLoadingSpinner();
+        void resetErrorLabel();
 
         void setAvatar(const QImage &img) { avatarImg_ = img; }
         void setupEditButton();
@@ -78,8 +89,6 @@ private:
 
         Avatar *avatar_;
 
-        //! Whether the user would be able to change the name or the topic of the room.
-        bool hasEditRights_  = true;
         bool usesEncryption_ = false;
         QHBoxLayout *btnLayout_;
 
@@ -89,6 +98,9 @@ private:
         QString room_id_;
         QImage avatarImg_;
 
+        QLabel *errorLabel_;
+        LoadingIndicator *spinner_;
+
         QComboBox *accessCombo;
         Toggle *encryptionToggle_;
         Toggle *keyRequestsToggle_;