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};
+ hiddenEvents.hidden_event_types = std::vector{
+ 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);
+ 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_;
};