From 5cd3e61cb0e39bdbbef0ccf3c252c3c65ba2824f Mon Sep 17 00:00:00 2001 From: tastytea Date: Tue, 11 Jan 2022 07:38:27 +0100 Subject: [PATCH 1/8] Add GUI to change hidden events per room This adds a dialog to the room settings in which the user can choose which of these three event types they want to hide (additionally to the default): - m.room.member - m.room.power_levels - m.sticker The current state is read when room settings are opened and saved when new settings are accepted. --- resources/qml/dialogs/HiddenEventsDialog.qml | 108 +++++++++++++++++++ resources/qml/dialogs/RoomSettings.qml | 17 ++- resources/res.qrc | 1 + src/ui/RoomSettings.cpp | 70 ++++++++++++ src/ui/RoomSettings.h | 5 + 5 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 resources/qml/dialogs/HiddenEventsDialog.qml diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml new file mode 100644 index 00000000..cfe75b06 --- /dev/null +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2022 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import ".." +import QtQuick 2.12 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.3 +import im.nheko 1.0 + +ApplicationWindow { + id: hiddenEventsDialog + + property alias prompt: promptLabel.text + property var onAccepted: undefined + + modality: Qt.NonModal + flags: Qt.Dialog + minimumWidth: 250 + minimumHeight: 220 + Component.onCompleted: Nheko.reparent(hiddenEventsDialog) + title: qsTr("Hidden events settings for %1").arg(roomSettings.roomName) + + Shortcut { + sequence: StandardKey.Cancel + onActivated: dbb.rejected() + } + + ColumnLayout { + spacing: Nheko.paddingMedium + anchors.margins: Nheko.paddingMedium + anchors.fill: parent + + MatrixText { + id: promptLabel + font.pixelSize: Math.floor(fontMetrics.font.pixelSize * 1.2) + Layout.fillWidth: true + Layout.fillHeight: false + } + + GridLayout { + columns: 2 + rowSpacing: Nheko.paddingMedium + Layout.fillWidth: true + Layout.fillHeight: true + + MatrixText { + text: qsTr("User events") + ToolTip.text: qsTr("Joins, leaves, invites, knocks and bans") + ToolTip.visible: hh1.hovered + Layout.fillWidth: true + + HoverHandler { + id: hh1 + } + } + + ToggleButton { + id: toggleRoomMember + checked: roomSettings.eventHidden(0) + Layout.alignment: Qt.AlignRight + } + + MatrixText { + text: qsTr("Power level changes") + ToolTip.text: qsTr("Is sent when a moderator is added or removed or the permissions of a room are changed (happens a lot in some IRC rooms)") + ToolTip.visible: hh2.hovered + Layout.fillWidth: true + + HoverHandler { + id: hh2 + } + } + + ToggleButton { + id: toggleRoomPowerLevels + checked: roomSettings.eventHidden(1) + Layout.alignment: Qt.AlignRight + } + + MatrixText { + text: qsTr("Stickers") + Layout.fillWidth: true + } + + ToggleButton { + id: toggleSticker + Layout.alignment: Qt.AlignRight + checked: roomSettings.eventHidden(2) + } + } + } + + footer: DialogButtonBox { + id: dbb + + standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel + onAccepted: { + roomSettings.saveHiddenEventsSettings(toggleRoomMember.checked, toggleRoomPowerLevels.checked, toggleSticker.checked); + + hiddenEventsDialog.close(); + } + onRejected: { + hiddenEventsDialog.close(); + } + } + +} diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml index fad7b4c7..dbf22b29 100644 --- a/resources/qml/dialogs/RoomSettings.qml +++ b/resources/qml/dialogs/RoomSettings.qml @@ -254,6 +254,22 @@ ApplicationWindow { Layout.alignment: Qt.AlignRight } + MatrixText { + text: qsTr("Hidden events") + } + + HiddenEventsDialog { + id: hiddenEventsDialog + prompt: qsTr("Select the events you want to hide from %1").arg(roomSettings.roomName) + } + + Button { + text: qsTr("Configure") + ToolTip.text: qsTr("Change which events are hidden in this room") + onClicked: hiddenEventsDialog.show() + Layout.alignment: Qt.AlignRight + } + Item { // for adding extra space between sections Layout.fillWidth: true @@ -302,5 +318,4 @@ ApplicationWindow { } } - } diff --git a/resources/res.qrc b/resources/res.qrc index 2fba5f4c..c8659150 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -152,6 +152,7 @@ qml/dialogs/RoomMembers.qml qml/dialogs/RoomSettings.qml qml/dialogs/UserProfile.qml + qml/dialogs/HiddenEventsDialog.qml qml/emoji/EmojiPicker.qml qml/emoji/StickerPicker.qml qml/ui/NhekoSlider.qml diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 5407edee..2180b5c1 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -12,14 +12,19 @@ #include #include #include +#include #include #include #include "Cache.h" +#include "Cache_p.h" #include "Config.h" #include "Logging.h" #include "MatrixClient.h" #include "Utils.h" +#include "mtx/events/event_type.hpp" +#include "mtx/events/nheko_extensions/hidden_events.hpp" +#include "mtxclient/http/client.hpp" #include "ui/TextField.h" using namespace mtx::events; @@ -224,6 +229,25 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent) accessRules_ = 4; } emit accessJoinRulesChanged(); + + // Get room's hidden events and store it in member variable. + using mtx::events::EventType; + if (auto hiddenEvents = + cache::client()->getAccountData(EventType::NhekoHiddenEvents, roomid_.toStdString())) { + if (auto tmp = std::get_if>(&*hiddenEvents)) { + const auto &types = tmp->content.hidden_event_types; + auto is_hidden{[&types](EventType searchFor) { + return std::find_if(types.begin(), types.end(), [&searchFor](const auto curType) { + return curType == searchFor; + }) != types.end(); + }}; + + hiddenEvents_ = {is_hidden(EventType::RoomMember), + is_hidden(EventType::RoomPowerLevels), + is_hidden(EventType::Sticker)}; + } + } } QString @@ -294,6 +318,20 @@ RoomSettings::accessJoinRules() return accessRules_; } +bool +RoomSettings::eventHidden(int index) +{ + try { + // Is empty if there are no preferences stored for this room. + if (!hiddenEvents_.empty()) { + return hiddenEvents_.at(index); + } + } catch (...) { + nhlog::db()->warn("Failed to retrieve hidden event setting at {}", index); + } + return false; +} + void RoomSettings::enableEncryption() { @@ -404,6 +442,38 @@ RoomSettings::openEditModal() }); } +void +RoomSettings::saveHiddenEventsSettings(const bool toggleRoomMember, + const bool toggleRoomPowerLevels, + const bool toggleSticker) +{ + const auto roomid = roomid_.toStdString(); + nhlog::ui()->debug("Setting events to hidden in room {}: m.room.member={}, " + "m.room.power_levels={}, m.sticker={}", + roomid, + toggleRoomMember, + toggleRoomPowerLevels, + toggleSticker); + + mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; + hiddenEvents.hidden_event_types = { + EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; + if (toggleRoomMember) { + hiddenEvents.hidden_event_types.emplace_back(mtx::events::EventType::RoomMember); + } + if (toggleRoomPowerLevels) { + hiddenEvents.hidden_event_types.emplace_back(mtx::events::EventType::RoomPowerLevels); + } + if (toggleSticker) { + hiddenEvents.hidden_event_types.emplace_back(mtx::events::EventType::Sticker); + } + http::client()->put_room_account_data(roomid, hiddenEvents, [&roomid](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error("Failed to update room account data in {}: {}", roomid, *e); + } + }); +} + void RoomSettings::changeNotifications(int currentIndex) { diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 75b7bae0..ee353d44 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -11,6 +11,7 @@ #include #include +#include #include "CacheStructs.h" @@ -107,8 +108,11 @@ public: Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void openEditModal(); + Q_INVOKABLE void + saveHiddenEventsSettings(bool toggleRoomMember, bool toggleRoomPowerLevels, bool toggleSticker); Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeNotifications(int currentIndex); + Q_INVOKABLE bool eventHidden(int index); signals: void loadingChanged(); @@ -137,4 +141,5 @@ private: RoomInfo info_; int notifications_ = 0; int accessRules_ = 0; + std::vector hiddenEvents_; }; From d4cc3507f8b2266742bfe332afca460c8f110865 Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 12 Jan 2022 10:03:47 +0100 Subject: [PATCH 2/8] Hidden events: Enhance tooltips Shorten tooltip for power levels, expand tooltip for user events. --- resources/qml/dialogs/HiddenEventsDialog.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml index cfe75b06..d4fc7626 100644 --- a/resources/qml/dialogs/HiddenEventsDialog.qml +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -46,7 +46,7 @@ ApplicationWindow { MatrixText { text: qsTr("User events") - ToolTip.text: qsTr("Joins, leaves, invites, knocks and bans") + ToolTip.text: qsTr("Joins, leaves, avatar and name changes, bans, …") ToolTip.visible: hh1.hovered Layout.fillWidth: true @@ -63,7 +63,7 @@ ApplicationWindow { MatrixText { text: qsTr("Power level changes") - ToolTip.text: qsTr("Is sent when a moderator is added or removed or the permissions of a room are changed (happens a lot in some IRC rooms)") + ToolTip.text: qsTr("Sent when a moderator is added/removed or the permissions of a room are changed.") ToolTip.visible: hh2.hovered Layout.fillWidth: true From f0bb64030ed054137608282b8bbc2bb2eacca06d Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 12 Jan 2022 23:26:50 +0100 Subject: [PATCH 3/8] Hidden events: Incorporate suggestions from review - Set TitleHint flag on dialog - Store hidden events as QSet instead of std::vector - Change wording in dialog (disable events instead of turning the hiding on) --- resources/qml/dialogs/HiddenEventsDialog.qml | 20 +++++-- resources/qml/dialogs/RoomSettings.qml | 4 +- src/ui/RoomSettings.cpp | 62 ++++++-------------- src/ui/RoomSettings.h | 10 ++-- 4 files changed, 39 insertions(+), 57 deletions(-) diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml index d4fc7626..f6fc830d 100644 --- a/resources/qml/dialogs/HiddenEventsDialog.qml +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -15,7 +15,7 @@ ApplicationWindow { property var onAccepted: undefined modality: Qt.NonModal - flags: Qt.Dialog + flags: Qt.Dialog | Qt.WindowTitleHint minimumWidth: 250 minimumHeight: 220 Component.onCompleted: Nheko.reparent(hiddenEventsDialog) @@ -57,7 +57,7 @@ ApplicationWindow { ToggleButton { id: toggleRoomMember - checked: roomSettings.eventHidden(0) + checked: !roomSettings.eventHidden("m.room.member") Layout.alignment: Qt.AlignRight } @@ -74,7 +74,7 @@ ApplicationWindow { ToggleButton { id: toggleRoomPowerLevels - checked: roomSettings.eventHidden(1) + checked: !roomSettings.eventHidden("m.room.power_levels") Layout.alignment: Qt.AlignRight } @@ -86,7 +86,7 @@ ApplicationWindow { ToggleButton { id: toggleSticker Layout.alignment: Qt.AlignRight - checked: roomSettings.eventHidden(2) + checked: !roomSettings.eventHidden("m.sticker") } } } @@ -96,7 +96,17 @@ ApplicationWindow { standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel onAccepted: { - roomSettings.saveHiddenEventsSettings(toggleRoomMember.checked, toggleRoomPowerLevels.checked, toggleSticker.checked); + let events = new Array; + if (!toggleRoomMember.checked) { + events.push("m.room.member"); + } + if (!toggleRoomPowerLevels.checked) { + events.push("m.room.power_levels"); + } + if (!toggleSticker.checked) { + events.push("m.sticker"); + } + roomSettings.saveHiddenEventsSettings(events); hiddenEventsDialog.close(); } diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml index dbf22b29..00743a20 100644 --- a/resources/qml/dialogs/RoomSettings.qml +++ b/resources/qml/dialogs/RoomSettings.qml @@ -260,12 +260,12 @@ ApplicationWindow { HiddenEventsDialog { id: hiddenEventsDialog - prompt: qsTr("Select the events you want to hide from %1").arg(roomSettings.roomName) + prompt: qsTr("These events will be be shown in %1:").arg(roomSettings.roomName) } Button { text: qsTr("Configure") - ToolTip.text: qsTr("Change which events are hidden in this room") + ToolTip.text: qsTr("Select events to hide in this room") onClicked: hiddenEventsDialog.show() Layout.alignment: Qt.AlignRight } diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 2180b5c1..0502b281 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -13,8 +13,11 @@ #include #include #include +#include +#include #include #include +#include #include "Cache.h" #include "Cache_p.h" @@ -22,9 +25,6 @@ #include "Logging.h" #include "MatrixClient.h" #include "Utils.h" -#include "mtx/events/event_type.hpp" -#include "mtx/events/nheko_extensions/hidden_events.hpp" -#include "mtxclient/http/client.hpp" #include "ui/TextField.h" using namespace mtx::events; @@ -231,21 +231,13 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent) emit accessJoinRulesChanged(); // Get room's hidden events and store it in member variable. - using mtx::events::EventType; - if (auto hiddenEvents = - cache::client()->getAccountData(EventType::NhekoHiddenEvents, roomid_.toStdString())) { + if (auto hiddenEvents = cache::client()->getAccountData( + mtx::events::EventType::NhekoHiddenEvents, roomid_.toStdString())) { if (auto tmp = std::get_if>(&*hiddenEvents)) { - const auto &types = tmp->content.hidden_event_types; - auto is_hidden{[&types](EventType searchFor) { - return std::find_if(types.begin(), types.end(), [&searchFor](const auto curType) { - return curType == searchFor; - }) != types.end(); - }}; - - hiddenEvents_ = {is_hidden(EventType::RoomMember), - is_hidden(EventType::RoomPowerLevels), - is_hidden(EventType::Sticker)}; + for (const auto event : tmp->content.hidden_event_types) { + hiddenEvents_.insert(mtx::events::to_string(event).data()); + } } } } @@ -319,17 +311,9 @@ RoomSettings::accessJoinRules() } bool -RoomSettings::eventHidden(int index) +RoomSettings::eventHidden(const QString event) const { - try { - // Is empty if there are no preferences stored for this room. - if (!hiddenEvents_.empty()) { - return hiddenEvents_.at(index); - } - } catch (...) { - nhlog::db()->warn("Failed to retrieve hidden event setting at {}", index); - } - return false; + return hiddenEvents_.contains(event); } void @@ -443,30 +427,18 @@ RoomSettings::openEditModal() } void -RoomSettings::saveHiddenEventsSettings(const bool toggleRoomMember, - const bool toggleRoomPowerLevels, - const bool toggleSticker) +RoomSettings::saveHiddenEventsSettings(const QSet events) { - const auto roomid = roomid_.toStdString(); - nhlog::ui()->debug("Setting events to hidden in room {}: m.room.member={}, " - "m.room.power_levels={}, m.sticker={}", - roomid, - toggleRoomMember, - toggleRoomPowerLevels, - toggleSticker); - + // TODO: Make this reusable for global account settings. mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; hiddenEvents.hidden_event_types = { EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; - if (toggleRoomMember) { - hiddenEvents.hidden_event_types.emplace_back(mtx::events::EventType::RoomMember); - } - if (toggleRoomPowerLevels) { - hiddenEvents.hidden_event_types.emplace_back(mtx::events::EventType::RoomPowerLevels); - } - if (toggleSticker) { - hiddenEvents.hidden_event_types.emplace_back(mtx::events::EventType::Sticker); + for (const auto &event : events) { + hiddenEvents.hidden_event_types.emplace_back( + mtx::events::getEventType(event.toStdString())); } + + const auto roomid = roomid_.toStdString(); http::client()->put_room_account_data(roomid, hiddenEvents, [&roomid](mtx::http::RequestErr e) { if (e) { nhlog::net()->error("Failed to update room account data in {}: {}", roomid, *e); diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index ee353d44..d5d42ce0 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -8,10 +8,11 @@ #include #include #include +#include #include +#include #include -#include #include "CacheStructs.h" @@ -108,11 +109,10 @@ public: Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void openEditModal(); - Q_INVOKABLE void - saveHiddenEventsSettings(bool toggleRoomMember, bool toggleRoomPowerLevels, bool toggleSticker); + Q_INVOKABLE void saveHiddenEventsSettings(QSet events); Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeNotifications(int currentIndex); - Q_INVOKABLE bool eventHidden(int index); + Q_INVOKABLE bool eventHidden(QString event) const; signals: void loadingChanged(); @@ -141,5 +141,5 @@ private: RoomInfo info_; int notifications_ = 0; int accessRules_ = 0; - std::vector hiddenEvents_; + QSet hiddenEvents_; }; From f7ca41bc498a8c5685a7ffd9733a5ba8bc94d797 Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 12 Jan 2022 23:52:32 +0100 Subject: [PATCH 4/8] Hidden events: Change title and prompt depending on isRoomSetting We would have to set text and title separately otherwise. --- resources/qml/dialogs/HiddenEventsDialog.qml | 19 +++++++++++++++++-- resources/qml/dialogs/RoomSettings.qml | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml index f6fc830d..004c8d30 100644 --- a/resources/qml/dialogs/HiddenEventsDialog.qml +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -11,7 +11,7 @@ import im.nheko 1.0 ApplicationWindow { id: hiddenEventsDialog - property alias prompt: promptLabel.text + property var isRoomSetting: false property var onAccepted: undefined modality: Qt.NonModal @@ -19,7 +19,14 @@ ApplicationWindow { minimumWidth: 250 minimumHeight: 220 Component.onCompleted: Nheko.reparent(hiddenEventsDialog) - title: qsTr("Hidden events settings for %1").arg(roomSettings.roomName) + title: { + if (isRoomSetting) { + return qsTr("Hidden events for %1").arg(roomSettings.roomName); + } + else { + return qsTr("Hidden events"); + } + } Shortcut { sequence: StandardKey.Cancel @@ -33,6 +40,14 @@ ApplicationWindow { MatrixText { id: promptLabel + text: { + if (isRoomSetting) { + return qsTr("These events will be be shown in %1:").arg(roomSettings.roomName); + } + else { + return qsTr("These events will be be shown:"); + } + } font.pixelSize: Math.floor(fontMetrics.font.pixelSize * 1.2) Layout.fillWidth: true Layout.fillHeight: false diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml index 00743a20..8af11b44 100644 --- a/resources/qml/dialogs/RoomSettings.qml +++ b/resources/qml/dialogs/RoomSettings.qml @@ -260,7 +260,7 @@ ApplicationWindow { HiddenEventsDialog { id: hiddenEventsDialog - prompt: qsTr("These events will be be shown in %1:").arg(roomSettings.roomName) + isRoomSetting: true } Button { From 49b313e3b85911acfc8186e548608bd44324a986 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 13 Jan 2022 00:39:26 +0100 Subject: [PATCH 5/8] Hidden events: Make save-function reusable for global account data --- resources/qml/dialogs/HiddenEventsDialog.qml | 2 +- src/ui/RoomSettings.cpp | 24 +++++++++++++------- src/ui/RoomSettings.h | 3 ++- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml index 004c8d30..8f2d01fd 100644 --- a/resources/qml/dialogs/HiddenEventsDialog.qml +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -121,7 +121,7 @@ ApplicationWindow { if (!toggleSticker.checked) { events.push("m.sticker"); } - roomSettings.saveHiddenEventsSettings(events); + roomSettings.saveHiddenEventsSettings(events, roomSettings.roomId); hiddenEventsDialog.close(); } diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 0502b281..3d68aebb 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -427,9 +427,8 @@ RoomSettings::openEditModal() } void -RoomSettings::saveHiddenEventsSettings(const QSet events) +RoomSettings::saveHiddenEventsSettings(const QSet &events, const QString &roomId) { - // TODO: Make this reusable for global account settings. mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; hiddenEvents.hidden_event_types = { EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; @@ -438,12 +437,21 @@ RoomSettings::saveHiddenEventsSettings(const QSet events) mtx::events::getEventType(event.toStdString())); } - const auto roomid = roomid_.toStdString(); - http::client()->put_room_account_data(roomid, hiddenEvents, [&roomid](mtx::http::RequestErr e) { - if (e) { - nhlog::net()->error("Failed to update room account data in {}: {}", roomid, *e); - } - }); + if (!roomId.isEmpty()) { + const auto rid = roomId.toStdString(); + http::client()->put_room_account_data(rid, hiddenEvents, [&rid](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error( + "Failed to update room account data with hidden events in {}: {}", rid, *e); + } + }); + } else { + http::client()->put_account_data(hiddenEvents, [](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error("Failed to update account data with hidden events: {}", *e); + } + }); + } } void diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index d5d42ce0..c6f4e95a 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -109,7 +109,8 @@ public: Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void openEditModal(); - Q_INVOKABLE void saveHiddenEventsSettings(QSet events); + Q_INVOKABLE void + saveHiddenEventsSettings(const QSet &events, const QString &roomId = {}); Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeNotifications(int currentIndex); Q_INVOKABLE bool eventHidden(QString event) const; From 72cfb06208e80252717541fa51d64e9f93bf0657 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 13 Jan 2022 05:24:54 +0100 Subject: [PATCH 6/8] Hidden events: Some cleanup --- resources/qml/dialogs/HiddenEventsDialog.qml | 2 +- src/ui/RoomSettings.cpp | 69 ++++++++++---------- src/ui/RoomSettings.h | 4 +- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml index 8f2d01fd..5973f4fd 100644 --- a/resources/qml/dialogs/HiddenEventsDialog.qml +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -45,7 +45,7 @@ ApplicationWindow { return qsTr("These events will be be shown in %1:").arg(roomSettings.roomName); } else { - return qsTr("These events will be be shown:"); + return qsTr("These events will be be shown in all rooms:"); } } font.pixelSize: Math.floor(fontMetrics.font.pixelSize * 1.2) diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 3d68aebb..288dac4e 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -230,7 +229,6 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent) } emit accessJoinRulesChanged(); - // Get room's hidden events and store it in member variable. if (auto hiddenEvents = cache::client()->getAccountData( mtx::events::EventType::NhekoHiddenEvents, roomid_.toStdString())) { if (auto tmp = std::get_if &events, const QString &roomId) -{ - mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; - hiddenEvents.hidden_event_types = { - EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; - for (const auto &event : events) { - hiddenEvents.hidden_event_types.emplace_back( - mtx::events::getEventType(event.toStdString())); - } - - if (!roomId.isEmpty()) { - const auto rid = roomId.toStdString(); - http::client()->put_room_account_data(rid, hiddenEvents, [&rid](mtx::http::RequestErr e) { - if (e) { - nhlog::net()->error( - "Failed to update room account data with hidden events in {}: {}", rid, *e); - } - }); - } else { - http::client()->put_account_data(hiddenEvents, [](mtx::http::RequestErr e) { - if (e) { - nhlog::net()->error("Failed to update account data with hidden events: {}", *e); - } - }); - } -} - void RoomSettings::changeNotifications(int currentIndex) { @@ -685,3 +649,36 @@ RoomSettings::updateAvatar() }); }); } + +void +RoomSettings::saveHiddenEventsSettings(const QSet &events, const QString &roomId) +{ + account_data::nheko_extensions::HiddenEvents hiddenEvents; + hiddenEvents.hidden_event_types = { + EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; + for (const auto &event : events) { + hiddenEvents.hidden_event_types.emplace_back(getEventType(event.toStdString())); + } + + if (!roomId.isEmpty()) { + const auto rid = roomId.toStdString(); + http::client()->put_room_account_data(rid, hiddenEvents, [&rid](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error( + "Failed to update room account data with hidden events in {}: {}", rid, *e); + } + }); + } else { + http::client()->put_account_data(hiddenEvents, [](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error("Failed to update account data with hidden events: {}", *e); + } + }); + } +} + +bool +RoomSettings::eventHidden(const QString event) const +{ + return hiddenEvents_.contains(event); +} diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index c6f4e95a..db1b6988 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -109,10 +109,10 @@ public: Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void openEditModal(); - Q_INVOKABLE void - saveHiddenEventsSettings(const QSet &events, const QString &roomId = {}); Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeNotifications(int currentIndex); + Q_INVOKABLE void + saveHiddenEventsSettings(const QSet &events, const QString &roomId = {}); Q_INVOKABLE bool eventHidden(QString event) const; signals: From 7ebced29e9783b472027ca27e955bd38284b0206 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 13 Jan 2022 05:49:32 +0100 Subject: [PATCH 7/8] Hidden events: Make reusable read function --- src/ui/RoomSettings.cpp | 24 +++++++++++++++--------- src/ui/RoomSettings.h | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index 288dac4e..b7fb0887 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -229,15 +229,7 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent) } emit accessJoinRulesChanged(); - if (auto hiddenEvents = cache::client()->getAccountData( - mtx::events::EventType::NhekoHiddenEvents, roomid_.toStdString())) { - if (auto tmp = std::get_if>(&*hiddenEvents)) { - for (const auto event : tmp->content.hidden_event_types) { - hiddenEvents_.insert(mtx::events::to_string(event).data()); - } - } - } + readHiddenEventsSettings(roomid_); } QString @@ -682,3 +674,17 @@ RoomSettings::eventHidden(const QString event) const { return hiddenEvents_.contains(event); } + +void +RoomSettings::readHiddenEventsSettings(const QString &roomId) +{ + if (auto hiddenEvents = cache::client()->getAccountData( + mtx::events::EventType::NhekoHiddenEvents, roomId.toStdString())) { + if (auto tmp = std::get_if>(&*hiddenEvents)) { + for (const auto event : tmp->content.hidden_event_types) { + hiddenEvents_.insert(mtx::events::to_string(event).data()); + } + } + } +} diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index db1b6988..438ac979 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -134,6 +134,7 @@ private: void updateAccessRules(const std::string &room_id, const mtx::events::state::JoinRules &, const mtx::events::state::GuestAccess &); + void readHiddenEventsSettings(const QString &roomId = {}); private: QString roomid_; From 47b822604d81a6c603ce6c9e868456c8ccc2e18d Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 12 Feb 2022 19:27:51 +0100 Subject: [PATCH 8/8] Hidden events: Refactor slightly for reusability --- CMakeLists.txt | 4 +- io.github.NhekoReborn.Nheko.yaml | 2 +- resources/qml/dialogs/HiddenEventsDialog.qml | 48 ++++---- resources/qml/dialogs/RoomSettings.qml | 3 +- src/Cache.cpp | 56 +++++++--- src/MainWindow.cpp | 2 + src/timeline/TimelineModel.cpp | 112 ++++++++++--------- src/timeline/TimelineModel.h | 2 + src/ui/HiddenEvents.cpp | 93 +++++++++++++++ src/ui/HiddenEvents.h | 46 ++++++++ src/ui/RoomSettings.cpp | 50 --------- src/ui/RoomSettings.h | 5 - 12 files changed, 270 insertions(+), 153 deletions(-) create mode 100644 src/ui/HiddenEvents.cpp create mode 100644 src/ui/HiddenEvents.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f4706a2e..4c7a9ccd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,6 +332,7 @@ set(SRC_FILES src/timeline/RoomlistModel.cpp # UI components + src/ui/HiddenEvents.cpp src/ui/MxcAnimatedImage.cpp src/ui/MxcMediaProxy.cpp src/ui/NhekoCursorShape.cpp @@ -403,7 +404,7 @@ if(USE_BUNDLED_MTXCLIENT) FetchContent_Declare( MatrixClient GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git - GIT_TAG 8c03d9ac58274695a71d0eb32519ebce29bc536e + GIT_TAG 31a703c9febdfcaaf4e8a74abd424b6fc462e573 ) set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "") set(BUILD_LIB_TESTS OFF CACHE INTERNAL "") @@ -527,6 +528,7 @@ qt5_wrap_cpp(MOC_HEADERS src/timeline/RoomlistModel.h # UI components + src/ui/HiddenEvents.h src/ui/MxcAnimatedImage.h src/ui/MxcMediaProxy.h src/ui/NhekoCursorShape.h diff --git a/io.github.NhekoReborn.Nheko.yaml b/io.github.NhekoReborn.Nheko.yaml index dec13987..04298bcb 100644 --- a/io.github.NhekoReborn.Nheko.yaml +++ b/io.github.NhekoReborn.Nheko.yaml @@ -191,7 +191,7 @@ modules: buildsystem: cmake-ninja name: mtxclient sources: - - commit: 8c03d9ac58274695a71d0eb32519ebce29bc536e + - commit: 31a703c9febdfcaaf4e8a74abd424b6fc462e573 #tag: v0.6.1 type: git url: https://github.com/Nheko-Reborn/mtxclient.git diff --git a/resources/qml/dialogs/HiddenEventsDialog.qml b/resources/qml/dialogs/HiddenEventsDialog.qml index 5973f4fd..cc6f17a5 100644 --- a/resources/qml/dialogs/HiddenEventsDialog.qml +++ b/resources/qml/dialogs/HiddenEventsDialog.qml @@ -11,17 +11,24 @@ import im.nheko 1.0 ApplicationWindow { id: hiddenEventsDialog - property var isRoomSetting: false + property string roomid: "" + property string roomName: "" property var onAccepted: undefined modality: Qt.NonModal flags: Qt.Dialog | Qt.WindowTitleHint minimumWidth: 250 minimumHeight: 220 - Component.onCompleted: Nheko.reparent(hiddenEventsDialog) + + HiddenEvents { + id: hiddenEvents + + roomid: hiddenEventsDialog.roomid + } + title: { - if (isRoomSetting) { - return qsTr("Hidden events for %1").arg(roomSettings.roomName); + if (roomid) { + return qsTr("Hidden events for %1").arg(roomName); } else { return qsTr("Hidden events"); @@ -41,8 +48,8 @@ ApplicationWindow { MatrixText { id: promptLabel text: { - if (isRoomSetting) { - return qsTr("These events will be be shown in %1:").arg(roomSettings.roomName); + if (roomid) { + return qsTr("These events will be be shown in %1:").arg(roomName); } else { return qsTr("These events will be be shown in all rooms:"); @@ -71,9 +78,9 @@ ApplicationWindow { } ToggleButton { - id: toggleRoomMember - checked: !roomSettings.eventHidden("m.room.member") Layout.alignment: Qt.AlignRight + checked: !hiddenEvents.hiddenEvents.includes(MtxEvent.Member) + onToggled: hiddenEvents.toggle(MtxEvent.Member) } MatrixText { @@ -88,9 +95,9 @@ ApplicationWindow { } ToggleButton { - id: toggleRoomPowerLevels - checked: !roomSettings.eventHidden("m.room.power_levels") Layout.alignment: Qt.AlignRight + checked: !hiddenEvents.hiddenEvents.includes(MtxEvent.PowerLevels) + onToggled: hiddenEvents.toggle(MtxEvent.PowerLevels) } MatrixText { @@ -99,9 +106,9 @@ ApplicationWindow { } ToggleButton { - id: toggleSticker Layout.alignment: Qt.AlignRight - checked: !roomSettings.eventHidden("m.sticker") + checked: !hiddenEvents.hiddenEvents.includes(MtxEvent.Sticker) + onToggled: hiddenEvents.toggle(MtxEvent.Sticker) } } } @@ -111,23 +118,10 @@ ApplicationWindow { standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel onAccepted: { - let events = new Array; - if (!toggleRoomMember.checked) { - events.push("m.room.member"); - } - if (!toggleRoomPowerLevels.checked) { - events.push("m.room.power_levels"); - } - if (!toggleSticker.checked) { - events.push("m.sticker"); - } - roomSettings.saveHiddenEventsSettings(events, roomSettings.roomId); - - hiddenEventsDialog.close(); - } - onRejected: { + hiddenEvents.save(); hiddenEventsDialog.close(); } + onRejected: hiddenEventsDialog.close(); } } diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml index 8af11b44..442010fd 100644 --- a/resources/qml/dialogs/RoomSettings.qml +++ b/resources/qml/dialogs/RoomSettings.qml @@ -260,7 +260,8 @@ ApplicationWindow { HiddenEventsDialog { id: hiddenEventsDialog - isRoomSetting: true + roomid: roomSettings.roomId + roomName: roomSettings.roomName } Button { diff --git a/src/Cache.cpp b/src/Cache.cpp index 9f3ada58..6bad336a 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -173,24 +173,31 @@ Cache::isHiddenEvent(lmdb::txn &txn, } mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; - hiddenEvents.hidden_event_types = { - EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; - - if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, "")) - hiddenEvents = - std::move(std::get>(*temp) - .content); - if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, room_id)) - hiddenEvents = - std::move(std::get>(*temp) - .content); + hiddenEvents.hidden_event_types = std::vector{ + EventType::Reaction, + EventType::CallCandidates, + EventType::Unsupported, + }; + + if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, "")) { + auto h = std::get< + mtx::events::AccountDataEvent>( + *temp); + if (h.content.hidden_event_types) + hiddenEvents = std::move(h.content); + } + if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, room_id)) { + auto h = std::get< + mtx::events::AccountDataEvent>( + *temp); + if (h.content.hidden_event_types) + hiddenEvents = std::move(h.content); + } return std::visit( [hiddenEvents](const auto &ev) { - return std::any_of(hiddenEvents.hidden_event_types.begin(), - hiddenEvents.hidden_event_types.end(), + return std::any_of(hiddenEvents.hidden_event_types->begin(), + hiddenEvents.hidden_event_types->end(), [ev](EventType type) { return type == ev.type; }); }, e); @@ -1515,6 +1522,16 @@ Cache::saveState(const mtx::responses::Sync &res) for (const auto &ev : res.account_data.events) std::visit( [&txn, &accountDataDb](const auto &event) { + if constexpr (std::is_same_v< + std::remove_cv_t>, + AccountDataEvent< + mtx::events::account_data::nheko_extensions::HiddenEvents>>) { + if (!event.content.hidden_event_types) { + accountDataDb.del(txn, "im.nheko.hidden_events"); + return; + } + } + auto j = json(event); accountDataDb.put(txn, j["type"].get(), j.dump()); }, @@ -1589,6 +1606,15 @@ Cache::saveState(const mtx::responses::Sync &res) for (const auto &evt : room.second.account_data.events) { std::visit( [&txn, &accountDataDb](const auto &event) { + if constexpr (std::is_same_v< + std::remove_cv_t>, + AccountDataEvent>) { + if (!event.content.hidden_event_types) { + accountDataDb.del(txn, "im.nheko.hidden_events"); + return; + } + } auto j = json(event); accountDataDb.put(txn, j["type"].get(), j.dump()); }, diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 83504d86..01a05891 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -44,6 +44,7 @@ #include "encryption/SelfVerificationStatus.h" #include "timeline/DelegateChooser.h" #include "timeline/TimelineViewManager.h" +#include "ui/HiddenEvents.h" #include "ui/MxcAnimatedImage.h" #include "ui/MxcMediaProxy.h" #include "ui/NhekoCursorShape.h" @@ -168,6 +169,7 @@ MainWindow::registerQmlTypes() qmlRegisterType("im.nheko", 1, 0, "RoomDirectoryModel"); qmlRegisterType("im.nheko", 1, 0, "Login"); qmlRegisterType("im.nheko", 1, 0, "Registration"); + qmlRegisterType("im.nheko", 1, 0, "HiddenEvents"); qmlRegisterUncreatableType( "im.nheko", 1, diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index c7aa0fa2..662bbb38 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -50,59 +50,7 @@ struct RoomEventType template qml_mtx_events::EventType operator()(const mtx::events::Event &e) { - using mtx::events::EventType; - switch (e.type) { - case EventType::RoomKeyRequest: - return qml_mtx_events::EventType::KeyRequest; - case EventType::Reaction: - return qml_mtx_events::EventType::Reaction; - case EventType::RoomAliases: - return qml_mtx_events::EventType::Aliases; - case EventType::RoomAvatar: - return qml_mtx_events::EventType::Avatar; - case EventType::RoomCanonicalAlias: - return qml_mtx_events::EventType::CanonicalAlias; - case EventType::RoomCreate: - return qml_mtx_events::EventType::RoomCreate; - case EventType::RoomEncrypted: - return qml_mtx_events::EventType::Encrypted; - case EventType::RoomEncryption: - return qml_mtx_events::EventType::Encryption; - case EventType::RoomGuestAccess: - return qml_mtx_events::EventType::RoomGuestAccess; - case EventType::RoomHistoryVisibility: - return qml_mtx_events::EventType::RoomHistoryVisibility; - case EventType::RoomJoinRules: - return qml_mtx_events::EventType::RoomJoinRules; - case EventType::RoomMember: - return qml_mtx_events::EventType::Member; - case EventType::RoomMessage: - return qml_mtx_events::EventType::UnknownMessage; - case EventType::RoomName: - return qml_mtx_events::EventType::Name; - case EventType::RoomPowerLevels: - return qml_mtx_events::EventType::PowerLevels; - case EventType::RoomTopic: - return qml_mtx_events::EventType::Topic; - case EventType::RoomTombstone: - return qml_mtx_events::EventType::Tombstone; - case EventType::RoomRedaction: - return qml_mtx_events::EventType::Redaction; - case EventType::RoomPinnedEvents: - return qml_mtx_events::EventType::PinnedEvents; - case EventType::Sticker: - return qml_mtx_events::EventType::Sticker; - case EventType::Tag: - return qml_mtx_events::EventType::Tag; - case EventType::SpaceParent: - return qml_mtx_events::EventType::SpaceParent; - case EventType::SpaceChild: - return qml_mtx_events::EventType::SpaceChild; - case EventType::Unsupported: - return qml_mtx_events::EventType::Unsupported; - default: - return qml_mtx_events::EventType::UnknownMessage; - } + return qml_mtx_events::toRoomEventType(e.type); } qml_mtx_events::EventType operator()(const mtx::events::Event &) { @@ -198,6 +146,64 @@ struct RoomEventType }; } +qml_mtx_events::EventType +qml_mtx_events::toRoomEventType(mtx::events::EventType e) +{ + using mtx::events::EventType; + switch (e) { + case EventType::RoomKeyRequest: + return qml_mtx_events::EventType::KeyRequest; + case EventType::Reaction: + return qml_mtx_events::EventType::Reaction; + case EventType::RoomAliases: + return qml_mtx_events::EventType::Aliases; + case EventType::RoomAvatar: + return qml_mtx_events::EventType::Avatar; + case EventType::RoomCanonicalAlias: + return qml_mtx_events::EventType::CanonicalAlias; + case EventType::RoomCreate: + return qml_mtx_events::EventType::RoomCreate; + case EventType::RoomEncrypted: + return qml_mtx_events::EventType::Encrypted; + case EventType::RoomEncryption: + return qml_mtx_events::EventType::Encryption; + case EventType::RoomGuestAccess: + return qml_mtx_events::EventType::RoomGuestAccess; + case EventType::RoomHistoryVisibility: + return qml_mtx_events::EventType::RoomHistoryVisibility; + case EventType::RoomJoinRules: + return qml_mtx_events::EventType::RoomJoinRules; + case EventType::RoomMember: + return qml_mtx_events::EventType::Member; + case EventType::RoomMessage: + return qml_mtx_events::EventType::UnknownMessage; + case EventType::RoomName: + return qml_mtx_events::EventType::Name; + case EventType::RoomPowerLevels: + return qml_mtx_events::EventType::PowerLevels; + case EventType::RoomTopic: + return qml_mtx_events::EventType::Topic; + case EventType::RoomTombstone: + return qml_mtx_events::EventType::Tombstone; + case EventType::RoomRedaction: + return qml_mtx_events::EventType::Redaction; + case EventType::RoomPinnedEvents: + return qml_mtx_events::EventType::PinnedEvents; + case EventType::Sticker: + return qml_mtx_events::EventType::Sticker; + case EventType::Tag: + return qml_mtx_events::EventType::Tag; + case EventType::SpaceParent: + return qml_mtx_events::EventType::SpaceParent; + case EventType::SpaceChild: + return qml_mtx_events::EventType::SpaceChild; + case EventType::Unsupported: + return qml_mtx_events::EventType::Unsupported; + default: + return qml_mtx_events::EventType::UnknownMessage; + } +} + qml_mtx_events::EventType toRoomEventType(const mtx::events::collections::TimelineEvents &event) { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index f6cc1e6b..6cdff285 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -125,6 +125,8 @@ enum EventType }; Q_ENUM_NS(EventType) mtx::events::EventType fromRoomEventType(qml_mtx_events::EventType); +qml_mtx_events::EventType +toRoomEventType(mtx::events::EventType e); enum EventState { diff --git a/src/ui/HiddenEvents.cpp b/src/ui/HiddenEvents.cpp new file mode 100644 index 00000000..a8da812e --- /dev/null +++ b/src/ui/HiddenEvents.cpp @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2022 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "HiddenEvents.h" + +#include "Cache_p.h" +#include "MainWindow.h" +#include "MatrixClient.h" + +void +HiddenEvents::load() +{ + using namespace mtx::events; + mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; + hiddenEvents.hidden_event_types = std::vector{ + EventType::Reaction, + EventType::CallCandidates, + EventType::Unsupported, + }; + + if (auto temp = + cache::client()->getAccountData(mtx::events::EventType::NhekoHiddenEvents, "")) { + auto h = std::get< + mtx::events::AccountDataEvent>( + *temp); + if (h.content.hidden_event_types) + hiddenEvents = std::move(h.content); + } + + if (!roomid_.isEmpty()) { + if (auto temp = cache::client()->getAccountData(mtx::events::EventType::NhekoHiddenEvents, + roomid_.toStdString())) { + auto h = std::get>(*temp); + if (h.content.hidden_event_types) + hiddenEvents = std::move(h.content); + } + } + + hiddenEvents_.clear(); + hiddenEvents_ = std::move(hiddenEvents.hidden_event_types.value()); + emit hiddenEventsChanged(); +} + +Q_INVOKABLE void +HiddenEvents::toggle(int type) +{ + auto t = qml_mtx_events::fromRoomEventType(static_cast(type)); + if (auto it = std::find(begin(hiddenEvents_), end(hiddenEvents_), t); it != end(hiddenEvents_)) + hiddenEvents_.erase(it); + else + hiddenEvents_.push_back(t); + emit hiddenEventsChanged(); +} + +QVariantList +HiddenEvents::hiddenEvents() const +{ + QVariantList l; + for (const auto &e : hiddenEvents_) { + l.push_back(qml_mtx_events::toRoomEventType(e)); + } + + return l; +} + +void +HiddenEvents::save() +{ + mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents; + hiddenEvents.hidden_event_types = hiddenEvents_; + + if (roomid_.isEmpty()) + http::client()->put_account_data(hiddenEvents, [](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error("Failed to set hidden events: {}", *e); + MainWindow::instance()->showNotification( + tr("Failed to set hidden events: %1") + .arg(QString::fromStdString(e->matrix_error.error))); + } + }); + else + http::client()->put_room_account_data( + roomid_.toStdString(), hiddenEvents, [](mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error("Failed to set hidden events: {}", *e); + MainWindow::instance()->showNotification( + tr("Failed to set hidden events: %1") + .arg(QString::fromStdString(e->matrix_error.error))); + } + }); +} diff --git a/src/ui/HiddenEvents.h b/src/ui/HiddenEvents.h new file mode 100644 index 00000000..928b14ba --- /dev/null +++ b/src/ui/HiddenEvents.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2022 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include + +#include "timeline/TimelineModel.h" + +class HiddenEvents : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged REQUIRED) + Q_PROPERTY(QVariantList hiddenEvents READ hiddenEvents NOTIFY hiddenEventsChanged) +public: + explicit HiddenEvents(QObject *p = nullptr) + : QObject(p) + {} + + Q_INVOKABLE void toggle(int type); + Q_INVOKABLE void save(); + + [[nodiscard]] QString roomid() const { return roomid_; } + void setRoomid(const QString &r) + { + roomid_ = r; + emit roomidChanged(); + + load(); + } + + [[nodiscard]] QVariantList hiddenEvents() const; + +signals: + void roomidChanged(); + void hiddenEventsChanged(); + +private: + QString roomid_; + std::vector hiddenEvents_; + + void load(); +}; diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp index b7fb0887..43a11b7f 100644 --- a/src/ui/RoomSettings.cpp +++ b/src/ui/RoomSettings.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -228,8 +227,6 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent) accessRules_ = 4; } emit accessJoinRulesChanged(); - - readHiddenEventsSettings(roomid_); } QString @@ -641,50 +638,3 @@ RoomSettings::updateAvatar() }); }); } - -void -RoomSettings::saveHiddenEventsSettings(const QSet &events, const QString &roomId) -{ - account_data::nheko_extensions::HiddenEvents hiddenEvents; - hiddenEvents.hidden_event_types = { - EventType::Reaction, EventType::CallCandidates, EventType::Unsupported}; - for (const auto &event : events) { - hiddenEvents.hidden_event_types.emplace_back(getEventType(event.toStdString())); - } - - if (!roomId.isEmpty()) { - const auto rid = roomId.toStdString(); - http::client()->put_room_account_data(rid, hiddenEvents, [&rid](mtx::http::RequestErr e) { - if (e) { - nhlog::net()->error( - "Failed to update room account data with hidden events in {}: {}", rid, *e); - } - }); - } else { - http::client()->put_account_data(hiddenEvents, [](mtx::http::RequestErr e) { - if (e) { - nhlog::net()->error("Failed to update account data with hidden events: {}", *e); - } - }); - } -} - -bool -RoomSettings::eventHidden(const QString event) const -{ - return hiddenEvents_.contains(event); -} - -void -RoomSettings::readHiddenEventsSettings(const QString &roomId) -{ - if (auto hiddenEvents = cache::client()->getAccountData( - mtx::events::EventType::NhekoHiddenEvents, roomId.toStdString())) { - if (auto tmp = std::get_if>(&*hiddenEvents)) { - for (const auto event : tmp->content.hidden_event_types) { - hiddenEvents_.insert(mtx::events::to_string(event).data()); - } - } - } -} diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h index 438ac979..f79aa3f7 100644 --- a/src/ui/RoomSettings.h +++ b/src/ui/RoomSettings.h @@ -111,9 +111,6 @@ public: Q_INVOKABLE void openEditModal(); Q_INVOKABLE void changeAccessRules(int index); Q_INVOKABLE void changeNotifications(int currentIndex); - Q_INVOKABLE void - saveHiddenEventsSettings(const QSet &events, const QString &roomId = {}); - Q_INVOKABLE bool eventHidden(QString event) const; signals: void loadingChanged(); @@ -134,7 +131,6 @@ private: void updateAccessRules(const std::string &room_id, const mtx::events::state::JoinRules &, const mtx::events::state::GuestAccess &); - void readHiddenEventsSettings(const QString &roomId = {}); private: QString roomid_; @@ -143,5 +139,4 @@ private: RoomInfo info_; int notifications_ = 0; int accessRules_ = 0; - QSet hiddenEvents_; };