mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Animate webm pack icon in the panel.
This commit is contained in:
parent
51fef843f0
commit
c359646702
1 changed files with 136 additions and 49 deletions
|
@ -124,7 +124,7 @@ public:
|
||||||
uint64 setId,
|
uint64 setId,
|
||||||
ValidateIconAnimations animations);
|
ValidateIconAnimations animations);
|
||||||
void refreshIcons(ValidateIconAnimations animations);
|
void refreshIcons(ValidateIconAnimations animations);
|
||||||
bool hasOnlyFeaturedSets() const;
|
[[nodiscard]] bool hasOnlyFeaturedSets() const;
|
||||||
|
|
||||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ public:
|
||||||
|
|
||||||
void clearHeavyData();
|
void clearHeavyData();
|
||||||
|
|
||||||
rpl::producer<> openSettingsRequests() const;
|
[[nodiscard]] rpl::producer<> openSettingsRequests() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
@ -153,8 +153,14 @@ private:
|
||||||
Settings,
|
Settings,
|
||||||
};
|
};
|
||||||
using OverState = std::variant<SpecialOver, int>;
|
using OverState = std::variant<SpecialOver, int>;
|
||||||
|
struct IconInfo {
|
||||||
|
int index = 0;
|
||||||
|
int left = 0;
|
||||||
|
bool visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
void enumerateVisibleIcons(Fn<void(const StickerIcon &, int)> callback);
|
void enumerateVisibleIcons(Fn<void(const IconInfo &)> callback);
|
||||||
|
void enumerateIcons(Fn<void(const IconInfo &)> callback);
|
||||||
|
|
||||||
bool iconsAnimationCallback(crl::time now);
|
bool iconsAnimationCallback(crl::time now);
|
||||||
void setSelectedIcon(
|
void setSelectedIcon(
|
||||||
|
@ -167,10 +173,15 @@ private:
|
||||||
void refreshIconsGeometry(ValidateIconAnimations animations);
|
void refreshIconsGeometry(ValidateIconAnimations animations);
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void updateSetIcon(uint64 setId);
|
void updateSetIcon(uint64 setId);
|
||||||
|
void updateSetIconAt(int left);
|
||||||
void finishDragging();
|
void finishDragging();
|
||||||
void paintStickerSettingsIcon(Painter &p) const;
|
void paintStickerSettingsIcon(Painter &p) const;
|
||||||
void paintSearchIcon(Painter &p) const;
|
void paintSearchIcon(Painter &p) const;
|
||||||
void paintSetIcon(Painter &p, const StickerIcon &icon, int x) const;
|
void paintSetIcon(
|
||||||
|
Painter &p,
|
||||||
|
const IconInfo &info,
|
||||||
|
crl::time now,
|
||||||
|
bool paused) const;
|
||||||
void paintSelectionBar(Painter &p) const;
|
void paintSelectionBar(Painter &p) const;
|
||||||
void paintLeftRightFading(Painter &p) const;
|
void paintLeftRightFading(Painter &p) const;
|
||||||
|
|
||||||
|
@ -179,6 +190,8 @@ private:
|
||||||
void resizeSearchControls();
|
void resizeSearchControls();
|
||||||
void scrollByWheelEvent(not_null<QWheelEvent*> e);
|
void scrollByWheelEvent(not_null<QWheelEvent*> e);
|
||||||
|
|
||||||
|
void clipCallback(Media::Clip::Notification notification, uint64 setId);
|
||||||
|
|
||||||
const not_null<StickersListWidget*> _pan;
|
const not_null<StickersListWidget*> _pan;
|
||||||
const bool _searchButtonVisible = true;
|
const bool _searchButtonVisible = true;
|
||||||
|
|
||||||
|
@ -371,7 +384,7 @@ void StickersListWidget::Footer::returnFocus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::Footer::enumerateVisibleIcons(
|
void StickersListWidget::Footer::enumerateVisibleIcons(
|
||||||
Fn<void(const StickerIcon &, int)> callback) {
|
Fn<void(const IconInfo &)> callback) {
|
||||||
auto iconsX = qRound(_iconsX.current());
|
auto iconsX = qRound(_iconsX.current());
|
||||||
auto x = _iconsLeft - (iconsX % st::stickerIconWidth);
|
auto x = _iconsLeft - (iconsX % st::stickerIconWidth);
|
||||||
auto first = floorclamp(iconsX, st::stickerIconWidth, 0, _icons.size());
|
auto first = floorclamp(iconsX, st::stickerIconWidth, 0, _icons.size());
|
||||||
|
@ -381,13 +394,32 @@ void StickersListWidget::Footer::enumerateVisibleIcons(
|
||||||
0,
|
0,
|
||||||
_icons.size());
|
_icons.size());
|
||||||
for (auto index = first; index != last; ++index) {
|
for (auto index = first; index != last; ++index) {
|
||||||
callback(_icons[index], x);
|
callback({ .index = index, .left = x, .visible = true });
|
||||||
|
x += st::stickerIconWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersListWidget::Footer::enumerateIcons(
|
||||||
|
Fn<void(const IconInfo &)> callback) {
|
||||||
|
auto iconsX = qRound(_iconsX.current());
|
||||||
|
auto x = _iconsLeft - (iconsX % st::stickerIconWidth);
|
||||||
|
auto first = floorclamp(iconsX, st::stickerIconWidth, 0, _icons.size());
|
||||||
|
auto last = ceilclamp(
|
||||||
|
iconsX + width(),
|
||||||
|
st::stickerIconWidth,
|
||||||
|
0,
|
||||||
|
_icons.size());
|
||||||
|
x -= first * st::stickerIconWidth;
|
||||||
|
for (auto i = 0, count = int(_icons.size()); i != count; ++i) {
|
||||||
|
const auto visible = (i >= first && i < last);
|
||||||
|
callback({ .index = i, .left = x, .visible = visible });
|
||||||
x += st::stickerIconWidth;
|
x += st::stickerIconWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::Footer::preloadImages() {
|
void StickersListWidget::Footer::preloadImages() {
|
||||||
enumerateVisibleIcons([](const StickerIcon &icon, int x) {
|
enumerateVisibleIcons([&](const IconInfo &info) {
|
||||||
|
const auto &icon = _icons[info.index];
|
||||||
if (const auto sticker = icon.sticker) {
|
if (const auto sticker = icon.sticker) {
|
||||||
Assert(icon.set != nullptr);
|
Assert(icon.set != nullptr);
|
||||||
if (icon.set->hasThumbnail()) {
|
if (icon.set->hasThumbnail()) {
|
||||||
|
@ -496,8 +528,11 @@ void StickersListWidget::Footer::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
p.setClipRect(clip);
|
p.setClipRect(clip);
|
||||||
|
|
||||||
enumerateVisibleIcons([&](const StickerIcon &icon, int x) {
|
const auto now = crl::now();
|
||||||
paintSetIcon(p, icon, x);
|
const auto paused = _pan->controller()->isGifPausedAtLeastFor(
|
||||||
|
Window::GifPauseReason::SavedGifs);
|
||||||
|
enumerateVisibleIcons([&](const IconInfo &info) {
|
||||||
|
paintSetIcon(p, info, now, paused);
|
||||||
});
|
});
|
||||||
|
|
||||||
paintSelectionBar(p);
|
paintSelectionBar(p);
|
||||||
|
@ -690,6 +725,36 @@ void StickersListWidget::Footer::scrollByWheelEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickersListWidget::Footer::clipCallback(
|
||||||
|
Media::Clip::Notification notification,
|
||||||
|
uint64 setId) {
|
||||||
|
using namespace Media::Clip;
|
||||||
|
switch (notification) {
|
||||||
|
case Notification::Reinit: {
|
||||||
|
enumerateIcons([&](const IconInfo &info) {
|
||||||
|
auto &icon = _icons[info.index];
|
||||||
|
if (icon.setId != setId || !icon.webm) {
|
||||||
|
return;
|
||||||
|
} else if (icon.webm->state() == State::Error) {
|
||||||
|
icon.webm.setBad();
|
||||||
|
} else if (!info.visible) {
|
||||||
|
icon.webm = nullptr;
|
||||||
|
} else if (icon.webm->ready() && !icon.webm->started()) {
|
||||||
|
icon.webm->start({
|
||||||
|
.frame = { icon.pixw, icon.pixh },
|
||||||
|
.keepAlpha = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateSetIconAt(info.left);
|
||||||
|
});
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Notification::Repaint:
|
||||||
|
updateSetIcon(setId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StickersListWidget::Footer::updateSelected() {
|
void StickersListWidget::Footer::updateSelected() {
|
||||||
if (_iconDown != SpecialOver::None) {
|
if (_iconDown != SpecialOver::None) {
|
||||||
return;
|
return;
|
||||||
|
@ -848,10 +913,13 @@ void StickersListWidget::Footer::validateIconWebmAnimation(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto id = icon.setId;
|
const auto id = icon.setId;
|
||||||
|
auto callback = [=](Media::Clip::Notification notification) {
|
||||||
|
clipCallback(notification, id);
|
||||||
|
};
|
||||||
icon.webm = WebmThumbnail(
|
icon.webm = WebmThumbnail(
|
||||||
icon.thumbnailMedia.get(),
|
icon.thumbnailMedia.get(),
|
||||||
icon.stickerMedia.get(),
|
icon.stickerMedia.get(),
|
||||||
[=](Media::Clip::Notification) { updateSetIcon(id); });
|
std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::Footer::validateIconAnimation(
|
void StickersListWidget::Footer::validateIconAnimation(
|
||||||
|
@ -861,18 +929,24 @@ void StickersListWidget::Footer::validateIconAnimation(
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::Footer::updateSetIcon(uint64 setId) {
|
void StickersListWidget::Footer::updateSetIcon(uint64 setId) {
|
||||||
enumerateVisibleIcons([&](const StickerIcon &icon, int x) {
|
enumerateVisibleIcons([&](const IconInfo &info) {
|
||||||
if (icon.setId != setId) {
|
if (_icons[info.index].setId != setId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
update(x, _iconsTop, st::stickerIconWidth, st::emojiFooterHeight);
|
updateSetIconAt(info.left);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickersListWidget::Footer::updateSetIconAt(int left) {
|
||||||
|
update(left, _iconsTop, st::stickerIconWidth, st::emojiFooterHeight);
|
||||||
|
}
|
||||||
|
|
||||||
void StickersListWidget::Footer::paintSetIcon(
|
void StickersListWidget::Footer::paintSetIcon(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const StickerIcon &icon,
|
const IconInfo &info,
|
||||||
int x) const {
|
crl::time now,
|
||||||
|
bool paused) const {
|
||||||
|
const auto &icon = _icons[info.index];
|
||||||
if (icon.sticker) {
|
if (icon.sticker) {
|
||||||
icon.ensureMediaCreated();
|
icon.ensureMediaCreated();
|
||||||
const_cast<Footer*>(this)->validateIconAnimation(icon);
|
const_cast<Footer*>(this)->validateIconAnimation(icon);
|
||||||
|
@ -882,8 +956,35 @@ void StickersListWidget::Footer::paintSetIcon(
|
||||||
: icon.stickerMedia
|
: icon.stickerMedia
|
||||||
? icon.stickerMedia->thumbnail()
|
? icon.stickerMedia->thumbnail()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (!icon.lottie
|
const auto x = info.left + (st::stickerIconWidth - icon.pixw) / 2;
|
||||||
|| (!icon.lottie->ready() && !icon.savedFrame.isNull())) {
|
const auto y = _iconsTop + (st::emojiFooterHeight - icon.pixh) / 2;
|
||||||
|
if (icon.lottie && icon.lottie->ready()) {
|
||||||
|
const auto frame = icon.lottie->frame();
|
||||||
|
const auto size = frame.size() / cIntRetinaFactor();
|
||||||
|
if (icon.savedFrame.isNull()) {
|
||||||
|
icon.savedFrame = QPixmap::fromImage(frame, Qt::ColorOnly);
|
||||||
|
icon.savedFrame.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
p.drawImage(
|
||||||
|
QRect(
|
||||||
|
info.left + (st::stickerIconWidth - size.width()) / 2,
|
||||||
|
_iconsTop + (st::emojiFooterHeight - size.height()) / 2,
|
||||||
|
size.width(),
|
||||||
|
size.height()),
|
||||||
|
frame);
|
||||||
|
if (!paused) {
|
||||||
|
icon.lottie->markFrameShown();
|
||||||
|
}
|
||||||
|
} else if (icon.webm && icon.webm->started()) {
|
||||||
|
const auto frame = icon.webm->current(
|
||||||
|
{ .frame = { icon.pixw, icon.pixh }, .keepAlpha = true },
|
||||||
|
paused ? 0 : now);
|
||||||
|
if (icon.savedFrame.isNull()) {
|
||||||
|
icon.savedFrame = frame;
|
||||||
|
icon.savedFrame.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
p.drawPixmapLeft(x, y, width(), frame);
|
||||||
|
} else if (!icon.savedFrame.isNull() || thumb) {
|
||||||
const auto pixmap = !icon.savedFrame.isNull()
|
const auto pixmap = !icon.savedFrame.isNull()
|
||||||
? icon.savedFrame
|
? icon.savedFrame
|
||||||
: (!icon.lottie && thumb)
|
: (!icon.lottie && thumb)
|
||||||
|
@ -894,33 +995,17 @@ void StickersListWidget::Footer::paintSetIcon(
|
||||||
} else if (icon.savedFrame.isNull()) {
|
} else if (icon.savedFrame.isNull()) {
|
||||||
icon.savedFrame = pixmap;
|
icon.savedFrame = pixmap;
|
||||||
}
|
}
|
||||||
p.drawPixmapLeft(
|
p.drawPixmapLeft(x, y, width(), pixmap);
|
||||||
x + (st::stickerIconWidth - icon.pixw) / 2,
|
|
||||||
_iconsTop + (st::emojiFooterHeight - icon.pixh) / 2,
|
|
||||||
width(),
|
|
||||||
pixmap);
|
|
||||||
} else if (icon.lottie->ready()) {
|
|
||||||
const auto frame = icon.lottie->frame();
|
|
||||||
const auto size = frame.size() / cIntRetinaFactor();
|
|
||||||
if (icon.savedFrame.isNull()) {
|
|
||||||
icon.savedFrame = QPixmap::fromImage(frame, Qt::ColorOnly);
|
|
||||||
icon.savedFrame.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
}
|
|
||||||
p.drawImage(
|
|
||||||
QRect(
|
|
||||||
x + (st::stickerIconWidth - size.width()) / 2,
|
|
||||||
_iconsTop + (st::emojiFooterHeight - size.height()) / 2,
|
|
||||||
size.width(),
|
|
||||||
size.height()),
|
|
||||||
frame);
|
|
||||||
const auto paused = _pan->controller()->isGifPausedAtLeastFor(
|
|
||||||
Window::GifPauseReason::SavedGifs);
|
|
||||||
if (!paused) {
|
|
||||||
icon.lottie->markFrameShown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (icon.megagroup) {
|
} else if (icon.megagroup) {
|
||||||
icon.megagroup->paintUserpicLeft(p, icon.megagroupUserpic, x + (st::stickerIconWidth - st::stickerGroupCategorySize) / 2, _iconsTop + (st::emojiFooterHeight - st::stickerGroupCategorySize) / 2, width(), st::stickerGroupCategorySize);
|
const auto size = st::stickerGroupCategorySize;
|
||||||
|
icon.megagroup->paintUserpicLeft(
|
||||||
|
p,
|
||||||
|
icon.megagroupUserpic,
|
||||||
|
info.left + (st::stickerIconWidth - size) / 2,
|
||||||
|
_iconsTop + (st::emojiFooterHeight - size) / 2,
|
||||||
|
width(),
|
||||||
|
st::stickerGroupCategorySize);
|
||||||
} else {
|
} else {
|
||||||
const auto paintedIcon = [&] {
|
const auto paintedIcon = [&] {
|
||||||
if (icon.setId == Data::Stickers::FeaturedSetId) {
|
if (icon.setId == Data::Stickers::FeaturedSetId) {
|
||||||
|
@ -935,7 +1020,7 @@ void StickersListWidget::Footer::paintSetIcon(
|
||||||
}();
|
}();
|
||||||
paintedIcon->paint(
|
paintedIcon->paint(
|
||||||
p,
|
p,
|
||||||
x + (st::stickerIconWidth - paintedIcon->width()) / 2,
|
info.left + (st::stickerIconWidth - paintedIcon->width()) / 2,
|
||||||
_iconsTop + (st::emojiFooterHeight - paintedIcon->height()) / 2,
|
_iconsTop + (st::emojiFooterHeight - paintedIcon->height()) / 2,
|
||||||
width());
|
width());
|
||||||
}
|
}
|
||||||
|
@ -2158,12 +2243,14 @@ void StickersListWidget::paintSticker(
|
||||||
}
|
}
|
||||||
set.lottiePlayer->unpause(sticker.lottie);
|
set.lottiePlayer->unpause(sticker.lottie);
|
||||||
} else if (sticker.webm && sticker.webm->started()) {
|
} else if (sticker.webm && sticker.webm->started()) {
|
||||||
p.drawPixmapLeft(
|
const auto frame = sticker.webm->current(
|
||||||
ppos,
|
{ .frame = size, .keepAlpha = true },
|
||||||
width(),
|
paused ? 0 : now);
|
||||||
sticker.webm->current(
|
if (sticker.savedFrame.isNull()) {
|
||||||
{ .frame = size, .keepAlpha = true },
|
sticker.savedFrame = frame;
|
||||||
paused ? 0 : now));
|
sticker.savedFrame.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
p.drawPixmapLeft(ppos, width(), frame);
|
||||||
} else {
|
} else {
|
||||||
const auto image = media->getStickerSmall();
|
const auto image = media->getStickerSmall();
|
||||||
const auto pixmap = !sticker.savedFrame.isNull()
|
const auto pixmap = !sticker.savedFrame.isNull()
|
||||||
|
|
Loading…
Add table
Reference in a new issue