summary refs log tree commit diff
path: root/src/timeline
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-05-02 18:01:18 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2021-05-02 18:06:56 +0200
commitab0baf5d9eb3319f8d3da15bd966ab8ab2810fce (patch)
treecba4d1153ec3e8573e8a6821d3e6b07d771fdccd /src/timeline
parentFix crash when you have no rooms and open the global user profile (diff)
downloadnheko-ab0baf5d9eb3319f8d3da15bd966ab8ab2810fce.tar.xz
Only show actions, when you have permissions to do them
Diffstat (limited to 'src/timeline')
-rw-r--r--src/timeline/Permissions.cpp63
-rw-r--r--src/timeline/Permissions.h33
-rw-r--r--src/timeline/TimelineModel.cpp119
-rw-r--r--src/timeline/TimelineModel.h7
4 files changed, 220 insertions, 2 deletions
diff --git a/src/timeline/Permissions.cpp b/src/timeline/Permissions.cpp
new file mode 100644

index 00000000..1eaab468 --- /dev/null +++ b/src/timeline/Permissions.cpp
@@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2021 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "Permissions.h" + +#include "Cache_p.h" +#include "MatrixClient.h" +#include "TimelineModel.h" + +Permissions::Permissions(TimelineModel *parent) + : QObject(parent) + , room(parent) +{ + invalidate(); +} + +void +Permissions::invalidate() +{ + pl = cache::client() + ->getStateEvent<mtx::events::state::PowerLevels>(room->roomId().toStdString()) + .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{}) + .content; +} + +bool +Permissions::canInvite() +{ + return pl.user_level(http::client()->user_id().to_string()) >= pl.invite; +} + +bool +Permissions::canBan() +{ + return pl.user_level(http::client()->user_id().to_string()) >= pl.ban; +} + +bool +Permissions::canKick() +{ + return pl.user_level(http::client()->user_id().to_string()) >= pl.kick; +} + +bool +Permissions::canRedact() +{ + return pl.user_level(http::client()->user_id().to_string()) >= pl.redact; +} +bool +Permissions::canChange(int eventType) +{ + return pl.user_level(http::client()->user_id().to_string()) >= + pl.state_level(to_string(qml_mtx_events::fromRoomEventType( + static_cast<qml_mtx_events::EventType>(eventType)))); +} +bool +Permissions::canSend(int eventType) +{ + return pl.user_level(http::client()->user_id().to_string()) >= + pl.event_level(to_string(qml_mtx_events::fromRoomEventType( + static_cast<qml_mtx_events::EventType>(eventType)))); +} diff --git a/src/timeline/Permissions.h b/src/timeline/Permissions.h new file mode 100644
index 00000000..f7e6f389 --- /dev/null +++ b/src/timeline/Permissions.h
@@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2021 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <QObject> + +#include <mtx/events/power_levels.hpp> + +class TimelineModel; + +class Permissions : public QObject +{ + Q_OBJECT + +public: + Permissions(TimelineModel *parent); + + Q_INVOKABLE bool canInvite(); + Q_INVOKABLE bool canBan(); + Q_INVOKABLE bool canKick(); + + Q_INVOKABLE bool canRedact(); + Q_INVOKABLE bool canChange(int eventType); + Q_INVOKABLE bool canSend(int eventType); + + void invalidate(); + +private: + TimelineModel *room; + mtx::events::state::PowerLevels pl; +}; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index c472ab33..a1e9ac0c 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp
@@ -207,6 +207,111 @@ toRoomEventTypeString(const mtx::events::collections::TimelineEvents &event) event); } +mtx::events::EventType +qml_mtx_events::fromRoomEventType(qml_mtx_events::EventType t) +{ + switch (t) { + // Unsupported event + case qml_mtx_events::Unsupported: + return mtx::events::EventType::Unsupported; + + /// m.room_key_request + case qml_mtx_events::KeyRequest: + return mtx::events::EventType::RoomKeyRequest; + /// m.reaction: + case qml_mtx_events::Reaction: + return mtx::events::EventType::Reaction; + /// m.room.aliases + case qml_mtx_events::Aliases: + return mtx::events::EventType::RoomAliases; + /// m.room.avatar + case qml_mtx_events::Avatar: + return mtx::events::EventType::RoomAvatar; + /// m.call.invite + case qml_mtx_events::CallInvite: + return mtx::events::EventType::CallInvite; + /// m.call.answer + case qml_mtx_events::CallAnswer: + return mtx::events::EventType::CallAnswer; + /// m.call.hangup + case qml_mtx_events::CallHangUp: + return mtx::events::EventType::CallHangUp; + /// m.call.candidates + case qml_mtx_events::CallCandidates: + return mtx::events::EventType::CallCandidates; + /// m.room.canonical_alias + case qml_mtx_events::CanonicalAlias: + return mtx::events::EventType::RoomCanonicalAlias; + /// m.room.create + case qml_mtx_events::RoomCreate: + return mtx::events::EventType::RoomCreate; + /// m.room.encrypted. + case qml_mtx_events::Encrypted: + return mtx::events::EventType::RoomEncrypted; + /// m.room.encryption. + case qml_mtx_events::Encryption: + return mtx::events::EventType::RoomEncryption; + /// m.room.guest_access + case qml_mtx_events::RoomGuestAccess: + return mtx::events::EventType::RoomGuestAccess; + /// m.room.history_visibility + case qml_mtx_events::RoomHistoryVisibility: + return mtx::events::EventType::RoomHistoryVisibility; + /// m.room.join_rules + case qml_mtx_events::RoomJoinRules: + return mtx::events::EventType::RoomJoinRules; + /// m.room.member + case qml_mtx_events::Member: + return mtx::events::EventType::RoomMember; + /// m.room.name + case qml_mtx_events::Name: + return mtx::events::EventType::RoomName; + /// m.room.power_levels + case qml_mtx_events::PowerLevels: + return mtx::events::EventType::RoomPowerLevels; + /// m.room.tombstone + case qml_mtx_events::Tombstone: + return mtx::events::EventType::RoomTombstone; + /// m.room.topic + case qml_mtx_events::Topic: + return mtx::events::EventType::RoomTopic; + /// m.room.redaction + case qml_mtx_events::Redaction: + return mtx::events::EventType::RoomRedaction; + /// m.room.pinned_events + case qml_mtx_events::PinnedEvents: + return mtx::events::EventType::RoomPinnedEvents; + // m.sticker + case qml_mtx_events::Sticker: + return mtx::events::EventType::Sticker; + // m.tag + case qml_mtx_events::Tag: + return mtx::events::EventType::Tag; + /// m.room.message + case qml_mtx_events::AudioMessage: + case qml_mtx_events::EmoteMessage: + case qml_mtx_events::FileMessage: + case qml_mtx_events::ImageMessage: + case qml_mtx_events::LocationMessage: + case qml_mtx_events::NoticeMessage: + case qml_mtx_events::TextMessage: + case qml_mtx_events::VideoMessage: + case qml_mtx_events::Redacted: + case qml_mtx_events::UnknownMessage: + case qml_mtx_events::KeyVerificationRequest: + case qml_mtx_events::KeyVerificationStart: + case qml_mtx_events::KeyVerificationMac: + case qml_mtx_events::KeyVerificationAccept: + case qml_mtx_events::KeyVerificationCancel: + case qml_mtx_events::KeyVerificationKey: + case qml_mtx_events::KeyVerificationDone: + case qml_mtx_events::KeyVerificationReady: + return mtx::events::EventType::RoomMessage; + default: + return mtx::events::EventType::Unsupported; + }; +} + TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObject *parent) : QAbstractListModel(parent) , events(room_id.toStdString(), this) @@ -282,6 +387,7 @@ TimelineModel::roleNames() const {Body, "body"}, {FormattedBody, "formattedBody"}, {PreviousMessageUserId, "previousMessageUserId"}, + {IsSender, "isSender"}, {UserId, "userId"}, {UserName, "userName"}, {PreviousMessageDay, "previousMessageDay"}, @@ -333,6 +439,8 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r namespace acc = mtx::accessors; switch (role) { + case IsSender: + return QVariant(acc::sender(event) == http::client()->user_id().to_string()); case UserId: return QVariant(QString::fromStdString(acc::sender(event))); case UserName: @@ -497,6 +605,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r m.insert(names[IsOnlyEmoji], data(event, static_cast<int>(IsOnlyEmoji))); m.insert(names[Body], data(event, static_cast<int>(Body))); m.insert(names[FormattedBody], data(event, static_cast<int>(FormattedBody))); + m.insert(names[IsSender], data(event, static_cast<int>(IsSender))); m.insert(names[UserId], data(event, static_cast<int>(UserId))); m.insert(names[UserName], data(event, static_cast<int>(UserName))); m.insert(names[Day], data(event, static_cast<int>(Day))); @@ -608,7 +717,10 @@ TimelineModel::syncState(const mtx::responses::State &s) emit roomNameChanged(); else if (std::holds_alternative<StateEvent<state::Topic>>(e)) emit roomTopicChanged(); - else if (std::holds_alternative<StateEvent<state::Member>>(e)) { + else if (std::holds_alternative<StateEvent<state::Topic>>(e)) { + permissions_.invalidate(); + emit permissionsChanged(); + } else if (std::holds_alternative<StateEvent<state::Member>>(e)) { emit roomAvatarUrlChanged(); emit roomNameChanged(); } @@ -661,7 +773,10 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline) emit roomNameChanged(); else if (std::holds_alternative<StateEvent<state::Topic>>(e)) emit roomTopicChanged(); - else if (std::holds_alternative<StateEvent<state::Member>>(e)) { + else if (std::holds_alternative<StateEvent<state::PowerLevels>>(e)) { + permissions_.invalidate(); + emit permissionsChanged(); + } else if (std::holds_alternative<StateEvent<state::Member>>(e)) { emit roomAvatarUrlChanged(); emit roomNameChanged(); } diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 33e77f53..caeb25cf 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h
@@ -16,6 +16,7 @@ #include "CacheCryptoStructs.h" #include "EventStore.h" #include "InputBar.h" +#include "Permissions.h" #include "ui/RoomSettings.h" #include "ui/UserProfile.h" @@ -105,6 +106,7 @@ enum EventType KeyVerificationReady }; Q_ENUM_NS(EventType) +mtx::events::EventType fromRoomEventType(qml_mtx_events::EventType); enum EventState { @@ -159,6 +161,7 @@ class TimelineModel : public QAbstractListModel Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged) Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) Q_PROPERTY(InputBar *input READ input CONSTANT) + Q_PROPERTY(Permissions *permissions READ permissions NOTIFY permissionsChanged) public: explicit TimelineModel(TimelineViewManager *manager, @@ -173,6 +176,7 @@ public: Body, FormattedBody, PreviousMessageUserId, + IsSender, UserId, UserName, PreviousMessageDay, @@ -300,6 +304,7 @@ public slots: QString roomName() const; QString roomTopic() const; InputBar *input() { return &input_; } + Permissions *permissions() { return &permissions_; } QString roomAvatarUrl() const; QString roomId() const { return room_id_; } @@ -331,6 +336,7 @@ signals: void roomNameChanged(); void roomTopicChanged(); void roomAvatarUrlChanged(); + void permissionsChanged(); void forwardToRoom(mtx::events::collections::TimelineEvents *e, QString roomId); void scrollTargetChanged(); @@ -359,6 +365,7 @@ private: TimelineViewManager *manager_; InputBar input_{this}; + Permissions permissions_{this}; QTimer showEventTimer{this}; QString eventIdToShow;