Rework how access rules for rooms are modified completely

This commit is contained in:
Nicolas Werner 2022-09-19 21:39:37 +02:00
parent 603b90a6f5
commit fe403ddc70
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
7 changed files with 562 additions and 79 deletions

View file

@ -94,6 +94,22 @@ Pane {
} }
Component {
id: allowedRoomSettingsComponent
AllowedRoomsSettingsDialog {
}
}
function showAllowedRoomsEditor(settings) {
var dialog = allowedRoomSettingsComponent.createObject(timelineRoot, {
"roomSettings": settings
});
dialog.show();
destroyOnClose(dialog);
}
Component { Component {
id: roomMembersComponent id: roomMembersComponent

View file

@ -0,0 +1,178 @@
// SPDX-FileCopyrightText: 2022 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
import ".."
import "../ui"
import Qt.labs.platform 1.1 as Platform
import QtQuick 2.15
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.13
import im.nheko 1.0
ApplicationWindow {
id: allowedDialog
property var roomSettings
minimumWidth: 340
minimumHeight: 450
width: 450
height: 680
palette: Nheko.colors
color: Nheko.colors.window
modality: Qt.NonModal
flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
title: qsTr("Allowed rooms settings")
Shortcut {
sequence: StandardKey.Cancel
onActivated: roomSettingsDialog.close()
}
ColumnLayout {
anchors.margins: Nheko.paddingMedium
anchors.fill: parent
spacing: 0
MatrixText {
text: qsTr("List of rooms that allow access to this room. Anyone who is in any of those rooms can join this room.")
font.pixelSize: Math.floor(fontMetrics.font.pixelSize * 1.1)
Layout.fillWidth: true
Layout.fillHeight: false
color: Nheko.colors.text
Layout.bottomMargin: Nheko.paddingMedium
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
id: view
clip: true
ScrollHelper {
flickable: parent
anchors.fill: parent
}
model: roomSettings.allowedRoomsModel
spacing: 4
cacheBuffer: 50
delegate: RowLayout {
anchors.left: parent.left
anchors.right: parent.right
ColumnLayout {
Layout.fillWidth: true
Text {
Layout.fillWidth: true
text: model.name
color: Nheko.colors.text
textFormat: Text.PlainText
}
Text {
Layout.fillWidth: true
text: model.isParent ? qsTr("Parent community") : qsTr("Other room")
color: Nheko.colors.buttonText
textFormat: Text.PlainText
}
}
ToggleButton {
checked: model.allowed
Layout.alignment: Qt.AlignRight
onCheckedChanged: model.allowed = checked
}
}
}
Column{
id: roomEntryCompleter
Layout.fillWidth: true
spacing: 1
z: 5
Completer {
id: roomCompleter
visible: roomEntry.text.length > 0
width: parent.width
roomId: allowedDialog.roomSettings.roomId
completerName: "room"
bottomToTop: true
fullWidth: true
avatarHeight: Nheko.avatarSize / 2
avatarWidth: Nheko.avatarSize / 2
centerRowContent: false
rowMargin: 2
rowSpacing: 2
}
MatrixTextField {
id: roomEntry
width: parent.width
placeholderText: qsTr("Enter additional rooms not in the list yet...")
//font.pixelSize: Math.ceil(quickSwitcher.textHeight * 0.6)
color: Nheko.colors.text
onTextEdited: {
roomCompleter.completer.searchString = text;
}
Keys.onPressed: {
if (event.key == Qt.Key_Up || event.key == Qt.Key_Backtab) {
event.accepted = true;
roomCompleter.up();
} else if (event.key == Qt.Key_Down || event.key == Qt.Key_Tab) {
event.accepted = true;
if (event.key == Qt.Key_Tab && (event.modifiers & Qt.ShiftModifier))
roomCompleter.up();
else
roomCompleter.down();
} else if (event.matches(StandardKey.InsertParagraphSeparator)) {
roomCompleter.finishCompletion();
event.accepted = true;
}
}
}
}
Connections {
function onCompletionSelected(id) {
console.log("selected: " + id);
roomSettings.allowedRoomsModel.addRoom(id);
roomEntry.clear();
}
function onCountChanged() {
if (roomCompleter.count > 0 && (roomCompleter.currentIndex < 0 || roomCompleter.currentIndex >= roomCompleter.count))
roomCompleter.currentIndex = 0;
}
target: roomCompleter
}
}
footer: DialogButtonBox {
id: dbb
standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
onAccepted: {
roomSettings.applyAllowedFromModel();
allowedDialog.close();
}
onRejected: allowedDialog.close()
}
}

View file

@ -288,32 +288,98 @@ ApplicationWindow {
} }
Label { Label {
text: qsTr("Room access") text: qsTr("Anyone can join")
Layout.fillWidth: true Layout.fillWidth: true
color: Nheko.colors.text color: Nheko.colors.text
} }
ComboBox { ToggleButton {
id: publicRoomButton
enabled: roomSettings.canChangeJoinRules enabled: roomSettings.canChangeJoinRules
model: { checked: !roomSettings.privateAccess
let opts = [qsTr("Anyone and guests"), qsTr("Anyone"), qsTr("Invited users")]; Layout.alignment: Qt.AlignRight
if (roomSettings.supportsKnocking) }
opts.push(qsTr("By knocking"));
if (roomSettings.supportsRestricted) Label {
opts.push(qsTr("Restricted by membership in other rooms")); text: qsTr("Allow knocking")
Layout.fillWidth: true
if (roomSettings.supportsKnockRestricted) color: Nheko.colors.text
opts.push(qsTr("Restricted by membership in other rooms or by knocking")); visible: knockingButton.visible
}
return opts;
} ToggleButton {
currentIndex: roomSettings.accessJoinRules id: knockingButton
onActivated: {
roomSettings.changeAccessRules(index); visible: !publicRoomButton.checked
} enabled: roomSettings.canChangeJoinRules && roomSettings.supportsKnocking
checked: roomSettings.knockingEnabled
onCheckedChanged: {
if (checked && !roomSettings.supportsKnockRestricted) restrictedButton.checked = false;
}
Layout.alignment: Qt.AlignRight
}
Label {
text: qsTr("Allow joining via other rooms")
Layout.fillWidth: true
color: Nheko.colors.text
visible: restrictedButton.visible
}
ToggleButton {
id: restrictedButton
visible: !publicRoomButton.checked
enabled: roomSettings.canChangeJoinRules && roomSettings.supportsRestricted
checked: roomSettings.restrictedEnabled
onCheckedChanged: {
if (checked && !roomSettings.supportsKnockRestricted) knockingButton.checked = false;
}
Layout.alignment: Qt.AlignRight
}
Label {
text: qsTr("Rooms to join via")
Layout.fillWidth: true
color: Nheko.colors.text
visible: allowedRoomsButton.visible
}
Button {
id: allowedRoomsButton
visible: restrictedButton.checked && restrictedButton.visible
enabled: roomSettings.canChangeJoinRules && roomSettings.supportsRestricted
text: qsTr("Change")
ToolTip.text: qsTr("Change the list of rooms users can join this room via. Usually this is the official community of this room.")
onClicked: timelineRoot.showAllowedRoomsEditor(roomSettings)
Layout.alignment: Qt.AlignRight
}
Label {
text: qsTr("Allow guests to join")
Layout.fillWidth: true
color: Nheko.colors.text
}
ToggleButton {
id: guestAccessButton
enabled: roomSettings.canChangeJoinRules
checked: roomSettings.guestAccess
Layout.alignment: Qt.AlignRight
}
Button {
visible: publicRoomButton.checked == roomSettings.privateAccess || knockingButton.checked != roomSettings.knockingEnabled || restrictedButton.checked != roomSettings.restrictedEnabled || guestAccessButton.checked != roomSettings.guestAccess || roomSettings.allowedRoomsModified
enabled: roomSettings.canChangeJoinRules
text: qsTr("Apply access rules")
onClicked: roomSettings.changeAccessRules(!publicRoomButton.checked, guestAccessButton.checked, knockingButton.checked, restrictedButton.checked)
Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
WheelHandler{} // suppress scrolling changing values
} }
Label { Label {

View file

@ -166,6 +166,7 @@
<file>qml/dialogs/ReadReceipts.qml</file> <file>qml/dialogs/ReadReceipts.qml</file>
<file>qml/dialogs/RoomDirectory.qml</file> <file>qml/dialogs/RoomDirectory.qml</file>
<file>qml/dialogs/RoomMembers.qml</file> <file>qml/dialogs/RoomMembers.qml</file>
<file>qml/dialogs/AllowedRoomsSettingsDialog.qml</file>
<file>qml/dialogs/RoomSettings.qml</file> <file>qml/dialogs/RoomSettings.qml</file>
<file>qml/dialogs/UserProfile.qml</file> <file>qml/dialogs/UserProfile.qml</file>
<file>qml/emoji/EmojiPicker.qml</file> <file>qml/emoji/EmojiPicker.qml</file>

View file

@ -148,6 +148,7 @@ MainWindow::registerQmlTypes()
qRegisterMetaType<mtx::responses::PublicRoom>(); qRegisterMetaType<mtx::responses::PublicRoom>();
qRegisterMetaType<mtx::responses::Profile>(); qRegisterMetaType<mtx::responses::Profile>();
qRegisterMetaType<CombinedImagePackModel *>(); qRegisterMetaType<CombinedImagePackModel *>();
qRegisterMetaType<RoomSettingsAllowedRoomsModel *>();
qRegisterMetaType<mtx::events::collections::TimelineEvents>(); qRegisterMetaType<mtx::events::collections::TimelineEvents>();
qRegisterMetaType<std::vector<DeviceInfo>>(); qRegisterMetaType<std::vector<DeviceInfo>>();

View file

@ -27,6 +27,7 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent)
: QObject(parent) : QObject(parent)
, roomid_{std::move(roomid)} , roomid_{std::move(roomid)}
{ {
connect(this, &RoomSettings::accessJoinRulesChanged, &RoomSettings::allowedRoomsChanged);
retrieveRoomInfo(); retrieveRoomInfo();
// get room setting notifications // get room setting notifications
@ -66,22 +67,15 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent)
}); });
// access rules // access rules
if (info_.join_rule == state::JoinRule::Public) { this->accessRules_ = cache::client()
if (info_.guest_access) { ->getStateEvent<mtx::events::state::JoinRules>(roomid_.toStdString())
accessRules_ = 0; .value_or(mtx::events::StateEvent<mtx::events::state::JoinRules>{})
} else { .content;
accessRules_ = 1; using mtx::events::state::AccessState;
} guestRules_ = info_.guest_access ? AccessState::CanJoin : AccessState::Forbidden;
} else if (info_.join_rule == state::JoinRule::Invite) {
accessRules_ = 2;
} else if (info_.join_rule == state::JoinRule::Knock) {
accessRules_ = 3;
} else if (info_.join_rule == state::JoinRule::Restricted) {
accessRules_ = 4;
} else if (info_.join_rule == state::JoinRule::KnockRestricted) {
accessRules_ = 5;
}
emit accessJoinRulesChanged(); emit accessJoinRulesChanged();
this->allowedRoomsModel = new RoomSettingsAllowedRoomsModel(this);
} }
QString QString
@ -158,10 +152,49 @@ RoomSettings::notifications()
return notifications_; return notifications_;
} }
int bool
RoomSettings::accessJoinRules() RoomSettings::privateAccess() const
{ {
return accessRules_; return accessRules_.join_rule != mtx::events::state::JoinRule::Public;
}
bool
RoomSettings::guestAccess() const
{
return guestRules_ == mtx::events::state::AccessState::CanJoin;
}
bool
RoomSettings::knockingEnabled() const
{
return accessRules_.join_rule == mtx::events::state::JoinRule::Knock ||
accessRules_.join_rule == mtx::events::state::JoinRule::KnockRestricted;
}
bool
RoomSettings::restrictedEnabled() const
{
return accessRules_.join_rule == mtx::events::state::JoinRule::Restricted ||
accessRules_.join_rule == mtx::events::state::JoinRule::KnockRestricted;
}
QStringList
RoomSettings::allowedRooms() const
{
QStringList rooms;
rooms.reserve(accessRules_.allow.size());
for (const auto &e : accessRules_.allow) {
if (e.type == mtx::events::state::JoinAllowanceType::RoomMembership)
rooms.push_back(QString::fromStdString(e.room_id));
}
return rooms;
}
void
RoomSettings::setAllowedRooms(QStringList rooms)
{
accessRules_.allow.clear();
for (const auto &e : rooms) {
accessRules_.allow.push_back(
{mtx::events::state::JoinAllowanceType::RoomMembership, e.toStdString()});
}
} }
void void
@ -254,24 +287,48 @@ RoomSettings::isEncryptionEnabled() const
bool bool
RoomSettings::supportsKnocking() const RoomSettings::supportsKnocking() const
{ {
return info_.version != "" && info_.version != "1" && info_.version != "2" && const static std::set<std::string_view> unsupported{
info_.version != "3" && info_.version != "4" && info_.version != "5" && "",
info_.version != "6"; "1",
"2",
"3",
"4",
"5",
"6",
};
return !unsupported.count(info_.version);
} }
bool bool
RoomSettings::supportsRestricted() const RoomSettings::supportsRestricted() const
{ {
return info_.version != "" && info_.version != "1" && info_.version != "2" && const static std::set<std::string_view> unsupported{
info_.version != "3" && info_.version != "4" && info_.version != "5" && "",
info_.version != "6" && info_.version != "7"; "1",
"2",
"3",
"4",
"5",
"6",
"7",
};
return !unsupported.count(info_.version);
} }
bool bool
RoomSettings::supportsKnockRestricted() const RoomSettings::supportsKnockRestricted() const
{ {
return info_.version != "" && info_.version != "1" && info_.version != "2" && const static std::set<std::string_view> unsupported{
info_.version != "3" && info_.version != "4" && info_.version != "5" && "",
info_.version != "6" && info_.version != "7" && info_.version != "8" && "1",
info_.version != "9"; "2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
};
return !unsupported.count(info_.version);
} }
void void
@ -327,47 +384,41 @@ RoomSettings::changeNotifications(int currentIndex)
} }
void void
RoomSettings::changeAccessRules(int index) RoomSettings::changeAccessRules(bool private_,
bool guestsAllowed,
bool knockingAllowed,
bool restrictedAllowed)
{ {
using namespace mtx::events::state; using namespace mtx::events::state;
auto guest_access = [](int index) -> state::GuestAccess { auto guest_access = [guestsAllowed]() -> state::GuestAccess {
state::GuestAccess event; state::GuestAccess event;
if (index == 0) if (guestsAllowed)
event.guest_access = state::AccessState::CanJoin; event.guest_access = state::AccessState::CanJoin;
else else
event.guest_access = state::AccessState::Forbidden; event.guest_access = state::AccessState::Forbidden;
return event; return event;
}(index); }();
auto join_rule = [](int index) -> state::JoinRules { auto join_rule = [this, private_, knockingAllowed, restrictedAllowed]() -> state::JoinRules {
state::JoinRules event; state::JoinRules event = this->accessRules_;
switch (index) { if (!private_) {
case 0:
case 1:
event.join_rule = state::JoinRule::Public; event.join_rule = state::JoinRule::Public;
break; } else if (knockingAllowed && restrictedAllowed && supportsKnockRestricted()) {
case 2:
event.join_rule = state::JoinRule::Invite;
break;
case 3:
event.join_rule = state::JoinRule::Knock;
break;
case 4:
event.join_rule = state::JoinRule::Restricted;
break;
case 5:
event.join_rule = state::JoinRule::KnockRestricted; event.join_rule = state::JoinRule::KnockRestricted;
break; } else if (knockingAllowed && supportsKnocking()) {
default: event.join_rule = state::JoinRule::Knock;
} else if (restrictedAllowed && supportsRestricted()) {
event.join_rule = state::JoinRule::Restricted;
} else {
event.join_rule = state::JoinRule::Invite; event.join_rule = state::JoinRule::Invite;
} }
return event; return event;
}(index); }();
updateAccessRules(roomid_.toStdString(), join_rule, guest_access); updateAccessRules(roomid_.toStdString(), join_rule, guest_access);
} }
@ -445,13 +496,16 @@ RoomSettings::updateAccessRules(const std::string &room_id,
const mtx::events::state::JoinRules &join_rule, const mtx::events::state::JoinRules &join_rule,
const mtx::events::state::GuestAccess &guest_access) const mtx::events::state::GuestAccess &guest_access)
{ {
isLoading_ = true; isLoading_ = true;
allowedRoomsModified_ = false;
emit loadingChanged(); emit loadingChanged();
emit allowedRoomsModifiedChanged();
http::client()->send_state_event( http::client()->send_state_event(
room_id, room_id,
join_rule, join_rule,
[this, room_id, guest_access](const mtx::responses::EventId &, mtx::http::RequestErr err) { [this, room_id, guest_access, join_rule](const mtx::responses::EventId &,
mtx::http::RequestErr err) {
if (err) { if (err) {
nhlog::net()->warn("failed to send m.room.join_rule: {} {}", nhlog::net()->warn("failed to send m.room.join_rule: {} {}",
static_cast<int>(err->status_code), static_cast<int>(err->status_code),
@ -465,7 +519,7 @@ RoomSettings::updateAccessRules(const std::string &room_id,
http::client()->send_state_event( http::client()->send_state_event(
room_id, room_id,
guest_access, guest_access,
[this](const mtx::responses::EventId &, mtx::http::RequestErr err) { [this, join_rule](const mtx::responses::EventId &, mtx::http::RequestErr err) {
if (err) { if (err) {
nhlog::net()->warn("failed to send m.room.guest_access: {} {}", nhlog::net()->warn("failed to send m.room.guest_access: {} {}",
static_cast<int>(err->status_code), static_cast<int>(err->status_code),
@ -475,6 +529,9 @@ RoomSettings::updateAccessRules(const std::string &room_id,
isLoading_ = false; isLoading_ = false;
emit loadingChanged(); emit loadingChanged();
this->accessRules_ = join_rule;
emit accessJoinRulesChanged();
}); });
}); });
} }
@ -576,3 +633,101 @@ RoomSettings::updateAvatar()
}); });
}); });
} }
RoomSettingsAllowedRoomsModel::RoomSettingsAllowedRoomsModel(RoomSettings *parent)
: QAbstractListModel(parent)
, settings(parent)
{
this->allowedRoomIds = settings->allowedRooms();
auto prIds = cache::client()->getParentRoomIds(settings->roomId().toStdString());
for (const auto &prId : prIds) {
this->parentSpaces.insert(QString::fromStdString(prId));
}
this->listedRoomIds = QStringList(parentSpaces.begin(), parentSpaces.end());
for (const auto &e : this->allowedRoomIds) {
if (!this->parentSpaces.count(e))
this->listedRoomIds.push_back(e);
}
}
QHash<int, QByteArray>
RoomSettingsAllowedRoomsModel::roleNames() const
{
return {
{Roles::Name, "name"},
{Roles::IsAllowed, "allowed"},
{Roles::IsSpaceParent, "isParent"},
};
}
int
RoomSettingsAllowedRoomsModel::rowCount(const QModelIndex &) const
{
return listedRoomIds.size();
}
QVariant
RoomSettingsAllowedRoomsModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() > listedRoomIds.size())
return {};
if (role == Roles::IsAllowed) {
return allowedRoomIds.contains(listedRoomIds.at(index.row()));
} else if (role == Roles::IsSpaceParent) {
return parentSpaces.find(listedRoomIds.at(index.row())) != parentSpaces.cend();
} else if (role == Roles::Name) {
auto id = listedRoomIds.at(index.row());
auto info = cache::client()->getRoomInfo({
id.toStdString(),
});
if (!info.empty())
return QString::fromStdString(info[id].name);
else
return "";
} else {
return {};
}
}
bool
RoomSettingsAllowedRoomsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.row() < 0 || index.row() > listedRoomIds.size())
return false;
if (role != Roles::IsAllowed)
return false;
if (value.toBool()) {
if (!allowedRoomIds.contains(listedRoomIds.at(index.row())))
allowedRoomIds.push_back(listedRoomIds.at(index.row()));
} else {
allowedRoomIds.removeAll(listedRoomIds.at(index.row()));
}
return true;
}
void
RoomSettingsAllowedRoomsModel::addRoom(QString room)
{
if (listedRoomIds.contains(room) || !room.startsWith('!'))
return;
beginInsertRows(QModelIndex(), listedRoomIds.size(), listedRoomIds.size());
listedRoomIds.push_back(room);
allowedRoomIds.push_back(room);
endInsertRows();
}
void
RoomSettings::applyAllowedFromModel()
{
this->setAllowedRooms(this->allowedRoomsModel->allowedRoomIds);
this->allowedRoomsModified_ = true;
emit allowedRoomsModifiedChanged();
}

