Use TabbedSearch control for stickers panel.

This commit is contained in:
John Preston 2023-01-24 17:08:35 +04:00
parent d4897c8a95
commit 65b1a0c9a4
12 changed files with 104 additions and 250 deletions

View File

@ -2001,7 +2001,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stickers_remove_group_set" = "Remove group sticker set?";
"lng_stickers_group_from_your" = "Choose from your stickers";
"lng_stickers_group_from_featured" = "Choose from trending stickers";
"lng_stickers_search_sets" = "Search sticker sets";
"lng_stickers_nothing_found" = "No stickers found";
"lng_stickers_remove_pack_confirm" = "Remove";
"lng_stickers_archive_pack" = "Archive Stickers";

View File

@ -321,11 +321,6 @@ stickerPanRemoveSet: IconButton(hashtagClose) {
iconPosition: point(-1px, -1px);
rippleAreaPosition: point(0px, 0px);
}
stickerIconWidth: 42px;
stickerIconPadding: 5px;
stickerIconOpacity: 0.7;
stickerIconSel: 2px;
stickerIconSelColor: emojiIconFgActive;
stickerIconMove: 400;
stickerPreviewDuration: 150;
stickerPreviewMin: 0.1;
@ -349,10 +344,6 @@ inlineBotsScroll: ScrollArea(defaultSolidScroll) {
}
gifsPadding: margins(9px, 5px, 3px, 9px);
gifsSearchField: defaultMultiSelectSearchField;
gifsSearchFieldPosition: point(42px, 7px);
gifsSearchCancel: defaultMultiSelectSearchCancel;
gifsSearchCancelPosition: point(1px, 1px);
emojiSuggestionsDropdown: InnerDropdown(defaultInnerDropdown) {
scrollMargin: margins(0px, emojiColorsPadding, 0px, emojiColorsPadding);

View File

@ -24,7 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/sticker_set_box.h"
#include "lang/lang_keys.h"
#include "layout/layout_position.h"
#include "data/data_emoji_statuses.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_peer_values.h"
@ -414,9 +413,6 @@ EmojiListWidget::EmojiListWidget(
_customSingleSize = Data::FrameSizeFromTag(
Data::CustomEmojiManager::SizeTag::Large
) / style::DevicePixelRatio();
_customSetIconSize = Data::FrameSizeFromTag(
Data::CustomEmojiManager::SizeTag::SetIcon
) / style::DevicePixelRatio();
_picker->hide();
@ -470,23 +466,13 @@ EmojiListWidget::~EmojiListWidget() {
}
void EmojiListWidget::setupSearch() {
using Descriptor = Ui::SearchDescriptor;
_search = std::make_unique<Ui::TabbedSearch>(this, st(), Descriptor{
.st = st().search,
.groups = (_mode == Mode::EmojiStatus
? session().data().emojiStatuses().statusGroupsValue()
: session().data().emojiStatuses().emojiGroupsValue()),
.customEmojiFactory = session().data().customEmojiManager().factory(
Data::CustomEmojiManager::SizeTag::SetIcon,
Ui::SearchWithGroups::IconSizeOverride())
});
_search->queryValue(
) | rpl::start_with_next([=](std::vector<QString> &&query) {
const auto session = &_controller->session();
_search = MakeSearch(this, st(), [=](std::vector<QString> &&query) {
_nextSearchQuery = std::move(query);
InvokeQueued(this, [=] {
applyNextSearchQuery();
});
}, lifetime());
}, session, (_mode == Mode::EmojiStatus));
}
void EmojiListWidget::applyNextSearchQuery() {
@ -1940,7 +1926,7 @@ std::vector<StickerIcon> EmojiListWidget::fillIcons() {
} else {
result.emplace_back(AllEmojiSectionSetId());
}
const auto esize = _customSetIconSize;
const auto esize = StickersListFooter::IconFrameSize();
for (const auto &custom : _custom) {
const auto set = custom.set;
result.emplace_back(set, custom.thumbnailDocument, esize, esize);

View File

@ -359,7 +359,6 @@ private:
DocumentId,
std::unique_ptr<Ui::Text::CustomEmoji>> _customRecent;
int _customSingleSize = 0;
int _customSetIconSize = 0;
bool _allowWithoutPremium = false;
Ui::RoundRect _overBg;

View File

@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_list_footer.h"
#include "data/data_photo.h"
#include "data/data_document.h"
#include "data/data_emoji_statuses.h"
#include "data/stickers/data_custom_emoji.h"
#include "data/data_session.h"
#include "data/data_user.h"
@ -199,26 +198,16 @@ std::vector<StickerIcon> GifsListWidget::fillIcons() {
auto result = std::vector<StickerIcon>();
result.reserve(_sections.size() + 1);
result.emplace_back(Data::Stickers::RecentSetId);
const auto side = StickersListFooter::IconFrameSize();
for (const auto &section : _sections) {
const auto s = section.document;
const auto id = s->id;
const auto availw = st::stickerIconWidth - 2 * st::stickerIconPadding;
const auto availh = st().footer - 2 * st::stickerIconPadding;
const auto size = s->hasThumbnail()
? QSize(
s->thumbnailLocation().width(),
s->thumbnailLocation().height())
: QSize();
auto thumbw = size.width(), thumbh = size.height(), pixw = 1, pixh = 1;
if (availw * thumbh > availh * thumbw) {
pixh = availh;
pixw = (pixh * thumbw) / thumbh;
} else {
pixw = availw;
pixh = thumbw ? ((pixw * thumbh) / thumbw) : 1;
}
if (pixw < 1) pixw = 1;
if (pixh < 1) pixh = 1;
const auto pix = size.scaled(side, side, Qt::KeepAspectRatio);
const auto owner = &s->owner();
const auto already = _fakeSets.find(id);
const auto set = (already != end(_fakeSets))
@ -235,7 +224,7 @@ std::vector<StickerIcon> GifsListWidget::fillIcons() {
0,
Data::StickersSetFlag::Special,
0)).first;
result.emplace_back(set->second.get(), s, pixw, pixh);
result.emplace_back(set->second.get(), s, pix.width(), pix.height());
}
return result;
}
@ -802,17 +791,8 @@ bool GifsListWidget::refreshInlineRows(int32 *added) {
}
void GifsListWidget::setupSearch() {
const auto owner = &_controller->session().data();
using Descriptor = Ui::SearchDescriptor;
_search = std::make_unique<Ui::TabbedSearch>(this, st(), Descriptor{
.st = st().search,
.groups = owner->emojiStatuses().emojiGroupsValue(),
.customEmojiFactory = owner->customEmojiManager().factory(
Data::CustomEmojiManager::SizeTag::SetIcon,
Ui::SearchWithGroups::IconSizeOverride())
});
_search->queryValue(
) | rpl::start_with_next([=](std::vector<QString> &&query) {
const auto session = &_controller->session();
_search = MakeSearch(this, st(), [=](std::vector<QString> &&query) {
_chosenSetId = Data::Stickers::RecentSetId;
refreshIcons();
searchForGifs(ranges::accumulate(query, QString(), [](
@ -820,7 +800,7 @@ void GifsListWidget::setupSearch() {
QString b) {
return a.isEmpty() ? b : (a + ' ' + b);
}));
}, lifetime());
}, session);
}
int32 GifsListWidget::showInlineRows(bool newResults) {

View File

@ -156,8 +156,8 @@ StickerIcon::StickerIcon(
: setId(set->id)
, set(set)
, sticker(sticker)
, pixw(pixw)
, pixh(pixh) {
, pixw(std::max(pixw, 1))
, pixh(std::max(pixh, 1)) {
}
StickerIcon::StickerIcon(StickerIcon&&) = default;
@ -255,14 +255,12 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
, _iconState([=] { update(); })
, _subiconState([=] { update(); })
, _selectionBg(st::emojiPanRadius, st::windowBgRipple)
, _subselectionBg(st().iconArea / 2, st::windowBgRipple)
, _barSelection(descriptor.barSelection) {
, _subselectionBg(st().iconArea / 2, st::windowBgRipple) {
setMouseTracking(true);
_iconsLeft = st().iconSkip;
_iconsRight = st().iconSkip + (_settingsButtonVisible
? st::stickerIconWidth
: 0);
_iconsLeft = st().iconSkip
+ (_settingsButtonVisible ? st().iconWidth : 0);
_iconsRight = st().iconSkip;
_session->downloaderTaskFinished(
) | rpl::start_with_next([=] {
@ -305,72 +303,10 @@ void StickersListFooter::paintExpanding(
p.setClipping(false);
}
void StickersListFooter::initSearch() {
_searchField.create(
this,
st::gifsSearchField,
tr::lng_stickers_search_sets());
_searchCancel.create(this, st::gifsSearchCancel);
_searchField->show();
_searchCancel->show(anim::type::instant);
const auto cancelSearch = [=] {
if (_searchField->getLastText().isEmpty()) {
toggleSearch(false);
} else {
_searchField->setText(QString());
}
};
connect(_searchField, &Ui::InputField::submitted, [=] {
_searchRequests.fire({
.text = _searchField->getLastText(),
.forced = true,
});
});
connect(_searchField, &Ui::InputField::cancelled, cancelSearch);
connect(_searchField, &Ui::InputField::changed, [=] {
_searchRequests.fire({
.text = _searchField->getLastText(),
});
});
_searchCancel->setClickedCallback(cancelSearch);
resizeSearchControls();
}
void StickersListFooter::toggleSearch(bool visible) {
if (_searchShown == visible) {
return;
}
_searchShown = visible;
if (_searchShown) {
initSearch();
stealFocus();
} else if (_searchField) {
returnFocus();
_searchField.destroy();
_searchCancel.destroy();
_focusTakenFrom = nullptr;
}
update();
}
void StickersListFooter::stealFocus() {
if (_searchField) {
if (!_focusTakenFrom) {
_focusTakenFrom = QApplication::focusWidget();
}
_searchField->setFocus();
}
}
void StickersListFooter::returnFocus() {
if (_searchField && _focusTakenFrom) {
if (_searchField->hasFocus()) {
_focusTakenFrom->setFocus();
}
_focusTakenFrom = nullptr;
}
int StickersListFooter::IconFrameSize() {
return Data::FrameSizeFromTag(
Data::CustomEmojiManager::SizeTag::SetIcon
) / style::DevicePixelRatio();
}
void StickersListFooter::enumerateVisibleIcons(
@ -611,12 +547,6 @@ void StickersListFooter::leaveToChildEvent(QEvent *e, QWidget *child) {
updateSelected();
}
void StickersListFooter::setLoading(bool loading) {
if (_searchCancel) {
_searchCancel->setLoadingAnimation(loading);
}
}
void StickersListFooter::paintEvent(QPaintEvent *e) {
auto p = Painter(this);
@ -627,7 +557,7 @@ void StickersListFooter::paintEvent(QPaintEvent *e) {
void StickersListFooter::paint(
Painter &p,
const ExpandingContext &context) const {
if (_icons.empty() || _searchShown) {
if (_icons.empty()) {
return;
}
@ -654,10 +584,7 @@ void StickersListFooter::paint(
} else {
p.setClipRect(clip);
}
if (!_barSelection) {
paintSelectionBg(p, context);
}
paintSelectionBg(p, context);
const auto iconCacheSize = QSize(_singleWidth, st().footer);
const auto full = iconCacheSize * style::DevicePixelRatio();
@ -672,10 +599,6 @@ void StickersListFooter::paint(
enumerateVisibleIcons([&](const IconInfo &info) {
paintSetIcon(p, context, info, now, paused);
});
if (_barSelection) {
paintSelectionBar(p);
}
paintLeftRightFading(p, context);
}
@ -720,21 +643,6 @@ void StickersListFooter::paintSelectionBg(
}
}
void StickersListFooter::paintSelectionBar(QPainter &p) const {
auto selxrel = _iconsLeft + qRound(_iconState.selectionX.current());
auto selx = selxrel - qRound(_iconState.x.current());
const auto selw = qRound(_iconState.selectionWidth.current());
if (rtl()) {
selx = width() - selx - selw;
}
p.fillRect(
selx,
_iconsTop + st().footer - st::stickerIconPadding,
selw,
st::stickerIconSel,
st::stickerIconSelColor);
}
void StickersListFooter::paintLeftRightFading(
QPainter &p,
const ExpandingContext &context) const {
@ -844,25 +752,9 @@ void StickersListFooter::validateFadeMask() const {
}
void StickersListFooter::resizeEvent(QResizeEvent *e) {
if (_searchField) {
resizeSearchControls();
}
refreshIconsGeometry(_activeByScrollId, ValidateIconAnimations::None);
}
void StickersListFooter::resizeSearchControls() {
Expects(_searchField != nullptr);
Expects(_searchCancel != nullptr);
const auto fieldWidth = width()
- st::gifsSearchFieldPosition.x()
- st::gifsSearchCancelPosition.x()
- st::gifsSearchCancel.width;
_searchField->resizeToWidth(fieldWidth);
_searchField->moveToLeft(st::gifsSearchFieldPosition.x(), st::gifsSearchFieldPosition.y());
_searchCancel->moveToRight(st::gifsSearchCancelPosition.x(), st::gifsSearchCancelPosition.y());
}
rpl::producer<uint64> StickersListFooter::setChosen() const {
return _setChosen.events();
}
@ -871,10 +763,6 @@ rpl::producer<> StickersListFooter::openSettingsRequests() const {
return _openSettingsRequests.events();
}
rpl::producer<StickersListFooter::SearchRequest> StickersListFooter::searchRequests() const {
return _searchRequests.events();
}
void StickersListFooter::mousePressEvent(QMouseEvent *e) {
if (e->button() != Qt::LeftButton) {
return;
@ -1065,8 +953,7 @@ void StickersListFooter::updateSelected() {
auto p = mapFromGlobal(_iconsMousePos);
auto x = p.x(), y = p.y();
if (rtl()) x = width() - x;
const auto settingsLeft = width() - _iconsRight;
const auto searchLeft = _iconsLeft - _singleWidth;
const auto settingsLeft = _iconsLeft - _singleWidth;
auto newOver = OverState(SpecialOver::None);
if (_settingsButtonVisible
&& x >= settingsLeft
@ -1174,9 +1061,7 @@ void StickersListFooter::refreshIconsGeometry(
_iconState.selectionWidth.finish();
_iconState.animationStart = 0;
_iconState.animation.stop();
if (_barSelection) {
_singleWidth = st::stickerIconWidth;
} else if (_icons.size() > 1
if (_icons.size() > 1
&& _icons[1].setId == EmojiSectionSetId(EmojiSection::People)) {
_singleWidth = (width() - _iconsLeft - _iconsRight) / _icons.size();
} else {
@ -1193,9 +1078,6 @@ void StickersListFooter::refreshIconsGeometry(
}
void StickersListFooter::refreshSubiconsGeometry() {
if (_barSelection) {
return;
}
using Section = Ui::Emoji::Section;
_subiconState.x.finish();
_subiconState.animationStart = 0;
@ -1228,7 +1110,7 @@ bool StickersListFooter::hasOnlyFeaturedSets() const {
}
void StickersListFooter::paintStickerSettingsIcon(QPainter &p) const {
const auto settingsLeft = width() - _iconsRight;
const auto settingsLeft = _iconsLeft - _singleWidth;
st::stickersSettings.paint(
p,
settingsLeft

View File

@ -113,7 +113,6 @@ public:
Fn<bool()> paused;
not_null<RpWidget*> parent;
bool settingsButtonVisible = false;
bool barSelection = false;
const style::EmojiPan *st = nullptr;
};
explicit StickersListFooter(Descriptor &&descriptor);
@ -131,27 +130,19 @@ public:
void leaveToChildEvent(QEvent *e, QWidget *child) override;
void stealFocus();
void returnFocus();
void setLoading(bool loading);
void clearHeavyData();
[[nodiscard]] rpl::producer<uint64> setChosen() const;
[[nodiscard]] rpl::producer<> openSettingsRequests() const;
struct SearchRequest {
QString text;
bool forced = false;
};
[[nodiscard]] rpl::producer<SearchRequest> searchRequests() const;
void paintExpanding(
Painter &p,
QRect clip,
float64 radius,
RectPart origin);
[[nodiscard]] static int IconFrameSize();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
@ -258,7 +249,6 @@ private:
void paintSelectionBg(
QPainter &p,
const ExpandingContext &context) const;
void paintSelectionBar(QPainter &p) const;
void paintLeftRightFading(
QPainter &p,
const ExpandingContext &context) const;
@ -266,9 +256,6 @@ private:
void updateEmojiSectionWidth();
void updateEmojiWidthCallback();
void initSearch();
void toggleSearch(bool visible);
void resizeSearchControls();
void scrollByWheelEvent(not_null<QWheelEvent*> e);
void validateFadeLeft(int leftWidth) const;
@ -311,17 +298,10 @@ private:
Ui::Animations::Simple _subiconsWidthAnimation;
int _subiconsWidth = 0;
bool _subiconsExpanded = false;
bool _barSelection = false;
bool _repaintScheduled = false;
bool _searchShown = false;
object_ptr<Ui::InputField> _searchField = { nullptr };
object_ptr<Ui::CrossButton> _searchCancel = { nullptr };
QPointer<QWidget> _focusTakenFrom;
rpl::event_stream<> _openSettingsRequests;
rpl::event_stream<uint64> _setChosen;
rpl::event_stream<SearchRequest> _searchRequests;
};

View File

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "menu/menu_send.h" // SendMenu::FillSendMenu
#include "chat_helpers/stickers_lottie.h"
#include "chat_helpers/stickers_list_footer.h"
#include "ui/controls/tabbed_search.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/effects/animations.h"
@ -201,6 +202,10 @@ StickersListWidget::StickersListWidget(
setMouseTracking(true);
setAttribute(Qt::WA_OpaquePaintEvent);
if (!_isMasks) {
setupSearch();
}
_settings->addClickHandler([=] {
using Section = StickersBox::Section;
controller->show(
@ -265,7 +270,6 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
.paused = pausedMethod(),
.parent = this,
.settingsButtonVisible = true,
.barSelection = true,
});
_footer = result;
@ -288,15 +292,6 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
Ui::LayerOption::KeepOther);
}, _footer->lifetime());
_footer->searchRequests(
) | rpl::start_with_next([=](StickersListFooter::SearchRequest request) {
if (request.forced) {
sendSearchRequest();
} else {
searchForSets(request.text);
}
}, _footer->lifetime());
return result;
}
@ -417,6 +412,7 @@ int StickersListWidget::featuredRowHeight() const {
template <typename Callback>
bool StickersListWidget::enumerateSections(Callback callback) const {
auto info = SectionInfo();
info.top = _search ? _search->height() : 0;
const auto &sets = shownSets();
for (auto i = 0; i != sets.size(); ++i) {
auto &set = sets[i];
@ -517,11 +513,11 @@ void StickersListWidget::sendSearchRequest() {
auto it = _searchCache.find(_searchQuery);
if (it != _searchCache.cend()) {
_footer->setLoading(false);
_search->setLoading(false);
return;
}
_footer->setLoading(true);
_search->setLoading(true);
const auto hash = uint64(0);
_searchRequestId = _api.request(MTPmessages_SearchStickerSets(
MTP_flags(0),
@ -531,7 +527,7 @@ void StickersListWidget::sendSearchRequest() {
searchResultsDone(result);
}).fail([=] {
// show error?
_footer->setLoading(false);
_search->setLoading(false);
_searchRequestId = 0;
}).handleAllErrors().send();
}
@ -544,7 +540,7 @@ void StickersListWidget::searchForSets(const QString &query) {
}
if (_searchQuery != cleaned) {
_footer->setLoading(false);
_search->setLoading(false);
if (const auto requestId = base::take(_searchRequestId)) {
_api.request(requestId).cancel();
}
@ -560,7 +556,7 @@ void StickersListWidget::searchForSets(const QString &query) {
}
void StickersListWidget::cancelSetsSearch() {
_footer->setLoading(false);
_search->setLoading(false);
if (const auto requestId = base::take(_searchRequestId)) {
_api.request(requestId).cancel();
}
@ -758,7 +754,7 @@ auto StickersListWidget::shownSets() -> std::vector<Set> & {
void StickersListWidget::searchResultsDone(
const MTPmessages_FoundStickerSets &result) {
_footer->setLoading(false);
_search->setLoading(false);
_searchRequestId = 0;
if (result.type() == mtpc_messages_foundStickerSetsNotModified) {
@ -926,7 +922,12 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
set.ripple.reset();
}
}
(selected ? st::stickerPanRemoveSet.iconOver : st::stickerPanRemoveSet.icon).paint(p, remove.topLeft() + st::stickerPanRemoveSet.iconPosition, width());
const auto &icon = selected ? st::stickerPanRemoveSet.iconOver : st::stickerPanRemoveSet.icon;
icon.paint(
p,
remove.x() + (remove.width() - icon.width()) / 2,
remove.y() + (remove.height() - icon.height()) / 2,
width());
widthForTitle -= remove.width();
}
@ -2253,10 +2254,6 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
std::vector<StickerIcon> StickersListWidget::fillIcons() {
auto result = std::vector<StickerIcon>();
result.reserve(_mySets.size() + 1);
if (!_officialSets.empty() && !_isMasks) {
result.emplace_back(Data::Stickers::FeaturedSetId);
}
auto i = 0;
if (i != _mySets.size() && _mySets[i].id == Data::Stickers::FavedSetId) {
++i;
@ -2268,6 +2265,7 @@ std::vector<StickerIcon> StickersListWidget::fillIcons() {
result.emplace_back(Data::Stickers::RecentSetId);
}
}
const auto side = StickersListFooter::IconFrameSize();
for (auto l = _mySets.size(); i != l; ++i) {
if (_mySets[i].id == Data::Stickers::MegagroupSetId) {
result.emplace_back(Data::Stickers::MegagroupSetId);
@ -2277,8 +2275,6 @@ std::vector<StickerIcon> StickersListWidget::fillIcons() {
const auto set = _mySets[i].set;
Assert(set != nullptr);
const auto s = _mySets[i].thumbnailDocument;
const auto availw = st::stickerIconWidth - 2 * st::stickerIconPadding;
const auto availh = st().footer - 2 * st::stickerIconPadding;
const auto size = set->hasThumbnail()
? QSize(
set->thumbnailLocation().width(),
@ -2288,17 +2284,8 @@ std::vector<StickerIcon> StickersListWidget::fillIcons() {
s->thumbnailLocation().width(),
s->thumbnailLocation().height())
: QSize();
auto thumbw = size.width(), thumbh = size.height(), pixw = 1, pixh = 1;
if (availw * thumbh > availh * thumbw) {
pixh = availh;
pixw = (pixh * thumbw) / thumbh;
} else {
pixw = availw;
pixh = thumbw ? ((pixw * thumbh) / thumbw) : 1;
}
if (pixw < 1) pixw = 1;
if (pixh < 1) pixh = 1;
result.emplace_back(set, s, pixw, pixh);
const auto pix = size.scaled(side, side, Qt::KeepAspectRatio);
result.emplace_back(set, s, pix.width(), pix.height());
}
return result;
}
@ -2471,7 +2458,7 @@ void StickersListWidget::showStickerSet(uint64 setId) {
auto y = 0;
enumerateSections([this, setId, &y](const SectionInfo &info) {
if (shownSets()[info.section].id == setId) {
y = info.top;
y = info.section ? info.top : 0;
return false;
}
return true;
@ -2527,17 +2514,28 @@ void StickersListWidget::showMegagroupSet(ChannelData *megagroup) {
}
void StickersListWidget::afterShown() {
if (_footer) {
_footer->stealFocus();
if (_search) {
_search->stealFocus();
}
}
void StickersListWidget::beforeHiding() {
if (_footer) {
_footer->returnFocus();
if (_search) {
_search->returnFocus();
}
}
void StickersListWidget::setupSearch() {
const auto session = &_controller->session();
_search = MakeSearch(this, st(), [=](std::vector<QString> &&query) {
searchForSets(ranges::accumulate(query, QString(), [](
QString a,
QString b) {
return a.isEmpty() ? b : (a + ' ' + b);
}));
}, session);
}
void StickersListWidget::displaySet(uint64 setId) {
if (setId == Data::Stickers::MegagroupSetId) {
if (_megagroupSet->canEditStickers()) {

View File

@ -29,6 +29,7 @@ class PopupMenu;
class RippleAnimation;
class BoxContent;
class PathShiftGradient;
class TabbedSearch;
} // namespace Ui
namespace Lottie {
@ -196,6 +197,7 @@ private:
const QVector<DocumentData*> &pack,
bool skipPremium);
void setupSearch();
void preloadMoreOfficial();
QSize boundingBoxSize() const;
@ -329,6 +331,7 @@ private:
not_null<DocumentData*> document);
not_null<Window::SessionController*> _controller;
std::unique_ptr<Ui::TabbedSearch> _search;
MTP::Sender _api;
std::unique_ptr<LocalStickersManager> _localSetsManager;
ChannelData *_megagroupSet = nullptr;

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_list_widget.h"
#include "chat_helpers/gifs_list_widget.h"
#include "menu/menu_send.h"
#include "ui/controls/tabbed_search.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/shadow.h"
@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h"
#include "storage/localstorage.h"
#include "data/data_channel.h"
#include "data/data_emoji_statuses.h"
#include "data/data_session.h"
#include "data/data_changes.h"
#include "data/stickers/data_stickers.h"
@ -288,6 +290,32 @@ void TabbedSelector::Tab::saveScrollTop() {
_scrollTop = widget()->getVisibleTop();
}
std::unique_ptr<Ui::TabbedSearch> MakeSearch(
not_null<Ui::RpWidget*> parent,
const style::EmojiPan &st,
Fn<void(std::vector<QString>&&)> callback,
not_null<Main::Session*> session,
bool statusCategories) {
using Descriptor = Ui::SearchDescriptor;
const auto owner = &session->data();
auto result = std::make_unique<Ui::TabbedSearch>(parent, st, Descriptor{
.st = st.search,
.groups = (statusCategories
? owner->emojiStatuses().statusGroupsValue()
: owner->emojiStatuses().emojiGroupsValue()),
.customEmojiFactory = owner->customEmojiManager().factory(
Data::CustomEmojiManager::SizeTag::SetIcon,
Ui::SearchWithGroups::IconSizeOverride())
});
result->queryValue(
) | rpl::skip(1) | rpl::start_with_next(
std::move(callback),
parent->lifetime());
return result;
}
TabbedSelector::TabbedSelector(
QWidget *parent,
not_null<Window::SessionController*> controller,

View File

@ -31,6 +31,7 @@ class ScrollArea;
class SettingsSlider;
class FlatLabel;
class BoxContent;
class TabbedSearch;
} // namespace Ui
namespace Window {
@ -77,6 +78,13 @@ struct EmojiChosen {
using InlineChosen = InlineBots::ResultSelected;
[[nodiscard]] std::unique_ptr<Ui::TabbedSearch> MakeSearch(
not_null<Ui::RpWidget*> parent,
const style::EmojiPan &st,
Fn<void(std::vector<QString>&&)> callback,
not_null<Main::Session*> session,
bool statusCategories = false);
class TabbedSelector : public Ui::RpWidget {
public:
static constexpr auto kPickCustomTimeId = -1;

View File

@ -397,7 +397,7 @@ void Autocomplete::setupContent() {
this,
object_ptr<Ui::InputField>(
this,
st::gifsSearchField,
st::defaultMultiSelectSearchField,
rpl::single(u"Search for templates"_q)), // #TODO hard_lang
st::autocompleteSearchPadding);
const auto input = inputWrap->entity();