mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-13 04:37:11 +02:00
Search by tag on click in Saved Messages.
This commit is contained in:
parent
94a542a1d1
commit
d1a0dfbb97
10 changed files with 102 additions and 20 deletions
|
@ -11,6 +11,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Data {
|
||||
|
||||
QString SearchTagToQuery(const ReactionId &tagId) {
|
||||
if (const auto customId = tagId.custom()) {
|
||||
return u"#tag-custom:%1"_q.arg(customId);
|
||||
} else if (!tagId) {
|
||||
return QString();
|
||||
}
|
||||
return u"#tag-emoji:"_q + tagId.emoji();
|
||||
}
|
||||
|
||||
ReactionId SearchTagFromQuery(const QString &query) {
|
||||
const auto list = query.split(QChar(' '));
|
||||
const auto tag = list.isEmpty() ? QString() : list[0];
|
||||
if (tag.startsWith(u"#tag-custom:"_q)) {
|
||||
return ReactionId{ DocumentId(tag.mid(12).toULongLong()) };
|
||||
} else if (tag.startsWith(u"#tag-emoji:"_q)) {
|
||||
return ReactionId{ tag.mid(11) };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString ReactionEntityData(const ReactionId &id) {
|
||||
if (id.empty()) {
|
||||
return {};
|
||||
|
|
|
@ -27,6 +27,10 @@ struct ReactionId {
|
|||
return custom ? *custom : DocumentId();
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !empty();
|
||||
}
|
||||
|
||||
friend inline auto operator<=>(
|
||||
const ReactionId &,
|
||||
const ReactionId &) = default;
|
||||
|
@ -41,6 +45,9 @@ struct MessageReaction {
|
|||
bool my = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] QString SearchTagToQuery(const ReactionId &tagId);
|
||||
[[nodiscard]] ReactionId SearchTagFromQuery(const QString &query);
|
||||
|
||||
[[nodiscard]] QString ReactionEntityData(const ReactionId &id);
|
||||
|
||||
[[nodiscard]] ReactionId ReactionFromMTP(const MTPReaction &reaction);
|
||||
|
|
|
@ -2968,13 +2968,17 @@ bool InnerWidget::hasFilteredResults() const {
|
|||
return !_filterResults.empty() && _hashtagResults.empty();
|
||||
}
|
||||
|
||||
void InnerWidget::searchInChat(Key key, PeerData *from) {
|
||||
void InnerWidget::searchInChat(
|
||||
Key key,
|
||||
PeerData *from,
|
||||
std::vector<Data::ReactionId> tags) {
|
||||
_searchInMigrated = nullptr;
|
||||
const auto sublist = key.sublist();
|
||||
const auto peer = sublist ? session().user().get() : key.peer();
|
||||
if (peer) {
|
||||
if (const auto migrateTo = peer->migrateTo()) {
|
||||
return searchInChat(peer->owner().history(migrateTo), from);
|
||||
const auto to = peer->owner().history(migrateTo);
|
||||
return searchInChat(to, from, tags);
|
||||
} else if (const auto migrateFrom = peer->migrateFrom()) {
|
||||
_searchInMigrated = peer->owner().history(migrateFrom);
|
||||
}
|
||||
|
@ -2990,7 +2994,8 @@ void InnerWidget::searchInChat(Key key, PeerData *from) {
|
|||
list()
|
||||
) | rpl::then(
|
||||
reactions->myTagsUpdates() | rpl::map(list)
|
||||
));
|
||||
),
|
||||
tags);
|
||||
|
||||
_searchTags->selectedValue(
|
||||
) | rpl::start_with_next([=](std::vector<Data::ReactionId> &&list) {
|
||||
|
|
|
@ -139,7 +139,10 @@ public:
|
|||
}
|
||||
[[nodiscard]] bool hasFilteredResults() const;
|
||||
|
||||
void searchInChat(Key key, PeerData *from);
|
||||
void searchInChat(
|
||||
Key key,
|
||||
PeerData *from,
|
||||
std::vector<Data::ReactionId> tags);
|
||||
[[nodiscard]] auto searchTagsValue() const
|
||||
-> rpl::producer<std::vector<Data::ReactionId>>;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "dialogs/dialogs_search_tags.h"
|
||||
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
|
@ -30,14 +31,24 @@ struct SearchTags::Tag {
|
|||
|
||||
SearchTags::SearchTags(
|
||||
not_null<Data::Session*> owner,
|
||||
rpl::producer<std::vector<Data::Reaction>> tags)
|
||||
: _owner(owner) {
|
||||
rpl::producer<std::vector<Data::Reaction>> tags,
|
||||
std::vector<Data::ReactionId> selected)
|
||||
: _owner(owner)
|
||||
, _added(selected) {
|
||||
std::move(
|
||||
tags
|
||||
) | rpl::start_with_next([=](const std::vector<Data::Reaction> &list) {
|
||||
fill(list);
|
||||
}, _lifetime);
|
||||
|
||||
// Mark the `selected` reactions as selected in `_tags`.
|
||||
for (const auto &id : selected) {
|
||||
const auto i = ranges::find(_tags, id, &Tag::id);
|
||||
if (i != end(_tags)) {
|
||||
i->selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
_normalBg = _selectedBg = QImage();
|
||||
|
@ -54,13 +65,17 @@ void SearchTags::fill(const std::vector<Data::Reaction> &list) {
|
|||
return std::make_shared<LambdaClickHandler>(crl::guard(this, [=] {
|
||||
const auto i = ranges::find(_tags, id, &Tag::id);
|
||||
if (i != end(_tags)) {
|
||||
if (!i->selected && !base::IsShiftPressed()) {
|
||||
for (auto &tag : _tags) {
|
||||
tag.selected = false;
|
||||
}
|
||||
}
|
||||
i->selected = !i->selected;
|
||||
_selectedChanges.fire({});
|
||||
}
|
||||
}));
|
||||
};
|
||||
for (const auto &reaction : list) {
|
||||
const auto id = reaction.id;
|
||||
const auto push = [&](Data::ReactionId id) {
|
||||
const auto customId = id.custom();
|
||||
_tags.push_back({
|
||||
.id = id,
|
||||
|
@ -75,6 +90,14 @@ void SearchTags::fill(const std::vector<Data::Reaction> &list) {
|
|||
if (!customId) {
|
||||
_owner->reactions().preloadImageFor(id);
|
||||
}
|
||||
};
|
||||
for (const auto &reaction : list) {
|
||||
push(reaction.id);
|
||||
}
|
||||
for (const auto &reaction : _added) {
|
||||
if (!ranges::contains(_tags, reaction, &Tag::id)) {
|
||||
push(reaction);
|
||||
}
|
||||
}
|
||||
if (_width > 0) {
|
||||
layout();
|
||||
|
|
|
@ -25,7 +25,8 @@ class SearchTags final : public base::has_weak_ptr {
|
|||
public:
|
||||
SearchTags(
|
||||
not_null<Data::Session*> owner,
|
||||
rpl::producer<std::vector<Data::Reaction>> tags);
|
||||
rpl::producer<std::vector<Data::Reaction>> tags,
|
||||
std::vector<Data::ReactionId> selected);
|
||||
~SearchTags();
|
||||
|
||||
void resizeToWidth(int width);
|
||||
|
@ -61,6 +62,7 @@ private:
|
|||
[[nodiscard]] const QImage &validateBg(bool selected) const;
|
||||
|
||||
const not_null<Data::Session*> _owner;
|
||||
std::vector<Data::ReactionId> _added;
|
||||
std::vector<Tag> _tags;
|
||||
rpl::event_stream<> _selectedChanges;
|
||||
rpl::event_stream<> _repaintRequests;
|
||||
|
|
|
@ -1911,7 +1911,7 @@ void Widget::showMainMenu() {
|
|||
controller()->widget()->showMainMenu();
|
||||
}
|
||||
|
||||
void Widget::searchMessages(const QString &query, Key inChat) {
|
||||
void Widget::searchMessages(QString query, Key inChat) {
|
||||
if (_childList) {
|
||||
const auto forum = controller()->shownForum().current();
|
||||
const auto topic = inChat.topic();
|
||||
|
@ -1926,6 +1926,12 @@ void Widget::searchMessages(const QString &query, Key inChat) {
|
|||
controller()->closeFolder();
|
||||
}
|
||||
|
||||
auto tags = std::vector<Data::ReactionId>();
|
||||
if (const auto tagId = Data::SearchTagFromQuery(query)) {
|
||||
inChat = session().data().history(session().user());
|
||||
query = QString();
|
||||
tags.push_back(tagId);
|
||||
}
|
||||
const auto inChatChanged = [&] {
|
||||
const auto inPeer = inChat.peer();
|
||||
const auto inTopic = inChat.topic();
|
||||
|
@ -1948,10 +1954,12 @@ void Widget::searchMessages(const QString &query, Key inChat) {
|
|||
}
|
||||
return true;
|
||||
}();
|
||||
if ((currentSearchQuery() != query) || inChatChanged) {
|
||||
if ((currentSearchQuery() != query)
|
||||
|| inChatChanged
|
||||
|| _searchTags != tags) {
|
||||
if (inChat) {
|
||||
cancelSearch();
|
||||
setSearchInChat(inChat);
|
||||
setSearchInChat(inChat, nullptr, tags);
|
||||
}
|
||||
setSearchQuery(query);
|
||||
applyFilterUpdate(true);
|
||||
|
@ -2595,9 +2603,12 @@ void Widget::searchInChat(Key chat) {
|
|||
searchMessages(QString(), chat);
|
||||
}
|
||||
|
||||
bool Widget::setSearchInChat(Key chat, PeerData *from) {
|
||||
bool Widget::setSearchInChat(
|
||||
Key chat,
|
||||
PeerData *from,
|
||||
std::vector<Data::ReactionId> tags) {
|
||||
if (_childList) {
|
||||
if (_childList->setSearchInChat(chat, from)) {
|
||||
if (_childList->setSearchInChat(chat, from, tags)) {
|
||||
return true;
|
||||
}
|
||||
hideChildList();
|
||||
|
@ -2634,7 +2645,8 @@ bool Widget::setSearchInChat(Key chat, PeerData *from) {
|
|||
if (_layout != Layout::Main) {
|
||||
return false;
|
||||
} else if (const auto migrateTo = peer->migrateTo()) {
|
||||
return setSearchInChat(peer->owner().history(migrateTo), from);
|
||||
const auto to = peer->owner().history(migrateTo);
|
||||
return setSearchInChat(to, from, tags);
|
||||
} else if (const auto migrateFrom = peer->migrateFrom()) {
|
||||
_searchInMigrated = peer->owner().history(migrateFrom);
|
||||
}
|
||||
|
@ -2653,7 +2665,8 @@ bool Widget::setSearchInChat(Key chat, PeerData *from) {
|
|||
if (_searchInChat && _layout == Layout::Main) {
|
||||
controller()->closeFolder();
|
||||
}
|
||||
_inner->searchInChat(_searchInChat, _searchFromAuthor);
|
||||
_searchTags = std::move(tags);
|
||||
_inner->searchInChat(_searchInChat, _searchFromAuthor, _searchTags);
|
||||
_searchTagsLifetime = _inner->searchTagsValue(
|
||||
) | rpl::start_with_next([=](std::vector<Data::ReactionId> &&list) {
|
||||
if (_searchTags != list) {
|
||||
|
|
|
@ -117,7 +117,7 @@ public:
|
|||
|
||||
void scrollToEntry(const RowDescriptor &entry);
|
||||
|
||||
void searchMessages(const QString &query, Key inChat = {});
|
||||
void searchMessages(QString query, Key inChat = {});
|
||||
void searchTopics();
|
||||
void searchMore();
|
||||
|
||||
|
@ -180,7 +180,10 @@ private:
|
|||
void trackScroll(not_null<Ui::RpWidget*> widget);
|
||||
[[nodiscard]] bool searchForPeersRequired(const QString &query) const;
|
||||
[[nodiscard]] bool searchForTopicsRequired(const QString &query) const;
|
||||
bool setSearchInChat(Key chat, PeerData *from = nullptr);
|
||||
bool setSearchInChat(
|
||||
Key chat,
|
||||
PeerData *from = nullptr,
|
||||
std::vector<Data::ReactionId> tags = {});
|
||||
void showCalendar();
|
||||
void showSearchFrom();
|
||||
void showMainMenu();
|
||||
|
|
|
@ -2965,8 +2965,14 @@ void Message::refreshReactions() {
|
|||
if (!_reactions) {
|
||||
const auto handlerFactory = [=](ReactionId id) {
|
||||
const auto weak = base::make_weak(this);
|
||||
return std::make_shared<LambdaClickHandler>([=] {
|
||||
return std::make_shared<LambdaClickHandler>([=](
|
||||
ClickContext context) {
|
||||
if (const auto strong = weak.get()) {
|
||||
if (strong->data()->reactionsAreTags()) {
|
||||
const auto tag = Data::SearchTagToQuery(id);
|
||||
HashtagClickHandler(tag).onClick(context);
|
||||
return;
|
||||
}
|
||||
strong->data()->toggleReaction(
|
||||
id,
|
||||
HistoryItem::ReactionSource::Existing);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0d111bd4633324533195aa0a840730b4bf6ba75b
|
||||
Subproject commit bc78a03b12b40ee6264ad2235465197b89588288
|
Loading…
Add table
Reference in a new issue