View file

@ -5,10 +5,13 @@
#pragma once #pragma once
#include <QAbstractListModel>
#include <QObject> #include <QObject>
#include <QSet> #include <QSet>
#include <QString> #include <QString>
#include <unordered_set>
#include <mtx/events/event_type.hpp> #include <mtx/events/event_type.hpp>
#include <mtx/events/guest_access.hpp> #include <mtx/events/guest_access.hpp>
@ -27,6 +30,43 @@ signals:
void stopLoading(); void stopLoading();
}; };
class RoomSettings;
class RoomSettingsAllowedRoomsModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles
{
Name,
IsAllowed,
IsSpaceParent,
};
explicit RoomSettingsAllowedRoomsModel(RoomSettings *parent);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool
setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole) override;
Q_INVOKABLE void addRoom(QString room);
Qt::ItemFlags flags(const QModelIndex &) const override
{
return Qt::ItemIsEditable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled |
Qt::ItemNeverHasChildren;
}
QStringList allowedRoomIds;
private:
QStringList listedRoomIds;
std::unordered_set<QString> parentSpaces;
RoomSettings *settings;
};
class RoomSettings : public QObject class RoomSettings : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -39,7 +79,10 @@ class RoomSettings : public QObject
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
Q_PROPERTY(int memberCount READ memberCount CONSTANT) Q_PROPERTY(int memberCount READ memberCount CONSTANT)
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged) Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged) Q_PROPERTY(bool privateAccess READ privateAccess NOTIFY accessJoinRulesChanged)
Q_PROPERTY(bool guestAccess READ guestAccess NOTIFY accessJoinRulesChanged)
Q_PROPERTY(bool knockingEnabled READ knockingEnabled NOTIFY accessJoinRulesChanged)
Q_PROPERTY(bool restrictedEnabled READ restrictedEnabled NOTIFY accessJoinRulesChanged)
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged) Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT) Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT) Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
@ -49,6 +92,11 @@ class RoomSettings : public QObject
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT) Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT) Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
Q_PROPERTY(bool supportsKnockRestricted READ supportsKnockRestricted CONSTANT) Q_PROPERTY(bool supportsKnockRestricted READ supportsKnockRestricted CONSTANT)
Q_PROPERTY(
QStringList allowedRooms READ allowedRooms WRITE setAllowedRooms NOTIFY allowedRoomsChanged)
Q_PROPERTY(RoomSettingsAllowedRoomsModel *allowedRoomsModel MEMBER allowedRoomsModel CONSTANT)
Q_PROPERTY(
bool allowedRoomsModified READ allowedRoomsModified NOTIFY allowedRoomsModifiedChanged)
public: public:
RoomSettings(QString roomid, QObject *parent = nullptr); RoomSettings(QString roomid, QObject *parent = nullptr);
@ -62,7 +110,10 @@ public:
QString roomAvatarUrl(); QString roomAvatarUrl();
int memberCount() const; int memberCount() const;
int notifications(); int notifications();
int accessJoinRules(); bool privateAccess() const;
bool guestAccess() const;
bool knockingEnabled() const;
bool restrictedEnabled() const;
bool isLoading() const; bool isLoading() const;
//! Whether the user has enough power level to send m.room.join_rules events. //! Whether the user has enough power level to send m.room.join_rules events.
bool canChangeJoinRules() const; bool canChangeJoinRules() const;
@ -76,14 +127,22 @@ public:
bool supportsKnocking() const; bool supportsKnocking() const;
bool supportsRestricted() const; bool supportsRestricted() const;
bool supportsKnockRestricted() const; bool supportsKnockRestricted() const;
QStringList allowedRooms() const;
void setAllowedRooms(QStringList rooms);
bool allowedRoomsModified() const { return allowedRoomsModified_; }
Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void enableEncryption();
Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void updateAvatar();
Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeAccessRules(bool private_,
bool guestsAllowed,
bool knockingAllowed,
bool restrictedAllowed);
Q_INVOKABLE void changeNotifications(int currentIndex); Q_INVOKABLE void changeNotifications(int currentIndex);
Q_INVOKABLE void changeTopic(QString topic); Q_INVOKABLE void changeTopic(QString topic);
Q_INVOKABLE void changeName(QString name); Q_INVOKABLE void changeName(QString name);
Q_INVOKABLE void applyAllowedFromModel();
signals: signals:
void loadingChanged(); void loadingChanged();
void roomNameChanged(); void roomNameChanged();
@ -92,7 +151,9 @@ signals:
void encryptionChanged(); void encryptionChanged();
void notificationsChanged(); void notificationsChanged();
void accessJoinRulesChanged(); void accessJoinRulesChanged();
void allowedRoomsChanged();
void displayError(const QString &errorMessage); void displayError(const QString &errorMessage);
void allowedRoomsModifiedChanged();
public slots: public slots:
void stopLoading(); void stopLoading();
@ -106,9 +167,14 @@ private:
private: private:
QString roomid_; QString roomid_;
bool usesEncryption_ = false; bool usesEncryption_ = false;
bool isLoading_ = false; bool isLoading_ = false;
bool allowedRoomsModified_ = false;
RoomInfo info_; RoomInfo info_;
int notifications_ = 0; int notifications_ = 0;
int accessRules_ = 0;
mtx::events::state::JoinRules accessRules_;
mtx::events::state::AccessState guestRules_ = mtx::events::state::AccessState::Forbidden;
RoomSettingsAllowedRoomsModel *allowedRoomsModel;
}; };