Allow user to configure join rules for a room

This commit is contained in:
Konstantinos Sideris 2018-08-09 16:38:11 +03:00
parent 509d3eb8b4
commit aec5587947
2 changed files with 188 additions and 41 deletions

View file

@ -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;
@ -397,30 +453,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()
{
@ -443,6 +475,15 @@ RoomSettings::enableEncryption()
});
}
void
RoomSettings::showEvent(QShowEvent *event)
{
resetErrorLabel();
stopLoadingSpinner();
QWidget::showEvent(event);
}
void
RoomSettings::paintEvent(QPaintEvent *)
{
@ -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();
}
}

View file

@ -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_;