From 2cd1a931c28d0fd8e8755e9622a7d8f56d1a24a0 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 9 Jun 2021 23:52:28 +0200 Subject: Basic community list model --- src/timeline/CommunitiesModel.cpp | 158 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/timeline/CommunitiesModel.cpp (limited to 'src/timeline/CommunitiesModel.cpp') diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp new file mode 100644 index 00000000..cedaacce --- /dev/null +++ b/src/timeline/CommunitiesModel.cpp @@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: 2021 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "CommunitiesModel.h" + +#include + +#include "Cache.h" +#include "UserSettingsPage.h" + +CommunitiesModel::CommunitiesModel(QObject *parent) + : QAbstractListModel(parent) +{} + +QHash +CommunitiesModel::roleNames() const +{ + return { + {AvatarUrl, "avatarUrl"}, + {DisplayName, "displayName"}, + {Tooltip, "tooltip"}, + {ChildrenHidden, "childrenHidden"}, + }; +} + +QVariant +CommunitiesModel::data(const QModelIndex &index, int role) const +{ + if (index.row() == 0) { + switch (role) { + case CommunitiesModel::Roles::AvatarUrl: + return QString(":/icons/icons/ui/world.png"); + case CommunitiesModel::Roles::DisplayName: + return tr("All rooms"); + case CommunitiesModel::Roles::Tooltip: + return tr("Shows all rooms without filtering."); + case CommunitiesModel::Roles::ChildrenHidden: + return false; + case CommunitiesModel::Roles::Id: + return ""; + } + } else if (index.row() - 1 < tags_.size()) { + auto tag = tags_.at(index.row() - 1); + if (tag == "m.favourite") { + switch (role) { + case CommunitiesModel::Roles::AvatarUrl: + return QString(":/icons/icons/ui/star.png"); + case CommunitiesModel::Roles::DisplayName: + return tr("Favourites"); + case CommunitiesModel::Roles::Tooltip: + return tr("Rooms you have favourited."); + } + } else if (tag == "m.lowpriority") { + switch (role) { + case CommunitiesModel::Roles::AvatarUrl: + return QString(":/icons/icons/ui/star.png"); + case CommunitiesModel::Roles::DisplayName: + return tr("Low Priority"); + case CommunitiesModel::Roles::Tooltip: + return tr("Rooms with low priority."); + } + } else if (tag == "m.server_notice") { + switch (role) { + case CommunitiesModel::Roles::AvatarUrl: + return QString(":/icons/icons/ui/tag.png"); + case CommunitiesModel::Roles::DisplayName: + return tr("Server Notices"); + case CommunitiesModel::Roles::Tooltip: + return tr("Messages from your server or administrator."); + } + } else { + switch (role) { + case CommunitiesModel::Roles::AvatarUrl: + return QString(":/icons/icons/ui/tag.png"); + case CommunitiesModel::Roles::DisplayName: + return tag.right(2); + case CommunitiesModel::Roles::Tooltip: + return tag.right(2); + } + } + + switch (role) { + case CommunitiesModel::Roles::ChildrenHidden: + return UserSettings::instance()->hiddenTags().contains("tag:" + tag); + case CommunitiesModel::Roles::Id: + return "tag:" + tag; + } + } + return QVariant(); +} + +void +CommunitiesModel::initializeSidebar() +{ + std::set ts; + for (const auto &e : cache::roomInfo()) { + for (const auto &t : e.tags) { + if (t.find("u.") == 0 || t.find("m." == 0)) { + ts.insert(t); + } + } + } + + beginResetModel(); + tags_.clear(); + for (const auto &t : ts) + tags_.push_back(QString::fromStdString(t)); + endResetModel(); + + emit tagsChanged(); +} + +void +CommunitiesModel::clear() +{ + beginResetModel(); + tags_.clear(); + endResetModel(); + + emit tagsChanged(); +} + +void +CommunitiesModel::sync(const mtx::responses::Rooms &rooms) +{ + bool tagsUpdated = false; + + for (const auto &[roomid, room] : rooms.join) { + (void)roomid; + for (const auto &e : room.account_data.events) + if (std::holds_alternative< + mtx::events::AccountDataEvent>(e)) { + tagsUpdated = true; + } + } + + if (tagsUpdated) + initializeSidebar(); +} + +void +CommunitiesModel::setCurrentTagId(QString tagId) +{ + if (tagId.startsWith("tag:")) { + auto tag = tagId.remove(0, 4); + for (const auto &t : tags_) { + if (t == tag) { + this->currentTagId_ = tagId; + emit currentTagIdChanged(); + return; + } + } + } + + this->currentTagId_ = ""; + emit currentTagIdChanged(); +} -- cgit 1.5.1 From d8c0d4874bb1864a677ae451d93727ab75484f84 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 11 Jun 2021 13:12:43 +0200 Subject: Render community items --- resources/qml/Avatar.qml | 2 + resources/qml/ChatPage.qml | 13 ++- resources/qml/CommunitiesList.qml | 151 ++++++++++++++++++++++++++ resources/qml/RoomList.qml | 6 +- resources/qml/device-verification/Success.qml | 1 + resources/res.qrc | 1 + src/Cache.cpp | 4 + src/Olm.cpp | 9 +- src/timeline/CommunitiesModel.cpp | 7 +- 9 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 resources/qml/CommunitiesList.qml (limited to 'src/timeline/CommunitiesModel.cpp') diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml index 84c22da1..9eb3380e 100644 --- a/resources/qml/Avatar.qml +++ b/resources/qml/Avatar.qml @@ -14,6 +14,7 @@ Rectangle { property alias url: img.source property string userid property string displayName + property alias textColor: label.color signal clicked(var mouse) @@ -26,6 +27,7 @@ Rectangle { } Label { + id: label anchors.fill: parent text: TimelineManager.escapeEmoji(displayName ? String.fromCodePoint(displayName.codePointAt(0)) : "") textFormat: Text.RichText diff --git a/resources/qml/ChatPage.qml b/resources/qml/ChatPage.qml index 0f884d75..5ccdd9f1 100644 --- a/resources/qml/ChatPage.qml +++ b/resources/qml/ChatPage.qml @@ -23,13 +23,14 @@ Rectangle { AdaptiveLayoutElement { id: communityListC - minimumWidth: Nheko.avatarSize * 2 + Nheko.paddingSmall * 2 - collapsedWidth: Nheko.avatarSize + Nheko.paddingSmall * 2 - preferredWidth: Nheko.avatarSize + Nheko.paddingSmall * 2 - maximumWidth: Nheko.avatarSize * 7 + Nheko.paddingSmall * 2 + minimumWidth: communitiesList.avatarSize * 4 + Nheko.paddingMedium * 2 + collapsedWidth: communitiesList.avatarSize + 2* Nheko.paddingMedium + preferredWidth: collapsedWidth + maximumWidth: communitiesList.avatarSize * 10 + 2* Nheko.paddingMedium - Rectangle { - color: Nheko.theme.sidebarBackground + CommunitiesList { + id: communitiesList + collapsed: parent.collapsed } } diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml new file mode 100644 index 00000000..6ca619c4 --- /dev/null +++ b/resources/qml/CommunitiesList.qml @@ -0,0 +1,151 @@ +// SPDX-FileCopyrightText: 2021 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import "./dialogs" +import Qt.labs.platform 1.1 as Platform +import QtQml 2.13 +import QtQuick 2.13 +import QtQuick.Controls 2.13 +import QtQuick.Layouts 1.3 +import im.nheko 1.0 + + +Page { + //leftPadding: Nheko.paddingSmall + //rightPadding: Nheko.paddingSmall + property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 1.6) + property bool collapsed: false + + ListView { + id: communitiesList + + anchors.left: parent.left + anchors.right: parent.right + height: parent.height + model: Communities + + ScrollHelper { + flickable: parent + anchors.fill: parent + enabled: !Settings.mobileMode + } + + Platform.Menu { + id: communityContextMenu + + property string id + + function show(id_, tags_) { + id = id_; + open(); + } + + Platform.MenuItem { + text: qsTr("Leave room") + onTriggered: Rooms.leave(roomContextMenu.roomid) + } + + } + + delegate: Rectangle { + id: communityItem + + property color background: Nheko.colors.window + property color importantText: Nheko.colors.text + property color unimportantText: Nheko.colors.buttonText + property color bubbleBackground: Nheko.colors.highlight + property color bubbleText: Nheko.colors.highlightedText + + color: background + height: avatarSize + 2 * Nheko.paddingMedium + width: ListView.view.width + state: "normal" + ToolTip.visible: hovered.hovered && collapsed + ToolTip.text: model.tooltip + states: [ + State { + name: "highlight" + when: hovered.hovered && !(Communities.currentTagId == model.id) + + PropertyChanges { + target: communityItem + background: Nheko.colors.dark + importantText: Nheko.colors.brightText + unimportantText: Nheko.colors.brightText + bubbleBackground: Nheko.colors.highlight + bubbleText: Nheko.colors.highlightedText + } + + }, + State { + name: "selected" + when: Communities.currentTagId == model.id + + PropertyChanges { + target: communityItem + background: Nheko.colors.highlight + importantText: Nheko.colors.highlightedText + unimportantText: Nheko.colors.highlightedText + bubbleBackground: Nheko.colors.highlightedText + bubbleText: Nheko.colors.highlight + } + + } + ] + + TapHandler { + margin: -Nheko.paddingSmall + acceptedButtons: Qt.RightButton + onSingleTapped: communityContextMenu.show(model.id); + + gesturePolicy: TapHandler.ReleaseWithinBounds + } + + TapHandler { + margin: -Nheko.paddingSmall + onSingleTapped: Communities.setCurrentTagId(model.id) + onLongPressed: communityContextMenu.show(model.id) + } + + HoverHandler { + id: hovered + + margin: -Nheko.paddingSmall + } + + RowLayout { + spacing: Nheko.paddingMedium + anchors.fill: parent + anchors.margins: Nheko.paddingMedium + + Avatar { + id: avatar + + enabled: false + Layout.alignment: Qt.AlignVCenter + height: avatarSize + width: avatarSize + url: { + if (model.avatarUrl.startsWith("mxc://")) { + return model.avatarUrl.replace("mxc://", "image://MxcImage/") + } else { + return "image://colorimage/"+model.avatarUrl+"?" + communityItem.unimportantText + } + } + displayName: model.displayName + color: communityItem.background + + } + + } + + } + + } + + background: Rectangle { + color: Nheko.theme.sidebarBackground + } + +} diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index a6637467..09fb3701 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -32,8 +32,8 @@ Page { Connections { onActiveTimelineChanged: { - roomlist.positionViewAtIndex(Rooms.roomidToIndex(TimelineManager.timeline.roomId()), ListView.Contain); - console.log("Test" + TimelineManager.timeline.roomId() + " " + Rooms.roomidToIndex(TimelineManager.timeline.roomId)); + roomlist.positionViewAtIndex(Rooms.roomidToIndex(Rooms.currentRoom.roomId()), ListView.Contain); + console.log("Test" + Rooms.currentRoom.roomId() + " " + Rooms.roomidToIndex(Rooms.currentRoom.roomId())); } target: TimelineManager } @@ -121,7 +121,7 @@ Page { states: [ State { name: "highlight" - when: hovered.hovered && !(TimelineManager.timeline && model.roomId == TimelineManager.timeline.roomId()) + when: hovered.hovered && !(Rooms.currentRoom && model.roomId == Rooms.currentRoom.roomId()) PropertyChanges { target: roomItem diff --git a/resources/qml/device-verification/Success.qml b/resources/qml/device-verification/Success.qml index b858a1a1..70cfafaf 100644 --- a/resources/qml/device-verification/Success.qml +++ b/resources/qml/device-verification/Success.qml @@ -5,6 +5,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.10 +import im.nheko 1.0 Pane { property string title: qsTr("Successful Verification") diff --git a/resources/res.qrc b/resources/res.qrc index 531e9be2..53c74ae3 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -125,6 +125,7 @@ qml/Root.qml qml/ChatPage.qml + qml/CommunitiesList.qml qml/RoomList.qml qml/TimelineView.qml qml/Avatar.qml diff --git a/src/Cache.cpp b/src/Cache.cpp index 4a99dd59..5684de37 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -3451,6 +3451,10 @@ Cache::updateUserKeys(const std::string &sync_token, const mtx::responses::Query if (!updateToWrite.master_keys.keys.empty() && update.master_keys.keys != updateToWrite.master_keys.keys) { + nhlog::db()->debug("Master key of {} changed:\nold: {}\nnew: {}", + user, + updateToWrite.master_keys.keys.size(), + update.master_keys.keys.size()); updateToWrite.master_key_changed = true; } diff --git a/src/Olm.cpp b/src/Olm.cpp index d08c1b3e..ff4c883b 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -206,8 +206,11 @@ handle_olm_message(const OlmMessage &msg) for (const auto &cipher : msg.ciphertext) { // We skip messages not meant for the current device. - if (cipher.first != my_key) + if (cipher.first != my_key) { + nhlog::crypto()->debug( + "Skipping message for {} since we are {}.", cipher.first, my_key); continue; + } const auto type = cipher.second.type; nhlog::crypto()->info("type: {}", type == 0 ? "OLM_PRE_KEY" : "OLM_MESSAGE"); @@ -661,8 +664,10 @@ try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCip for (const auto &id : session_ids) { auto session = cache::getOlmSession(sender_key, id); - if (!session) + if (!session) { + nhlog::crypto()->warn("Unknown olm session: {}:{}", sender_key, id); continue; + } mtx::crypto::BinaryBuf text; diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index cedaacce..c8ebaa96 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -21,6 +21,7 @@ CommunitiesModel::roleNames() const {DisplayName, "displayName"}, {Tooltip, "tooltip"}, {ChildrenHidden, "childrenHidden"}, + {Id, "id"}, }; } @@ -74,9 +75,9 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::AvatarUrl: return QString(":/icons/icons/ui/tag.png"); case CommunitiesModel::Roles::DisplayName: - return tag.right(2); + return tag.mid(2); case CommunitiesModel::Roles::Tooltip: - return tag.right(2); + return tag.mid(2); } } @@ -143,7 +144,7 @@ void CommunitiesModel::setCurrentTagId(QString tagId) { if (tagId.startsWith("tag:")) { - auto tag = tagId.remove(0, 4); + auto tag = tagId.mid(4); for (const auto &t : tags_) { if (t == tag) { this->currentTagId_ = tagId; -- cgit 1.5.1 From 8d2d8dc26727a5b46613d83522490f568aef7cad Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 11 Jun 2021 14:51:29 +0200 Subject: Enable toggling tags --- resources/qml/Avatar.qml | 1 + resources/qml/ChatPage.qml | 5 +++-- resources/qml/CommunitiesList.qml | 25 +++++++++++++++++-------- src/timeline/CommunitiesModel.cpp | 5 +++-- src/timeline/CommunitiesModel.h | 4 ++-- src/timeline/RoomlistModel.cpp | 17 +++++++++++++++++ src/timeline/RoomlistModel.h | 23 +++++++++++++++++++++++ src/timeline/TimelineViewManager.cpp | 8 +++++++- 8 files changed, 73 insertions(+), 15 deletions(-) (limited to 'src/timeline/CommunitiesModel.cpp') diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml index 9eb3380e..6c12952a 100644 --- a/resources/qml/Avatar.qml +++ b/resources/qml/Avatar.qml @@ -28,6 +28,7 @@ Rectangle { Label { id: label + anchors.fill: parent text: TimelineManager.escapeEmoji(displayName ? String.fromCodePoint(displayName.codePointAt(0)) : "") textFormat: Text.RichText diff --git a/resources/qml/ChatPage.qml b/resources/qml/ChatPage.qml index 5ccdd9f1..6cd48788 100644 --- a/resources/qml/ChatPage.qml +++ b/resources/qml/ChatPage.qml @@ -24,12 +24,13 @@ Rectangle { id: communityListC minimumWidth: communitiesList.avatarSize * 4 + Nheko.paddingMedium * 2 - collapsedWidth: communitiesList.avatarSize + 2* Nheko.paddingMedium + collapsedWidth: communitiesList.avatarSize + 2 * Nheko.paddingMedium preferredWidth: collapsedWidth - maximumWidth: communitiesList.avatarSize * 10 + 2* Nheko.paddingMedium + maximumWidth: communitiesList.avatarSize * 10 + 2 * Nheko.paddingMedium CommunitiesList { id: communitiesList + collapsed: parent.collapsed } diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 6ca619c4..0ccd7e82 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -10,7 +10,6 @@ import QtQuick.Controls 2.13 import QtQuick.Layouts 1.3 import im.nheko 1.0 - Page { //leftPadding: Nheko.paddingSmall //rightPadding: Nheko.paddingSmall @@ -97,8 +96,7 @@ Page { TapHandler { margin: -Nheko.paddingSmall acceptedButtons: Qt.RightButton - onSingleTapped: communityContextMenu.show(model.id); - + onSingleTapped: communityContextMenu.show(model.id) gesturePolicy: TapHandler.ReleaseWithinBounds } @@ -127,15 +125,26 @@ Page { height: avatarSize width: avatarSize url: { - if (model.avatarUrl.startsWith("mxc://")) { - return model.avatarUrl.replace("mxc://", "image://MxcImage/") - } else { - return "image://colorimage/"+model.avatarUrl+"?" + communityItem.unimportantText - } + if (model.avatarUrl.startsWith("mxc://")) + return model.avatarUrl.replace("mxc://", "image://MxcImage/"); + else + return "image://colorimage/" + model.avatarUrl + "?" + communityItem.unimportantText; } displayName: model.displayName color: communityItem.background + } + + ElidedLabel { + visible: !collapsed + Layout.alignment: Qt.AlignVCenter + color: communityItem.importantText + elideWidth: parent.width - avatar.width - Nheko.paddingMedium + fullText: model.displayName + textFormat: Text.PlainText + } + Item { + Layout.fillWidth: true } } diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index c8ebaa96..9b758e97 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -118,6 +118,7 @@ CommunitiesModel::clear() beginResetModel(); tags_.clear(); endResetModel(); + resetCurrentTagId(); emit tagsChanged(); } @@ -148,12 +149,12 @@ CommunitiesModel::setCurrentTagId(QString tagId) for (const auto &t : tags_) { if (t == tag) { this->currentTagId_ = tagId; - emit currentTagIdChanged(); + emit currentTagIdChanged(currentTagId_); return; } } } this->currentTagId_ = ""; - emit currentTagIdChanged(); + emit currentTagIdChanged(currentTagId_); } diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index 3f6a2a4c..038c253b 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -46,12 +46,12 @@ public slots: void resetCurrentTagId() { currentTagId_.clear(); - emit currentTagIdChanged(); + emit currentTagIdChanged(currentTagId_); } QStringList tags() const { return tags_; } signals: - void currentTagIdChanged(); + void currentTagIdChanged(QString tagId); void tagsChanged(); private: diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp index 4dd44b30..c0fb74a4 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp @@ -324,6 +324,7 @@ RoomlistModel::initializeRooms() models.clear(); roomids.clear(); invites.clear(); + currentRoom_ = nullptr; invites = cache::client()->invites(); for (const auto &id : invites.keys()) @@ -461,6 +462,22 @@ FilteredRoomlistModel::lessThan(const QModelIndex &left, const QModelIndex &righ return left.row() < right.row(); } +bool +FilteredRoomlistModel::filterAcceptsRow(int sourceRow, const QModelIndex &) const +{ + if (filterType == FilterBy::Nothing) + return true; + else if (filterType == FilterBy::Tag) { + auto tags = sourceModel() + ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags) + .toStringList(); + + return tags.contains(filterStr); + } else { + return true; + } +} + FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *parent) : QSortFilterProxyModel(parent) , roomlistmodel(model) diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h index 7ee0419f..b89c9a54 100644 --- a/src/timeline/RoomlistModel.h +++ b/src/timeline/RoomlistModel.h @@ -109,6 +109,7 @@ class FilteredRoomlistModel : public QSortFilterProxyModel public: FilteredRoomlistModel(RoomlistModel *model, QObject *parent = nullptr); bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override; public slots: int roomidToIndex(QString roomid) @@ -128,6 +129,19 @@ public slots: void nextRoom(); void previousRoom(); + void updateFilterTag(QString tagId) + { + if (tagId.startsWith("tag:")) { + filterType = FilterBy::Tag; + filterStr = tagId.mid(4); + } else { + filterType = FilterBy::Nothing; + filterStr.clear(); + } + + invalidateFilter(); + } + signals: void currentRoomChanged(); @@ -135,4 +149,13 @@ private: short int calculateImportance(const QModelIndex &idx) const; RoomlistModel *roomlistmodel; bool sortByImportance = true; + + enum class FilterBy + { + Tag, + Space, + Nothing, + }; + QString filterStr = ""; + FilterBy filterType = FilterBy::Nothing; }; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index faf56b85..2ee79d4f 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -195,7 +195,13 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par }); qmlRegisterSingletonType( "im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * { - return new FilteredRoomlistModel(self->rooms_); + auto ptr = new FilteredRoomlistModel(self->rooms_); + + connect(self->communities_, + &CommunitiesModel::currentTagIdChanged, + ptr, + &FilteredRoomlistModel::updateFilterTag); + return ptr; }); qmlRegisterSingletonType( "im.nheko", 1, 0, "Communities", [](QQmlEngine *, QJSEngine *) -> QObject * { -- cgit 1.5.1 From a5291605a9912a411100edf8ee88e59857d8b9aa Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 11 Jun 2021 17:54:05 +0200 Subject: Reenable tag hiding --- resources/qml/CommunitiesList.qml | 10 +++--- src/timeline/CommunitiesModel.cpp | 30 ++++++++++++++++- src/timeline/CommunitiesModel.h | 4 +++ src/timeline/RoomlistModel.cpp | 65 +++++++++++++++++++++++++++--------- src/timeline/RoomlistModel.h | 3 ++ src/timeline/TimelineViewManager.cpp | 4 +++ 6 files changed, 94 insertions(+), 22 deletions(-) (limited to 'src/timeline/CommunitiesModel.cpp') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 0ccd7e82..6aab949c 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -33,16 +33,16 @@ Page { Platform.Menu { id: communityContextMenu - property string id + property string tagId function show(id_, tags_) { - id = id_; + tagId = id_; open(); } Platform.MenuItem { - text: qsTr("Leave room") - onTriggered: Rooms.leave(roomContextMenu.roomid) + text: qsTr("Hide rooms with this tag or from this space by default.") + onTriggered: Communities.toggleTagId(communityContextMenu.tagId) } } @@ -65,7 +65,7 @@ Page { states: [ State { name: "highlight" - when: hovered.hovered && !(Communities.currentTagId == model.id) + when: (hovered.hovered || model.hidden) && !(Communities.currentTagId == model.id) PropertyChanges { target: communityItem diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 9b758e97..96a450ea 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -21,6 +21,7 @@ CommunitiesModel::roleNames() const {DisplayName, "displayName"}, {Tooltip, "tooltip"}, {ChildrenHidden, "childrenHidden"}, + {Hidden, "hidden"}, {Id, "id"}, }; } @@ -38,6 +39,8 @@ CommunitiesModel::data(const QModelIndex &index, int role) const return tr("Shows all rooms without filtering."); case CommunitiesModel::Roles::ChildrenHidden: return false; + case CommunitiesModel::Roles::Hidden: + return false; case CommunitiesModel::Roles::Id: return ""; } @@ -82,8 +85,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const } switch (role) { + case CommunitiesModel::Roles::Hidden: + return hiddentTagIds_.contains("tag:" + tag); case CommunitiesModel::Roles::ChildrenHidden: - return UserSettings::instance()->hiddenTags().contains("tag:" + tag); + return true; case CommunitiesModel::Roles::Id: return "tag:" + tag; } @@ -107,9 +112,12 @@ CommunitiesModel::initializeSidebar() tags_.clear(); for (const auto &t : ts) tags_.push_back(QString::fromStdString(t)); + + hiddentTagIds_ = UserSettings::instance()->hiddenTags(); endResetModel(); emit tagsChanged(); + emit hiddenTagsChanged(); } void @@ -158,3 +166,23 @@ CommunitiesModel::setCurrentTagId(QString tagId) this->currentTagId_ = ""; emit currentTagIdChanged(currentTagId_); } + +void +CommunitiesModel::toggleTagId(QString tagId) +{ + if (hiddentTagIds_.contains(tagId)) { + hiddentTagIds_.removeOne(tagId); + UserSettings::instance()->setHiddenTags(hiddentTagIds_); + } else { + hiddentTagIds_.push_back(tagId); + UserSettings::instance()->setHiddenTags(hiddentTagIds_); + } + + if (tagId.startsWith("tag:")) { + auto idx = tags_.indexOf(tagId.mid(4)); + if (idx != -1) + emit dataChanged(index(idx), index(idx), {Hidden}); + } + + emit hiddenTagsChanged(); +} diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index 038c253b..c98b5955 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -25,6 +25,7 @@ public: DisplayName, Tooltip, ChildrenHidden, + Hidden, Id, }; @@ -49,12 +50,15 @@ public slots: emit currentTagIdChanged(currentTagId_); } QStringList tags() const { return tags_; } + void toggleTagId(QString tagId); signals: void currentTagIdChanged(QString tagId); + void hiddenTagsChanged(); void tagsChanged(); private: QStringList tags_; QString currentTagId_; + QStringList hiddentTagIds_; }; diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp index c0fb74a4..0f980c6c 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp @@ -462,22 +462,6 @@ FilteredRoomlistModel::lessThan(const QModelIndex &left, const QModelIndex &righ return left.row() < right.row(); } -bool -FilteredRoomlistModel::filterAcceptsRow(int sourceRow, const QModelIndex &) const -{ - if (filterType == FilterBy::Nothing) - return true; - else if (filterType == FilterBy::Tag) { - auto tags = sourceModel() - ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags) - .toStringList(); - - return tags.contains(filterStr); - } else { - return true; - } -} - FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *parent) : QSortFilterProxyModel(parent) , roomlistmodel(model) @@ -502,6 +486,55 @@ FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *pare sort(0); } +void +FilteredRoomlistModel::updateHiddenTagsAndSpaces() +{ + hiddenTags.clear(); + hiddenSpaces.clear(); + for (const auto &t : UserSettings::instance()->hiddenTags()) { + if (t.startsWith("tag:")) + hiddenTags.push_back(t.mid(4)); + else if (t.startsWith("space:")) + hiddenSpaces.push_back(t.mid(6)); + } + + invalidateFilter(); +} + +bool +FilteredRoomlistModel::filterAcceptsRow(int sourceRow, const QModelIndex &) const +{ + if (filterType == FilterBy::Nothing) { + if (!hiddenTags.empty()) { + auto tags = + sourceModel() + ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags) + .toStringList(); + + for (const auto &t : tags) + if (hiddenTags.contains(t)) + return false; + } + + return true; + } else if (filterType == FilterBy::Tag) { + auto tags = sourceModel() + ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags) + .toStringList(); + + if (!tags.contains(filterStr)) + return false; + else if (!hiddenTags.empty()) { + for (const auto &t : tags) + if (t != filterStr && hiddenTags.contains(t)) + return false; + } + return true; + } else { + return true; + } +} + void FilteredRoomlistModel::toggleTag(QString roomid, QString tag, bool on) { diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h index b89c9a54..b0244886 100644 --- a/src/timeline/RoomlistModel.h +++ b/src/timeline/RoomlistModel.h @@ -142,6 +142,8 @@ public slots: invalidateFilter(); } + void updateHiddenTagsAndSpaces(); + signals: void currentRoomChanged(); @@ -158,4 +160,5 @@ private: }; QString filterStr = ""; FilterBy filterType = FilterBy::Nothing; + QStringList hiddenTags, hiddenSpaces; }; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 2ee79d4f..c109d38e 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -201,6 +201,10 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par &CommunitiesModel::currentTagIdChanged, ptr, &FilteredRoomlistModel::updateFilterTag); + connect(self->communities_, + &CommunitiesModel::hiddenTagsChanged, + ptr, + &FilteredRoomlistModel::updateHiddenTagsAndSpaces); return ptr; }); qmlRegisterSingletonType( -- cgit 1.5.1