mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Optimize sets stickers / gifs panel repainting.
This commit is contained in:
parent
1a3a0fb124
commit
51fef843f0
3 changed files with 93 additions and 14 deletions
|
@ -46,7 +46,7 @@ namespace {
|
||||||
constexpr auto kSearchRequestDelay = 400;
|
constexpr auto kSearchRequestDelay = 400;
|
||||||
constexpr auto kInlineItemsMaxPerRow = 5;
|
constexpr auto kInlineItemsMaxPerRow = 5;
|
||||||
constexpr auto kSearchBotUsername = "gif"_cs;
|
constexpr auto kSearchBotUsername = "gif"_cs;
|
||||||
constexpr auto kMinRepaintDelay = crl::time(16);
|
constexpr auto kMinRepaintDelay = crl::time(33);
|
||||||
constexpr auto kMinAfterScrollDelay = crl::time(33);
|
constexpr auto kMinAfterScrollDelay = crl::time(33);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -175,9 +175,7 @@ GifsListWidget::GifsListWidget(
|
||||||
, _mosaic(st::emojiPanWidth - st::inlineResultsLeft)
|
, _mosaic(st::emojiPanWidth - st::inlineResultsLeft)
|
||||||
, _previewTimer([=] { showPreview(); }) {
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
// Otherwise our optimization on repainting is too aggressive.
|
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
|
||||||
|
|
||||||
_inlineRequestTimer.setSingleShot(true);
|
_inlineRequestTimer.setSingleShot(true);
|
||||||
connect(
|
connect(
|
||||||
|
@ -193,14 +191,14 @@ GifsListWidget::GifsListWidget(
|
||||||
|
|
||||||
controller->session().downloaderTaskFinished(
|
controller->session().downloaderTaskFinished(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
update();
|
updateInlineItems();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
controller->gifPauseLevelChanged(
|
controller->gifPauseLevelChanged(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
if (!controller->isGifPausedAtLeastFor(
|
if (!controller->isGifPausedAtLeastFor(
|
||||||
Window::GifPauseReason::SavedGifs)) {
|
Window::GifPauseReason::SavedGifs)) {
|
||||||
update();
|
updateInlineItems();
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
@ -240,10 +238,11 @@ object_ptr<TabbedSelector::InnerFooter> GifsListWidget::createFooter() {
|
||||||
void GifsListWidget::visibleTopBottomUpdated(
|
void GifsListWidget::visibleTopBottomUpdated(
|
||||||
int visibleTop,
|
int visibleTop,
|
||||||
int visibleBottom) {
|
int visibleBottom) {
|
||||||
auto top = getVisibleTop();
|
const auto top = getVisibleTop();
|
||||||
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
|
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
|
||||||
if (top != getVisibleTop()) {
|
if (top != getVisibleTop()) {
|
||||||
_lastScrolledAt = crl::now();
|
_lastScrolledAt = crl::now();
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
checkLoadMore();
|
checkLoadMore();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ constexpr auto kSearchRequestDelay = 400;
|
||||||
constexpr auto kRecentDisplayLimit = 20;
|
constexpr auto kRecentDisplayLimit = 20;
|
||||||
constexpr auto kPreloadOfficialPages = 4;
|
constexpr auto kPreloadOfficialPages = 4;
|
||||||
constexpr auto kOfficialLoadLimit = 40;
|
constexpr auto kOfficialLoadLimit = 40;
|
||||||
|
constexpr auto kMinRepaintDelay = crl::time(33);
|
||||||
|
constexpr auto kMinAfterScrollDelay = crl::time(33);
|
||||||
|
|
||||||
using Data::StickersSet;
|
using Data::StickersSet;
|
||||||
using Data::StickersPack;
|
using Data::StickersPack;
|
||||||
|
@ -968,6 +970,8 @@ StickersListWidget::StickersListWidget(
|
||||||
, _api(&controller->session().mtp())
|
, _api(&controller->session().mtp())
|
||||||
, _section(Section::Stickers)
|
, _section(Section::Stickers)
|
||||||
, _isMasks(masks)
|
, _isMasks(masks)
|
||||||
|
, _updateItemsTimer([=] { updateItems(); })
|
||||||
|
, _updateSetsTimer([=] { updateSets(); })
|
||||||
, _pathGradient(std::make_unique<Ui::PathShiftGradient>(
|
, _pathGradient(std::make_unique<Ui::PathShiftGradient>(
|
||||||
st::windowBgRipple,
|
st::windowBgRipple,
|
||||||
st::windowBgOver,
|
st::windowBgOver,
|
||||||
|
@ -991,7 +995,7 @@ StickersListWidget::StickersListWidget(
|
||||||
session().downloaderTaskFinished(
|
session().downloaderTaskFinished(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
repaintItems();
|
updateItems();
|
||||||
readVisibleFeatured(getVisibleTop(), getVisibleBottom());
|
readVisibleFeatured(getVisibleTop(), getVisibleBottom());
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
@ -1065,7 +1069,13 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
|
||||||
void StickersListWidget::visibleTopBottomUpdated(
|
void StickersListWidget::visibleTopBottomUpdated(
|
||||||
int visibleTop,
|
int visibleTop,
|
||||||
int visibleBottom) {
|
int visibleBottom) {
|
||||||
|
const auto top = getVisibleTop();
|
||||||
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
|
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
|
||||||
|
if (top != getVisibleTop()) {
|
||||||
|
_lastScrolledAt = crl::now();
|
||||||
|
_repaintSetsIds.clear();
|
||||||
|
update();
|
||||||
|
}
|
||||||
if (_section == Section::Featured) {
|
if (_section == Section::Featured) {
|
||||||
checkVisibleFeatured(visibleTop, visibleBottom);
|
checkVisibleFeatured(visibleTop, visibleBottom);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1925,7 +1935,7 @@ void StickersListWidget::ensureLottiePlayer(Set &set) {
|
||||||
if (sets[info.section].lottiePlayer.get() != raw) {
|
if (sets[info.section].lottiePlayer.get() != raw) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
repaintItems(info);
|
updateSet(info);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}, set.lottieLifetime);
|
}, set.lottieLifetime);
|
||||||
|
@ -2000,7 +2010,7 @@ void StickersListWidget::clipCallback(
|
||||||
case Notification::Repaint: break;
|
case Notification::Repaint: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
repaintItems(info);
|
updateSet(info);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2016,16 +2026,73 @@ bool StickersListWidget::itemVisible(
|
||||||
return (visibleTop < bottom) && (visibleBottom > top);
|
return (visibleTop < bottom) && (visibleBottom > top);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::repaintItems(const SectionInfo &info) {
|
void StickersListWidget::updateSets() {
|
||||||
|
if (_repaintSetsIds.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto repaint = base::take(_repaintSetsIds);
|
||||||
|
auto &sets = shownSets();
|
||||||
|
enumerateSections([&](const SectionInfo &info) {
|
||||||
|
if (repaint.contains(sets[info.section].id)) {
|
||||||
|
updateSet(info);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersListWidget::updateSet(const SectionInfo &info) {
|
||||||
|
auto &set = shownSets()[info.section];
|
||||||
|
|
||||||
|
const auto now = crl::now();
|
||||||
|
const auto delay = std::max(
|
||||||
|
_lastScrolledAt + kMinAfterScrollDelay - now,
|
||||||
|
set.lastUpdateTime + kMinRepaintDelay - now);
|
||||||
|
if (delay <= 0) {
|
||||||
|
repaintItems(info, now);
|
||||||
|
} else {
|
||||||
|
_repaintSetsIds.emplace(set.id);
|
||||||
|
if (!_updateSetsTimer.isActive()
|
||||||
|
|| _updateSetsTimer.remainingTime() > kMinRepaintDelay) {
|
||||||
|
_updateSetsTimer.callOnce(std::max(delay, kMinRepaintDelay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersListWidget::repaintItems(
|
||||||
|
const SectionInfo &info,
|
||||||
|
crl::time now) {
|
||||||
update(
|
update(
|
||||||
0,
|
0,
|
||||||
info.rowsTop,
|
info.rowsTop,
|
||||||
width(),
|
width(),
|
||||||
info.rowsBottom - info.rowsTop);
|
info.rowsBottom - info.rowsTop);
|
||||||
|
auto &set = shownSets()[info.section];
|
||||||
|
set.lastUpdateTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::repaintItems() {
|
void StickersListWidget::updateItems() {
|
||||||
|
const auto now = crl::now();
|
||||||
|
const auto delay = std::max(
|
||||||
|
_lastScrolledAt + kMinAfterScrollDelay - now,
|
||||||
|
_lastFullUpdatedAt + kMinRepaintDelay - now);
|
||||||
|
if (delay <= 0) {
|
||||||
|
repaintItems(now);
|
||||||
|
} else if (!_updateItemsTimer.isActive()
|
||||||
|
|| _updateItemsTimer.remainingTime() > kMinRepaintDelay) {
|
||||||
|
_updateItemsTimer.callOnce(std::max(delay, kMinRepaintDelay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersListWidget::repaintItems(crl::time now) {
|
||||||
|
update();
|
||||||
|
_repaintSetsIds.clear();
|
||||||
|
if (!now) {
|
||||||
|
now = crl::now();
|
||||||
|
}
|
||||||
|
_lastFullUpdatedAt = now;
|
||||||
|
for (auto &set : shownSets()) {
|
||||||
|
set.lastUpdateTime = now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize StickersListWidget::boundingBoxSize() const {
|
QSize StickersListWidget::boundingBoxSize() const {
|
||||||
|
|
|
@ -205,6 +205,7 @@ private:
|
||||||
QString shortName;
|
QString shortName;
|
||||||
std::vector<Sticker> stickers;
|
std::vector<Sticker> stickers;
|
||||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||||
|
crl::time lastUpdateTime = 0;
|
||||||
|
|
||||||
std::unique_ptr<Lottie::MultiPlayer> lottiePlayer;
|
std::unique_ptr<Lottie::MultiPlayer> lottiePlayer;
|
||||||
rpl::lifetime lottieLifetime;
|
rpl::lifetime lottieLifetime;
|
||||||
|
@ -305,8 +306,13 @@ private:
|
||||||
void takeHeavyData(Sticker &to, Sticker &from);
|
void takeHeavyData(Sticker &to, Sticker &from);
|
||||||
void clearHeavyIn(Set &set, bool clearSavedFrames = true);
|
void clearHeavyIn(Set &set, bool clearSavedFrames = true);
|
||||||
void clearHeavyData();
|
void clearHeavyData();
|
||||||
void repaintItems();
|
void updateItems();
|
||||||
void repaintItems(const SectionInfo &info);
|
void updateSets();
|
||||||
|
void repaintItems(crl::time now = 0);
|
||||||
|
void updateSet(const SectionInfo &info);
|
||||||
|
void repaintItems(
|
||||||
|
const SectionInfo &info,
|
||||||
|
crl::time now);
|
||||||
|
|
||||||
int stickersRight() const;
|
int stickersRight() const;
|
||||||
bool featuredHasAddButton(int index) const;
|
bool featuredHasAddButton(int index) const;
|
||||||
|
@ -364,12 +370,19 @@ private:
|
||||||
base::flat_set<not_null<DocumentData*>> _favedStickersMap;
|
base::flat_set<not_null<DocumentData*>> _favedStickersMap;
|
||||||
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
|
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
|
||||||
|
|
||||||
|
crl::time _lastScrolledAt = 0;
|
||||||
|
crl::time _lastFullUpdatedAt = 0;
|
||||||
|
|
||||||
mtpRequestId _officialRequestId = 0;
|
mtpRequestId _officialRequestId = 0;
|
||||||
int _officialOffset = 0;
|
int _officialOffset = 0;
|
||||||
|
|
||||||
Section _section = Section::Stickers;
|
Section _section = Section::Stickers;
|
||||||
const bool _isMasks;
|
const bool _isMasks;
|
||||||
|
|
||||||
|
base::Timer _updateItemsTimer;
|
||||||
|
base::Timer _updateSetsTimer;
|
||||||
|
base::flat_set<uint64> _repaintSetsIds;
|
||||||
|
|
||||||
bool _displayingSet = false;
|
bool _displayingSet = false;
|
||||||
uint64 _removingSetId = 0;
|
uint64 _removingSetId = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue