mirror of https://github.com/procxx/kepka.git
				
				
				
			Show animated stickers in the panel.
This commit is contained in:
		
							parent
							
								
									040cae6a9a
								
							
						
					
					
						commit
						0d6ee3929d
					
				| 
						 | 
					@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "ui/effects/animations.h"
 | 
					#include "ui/effects/animations.h"
 | 
				
			||||||
#include "ui/effects/ripple_animation.h"
 | 
					#include "ui/effects/ripple_animation.h"
 | 
				
			||||||
#include "ui/image/image.h"
 | 
					#include "ui/image/image.h"
 | 
				
			||||||
 | 
					#include "lottie/lottie_animation.h"
 | 
				
			||||||
#include "boxes/stickers_box.h"
 | 
					#include "boxes/stickers_box.h"
 | 
				
			||||||
#include "inline_bots/inline_bot_result.h"
 | 
					#include "inline_bots/inline_bot_result.h"
 | 
				
			||||||
#include "chat_helpers/stickers.h"
 | 
					#include "chat_helpers/stickers.h"
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "boxes/sticker_set_box.h"
 | 
					#include "boxes/sticker_set_box.h"
 | 
				
			||||||
#include "boxes/stickers_box.h"
 | 
					#include "boxes/stickers_box.h"
 | 
				
			||||||
#include "boxes/confirm_box.h"
 | 
					#include "boxes/confirm_box.h"
 | 
				
			||||||
 | 
					#include "window/window_session_controller.h" // GifPauseReason.
 | 
				
			||||||
#include "auth_session.h"
 | 
					#include "auth_session.h"
 | 
				
			||||||
#include "observer_peer.h"
 | 
					#include "observer_peer.h"
 | 
				
			||||||
#include "apiwrap.h"
 | 
					#include "apiwrap.h"
 | 
				
			||||||
