Show animated stickers in the panel.

This commit is contained in:
John Preston 2019-06-25 14:25:02 +02:00
parent 040cae6a9a
commit 0d6ee3929d
2 changed files with 131 additions and 67 deletions

View File

@ -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;
} }
} }

View File

@ -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;