mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Use TabbedSearch control for stickers panel.
This commit is contained in:
parent
d4897c8a95
commit
65b1a0c9a4
12 changed files with 104 additions and 250 deletions
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 §ion : _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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue