mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Implement effects search.
This commit is contained in:
parent
bbb3a51b74
commit
d102d256a9
7 changed files with 115 additions and 54 deletions
|
@ -583,9 +583,14 @@ void EmojiListWidget::setupSearch() {
|
|||
InvokeQueued(this, [=] {
|
||||
applyNextSearchQuery();
|
||||
});
|
||||
_searchQueries.fire_copy(_nextSearchQuery);
|
||||
}, session, type);
|
||||
}
|
||||
|
||||
rpl::producer<std::vector<QString>> EmojiListWidget::searchQueries() const {
|
||||
return _searchQueries.events();
|
||||
}
|
||||
|
||||
void EmojiListWidget::applyNextSearchQuery() {
|
||||
if (_searchQuery == _nextSearchQuery) {
|
||||
return;
|
||||
|
@ -834,7 +839,8 @@ void EmojiListWidget::unloadCustomIn(const SectionInfo &info) {
|
|||
object_ptr<TabbedSelector::InnerFooter> EmojiListWidget::createFooter() {
|
||||
Expects(_footer == nullptr);
|
||||
|
||||
if (_mode == EmojiListMode::RecentReactions) {
|
||||
if (_mode == EmojiListMode::RecentReactions
|
||||
|| _mode == EmojiListMode::MessageEffects) {
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
|
@ -2131,7 +2137,7 @@ void EmojiListWidget::refreshRecent() {
|
|||
}
|
||||
|
||||
void EmojiListWidget::refreshCustom() {
|
||||
if (_mode == Mode::RecentReactions) {
|
||||
if (_mode == Mode::RecentReactions || _mode == Mode::MessageEffects) {
|
||||
return;
|
||||
}
|
||||
auto old = base::take(_custom);
|
||||
|
|
|
@ -77,6 +77,7 @@ enum class EmojiListMode {
|
|||
UserpicBuilder,
|
||||
BackgroundEmoji,
|
||||
PeerTitle,
|
||||
MessageEffects,
|
||||
};
|
||||
|
||||
struct EmojiListDescriptor {
|
||||
|
@ -146,6 +147,8 @@ public:
|
|||
base::unique_qptr<Ui::PopupMenu> fillContextMenu(
|
||||
const SendMenu::Details &details) override;
|
||||
|
||||
[[nodiscard]] rpl::producer<std::vector<QString>> searchQueries() const;
|
||||
|
||||
protected:
|
||||
void visibleTopBottomUpdated(
|
||||
int visibleTop,
|
||||
|
@ -418,6 +421,7 @@ private:
|
|||
bool _colorAllRippleForced = false;
|
||||
rpl::lifetime _colorAllRippleForcedLifetime;
|
||||
|
||||
rpl::event_stream<std::vector<QString>> _searchQueries;
|
||||
std::vector<QString> _nextSearchQuery;
|
||||
std::vector<QString> _searchQuery;
|
||||
base::flat_set<EmojiPtr> _searchEmoji;
|
||||
|
|
|
@ -547,7 +547,7 @@ int StickersListWidget::countDesiredHeight(int newWidth) {
|
|||
}
|
||||
|
||||
void StickersListWidget::sendSearchRequest() {
|
||||
if (_searchRequestId || _searchNextQuery.isEmpty()) {
|
||||
if (_searchRequestId || _searchNextQuery.isEmpty() || _isEffects) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -556,14 +556,12 @@ void StickersListWidget::sendSearchRequest() {
|
|||
|
||||
auto it = _searchCache.find(_searchQuery);
|
||||
if (it != _searchCache.cend()) {
|
||||
_search->setLoading(false);
|
||||
toggleSearchLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_search->setLoading(true);
|
||||
|
||||
toggleSearchLoading(true);
|
||||
if (_searchQuery == Ui::PremiumGroupFakeEmoticon()) {
|
||||
_search->setLoading(false);
|
||||
toggleSearchLoading(false);
|
||||
_searchRequestId = 0;
|
||||
_searchCache.emplace(_searchQuery, std::vector<uint64>());
|
||||
showSearchResults();
|
||||
|
@ -579,7 +577,7 @@ void StickersListWidget::sendSearchRequest() {
|
|||
searchResultsDone(result);
|
||||
}).fail([=] {
|
||||
// show error?
|
||||
_search->setLoading(false);
|
||||
toggleSearchLoading(false);
|
||||
_searchRequestId = 0;
|
||||
}).handleAllErrors().send();
|
||||
}
|
||||
|
@ -593,7 +591,10 @@ void StickersListWidget::searchForSets(
|
|||
return;
|
||||
}
|
||||
|
||||
if (query == Ui::PremiumGroupFakeEmoticon()) {
|
||||
_filterStickersCornerEmoji.clear();
|
||||
if (_isEffects) {
|
||||
filterEffectsByEmoji(std::move(emoji));
|
||||
} else if (query == Ui::PremiumGroupFakeEmoticon()) {
|
||||
_filteredStickers = session().data().stickers().getPremiumList(0);
|
||||
} else {
|
||||
_filteredStickers = session().data().stickers().getListByEmoji(
|
||||
|
@ -602,7 +603,7 @@ void StickersListWidget::searchForSets(
|
|||
true);
|
||||
}
|
||||
if (_searchQuery != cleaned) {
|
||||
_search->setLoading(false);
|
||||
toggleSearchLoading(false);
|
||||
if (const auto requestId = base::take(_searchRequestId)) {
|
||||
_api.request(requestId).cancel();
|
||||
}
|
||||
|
@ -618,13 +619,14 @@ void StickersListWidget::searchForSets(
|
|||
}
|
||||
|
||||
void StickersListWidget::cancelSetsSearch() {
|
||||
_search->setLoading(false);
|
||||
toggleSearchLoading(false);
|
||||
if (const auto requestId = base::take(_searchRequestId)) {
|
||||
_api.request(requestId).cancel();
|
||||
}
|
||||
_searchRequestTimer.cancel();
|
||||
_searchQuery = _searchNextQuery = QString();
|
||||
_filteredStickers.clear();
|
||||
_filterStickersCornerEmoji.clear();
|
||||
_searchCache.clear();
|
||||
refreshSearchRows(nullptr);
|
||||
}
|
||||
|
@ -655,8 +657,9 @@ void StickersListWidget::refreshSearchRows(
|
|||
});
|
||||
|
||||
fillFilteredStickersRow();
|
||||
fillLocalSearchRows(_searchNextQuery);
|
||||
|
||||
if (!_isEffects) {
|
||||
fillLocalSearchRows(_searchNextQuery);
|
||||
}
|
||||
if (!cloudSets && _searchNextQuery.isEmpty()) {
|
||||
showStickerSet(!_mySets.empty()
|
||||
? _mySets[0].id
|
||||
|
@ -665,11 +668,10 @@ void StickersListWidget::refreshSearchRows(
|
|||
}
|
||||
|
||||
setSection(Section::Search);
|
||||
if (cloudSets) {
|
||||
if (!_isEffects && cloudSets) {
|
||||
fillCloudSearchRows(*cloudSets);
|
||||
}
|
||||
refreshIcons(ValidateIconAnimations::Scroll);
|
||||
|
||||
_lastMousePosition = QCursor::pos();
|
||||
|
||||
resizeToWidth(width());
|
||||
|
@ -735,7 +737,7 @@ void StickersListWidget::fillFilteredStickersRow() {
|
|||
SearchEmojiSectionSetId(),
|
||||
nullptr,
|
||||
Data::StickersSetFlag::Special,
|
||||
QString(), // title
|
||||
_isEffects ? tr::lng_effect_stickers_title(tr::now) : QString(),
|
||||
QString(), // shortName
|
||||
_filteredStickers.size(),
|
||||
false, // externalLayout
|
||||
|
@ -758,6 +760,12 @@ void StickersListWidget::addSearchRow(not_null<StickersSet*> set) {
|
|||
std::move(elements));
|
||||
}
|
||||
|
||||
void StickersListWidget::toggleSearchLoading(bool loading) {
|
||||
if (_search) {
|
||||
_search->setLoading(loading);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::takeHeavyData(
|
||||
std::vector<Set> &to,
|
||||
std::vector<Set> &from) {
|
||||
|
@ -839,7 +847,7 @@ auto StickersListWidget::shownSets() -> std::vector<Set> & {
|
|||
|
||||
void StickersListWidget::searchResultsDone(
|
||||
const MTPmessages_FoundStickerSets &result) {
|
||||
_search->setLoading(false);
|
||||
toggleSearchLoading(false);
|
||||
_searchRequestId = 0;
|
||||
|
||||
if (result.type() == mtpc_messages_foundStickerSetsNotModified) {
|
||||
|
@ -1476,9 +1484,14 @@ void StickersListWidget::paintSticker(
|
|||
}
|
||||
|
||||
auto cornerPainted = false;
|
||||
if (set.id == Data::Stickers::RecentSetId && !_cornerEmoji.empty()) {
|
||||
Assert(index < _cornerEmoji.size());
|
||||
if (const auto emoji = _cornerEmoji[index]) {
|
||||
const auto corner = (set.id == Data::Stickers::RecentSetId)
|
||||
? &_cornerEmoji
|
||||
: (set.id == SearchEmojiSectionSetId())
|
||||
? &_filterStickersCornerEmoji
|
||||
: nullptr;
|
||||
if (corner && !corner->empty()) {
|
||||
Assert(index < corner->size());
|
||||
if (const auto emoji = (*corner)[index]) {
|
||||
const auto size = Ui::Emoji::GetSizeNormal();
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto radius = st::roundRadiusSmall;
|
||||
|
@ -2492,14 +2505,14 @@ void StickersListWidget::updateSelected() {
|
|||
}
|
||||
|
||||
bool StickersListWidget::setHasTitle(const Set &set) const {
|
||||
if (set.id == Data::Stickers::FavedSetId
|
||||
if (_isEffects) {
|
||||
return true;
|
||||
} else if (set.id == Data::Stickers::FavedSetId
|
||||
|| set.id == SearchEmojiSectionSetId()) {
|
||||
return false;
|
||||
} else if (set.id == Data::Stickers::RecentSetId) {
|
||||
return !_mySets.empty()
|
||||
&& (_isMasks
|
||||
|| _isEffects
|
||||
|| (_mySets[0].id == Data::Stickers::FavedSetId));
|
||||
&& (_isMasks || (_mySets[0].id == Data::Stickers::FavedSetId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2581,9 +2594,10 @@ void StickersListWidget::showStickerSet(uint64 setId) {
|
|||
const auto guard = gsl::finally([&] { _showingSetById = false; });
|
||||
|
||||
clearSelection();
|
||||
if (_search
|
||||
&& (!_searchQuery.isEmpty() || !_searchNextQuery.isEmpty())) {
|
||||
_search->cancel();
|
||||
if (!_searchQuery.isEmpty() || !_searchNextQuery.isEmpty()) {
|
||||
if (_search) {
|
||||
_search->cancel();
|
||||
}
|
||||
cancelSetsSearch();
|
||||
}
|
||||
|
||||
|
@ -2686,14 +2700,18 @@ void StickersListWidget::setupSearch() {
|
|||
? TabbedSearchType::Greeting
|
||||
: TabbedSearchType::Stickers;
|
||||
_search = MakeSearch(this, st(), [=](std::vector<QString> &&query) {
|
||||
auto set = base::flat_set<EmojiPtr>();
|
||||
auto text = ranges::accumulate(query, QString(), [](
|
||||
applySearchQuery(std::move(query));
|
||||
}, session, type);
|
||||
}
|
||||
|
||||
void StickersListWidget::applySearchQuery(std::vector<QString> &&query) {
|
||||
auto set = base::flat_set<EmojiPtr>();
|
||||
auto text = ranges::accumulate(query, QString(), [](
|
||||
QString a,
|
||||
QString b) {
|
||||
return a.isEmpty() ? b : (a + ' ' + b);
|
||||
});
|
||||
searchForSets(std::move(text), SearchEmoji(query, set));
|
||||
}, session, type);
|
||||
return a.isEmpty() ? b : (a + ' ' + b);
|
||||
});
|
||||
searchForSets(std::move(text), SearchEmoji(query, set));
|
||||
}
|
||||
|
||||
void StickersListWidget::displaySet(uint64 setId) {
|
||||
|
@ -2768,6 +2786,32 @@ bool StickersListWidget::mySetsEmpty() const {
|
|||
return _mySets.empty();
|
||||
}
|
||||
|
||||
void StickersListWidget::filterEffectsByEmoji(
|
||||
const std::vector<EmojiPtr> &emoji) {
|
||||
_filteredStickers.clear();
|
||||
_filterStickersCornerEmoji.clear();
|
||||
if (_mySets.empty()
|
||||
|| _mySets.front().id != Data::Stickers::RecentSetId
|
||||
|| _mySets.front().stickers.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto &list = _mySets.front().stickers;
|
||||
auto all = base::flat_set<EmojiPtr>();
|
||||
for (const auto &one : emoji) {
|
||||
all.emplace(one->original());
|
||||
}
|
||||
const auto count = int(list.size());
|
||||
_filteredStickers.reserve(count);
|
||||
_filterStickersCornerEmoji.reserve(count);
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
Assert(i < _cornerEmoji.size());
|
||||
if (all.contains(_cornerEmoji[i])) {
|
||||
_filteredStickers.push_back(list[i].document);
|
||||
_filterStickersCornerEmoji.push_back(_cornerEmoji[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StickersListWidget::~StickersListWidget() = default;
|
||||
|
||||
object_ptr<Ui::BoxContent> MakeConfirmRemoveSetBox(
|
||||
|
|
|
@ -127,6 +127,8 @@ public:
|
|||
|
||||
bool mySetsEmpty() const;
|
||||
|
||||
void applySearchQuery(std::vector<QString> &&query);
|
||||
|
||||
~StickersListWidget();
|
||||
|
||||
protected:
|
||||
|
@ -261,12 +263,13 @@ private:
|
|||
void updateSelected();
|
||||
void setSelected(OverState newSelected);
|
||||
void setPressed(OverState newPressed);
|
||||
std::unique_ptr<Ui::RippleAnimation> createButtonRipple(int section);
|
||||
QPoint buttonRippleTopLeft(int section) const;
|
||||
[[nodiscard]] std::unique_ptr<Ui::RippleAnimation> createButtonRipple(
|
||||
int section);
|
||||
[[nodiscard]] QPoint buttonRippleTopLeft(int section) const;
|
||||
|
||||
std::vector<Set> &shownSets();
|
||||
const std::vector<Set> &shownSets() const;
|
||||
int featuredRowHeight() const;
|
||||
[[nodiscard]] std::vector<Set> &shownSets();
|
||||
[[nodiscard]] const std::vector<Set> &shownSets() const;
|
||||
[[nodiscard]] int featuredRowHeight() const;
|
||||
void checkVisibleFeatured(int visibleTop, int visibleBottom);
|
||||
void readVisibleFeatured(int visibleTop, int visibleBottom);
|
||||
|
||||
|
@ -324,6 +327,7 @@ private:
|
|||
|
||||
[[nodiscard]] const Data::StickersSetsOrder &defaultSetsOrder() const;
|
||||
[[nodiscard]] Data::StickersSetsOrder &defaultSetsOrderRef();
|
||||
void filterEffectsByEmoji(const std::vector<EmojiPtr> &emoji);
|
||||
|
||||
enum class AppendSkip {
|
||||
None,
|
||||
|
@ -356,6 +360,7 @@ private:
|
|||
void fillLocalSearchRows(const QString &query);
|
||||
void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
|
||||
void addSearchRow(not_null<Data::StickersSet*> set);
|
||||
void toggleSearchLoading(bool loading);
|
||||
|
||||
void showPreview();
|
||||
|
||||
|
@ -431,6 +436,7 @@ private:
|
|||
std::unique_ptr<StickerPremiumMark> _premiumMark;
|
||||
|
||||
std::vector<not_null<DocumentData*>> _filteredStickers;
|
||||
std::vector<EmojiPtr> _filterStickersCornerEmoji;
|
||||
std::map<QString, std::vector<uint64>> _searchCache;
|
||||
std::vector<std::pair<uint64, QStringList>> _searchIndex;
|
||||
base::Timer _searchRequestTimer;
|
||||
|
|
|
@ -1460,9 +1460,7 @@ int TabbedSelector::Inner::resizeGetHeight(int newWidth) {
|
|||
}
|
||||
|
||||
int TabbedSelector::Inner::minimalHeight() const {
|
||||
return (_minimalHeight > 0)
|
||||
? _minimalHeight
|
||||
: defaultMinimalHeight();
|
||||
return _minimalHeight.value_or(defaultMinimalHeight());
|
||||
}
|
||||
|
||||
int TabbedSelector::Inner::defaultMinimalHeight() const {
|
||||
|
|
|
@ -422,7 +422,7 @@ private:
|
|||
|
||||
int _visibleTop = 0;
|
||||
int _visibleBottom = 0;
|
||||
int _minimalHeight = 0;
|
||||
std::optional<int> _minimalHeight;
|
||||
|
||||
rpl::event_stream<int> _scrollToRequests;
|
||||
rpl::event_stream<bool> _disableScrollRequests;
|
||||
|
|
|
@ -211,7 +211,9 @@ Selector::Selector(
|
|||
reactions,
|
||||
(reactions.customAllowed
|
||||
? ChatHelpers::EmojiListMode::FullReactions
|
||||
: ChatHelpers::EmojiListMode::RecentReactions),
|
||||
: reactions.stickers.empty()
|
||||
? ChatHelpers::EmojiListMode::RecentReactions
|
||||
: ChatHelpers::EmojiListMode::MessageEffects),
|
||||
{},
|
||||
std::move(about),
|
||||
iconFactory,
|
||||
|
@ -1075,15 +1077,6 @@ void Selector::createList() {
|
|||
_shadow->update();
|
||||
}
|
||||
}, _list->lifetime());
|
||||
if (_stickers) {
|
||||
_stickers->scrollToRequests(
|
||||
) | rpl::start_with_next([=](int y) {
|
||||
_scroll->scrollToY(_list->height() + y);
|
||||
if (_shadow) {
|
||||
_shadow->update();
|
||||
}
|
||||
}, _stickers->lifetime());
|
||||
}
|
||||
|
||||
_scroll->setGeometry(inner.marginsRemoved({
|
||||
_st.margin.left(),
|
||||
|
@ -1091,7 +1084,17 @@ void Selector::createList() {
|
|||
0,
|
||||
0,
|
||||
}));
|
||||
_list->setMinimalHeight(geometry.width(), _scroll->height());
|
||||
if (_stickers) {
|
||||
_list->setMinimalHeight(geometry.width(), 0);
|
||||
_stickers->setMinimalHeight(geometry.width(), 0);
|
||||
|
||||
_list->searchQueries(
|
||||
) | rpl::start_with_next([=](std::vector<QString> &&query) {
|
||||
_stickers->applySearchQuery(std::move(query));
|
||||
}, _stickers->lifetime());
|
||||
} else {
|
||||
_list->setMinimalHeight(geometry.width(), _scroll->height());
|
||||
}
|
||||
|
||||
updateVisibleTopBottom();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue