2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 14:45:14 +00:00

Animate inline path thumbnails with sliding gradient.

This commit is contained in:
John Preston
2021-07-02 18:29:13 +03:00
parent 22d23c8be1
commit b22e2ffe1d
27 changed files with 258 additions and 39 deletions

View File

@@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/input_fields.h"
#include "ui/image/image.h"
#include "ui/effects/path_shift_gradient.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "base/unixtime.h"
@@ -125,6 +126,8 @@ private:
bool _isOneColumn = false;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
Fn<SendMenu::Type()> _sendMenuType;
rpl::event_stream<FieldAutocomplete::MentionChosen> _mentionChosen;
@@ -738,6 +741,10 @@ FieldAutocomplete::Inner::Inner(
, _hrows(hrows)
, _brows(brows)
, _srows(srows)
, _pathGradient(std::make_unique<Ui::PathShiftGradient>(
st::windowBgRipple,
st::windowBgOver,
[=] { update(); }))
, _previewTimer([=] { showPreview(); }) {
controller->session().downloaderTaskFinished(
) | rpl::start_with_next([=] {
@@ -770,6 +777,11 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
- st::defaultScrollArea.width;
if (!_srows->empty()) {
_pathGradient->startFrame(
0,
width(),
std::min(st::msgMaxWidth / 2, width() / 2));
int32 rows = rowscount(_srows->size(), _stickersPerRow);
int32 fromrow = floorclamp(r.y() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
int32 torow = ceilclamp(r.y() + r.height() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
@@ -815,6 +827,17 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
w = std::max(qRound(coef * document->dimensions.width()), 1);
h = std::max(qRound(coef * document->dimensions.height()), 1);
}
QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
ChatHelpers::PaintStickerThumbnailPath(
p,
media.get(),
QRect(ppos, QSize(w, h)),
_pathGradient.get());
continue; AssertIsDebug();
if (sticker.animated && sticker.animated->ready()) {
const auto frame = sticker.animated->frame();
const auto size = frame.size() / cIntRetinaFactor();
@@ -838,7 +861,7 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
p,
media.get(),
QRect(ppos, QSize(w, h)),
st::windowBgRipple->c);
_pathGradient.get());
}
}
}

View File

@@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/popup_menu.h"
#include "ui/effects/animations.h"
#include "ui/effects/ripple_animation.h"
#include "ui/effects/path_shift_gradient.h"
#include "ui/image/image.h"
#include "ui/cached_round_corners.h"
#include "lottie/lottie_multi_player.h"
@@ -899,6 +900,10 @@ StickersListWidget::StickersListWidget(
: Inner(parent, controller)
, _api(&controller->session().mtp())
, _section(Section::Stickers)
, _pathGradient(std::make_unique<Ui::PathShiftGradient>(
st::windowBgRipple,
st::windowBgOver,
[=] { update(); }))
, _megagroupSetAbout(st::columnMinimalWidthThird - st::emojiScroll.width - st::emojiPanHeaderLeft)
, _addText(tr::lng_stickers_featured_add(tr::now).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
@@ -1531,6 +1536,8 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
toColumn = _columnCount - toColumn;
}
_pathGradient->startFrame(0, width(), width() / 2);
auto &sets = shownSets();
auto selectedSticker = std::get_if<OverSticker>(&_selected);
auto selectedButton = std::get_if<OverButton>(!v::is_null(_pressed)
@@ -1889,6 +1896,16 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
h = std::max(qRound(coef * document->dimensions.height()), 1);
}
auto ppos = pos + QPoint((_singleSize.width() - w) / 2, (_singleSize.height() - h) / 2);
PaintStickerThumbnailPath(
p,
media.get(),
QRect(ppos, QSize{ w, h }),
_pathGradient.get());
return; AssertIsDebug();
if (sticker.animated && sticker.animated->ready()) {
auto request = Lottie::FrameRequest();
request.box = boundingBoxSize() * cIntRetinaFactor();
@@ -1923,7 +1940,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
p,
media.get(),
QRect(ppos, QSize{ w, h }),
st::windowBgRipple->c);
_pathGradient.get());
}
}

View File

@@ -25,6 +25,7 @@ class LinkButton;
class PopupMenu;
class RippleAnimation;
class BoxContent;
class PathShiftGradient;
} // namespace Ui
namespace Lottie {
@@ -361,6 +362,8 @@ private:
OverState _pressed;
QPoint _lastMousePosition;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
Ui::Text::String _megagroupSetAbout;
QString _megagroupSetButtonText;
int _megagroupSetButtonTextWidth = 0;

View File

@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "storage/cache/storage_cache_database.h"
#include "ui/effects/path_shift_gradient.h"
#include "main/main_session.h"
namespace ChatHelpers {
@@ -192,17 +193,25 @@ bool PaintStickerThumbnailPath(
QPainter &p,
not_null<Data::DocumentMedia*> media,
QRect target,
QColor fg) {
QLinearGradient *gradient) {
const auto &path = media->thumbnailPath();
const auto dimensions = media->owner()->dimensions;
if (path.isEmpty() || dimensions.isEmpty()) {
if (path.isEmpty() || dimensions.isEmpty() || target.isEmpty()) {
return false;
}
p.save();
auto hq = PainterHighQualityEnabler(p);
p.setBrush(fg);
p.setPen(Qt::NoPen);
p.translate(target.topLeft());
if (gradient) {
const auto scale = dimensions.width() / float64(target.width());
const auto shift = p.worldTransform().dx();
gradient->setStart((gradient->start().x() - shift) * scale, 0);
gradient->setFinalStop(
(gradient->finalStop().x() - shift) * scale,
0);
p.setBrush(*gradient);
}
p.scale(
target.width() / float64(dimensions.width()),
target.height() / float64(dimensions.height()));
@@ -211,4 +220,19 @@ bool PaintStickerThumbnailPath(
return true;
}
bool PaintStickerThumbnailPath(
QPainter &p,
not_null<Data::DocumentMedia*> media,
QRect target,
not_null<Ui::PathShiftGradient*> gradient) {
return gradient->paint([&](const Ui::PathShiftGradient::Background &bg) {
if (const auto color = std::get_if<style::color>(&bg)) {
p.setBrush(*color);
return PaintStickerThumbnailPath(p, media, target);
}
const auto gradient = v::get<QLinearGradient*>(bg);
return PaintStickerThumbnailPath(p, media, target, gradient);
});
}
} // namespace ChatHelpers

View File

@@ -26,6 +26,10 @@ namespace Main {
class Session;
} // namespace Main
namespace Ui {
class PathShiftGradient;
} // namespace Ui
namespace Data {
class DocumentMedia;
class StickersSetThumbnailView;
@@ -75,6 +79,12 @@ bool PaintStickerThumbnailPath(
QPainter &p,
not_null<Data::DocumentMedia*> media,
QRect target,
QColor fg);
QLinearGradient *gradient = nullptr);
bool PaintStickerThumbnailPath(
QPainter &p,
not_null<Data::DocumentMedia*> media,
QRect target,
not_null<Ui::PathShiftGradient*> gradient);
} // namespace ChatHelpers