| 
						 | 
					@ -155,6 +157,15 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto StickersListWidget::PrepareStickers(const Stickers::Pack &pack)
 | 
				
			||||||
 | 
					-> std::vector<Sticker> {
 | 
				
			||||||
 | 
						return ranges::view::all(
 | 
				
			||||||
 | 
							pack
 | 
				
			||||||
 | 
						) | ranges::view::transform([](DocumentData *document) {
 | 
				
			||||||
 | 
							return Sticker{ document };
 | 
				
			||||||
 | 
						}) | ranges::to_vector;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
StickersListWidget::Set::Set(
 | 
					StickersListWidget::Set::Set(
 | 
				
			||||||
	uint64 id,
 | 
						uint64 id,
 | 
				
			||||||
	MTPDstickerSet::Flags flags,
 | 
						MTPDstickerSet::Flags flags,
 | 
				
			||||||
| 
						 | 
					@ -163,13 +174,13 @@ StickersListWidget::Set::Set(
 | 
				
			||||||
	ImagePtr thumbnail,
 | 
						ImagePtr thumbnail,
 | 
				
			||||||
	bool externalLayout,
 | 
						bool externalLayout,
 | 
				
			||||||
	int count,
 | 
						int count,
 | 
				
			||||||
	const Stickers::Pack &pack)
 | 
						std::vector<Sticker> &&stickers)
 | 
				
			||||||
: id(id)
 | 
					: id(id)
 | 
				
			||||||
, flags(flags)
 | 
					, flags(flags)
 | 
				
			||||||
, title(title)
 | 
					, title(title)
 | 
				
			||||||
, shortName(shortName)
 | 
					, shortName(shortName)
 | 
				
			||||||
, thumbnail(thumbnail)
 | 
					, thumbnail(thumbnail)
 | 
				
			||||||
, pack(pack)
 | 
					, stickers(std::move(stickers))
 | 
				
			||||||
, externalLayout(externalLayout)
 | 
					, externalLayout(externalLayout)
 | 
				
			||||||
, count(count) {
 | 
					, count(count) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -773,12 +784,12 @@ void StickersListWidget::readVisibleSets() {
 | 
				
			||||||
		if (i * rowHeight < itemsVisibleTop || (i + 1) * rowHeight > itemsVisibleBottom) {
 | 
							if (i * rowHeight < itemsVisibleTop || (i + 1) * rowHeight > itemsVisibleBottom) {
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		int count = qMin(set.pack.size(), _columnCount);
 | 
							int count = qMin(int(set.stickers.size()), _columnCount);
 | 
				
			||||||
		int loaded = 0;
 | 
							int loaded = 0;
 | 
				
			||||||
		for (int j = 0; j < count; ++j) {
 | 
							for (int j = 0; j < count; ++j) {
 | 
				
			||||||
			if (!set.pack[j]->hasThumbnail()
 | 
								if (!set.stickers[j].document->hasThumbnail()
 | 
				
			||||||
				|| set.pack[j]->thumbnail()->loaded()
 | 
									|| set.stickers[j].document->thumbnail()->loaded()
 | 
				
			||||||
				|| set.pack[j]->loaded()) {
 | 
									|| set.stickers[j].document->loaded()) {
 | 
				
			||||||
				++loaded;
 | 
									++loaded;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -801,7 +812,7 @@ bool StickersListWidget::enumerateSections(Callback callback) const {
 | 
				
			||||||
	for (auto i = 0; i != sets.size(); ++i) {
 | 
						for (auto i = 0; i != sets.size(); ++i) {
 | 
				
			||||||
		auto &set = sets[i];
 | 
							auto &set = sets[i];
 | 
				
			||||||
		info.section = i;
 | 
							info.section = i;
 | 
				
			||||||
		info.count = set.pack.size();
 | 
							info.count = set.stickers.size();
 | 
				
			||||||
		const auto titleSkip = set.externalLayout
 | 
							const auto titleSkip = set.externalLayout
 | 
				
			||||||
			? st::stickersTrendingHeader
 | 
								? st::stickersTrendingHeader
 | 
				
			||||||
			: setHasTitle(set)
 | 
								: setHasTitle(set)
 | 
				
			||||||
| 
						 | 
					@ -1061,7 +1072,9 @@ void StickersListWidget::addSearchRow(not_null<const Stickers::Set*> set) {
 | 
				
			||||||
		set->thumbnail,
 | 
							set->thumbnail,
 | 
				
			||||||
		!SetInMyList(set->flags),
 | 
							!SetInMyList(set->flags),
 | 
				
			||||||
		set->count,
 | 
							set->count,
 | 
				
			||||||
		set->stickers.empty() ? set->covers : set->stickers);
 | 
							PrepareStickers(set->stickers.empty()
 | 
				
			||||||
 | 
								? set->covers
 | 
				
			||||||
 | 
								: set->stickers));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto StickersListWidget::shownSets() const -> const std::vector<Set> & {
 | 
					auto StickersListWidget::shownSets() const -> const std::vector<Set> & {
 | 
				
			||||||
| 
						 | 
					@ -1102,7 +1115,7 @@ void StickersListWidget::searchResultsDone(
 | 
				
			||||||
			std::vector<uint64>()).first;
 | 
								std::vector<uint64>()).first;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto &d = result.c_messages_foundStickerSets();
 | 
						auto &d = result.c_messages_foundStickerSets();
 | 
				
			||||||
	for_const (const auto &stickerSet, d.vsets.v) {
 | 
						for (const auto &stickerSet : d.vsets.v) {
 | 
				
			||||||
		const MTPDstickerSet *setData = nullptr;
 | 
							const MTPDstickerSet *setData = nullptr;
 | 
				
			||||||
		Stickers::Pack covers;
 | 
							Stickers::Pack covers;
 | 
				
			||||||
		switch (stickerSet.type()) {
 | 
							switch (stickerSet.type()) {
 | 
				
			||||||
| 
						 | 
					@ -1146,8 +1159,8 @@ int StickersListWidget::stickersLeft() const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QRect StickersListWidget::stickerRect(int section, int sel) {
 | 
					QRect StickersListWidget::stickerRect(int section, int sel) {
 | 
				
			||||||
	auto info = sectionInfo(section);
 | 
						auto info = sectionInfo(section);
 | 
				
			||||||
	if (sel >= shownSets()[section].pack.size()) {
 | 
						if (sel >= shownSets()[section].stickers.size()) {
 | 
				
			||||||
		sel -= shownSets()[section].pack.size();
 | 
							sel -= shownSets()[section].stickers.size();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto countTillItem = (sel - (sel % _columnCount));
 | 
						auto countTillItem = (sel - (sel % _columnCount));
 | 
				
			||||||
	auto rowsToSkip = (countTillItem / _columnCount) + ((countTillItem % _columnCount) ? 1 : 0);
 | 
						auto rowsToSkip = (countTillItem / _columnCount) + ((countTillItem % _columnCount) ? 1 : 0);
 | 
				
			||||||
| 
						 | 
					@ -1191,7 +1204,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
 | 
				
			||||||
			const auto size = (set.flags
 | 
								const auto size = (set.flags
 | 
				
			||||||
				& MTPDstickerSet_ClientFlag::f_not_loaded)
 | 
									& MTPDstickerSet_ClientFlag::f_not_loaded)
 | 
				
			||||||
				? set.count
 | 
									? set.count
 | 
				
			||||||
				: int(set.pack.size());
 | 
									: int(set.stickers.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto widthForTitle = stickersRight() - (st::emojiPanHeaderLeft - st::buttonRadius);
 | 
								auto widthForTitle = stickersRight() - (st::emojiPanHeaderLeft - st::buttonRadius);
 | 
				
			||||||
			if (featuredHasAddButton(info.section)) {
 | 
								if (featuredHasAddButton(info.section)) {
 | 
				
			||||||
| 
						 | 
					@ -1256,7 +1269,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				auto selected = selectedSticker ? (selectedSticker->section == info.section && selectedSticker->index == index) : false;
 | 
									auto selected = selectedSticker ? (selectedSticker->section == info.section && selectedSticker->index == index) : false;
 | 
				
			||||||
				auto deleteSelected = false;
 | 
									auto deleteSelected = false;
 | 
				
			||||||
				paintSticker(p, set, info.rowsTop, index, selected, deleteSelected);
 | 
									paintSticker(p, set, info.rowsTop, info.section, index, selected, deleteSelected);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1286,7 +1299,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
 | 
				
			||||||
			p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, info.top + st::emojiPanHeaderTop, width(), titleText, titleWidth);
 | 
								p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, info.top + st::emojiPanHeaderTop, width(), titleText, titleWidth);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (clip.top() + clip.height() > info.rowsTop) {
 | 
							if (clip.top() + clip.height() > info.rowsTop) {
 | 
				
			||||||
			if (set.id == Stickers::MegagroupSetId && set.pack.empty()) {
 | 
								if (set.id == Stickers::MegagroupSetId && set.stickers.empty()) {
 | 
				
			||||||
				auto buttonSelected = (base::get_if<OverGroupAdd>(&_selected) != nullptr);
 | 
									auto buttonSelected = (base::get_if<OverGroupAdd>(&_selected) != nullptr);
 | 
				
			||||||
				paintMegagroupEmptySet(p, info.rowsTop, buttonSelected);
 | 
									paintMegagroupEmptySet(p, info.rowsTop, buttonSelected);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
| 
						 | 
					@ -1300,7 +1313,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						auto selected = selectedSticker ? (selectedSticker->section == info.section && selectedSticker->index == index) : false;
 | 
											auto selected = selectedSticker ? (selectedSticker->section == info.section && selectedSticker->index == index) : false;
 | 
				
			||||||
						auto deleteSelected = selected && selectedSticker->overDelete;
 | 
											auto deleteSelected = selected && selectedSticker->overDelete;
 | 
				
			||||||
						paintSticker(p, set, info.rowsTop, index, selected, deleteSelected);
 | 
											paintSticker(p, set, info.rowsTop, info.section, index, selected, deleteSelected);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1351,9 +1364,34 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe
 | 
				
			||||||
	p.drawTextLeft(button.x() - (st::stickerGroupCategoryAdd.width / 2), button.y() + st::stickerGroupCategoryAdd.textTop, width(), _megagroupSetButtonText, _megagroupSetButtonTextWidth);
 | 
						p.drawTextLeft(button.x() - (st::stickerGroupCategoryAdd.width / 2), button.y() + st::stickerGroupCategoryAdd.textTop, width(), _megagroupSetButtonText, _megagroupSetButtonTextWidth);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int index, bool selected, bool deleteSelected) {
 | 
					void StickersListWidget::setupLottie(Set &set, int section, int index) {
 | 
				
			||||||
	auto document = set.pack[index];
 | 
						auto &sticker = set.stickers[index];
 | 
				
			||||||
	if (!document->sticker()) return;
 | 
						const auto document = sticker.document;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sticker.animated = document->data().isEmpty()
 | 
				
			||||||
 | 
							? Lottie::FromFile(document->filepath())
 | 
				
			||||||
 | 
							: Lottie::FromData(document->data());
 | 
				
			||||||
 | 
						const auto animation = sticker.animated.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						animation->updates(
 | 
				
			||||||
 | 
						) | rpl::start_with_next_error([=](Lottie::Update update) {
 | 
				
			||||||
 | 
							rtlupdate(stickerRect(section, index));
 | 
				
			||||||
 | 
						}, [=](Lottie::Error error) {
 | 
				
			||||||
 | 
						}, lifetime());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected) {
 | 
				
			||||||
 | 
						auto &sticker = set.stickers[index];
 | 
				
			||||||
 | 
						const auto document = sticker.document;
 | 
				
			||||||
 | 
						if (!document->sticker()) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (document->sticker()->animated
 | 
				
			||||||
 | 
							&& !sticker.animated
 | 
				
			||||||
 | 
							&& document->loaded()) {
 | 
				
			||||||
 | 
							setupLottie(set, section, index);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int row = (index / _columnCount), col = (index % _columnCount);
 | 
						int row = (index / _columnCount), col = (index % _columnCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1371,7 +1409,19 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int index, bo
 | 
				
			||||||
	auto w = qMax(qRound(coef * document->dimensions.width()), 1);
 | 
						auto w = qMax(qRound(coef * document->dimensions.width()), 1);
 | 
				
			||||||
	auto h = qMax(qRound(coef * document->dimensions.height()), 1);
 | 
						auto h = qMax(qRound(coef * document->dimensions.height()), 1);
 | 
				
			||||||
	auto ppos = pos + QPoint((_singleSize.width() - w) / 2, (_singleSize.height() - h) / 2);
 | 
						auto ppos = pos + QPoint((_singleSize.width() - w) / 2, (_singleSize.height() - h) / 2);
 | 
				
			||||||
	if (const auto image = document->getStickerSmall()) {
 | 
						if (sticker.animated && sticker.animated->ready()) {
 | 
				
			||||||
 | 
							const auto size = QSize(w, h);
 | 
				
			||||||
 | 
							auto request = Lottie::FrameRequest();
 | 
				
			||||||
 | 
							request.resize = size * cIntRetinaFactor();
 | 
				
			||||||
 | 
							const auto paused = controller()->isGifPausedAtLeastFor(
 | 
				
			||||||
 | 
								Window::GifPauseReason::SavedGifs);
 | 
				
			||||||
 | 
							if (!paused) {
 | 
				
			||||||
 | 
								sticker.animated->markFrameShown();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.drawImage(
 | 
				
			||||||
 | 
								QRect(ppos, size),
 | 
				
			||||||
 | 
								sticker.animated->frame(request));
 | 
				
			||||||
 | 
						} else if (const auto image = document->getStickerSmall()) {
 | 
				
			||||||
		if (image->loaded()) {
 | 
							if (image->loaded()) {
 | 
				
			||||||
			p.drawPixmapLeft(
 | 
								p.drawPixmapLeft(
 | 
				
			||||||
				ppos,
 | 
									ppos,
 | 
				
			||||||
| 
						 | 
					@ -1435,7 +1485,7 @@ bool StickersListWidget::hasRemoveButton(int index) const {
 | 
				
			||||||
		if (index + 1 != shownSets().size()) {
 | 
							if (index + 1 != shownSets().size()) {
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return !set.pack.empty() && _megagroupSet->canEditStickers();
 | 
							return !set.stickers.empty() && _megagroupSet->canEditStickers();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1559,7 +1609,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
 | 
				
			||||||
		if (auto sticker = base::get_if<OverSticker>(&pressed)) {
 | 
							if (auto sticker = base::get_if<OverSticker>(&pressed)) {
 | 
				
			||||||
			Assert(sticker->section >= 0 && sticker->section < sets.size());
 | 
								Assert(sticker->section >= 0 && sticker->section < sets.size());
 | 
				
			||||||
			auto &set = sets[sticker->section];
 | 
								auto &set = sets[sticker->section];
 | 
				
			||||||
			Assert(sticker->index >= 0 && sticker->index < set.pack.size());
 | 
								Assert(sticker->index >= 0 && sticker->index < set.stickers.size());
 | 
				
			||||||
			if (stickerHasDeleteButton(set, sticker->index) && sticker->overDelete) {
 | 
								if (stickerHasDeleteButton(set, sticker->index) && sticker->overDelete) {
 | 
				
			||||||
				if (set.id == Stickers::RecentSetId) {
 | 
									if (set.id == Stickers::RecentSetId) {
 | 
				
			||||||
					removeRecentSticker(sticker->section, sticker->index);
 | 
										removeRecentSticker(sticker->section, sticker->index);
 | 
				
			||||||
| 
						 | 
					@ -1570,7 +1620,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			_chosen.fire_copy(set.pack[sticker->index]);
 | 
								_chosen.fire_copy(set.stickers[sticker->index].document);
 | 
				
			||||||
		} else if (auto set = base::get_if<OverSet>(&pressed)) {
 | 
							} else if (auto set = base::get_if<OverSet>(&pressed)) {
 | 
				
			||||||
			Assert(set->section >= 0 && set->section < sets.size());
 | 
								Assert(set->section >= 0 && set->section < sets.size());
 | 
				
			||||||
			displaySet(sets[set->section].id);
 | 
								displaySet(sets[set->section].id);
 | 
				
			||||||
| 
						 | 
					@ -1579,7 +1629,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
 | 
				
			||||||
			if (sets[button->section].externalLayout) {
 | 
								if (sets[button->section].externalLayout) {
 | 
				
			||||||
				installSet(sets[button->section].id);
 | 
									installSet(sets[button->section].id);
 | 
				
			||||||
			} else if (sets[button->section].id == Stickers::MegagroupSetId) {
 | 
								} else if (sets[button->section].id == Stickers::MegagroupSetId) {
 | 
				
			||||||
				auto removeLocally = sets[button->section].pack.empty()
 | 
									auto removeLocally = sets[button->section].stickers.empty()
 | 
				
			||||||
					|| !_megagroupSet->canEditStickers();
 | 
										|| !_megagroupSet->canEditStickers();
 | 
				
			||||||
				removeMegagroupSet(removeLocally);
 | 
									removeMegagroupSet(removeLocally);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
| 
						 | 
					@ -1609,10 +1659,11 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clearSelection();
 | 
						clearSelection();
 | 
				
			||||||
	bool refresh = false;
 | 
						bool refresh = false;
 | 
				
			||||||
	auto sticker = _mySets[section].pack[index];
 | 
						auto &sticker = _mySets[section].stickers[index];
 | 
				
			||||||
 | 
						const auto document = sticker.document;
 | 
				
			||||||
	auto &recent = Stickers::GetRecentPack();
 | 
						auto &recent = Stickers::GetRecentPack();
 | 
				
			||||||
	for (int32 i = 0, l = recent.size(); i < l; ++i) {
 | 
						for (int32 i = 0, l = recent.size(); i < l; ++i) {
 | 
				
			||||||
		if (recent.at(i).first == sticker) {
 | 
							if (recent.at(i).first == document) {
 | 
				
			||||||
			recent.removeAt(i);
 | 
								recent.removeAt(i);
 | 
				
			||||||
			Local::writeUserSettings();
 | 
								Local::writeUserSettings();
 | 
				
			||||||
			refresh = true;
 | 
								refresh = true;
 | 
				
			||||||
| 
						 | 
					@ -1623,7 +1674,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
 | 
				
			||||||
	auto it = sets.find(Stickers::CustomSetId);
 | 
						auto it = sets.find(Stickers::CustomSetId);
 | 
				
			||||||
	if (it != sets.cend()) {
 | 
						if (it != sets.cend()) {
 | 
				
			||||||
		for (int i = 0, l = it->stickers.size(); i < l; ++i) {
 | 
							for (int i = 0, l = it->stickers.size(); i < l; ++i) {
 | 
				
			||||||
			if (it->stickers.at(i) == sticker) {
 | 
								if (it->stickers.at(i) == document) {
 | 
				
			||||||
				it->stickers.removeAt(i);
 | 
									it->stickers.removeAt(i);
 | 
				
			||||||
				if (it->stickers.isEmpty()) {
 | 
									if (it->stickers.isEmpty()) {
 | 
				
			||||||
					sets.erase(it);
 | 
										sets.erase(it);
 | 
				
			||||||
| 
						 | 
					@ -1649,10 +1700,11 @@ void StickersListWidget::removeFavedSticker(int section, int index) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clearSelection();
 | 
						clearSelection();
 | 
				
			||||||
	auto sticker = _mySets[section].pack[index];
 | 
						auto &sticker = _mySets[section].stickers[index];
 | 
				
			||||||
	Stickers::SetFaved(sticker, false);
 | 
						const auto document = sticker.document;
 | 
				
			||||||
 | 
						Stickers::SetFaved(document, false);
 | 
				
			||||||
	Auth().api().toggleFavedSticker(
 | 
						Auth().api().toggleFavedSticker(
 | 
				
			||||||
		sticker,
 | 
							document,
 | 
				
			||||||
		Data::FileOriginStickerSet(Stickers::FavedSetId, 0),
 | 
							Data::FileOriginStickerSet(Stickers::FavedSetId, 0),
 | 
				
			||||||
		false);
 | 
							false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1764,7 +1816,8 @@ void StickersListWidget::refreshSearchSets() {
 | 
				
			||||||
		if (const auto it = sets.find(set.id); it != sets.end()) {
 | 
							if (const auto it = sets.find(set.id); it != sets.end()) {
 | 
				
			||||||
			set.flags = it->flags;
 | 
								set.flags = it->flags;
 | 
				
			||||||
			if (!it->stickers.empty()) {
 | 
								if (!it->stickers.empty()) {
 | 
				
			||||||
				set.pack = it->stickers;
 | 
									// #TODO stickers preserve lottie etc.
 | 
				
			||||||
 | 
									set.stickers = PrepareStickers(it->stickers);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (!SetInMyList(set.flags)) {
 | 
								if (!SetInMyList(set.flags)) {
 | 
				
			||||||
				_installedLocallySets.remove(set.id);
 | 
									_installedLocallySets.remove(set.id);
 | 
				
			||||||
| 
						 | 
					@ -1801,14 +1854,14 @@ void StickersListWidget::refreshFooterIcons() {
 | 
				
			||||||
void StickersListWidget::preloadImages() {
 | 
					void StickersListWidget::preloadImages() {
 | 
				
			||||||
	auto &sets = shownSets();
 | 
						auto &sets = shownSets();
 | 
				
			||||||
	for (int i = 0, l = sets.size(), k = 0; i < l; ++i) {
 | 
						for (int i = 0, l = sets.size(), k = 0; i < l; ++i) {
 | 
				
			||||||
		int count = sets[i].pack.size();
 | 
							int count = sets[i].stickers.size();
 | 
				
			||||||
		if (sets[i].externalLayout) {
 | 
							if (sets[i].externalLayout) {
 | 
				
			||||||
			accumulate_min(count, _columnCount);
 | 
								accumulate_min(count, _columnCount);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (int j = 0; j != count; ++j) {
 | 
							for (int j = 0; j != count; ++j) {
 | 
				
			||||||
			if (++k > _columnCount * (_columnCount + 1)) break;
 | 
								if (++k > _columnCount * (_columnCount + 1)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const auto document = sets[i].pack[j];
 | 
								const auto document = sets[i].stickers[j].document;
 | 
				
			||||||
			if (!document || !document->sticker()) continue;
 | 
								if (!document || !document->sticker()) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			document->checkStickerSmall();
 | 
								document->checkStickerSmall();
 | 
				
			||||||
| 
						 | 
					@ -1860,7 +1913,7 @@ void StickersListWidget::appendSet(
 | 
				
			||||||
		it->thumbnail,
 | 
							it->thumbnail,
 | 
				
			||||||
		externalLayout,
 | 
							externalLayout,
 | 
				
			||||||
		it->count,
 | 
							it->count,
 | 
				
			||||||
		it->stickers);
 | 
							PrepareStickers(it->stickers));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void StickersListWidget::refreshRecent() {
 | 
					void StickersListWidget::refreshRecent() {
 | 
				
			||||||
| 
						 | 
					@ -1872,14 +1925,14 @@ void StickersListWidget::refreshRecent() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Stickers::Pack StickersListWidget::collectRecentStickers() {
 | 
					auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
 | 
				
			||||||
	_custom.clear();
 | 
						_custom.clear();
 | 
				
			||||||
	auto result = Stickers::Pack();
 | 
						auto result = std::vector<Sticker>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto &sets = Auth().data().stickerSets();
 | 
						const auto &sets = Auth().data().stickerSets();
 | 
				
			||||||
	auto &recent = Stickers::GetRecentPack();
 | 
						const auto &recent = Stickers::GetRecentPack();
 | 
				
			||||||
	auto customIt = sets.constFind(Stickers::CustomSetId);
 | 
						const auto customIt = sets.constFind(Stickers::CustomSetId);
 | 
				
			||||||
	auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
 | 
						const auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
 | 
				
			||||||
	const auto customCount = (customIt != sets.cend())
 | 
						const auto customCount = (customIt != sets.cend())
 | 
				
			||||||
		? customIt->stickers.size()
 | 
							? customIt->stickers.size()
 | 
				
			||||||
		: 0;
 | 
							: 0;
 | 
				
			||||||
| 
						 | 
					@ -1893,28 +1946,29 @@ Stickers::Pack StickersListWidget::collectRecentStickers() {
 | 
				
			||||||
		if (result.size() >= kRecentDisplayLimit) {
 | 
							if (result.size() >= kRecentDisplayLimit) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		const auto index = result.indexOf(document);
 | 
							const auto i = ranges::find(result, document, &Sticker::document);
 | 
				
			||||||
		if (index >= 0) {
 | 
							if (i != end(result)) {
 | 
				
			||||||
 | 
								const auto index = (i - begin(result));
 | 
				
			||||||
			if (index >= cloudCount && custom) {
 | 
								if (index >= cloudCount && custom) {
 | 
				
			||||||
				// Mark stickers from local recent as custom.
 | 
									// Mark stickers from local recent as custom.
 | 
				
			||||||
				_custom[index] = true;
 | 
									_custom[index] = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (!_favedStickersMap.contains(document)) {
 | 
							} else if (!_favedStickersMap.contains(document)) {
 | 
				
			||||||
			result.push_back(document);
 | 
								result.push_back(Sticker{ document });
 | 
				
			||||||
			_custom.push_back(custom);
 | 
								_custom.push_back(custom);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cloudCount > 0) {
 | 
						if (cloudCount > 0) {
 | 
				
			||||||
		for_const (auto document, cloudIt->stickers) {
 | 
							for (const auto document : cloudIt->stickers) {
 | 
				
			||||||
			add(document, false);
 | 
								add(document, false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for_const (auto &recentSticker, recent) {
 | 
						for (const auto &recentSticker : recent) {
 | 
				
			||||||
		add(recentSticker.first, false);
 | 
							add(recentSticker.first, false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (customCount > 0) {
 | 
						if (customCount > 0) {
 | 
				
			||||||
		for_const (auto document, customIt->stickers) {
 | 
							for (const auto document : customIt->stickers) {
 | 
				
			||||||
			add(document, true);
 | 
								add(document, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1942,9 +1996,9 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
 | 
				
			||||||
				thumbnail,
 | 
									thumbnail,
 | 
				
			||||||
				externalLayout,
 | 
									externalLayout,
 | 
				
			||||||
				recentPack.size(),
 | 
									recentPack.size(),
 | 
				
			||||||
				recentPack);
 | 
									std::move(recentPack));
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			recentIt->pack = recentPack;
 | 
								recentIt->stickers = std::move(recentPack);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (recentIt != _mySets.end()) {
 | 
						} else if (recentIt != _mySets.end()) {
 | 
				
			||||||
		_mySets.erase(recentIt);
 | 
							_mySets.erase(recentIt);
 | 
				
			||||||
| 
						 | 
					@ -1975,7 +2029,7 @@ void StickersListWidget::refreshFavedStickers() {
 | 
				
			||||||
		thumbnail,
 | 
							thumbnail,
 | 
				
			||||||
		externalLayout,
 | 
							externalLayout,
 | 
				
			||||||
		it->count,
 | 
							it->count,
 | 
				
			||||||
		it->stickers);
 | 
							PrepareStickers(it->stickers));
 | 
				
			||||||
	_favedStickersMap = base::flat_set<not_null<DocumentData*>> { it->stickers.begin(), it->stickers.end() };
 | 
						_favedStickersMap = base::flat_set<not_null<DocumentData*>> { it->stickers.begin(), it->stickers.end() };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2041,7 +2095,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
 | 
				
			||||||
				thumbnail,
 | 
									thumbnail,
 | 
				
			||||||
				externalLayout,
 | 
									externalLayout,
 | 
				
			||||||
				it->count,
 | 
									it->count,
 | 
				
			||||||
				it->stickers);
 | 
									PrepareStickers(it->stickers));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	} else if (!isShownHere(hidden)
 | 
						} else if (!isShownHere(hidden)
 | 
				
			||||||
| 
						 | 
					@ -2089,7 +2143,7 @@ void StickersListWidget::fillIcons(QList<StickerIcon> &icons) {
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		const auto thumbnail = _mySets[i].thumbnail;
 | 
							const auto thumbnail = _mySets[i].thumbnail;
 | 
				
			||||||
		const auto s = _mySets[i].pack[0];
 | 
							const auto s = _mySets[i].stickers[0].document;
 | 
				
			||||||
		const auto availw = st::stickerIconWidth - 2 * st::stickerIconPadding;
 | 
							const auto availw = st::stickerIconWidth - 2 * st::stickerIconPadding;
 | 
				
			||||||
		const auto availh = st::emojiFooterHeight - 2 * st::stickerIconPadding;
 | 
							const auto availh = st::emojiFooterHeight - 2 * st::stickerIconPadding;
 | 
				
			||||||
		const auto size = thumbnail
 | 
							const auto size = thumbnail
 | 
				
			||||||
| 
						 | 
					@ -2151,13 +2205,13 @@ void StickersListWidget::updateSelected() {
 | 
				
			||||||
			} else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) {
 | 
								} else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) {
 | 
				
			||||||
				newSelected = OverSet { section };
 | 
									newSelected = OverSet { section };
 | 
				
			||||||
			} else if (sets[section].id == Stickers::MegagroupSetId
 | 
								} else if (sets[section].id == Stickers::MegagroupSetId
 | 
				
			||||||
					&& (_megagroupSet->canEditStickers() || !sets[section].pack.empty())) {
 | 
										&& (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) {
 | 
				
			||||||
				newSelected = OverSet { section };
 | 
									newSelected = OverSet { section };
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) {
 | 
							} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) {
 | 
				
			||||||
			auto yOffset = p.y() - info.rowsTop;
 | 
								auto yOffset = p.y() - info.rowsTop;
 | 
				
			||||||
			auto &set = sets[section];
 | 
								auto &set = sets[section];
 | 
				
			||||||
			if (set.id == Stickers::MegagroupSetId && set.pack.empty()) {
 | 
								if (set.id == Stickers::MegagroupSetId && set.stickers.empty()) {
 | 
				
			||||||
				if (_megagroupSetButtonRect.contains(stickersLeft() + sx, yOffset)) {
 | 
									if (_megagroupSetButtonRect.contains(stickersLeft() + sx, yOffset)) {
 | 
				
			||||||
					newSelected = OverGroupAdd {};
 | 
										newSelected = OverGroupAdd {};
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -2166,7 +2220,7 @@ void StickersListWidget::updateSelected() {
 | 
				
			||||||
				auto rowIndex = qFloor(yOffset / _singleSize.height());
 | 
									auto rowIndex = qFloor(yOffset / _singleSize.height());
 | 
				
			||||||
				auto columnIndex = qFloor(sx / _singleSize.width());
 | 
									auto columnIndex = qFloor(sx / _singleSize.width());
 | 
				
			||||||
				auto index = rowIndex * _columnCount + columnIndex;
 | 
									auto index = rowIndex * _columnCount + columnIndex;
 | 
				
			||||||
				if (index >= 0 && index < set.pack.size()) {
 | 
									if (index >= 0 && index < set.stickers.size()) {
 | 
				
			||||||
					auto overDelete = false;
 | 
										auto overDelete = false;
 | 
				
			||||||
					if (stickerHasDeleteButton(set, index)) {
 | 
										if (stickerHasDeleteButton(set, index)) {
 | 
				
			||||||
						auto inx = sx - (columnIndex * _singleSize.width());
 | 
											auto inx = sx - (columnIndex * _singleSize.width());
 | 
				
			||||||
| 
						 | 
					@ -2226,14 +2280,13 @@ void StickersListWidget::setSelected(OverState newSelected) {
 | 
				
			||||||
		updateSelected();
 | 
							updateSelected();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (_previewShown && _pressed != _selected) {
 | 
							if (_previewShown && _pressed != _selected) {
 | 
				
			||||||
			if (auto sticker = base::get_if<OverSticker>(&_selected)) {
 | 
								if (const auto sticker = base::get_if<OverSticker>(&_selected)) {
 | 
				
			||||||
				_pressed = _selected;
 | 
									_pressed = _selected;
 | 
				
			||||||
				Assert(sticker->section >= 0 && sticker->section < sets.size());
 | 
									Assert(sticker->section >= 0 && sticker->section < sets.size());
 | 
				
			||||||
				auto &set = sets[sticker->section];
 | 
									const auto &set = sets[sticker->section];
 | 
				
			||||||
				Assert(sticker->index >= 0 && sticker->index < set.pack.size());
 | 
									Assert(sticker->index >= 0 && sticker->index < set.stickers.size());
 | 
				
			||||||
				Ui::showMediaPreview(
 | 
									const auto document = set.stickers[sticker->index].document;
 | 
				
			||||||
					set.pack[sticker->index]->stickerSetOrigin(),
 | 
									Ui::showMediaPreview(document->stickerSetOrigin(), document);
 | 
				
			||||||
					set.pack[sticker->index]);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2244,10 +2297,9 @@ void StickersListWidget::showPreview() {
 | 
				
			||||||
		const auto &sets = shownSets();
 | 
							const auto &sets = shownSets();
 | 
				
			||||||
		Assert(sticker->section >= 0 && sticker->section < sets.size());
 | 
							Assert(sticker->section >= 0 && sticker->section < sets.size());
 | 
				
			||||||
		const auto &set = sets[sticker->section];
 | 
							const auto &set = sets[sticker->section];
 | 
				
			||||||
		Assert(sticker->index >= 0 && sticker->index < set.pack.size());
 | 
							Assert(sticker->index >= 0 && sticker->index < set.stickers.size());
 | 
				
			||||||
		Ui::showMediaPreview(
 | 
							const auto document = set.stickers[sticker->index].document;
 | 
				
			||||||
			set.pack[sticker->index]->stickerSetOrigin(),
 | 
							Ui::showMediaPreview(document->stickerSetOrigin(), document);
 | 
				
			||||||
			set.pack[sticker->index]);
 | 
					 | 
				
			||||||
		_previewShown = true;
 | 
							_previewShown = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,10 @@ class LinkButton;
 | 
				
			||||||
class RippleAnimation;
 | 
					class RippleAnimation;
 | 
				
			||||||
} // namespace Ui
 | 
					} // namespace Ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Lottie {
 | 
				
			||||||
 | 
					class Animation;
 | 
				
			||||||
 | 
					} // namespace Lottie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ChatHelpers {
 | 
					namespace ChatHelpers {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct StickerIcon;
 | 
					struct StickerIcon;
 | 
				
			||||||
| 
						 | 
					@ -129,6 +133,11 @@ private:
 | 
				
			||||||
		int rowsBottom = 0;
 | 
							int rowsBottom = 0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct Sticker {
 | 
				
			||||||
 | 
							not_null<DocumentData*> document;
 | 
				
			||||||
 | 
							std::unique_ptr<Lottie::Animation> animated;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct Set {
 | 
						struct Set {
 | 
				
			||||||
		Set(
 | 
							Set(
 | 
				
			||||||
			uint64 id,
 | 
								uint64 id,
 | 
				
			||||||
| 
						 | 
					@ -138,7 +147,7 @@ private:
 | 
				
			||||||
			ImagePtr thumbnail,
 | 
								ImagePtr thumbnail,
 | 
				
			||||||
			bool externalLayout,
 | 
								bool externalLayout,
 | 
				
			||||||
			int count,
 | 
								int count,
 | 
				
			||||||
			const Stickers::Pack &pack = Stickers::Pack());
 | 
								std::vector<Sticker> &&stickers = {});
 | 
				
			||||||
		Set(Set &&other);
 | 
							Set(Set &&other);
 | 
				
			||||||
		Set &operator=(Set &&other);
 | 
							Set &operator=(Set &&other);
 | 
				
			||||||
		~Set();
 | 
							~Set();
 | 
				
			||||||
| 
						 | 
					@ -148,12 +157,14 @@ private:
 | 
				
			||||||
		QString title;
 | 
							QString title;
 | 
				
			||||||
		QString shortName;
 | 
							QString shortName;
 | 
				
			||||||
		ImagePtr thumbnail;
 | 
							ImagePtr thumbnail;
 | 
				
			||||||
		Stickers::Pack pack;
 | 
							std::vector<Sticker> stickers;
 | 
				
			||||||
		std::unique_ptr<Ui::RippleAnimation> ripple;
 | 
							std::unique_ptr<Ui::RippleAnimation> ripple;
 | 
				
			||||||
		bool externalLayout = false;
 | 
							bool externalLayout = false;
 | 
				
			||||||
		int count = 0;
 | 
							int count = 0;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static std::vector<Sticker> PrepareStickers(const Stickers::Pack &pack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template <typename Callback>
 | 
						template <typename Callback>
 | 
				
			||||||
	bool enumerateSections(Callback callback) const;
 | 
						bool enumerateSections(Callback callback) const;
 | 
				
			||||||
	SectionInfo sectionInfo(int section) const;
 | 
						SectionInfo sectionInfo(int section) const;
 | 
				
			||||||
| 
						 | 
					@ -171,7 +182,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool setHasTitle(const Set &set) const;
 | 
						bool setHasTitle(const Set &set) const;
 | 
				
			||||||
	bool stickerHasDeleteButton(const Set &set, int index) const;
 | 
						bool stickerHasDeleteButton(const Set &set, int index) const;
 | 
				
			||||||
	Stickers::Pack collectRecentStickers();
 | 
						std::vector<Sticker> collectRecentStickers();
 | 
				
			||||||
	void refreshRecentStickers(bool resize = true);
 | 
						void refreshRecentStickers(bool resize = true);
 | 
				
			||||||
	void refreshFavedStickers();
 | 
						void refreshFavedStickers();
 | 
				
			||||||
	enum class GroupStickersPlace {
 | 
						enum class GroupStickersPlace {
 | 
				
			||||||
| 
						 | 
					@ -202,8 +213,9 @@ private:
 | 
				
			||||||
	void paintFeaturedStickers(Painter &p, QRect clip);
 | 
						void paintFeaturedStickers(Painter &p, QRect clip);
 | 
				
			||||||
	void paintStickers(Painter &p, QRect clip);
 | 
						void paintStickers(Painter &p, QRect clip);
 | 
				
			||||||
	void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected);
 | 
						void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected);
 | 
				
			||||||
	void paintSticker(Painter &p, Set &set, int y, int index, bool selected, bool deleteSelected);
 | 
						void paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected);
 | 
				
			||||||
	void paintEmptySearchResults(Painter &p);
 | 
						void paintEmptySearchResults(Painter &p);
 | 
				
			||||||
 | 
						void setupLottie(Set &set, int section, int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int stickersRight() const;
 | 
						int stickersRight() const;
 | 
				
			||||||
	bool featuredHasAddButton(int index) const;
 | 
						bool featuredHasAddButton(int index) const;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue