Clear lottie on panel hide.

This commit is contained in:
John Preston 2019-07-01 17:34:29 +02:00
parent a10b91fe1a
commit db2d24ff32
2 changed files with 145 additions and 42 deletions

View File

@ -1012,6 +1012,13 @@ void StickersListWidget::refreshSearchRows(
const std::vector<uint64> *cloudSets) { const std::vector<uint64> *cloudSets) {
clearSelection(); clearSelection();
const auto wasSection = _section;
const auto guard = gsl::finally([&] {
if (_section == wasSection && _section == Section::Search) {
refillLottieData();
}
});
_searchSets.clear(); _searchSets.clear();
fillLocalSearchRows(_searchNextQuery); fillLocalSearchRows(_searchNextQuery);
@ -1022,9 +1029,7 @@ void StickersListWidget::refreshSearchRows(
return; return;
} }
if (_section != Section::Search) { setSection(Section::Search);
_section = Section::Search;
}
if (cloudSets) { if (cloudSets) {
fillCloudSearchRows(*cloudSets); fillCloudSearchRows(*cloudSets);
} }
@ -1345,7 +1350,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
} }
void StickersListWidget::markLottieFrameShown(Set &set) { void StickersListWidget::markLottieFrameShown(Set &set) {
if (const auto player = set.lottiePlayer.get()) { if (const auto player = set.lottiePlayer) {
const auto paused = controller()->isGifPausedAtLeastFor( const auto paused = controller()->isGifPausedAtLeastFor(
Window::GifPauseReason::SavedGifs); Window::GifPauseReason::SavedGifs);
if (!paused) { if (!paused) {
@ -1384,11 +1389,12 @@ void StickersListWidget::destroyLottieIn(Set &set) {
for (auto &sticker : set.stickers) { for (auto &sticker : set.stickers) {
sticker.animated = nullptr; sticker.animated = nullptr;
} }
_lottieData.remove(set.id);
} }
void StickersListWidget::pauseInvisibleLottieIn(const SectionInfo &info) { void StickersListWidget::pauseInvisibleLottieIn(const SectionInfo &info) {
auto &set = shownSets()[info.section]; auto &set = shownSets()[info.section];
const auto player = set.lottiePlayer.get(); const auto player = set.lottiePlayer;
if (!player) { if (!player) {
return; return;
} }
@ -1474,15 +1480,19 @@ void StickersListWidget::ensureLottiePlayer(Set &set) {
if (set.lottiePlayer) { if (set.lottiePlayer) {
return; return;
} }
set.lottiePlayer = std::make_unique<Lottie::MultiPlayer>( const auto [i, ok] = _lottieData.emplace(
getLottieRenderer()); set.id,
const auto raw = set.lottiePlayer.get(); LottieSet{ std::make_unique<Lottie::MultiPlayer>(
set.lottiePlayer->updates( getLottieRenderer()) });
Assert(ok);
const auto raw = set.lottiePlayer = i->second.player.get();
raw->updates(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
const auto &sets = shownSets(); const auto &sets = shownSets();
PROFILE_LOG(("WIDGET REPAINT REQUESTED")); PROFILE_LOG(("WIDGET REPAINT REQUESTED"));
enumerateSections([&](const SectionInfo &info) { enumerateSections([&](const SectionInfo &info) {
if (shownSets()[info.section].lottiePlayer.get() == raw) { if (shownSets()[info.section].lottiePlayer == raw) {
update( update(
0, 0,
info.rowsTop, info.rowsTop,
@ -1492,7 +1502,7 @@ void StickersListWidget::ensureLottiePlayer(Set &set) {
} }
return true; return true;
}); });
}, lifetime()); },i->second.lifetime);
} }
void StickersListWidget::setupLottie(Set &set, int section, int index) { void StickersListWidget::setupLottie(Set &set, int section, int index) {
@ -1501,10 +1511,13 @@ void StickersListWidget::setupLottie(Set &set, int section, int index) {
ensureLottiePlayer(set); ensureLottiePlayer(set);
sticker.animated = Stickers::LottieAnimationFromDocument( sticker.animated = Stickers::LottieAnimationFromDocument(
set.lottiePlayer.get(), set.lottiePlayer,
document, document,
Stickers::LottieSize::StickersPanel, Stickers::LottieSize::StickersPanel,
boundingBoxSize() * cIntRetinaFactor()); boundingBoxSize() * cIntRetinaFactor());
_lottieData[set.id].items.emplace(
document->id,
LottieSet::Item{ sticker.animated });
} }
QSize StickersListWidget::boundingBoxSize() const { QSize StickersListWidget::boundingBoxSize() const {
@ -1789,7 +1802,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
clearSelection(); clearSelection();
bool refresh = false; bool refresh = false;
auto &sticker = _mySets[section].stickers[index]; const auto &sticker = _mySets[section].stickers[index];
const auto document = sticker.document; 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) {
@ -1830,7 +1843,7 @@ void StickersListWidget::removeFavedSticker(int section, int index) {
} }
clearSelection(); clearSelection();
auto &sticker = _mySets[section].stickers[index]; const auto &sticker = _mySets[section].stickers[index];
const auto document = sticker.document; const auto document = sticker.document;
Stickers::SetFaved(document, false); Stickers::SetFaved(document, false);
Auth().api().toggleFavedSticker( Auth().api().toggleFavedSticker(
@ -1887,44 +1900,42 @@ TabbedSelector::InnerFooter *StickersListWidget::getFooter() const {
void StickersListWidget::processHideFinished() { void StickersListWidget::processHideFinished() {
clearSelection(); clearSelection();
clearLottieData();
} }
void StickersListWidget::processPanelHideFinished() { void StickersListWidget::processPanelHideFinished() {
clearInstalledLocally(); clearInstalledLocally();
clearLottieData();
// Preserve panel state through visibility toggles. // Preserve panel state through visibility toggles.
//// Reset to the recent stickers section. //// Reset to the recent stickers section.
//if (_section == Section::Featured && (!_footer || !_footer->hasOnlyFeaturedSets())) { //if (_section == Section::Featured && (!_footer || !_footer->hasOnlyFeaturedSets())) {
// _section = Section::Stickers; // setSection(Section::Stickers);
// validateSelectedIcon(ValidateIconAnimations::None); // validateSelectedIcon(ValidateIconAnimations::None);
//} //}
} }
void StickersListWidget::setSection(Section section) {
if (_section == section) {
return;
}
clearLottieData();
_section = section;
}
void StickersListWidget::clearLottieData() {
for (auto &set : shownSets()) {
destroyLottieIn(set);
}
_lottieData.clear();
}
void StickersListWidget::refreshStickers() { void StickersListWidget::refreshStickers() {
clearSelection(); clearSelection();
_mySets.clear(); refreshMySets();
_favedStickersMap.clear(); refreshFeaturedSets();
_mySets.reserve(Auth().data().stickerSetsOrder().size() + 3);
refreshFavedStickers();
refreshRecentStickers(false);
refreshMegagroupStickers(GroupStickersPlace::Visible);
for (const auto setId : Auth().data().stickerSetsOrder()) {
const auto externalLayout = false;
appendSet(_mySets, setId, externalLayout, AppendSkip::Archived);
}
refreshMegagroupStickers(GroupStickersPlace::Hidden);
_featuredSets.clear();
_featuredSets.reserve(Auth().data().featuredStickerSetsOrder().size());
for (const auto setId : Auth().data().featuredStickerSetsOrder()) {
const auto externalLayout = true;
appendSet(_featuredSets, setId, externalLayout, AppendSkip::Installed);
}
refreshSearchSets(); refreshSearchSets();
refillLottieData();
resizeToWidth(width()); resizeToWidth(width());
@ -1938,6 +1949,31 @@ void StickersListWidget::refreshStickers() {
update(); update();
} }
void StickersListWidget::refreshMySets() {
_mySets.clear();
_favedStickersMap.clear();
_mySets.reserve(Auth().data().stickerSetsOrder().size() + 3);
refreshFavedStickers();
refreshRecentStickers(false);
refreshMegagroupStickers(GroupStickersPlace::Visible);
for (const auto setId : Auth().data().stickerSetsOrder()) {
const auto externalLayout = false;
appendSet(_mySets, setId, externalLayout, AppendSkip::Archived);
}
refreshMegagroupStickers(GroupStickersPlace::Hidden);
}
void StickersListWidget::refreshFeaturedSets() {
_featuredSets.clear();
_featuredSets.reserve(Auth().data().featuredStickerSetsOrder().size());
for (const auto setId : Auth().data().featuredStickerSetsOrder()) {
const auto externalLayout = true;
appendSet(_featuredSets, setId, externalLayout, AppendSkip::Installed);
}
}
void StickersListWidget::refreshSearchSets() { void StickersListWidget::refreshSearchSets() {
refreshSearchIndex(); refreshSearchIndex();
@ -1946,7 +1982,7 @@ 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()) {
// #TODO stickers preserve lottie etc. set.lottiePlayer = nullptr;
set.stickers = PrepareStickers(it->stickers); set.stickers = PrepareStickers(it->stickers);
} }
if (!SetInMyList(set.flags)) { if (!SetInMyList(set.flags)) {
@ -1969,6 +2005,53 @@ void StickersListWidget::refreshSearchIndex() {
} }
} }
void StickersListWidget::refillLottieData() {
for (auto &set : _lottieData) {
set.second.stale = true;
}
for (auto &set : shownSets()) {
refillLottieData(set);
}
for (auto i = begin(_lottieData); i != end(_lottieData);) {
if (i->second.stale) {
i = _lottieData.erase(i);
} else {
++i;
}
}
}
void StickersListWidget::refillLottieData(Set &set) {
const auto i = _lottieData.find(set.id);
if (i == end(_lottieData)) {
return;
}
i->second.stale = true;
auto &items = i->second.items;
for (auto &item : items) {
item.second.stale = true;
}
for (auto &sticker : set.stickers) {
const auto j = items.find(sticker.document->id);
if (j != end(items)) {
sticker.animated = j->second.animation;
i->second.stale = j->second.stale = false;
}
}
if (i->second.stale) {
_lottieData.erase(i);
return;
}
for (auto j = begin(items); j != end(items);) {
if (j->second.stale) {
j = items.erase(j);
} else {
++j;
}
}
set.lottiePlayer = i->second.player.get();
}
void StickersListWidget::refreshSettingsVisibility() { void StickersListWidget::refreshSettingsVisibility() {
const auto visible = (_section == Section::Stickers) && _mySets.empty(); const auto visible = (_section == Section::Stickers) && _mySets.empty();
_settings->setVisible(visible); _settings->setVisible(visible);
@ -2128,9 +2211,12 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
recentPack.size(), recentPack.size(),
std::move(recentPack)); std::move(recentPack));
} else { } else {
recentIt->lottiePlayer = nullptr;
recentIt->stickers = std::move(recentPack); recentIt->stickers = std::move(recentPack);
refillLottieData(*recentIt);
} }
} else if (recentIt != _mySets.end()) { } else if (recentIt != _mySets.end()) {
_lottieData.remove(recentIt->id);
_mySets.erase(recentIt); _mySets.erase(recentIt);
} }
@ -2449,8 +2535,7 @@ void StickersListWidget::showStickerSet(uint64 setId) {
if (setId == Stickers::FeaturedSetId) { if (setId == Stickers::FeaturedSetId) {
if (_section != Section::Featured) { if (_section != Section::Featured) {
_section = Section::Featured; setSection(Section::Featured);
refreshRecentStickers(true); refreshRecentStickers(true);
refreshSettingsVisibility(); refreshSettingsVisibility();
if (_footer) { if (_footer) {
@ -2466,7 +2551,7 @@ void StickersListWidget::showStickerSet(uint64 setId) {
auto needRefresh = (_section != Section::Stickers); auto needRefresh = (_section != Section::Stickers);
if (needRefresh) { if (needRefresh) {
_section = Section::Stickers; setSection(Section::Stickers);
refreshRecentStickers(true); refreshRecentStickers(true);
refreshSettingsVisibility(); refreshSettingsVisibility();
} }

View File

@ -167,10 +167,20 @@ private:
ImagePtr thumbnail; ImagePtr thumbnail;
std::vector<Sticker> stickers; std::vector<Sticker> stickers;
std::unique_ptr<Ui::RippleAnimation> ripple; std::unique_ptr<Ui::RippleAnimation> ripple;
std::unique_ptr<Lottie::MultiPlayer> lottiePlayer; Lottie::MultiPlayer *lottiePlayer = nullptr;
bool externalLayout = false; bool externalLayout = false;
int count = 0; int count = 0;
}; };
struct LottieSet {
struct Item {
not_null<Lottie::Animation*> animation;
bool stale = false;
};
std::unique_ptr<Lottie::MultiPlayer> player;
base::flat_map<DocumentId, Item> items;
bool stale = false;
rpl::lifetime lifetime;
};
static std::vector<Sticker> PrepareStickers(const Stickers::Pack &pack); static std::vector<Sticker> PrepareStickers(const Stickers::Pack &pack);
@ -181,6 +191,7 @@ private:
SectionInfo sectionInfo(int section) const; SectionInfo sectionInfo(int section) const;
SectionInfo sectionInfoByOffset(int yOffset) const; SectionInfo sectionInfoByOffset(int yOffset) const;
void setSection(Section section);
void displaySet(uint64 setId); void displaySet(uint64 setId);
void installSet(uint64 setId); void installSet(uint64 setId);
void removeMegagroupSet(bool locally); void removeMegagroupSet(bool locally);
@ -188,6 +199,8 @@ private:
void sendInstallRequest( void sendInstallRequest(
uint64 setId, uint64 setId,
const MTPInputStickerSet &input); const MTPInputStickerSet &input);
void refreshMySets();
void refreshFeaturedSets();
void refreshSearchSets(); void refreshSearchSets();
void refreshSearchIndex(); void refreshSearchIndex();
@ -233,6 +246,9 @@ private:
void checkVisibleLottie(); void checkVisibleLottie();
void pauseInvisibleLottieIn(const SectionInfo &info); void pauseInvisibleLottieIn(const SectionInfo &info);
void destroyLottieIn(Set &set); void destroyLottieIn(Set &set);
void refillLottieData();
void refillLottieData(Set &set);
void clearLottieData();
int stickersRight() const; int stickersRight() const;
bool featuredHasAddButton(int index) const; bool featuredHasAddButton(int index) const;
@ -320,6 +336,8 @@ private:
QString _searchQuery, _searchNextQuery; QString _searchQuery, _searchNextQuery;
mtpRequestId _searchRequestId = 0; mtpRequestId _searchRequestId = 0;
base::flat_map<uint64, LottieSet> _lottieData;
rpl::event_stream<not_null<DocumentData*>> _chosen; rpl::event_stream<not_null<DocumentData*>> _chosen;
rpl::event_stream<> _scrollUpdated; rpl::event_stream<> _scrollUpdated;
rpl::event_stream<> _checkForHide; rpl::event_stream<> _checkForHide;