From fa8294d4b907ab77dd15c9581f21185297420e61 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Fri, 29 Aug 2025 21:52:36 -0400 Subject: [PATCH] Add action to user detail dialog to search for their messages in room In other messaging applications (e.g. Discord) this is possible through text modifiers like "from:@user". We don't support that, and I'm not super keen on implementing yet-another-parsing-thing, so an action in the user detail dialog should work for now. Very useful to sift through large rooms but when you only care about a specific person's messages (maybe your own?) --- src/app/qml/UserDetailDialog.qml | 14 ++++++++++++++ src/roominfo/RoomSearchPage.qml | 6 ++++++ src/timeline/models/searchmodel.cpp | 14 ++++++++++++++ src/timeline/models/searchmodel.h | 10 ++++++++++ 4 files changed, 44 insertions(+) diff --git a/src/app/qml/UserDetailDialog.qml b/src/app/qml/UserDetailDialog.qml index aa2840395..bc834400b 100644 --- a/src/app/qml/UserDetailDialog.qml +++ b/src/app/qml/UserDetailDialog.qml @@ -274,6 +274,20 @@ Kirigami.Dialog { } } + FormCard.FormButtonDelegate { + text: i18nc("@action:button %1 is the name of the user.", "Search room for %1's messages", root.room ? root.room.member(root.user.id).htmlSafeDisplayName : QmlUtils.escapeString(root.user.displayName)) + icon.name: "search-symbolic" + onClicked: { + pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), { + room: root.room, + senderId: root.user.id + }, { + title: i18nc("@action:title", "Search") + }); + root.close(); + } + } + FormCard.FormButtonDelegate { text: i18n("Copy link") icon.name: "username-copy" diff --git a/src/roominfo/RoomSearchPage.qml b/src/roominfo/RoomSearchPage.qml index 384baaa9d..785cef129 100644 --- a/src/roominfo/RoomSearchPage.qml +++ b/src/roominfo/RoomSearchPage.qml @@ -23,11 +23,17 @@ SearchPage { */ required property NeoChatRoom room + /** + * @brief If set, limits the search to events from a specific user id. + */ + property string senderId + title: i18nc("@action:title", "Search Messages") model: SearchModel { id: searchModel room: root.room + senderId: root.senderId } modelDelegate: EventDelegate { diff --git a/src/timeline/models/searchmodel.cpp b/src/timeline/models/searchmodel.cpp index 4cdbfd8f3..781c3385d 100644 --- a/src/timeline/models/searchmodel.cpp +++ b/src/timeline/models/searchmodel.cpp @@ -51,6 +51,9 @@ void SearchModel::search() filter.notRooms = QStringList(); filter.rooms = QStringList{m_room->id()}; filter.containsUrl = false; + if (!m_senderId.isEmpty()) { + filter.senders = {m_senderId}; + } SearchJob::RoomEventsCriteria criteria{ .searchTerm = m_searchText, @@ -112,4 +115,15 @@ void SearchModel::setSearching(bool searching) Q_EMIT searchingChanged(); } +QString SearchModel::senderId() const +{ + return m_senderId; +} + +void SearchModel::setSenderId(const QString &sender) +{ + m_senderId = sender; + Q_EMIT senderIdChanged(); +} + #include "moc_searchmodel.cpp" diff --git a/src/timeline/models/searchmodel.h b/src/timeline/models/searchmodel.h index 669a82737..f3444e730 100644 --- a/src/timeline/models/searchmodel.h +++ b/src/timeline/models/searchmodel.h @@ -37,6 +37,11 @@ class SearchModel : public MessageModel */ Q_PROPERTY(bool searching READ searching NOTIFY searchingChanged) + /** + * @brief If set, limits the search to this specific sender. + */ + Q_PROPERTY(QString senderId READ senderId WRITE setSenderId NOTIFY senderIdChanged) + public: explicit SearchModel(QObject *parent = nullptr); @@ -45,6 +50,9 @@ public: bool searching() const; + QString senderId() const; + void setSenderId(const QString &sender); + /** * @brief Number of rows in the model. * @@ -61,6 +69,7 @@ Q_SIGNALS: void searchTextChanged(); void roomChanged(); void searchingChanged(); + void senderIdChanged(); private: std::optional> getEventForIndex(QModelIndex index) const override; @@ -71,4 +80,5 @@ private: std::optional m_result = std::nullopt; Quotient::SearchJob *m_job = nullptr; bool m_searching = false; + QString m_senderId; };