mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support multiple reaction animations in one message.
This commit is contained in:
parent
4f1e04cf9e
commit
8bde488662
10 changed files with 149 additions and 78 deletions
|
@ -313,19 +313,22 @@ void BottomInfo::paintReactions(
|
||||||
int top,
|
int top,
|
||||||
int availableWidth,
|
int availableWidth,
|
||||||
const PaintContext &context) const {
|
const PaintContext &context) const {
|
||||||
|
struct SingleAnimation {
|
||||||
|
not_null<Reactions::Animation*> animation;
|
||||||
|
QRect target;
|
||||||
|
};
|
||||||
|
std::vector<SingleAnimation> animations;
|
||||||
|
|
||||||
auto x = left;
|
auto x = left;
|
||||||
auto y = top;
|
auto y = top;
|
||||||
auto widthLeft = availableWidth;
|
auto widthLeft = availableWidth;
|
||||||
const auto animated = _reactionAnimation
|
|
||||||
? _reactionAnimation->playingAroundEmoji()
|
|
||||||
: QString();
|
|
||||||
if (_reactionAnimation
|
|
||||||
&& context.reactionInfo
|
|
||||||
&& animated.isEmpty()) {
|
|
||||||
_reactionAnimation = nullptr;
|
|
||||||
}
|
|
||||||
for (const auto &reaction : _reactions) {
|
for (const auto &reaction : _reactions) {
|
||||||
const auto animating = (reaction.emoji == animated);
|
if (context.reactionInfo
|
||||||
|
&& reaction.animation
|
||||||
|
&& reaction.animation->finished()) {
|
||||||
|
reaction.animation = nullptr;
|
||||||
|
}
|
||||||
|
const auto animating = (reaction.animation != nullptr);
|
||||||
const auto add = (reaction.countTextWidth > 0)
|
const auto add = (reaction.countTextWidth > 0)
|
||||||
? st::reactionInfoDigitSkip
|
? st::reactionInfoDigitSkip
|
||||||
: st::reactionInfoBetween;
|
: st::reactionInfoBetween;
|
||||||
|
@ -349,14 +352,15 @@ void BottomInfo::paintReactions(
|
||||||
st::reactionInfoImage,
|
st::reactionInfoImage,
|
||||||
st::reactionInfoImage);
|
st::reactionInfoImage);
|
||||||
const auto skipImage = animating
|
const auto skipImage = animating
|
||||||
&& (reaction.count < 2 || !_reactionAnimation->flying());
|
&& (reaction.count < 2 || !reaction.animation->flying());
|
||||||
if (!reaction.image.isNull() && !skipImage) {
|
if (!reaction.image.isNull() && !skipImage) {
|
||||||
p.drawImage(image.topLeft(), reaction.image);
|
p.drawImage(image.topLeft(), reaction.image);
|
||||||
}
|
}
|
||||||
if (animating) {
|
if (animating) {
|
||||||
context.reactionInfo->effectPaint = [=](QPainter &p) {
|
animations.push_back({
|
||||||
return _reactionAnimation->paintGetArea(p, origin, image);
|
.animation = reaction.animation.get(),
|
||||||
};
|
.target = image,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (reaction.countTextWidth > 0) {
|
if (reaction.countTextWidth > 0) {
|
||||||
p.drawText(
|
p.drawText(
|
||||||
|
@ -367,6 +371,19 @@ void BottomInfo::paintReactions(
|
||||||
x += width + add;
|
x += width + add;
|
||||||
widthLeft -= width + add;
|
widthLeft -= width + add;
|
||||||
}
|
}
|
||||||
|
if (!animations.empty()) {
|
||||||
|
context.reactionInfo->effectPaint = [=](QPainter &p) {
|
||||||
|
auto result = QRect();
|
||||||
|
for (const auto &single : animations) {
|
||||||
|
const auto area = single.animation->paintGetArea(
|
||||||
|
p,
|
||||||
|
origin,
|
||||||
|
single.target);
|
||||||
|
result = result.isEmpty() ? area : result.united(area);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize BottomInfo::countCurrentSize(int newWidth) {
|
QSize BottomInfo::countCurrentSize(int newWidth) {
|
||||||
|
@ -440,11 +457,6 @@ void BottomInfo::layoutRepliesText() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BottomInfo::layoutReactionsText() {
|
void BottomInfo::layoutReactionsText() {
|
||||||
if (_reactionAnimation
|
|
||||||
&& !_data.reactions.contains(
|
|
||||||
_reactionAnimation->playingAroundEmoji())) {
|
|
||||||
_reactionAnimation = nullptr;
|
|
||||||
}
|
|
||||||
if (_data.reactions.empty()) {
|
if (_data.reactions.empty()) {
|
||||||
_reactions.clear();
|
_reactions.clear();
|
||||||
return;
|
return;
|
||||||
|
@ -515,21 +527,39 @@ void BottomInfo::setReactionCount(Reaction &reaction, int count) {
|
||||||
void BottomInfo::animateReaction(
|
void BottomInfo::animateReaction(
|
||||||
ReactionAnimationArgs &&args,
|
ReactionAnimationArgs &&args,
|
||||||
Fn<void()> repaint) {
|
Fn<void()> repaint) {
|
||||||
_reactionAnimation = std::make_unique<Reactions::Animation>(
|
const auto i = ranges::find(_reactions, args.emoji, &Reaction::emoji);
|
||||||
|
if (i == end(_reactions)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i->animation = std::make_unique<Reactions::Animation>(
|
||||||
_reactionsOwner,
|
_reactionsOwner,
|
||||||
args.translated(QPoint(width(), height())),
|
args.translated(QPoint(width(), height())),
|
||||||
std::move(repaint),
|
std::move(repaint),
|
||||||
st::reactionInfoImage);
|
st::reactionInfoImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BottomInfo::takeSendReactionAnimation()
|
auto BottomInfo::takeReactionAnimations()
|
||||||
-> std::unique_ptr<Reactions::Animation> {
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>> {
|
||||||
return std::move(_reactionAnimation);
|
auto result = base::flat_map<
|
||||||
|
QString,
|
||||||
|
std::unique_ptr<Reactions::Animation>>();
|
||||||
|
for (auto &reaction : _reactions) {
|
||||||
|
if (reaction.animation) {
|
||||||
|
result.emplace(reaction.emoji, std::move(reaction.animation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BottomInfo::continueSendReactionAnimation(
|
void BottomInfo::continueReactionAnimations(base::flat_map<
|
||||||
std::unique_ptr<Reactions::Animation> animation) {
|
QString,
|
||||||
_reactionAnimation = std::move(animation);
|
std::unique_ptr<Reactions::Animation>> animations) {
|
||||||
|
for (auto &[emoji, animation] : animations) {
|
||||||
|
const auto i = ranges::find(_reactions, emoji, &Reaction::emoji);
|
||||||
|
if (i != end(_reactions)) {
|
||||||
|
i->animation = std::move(animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BottomInfo::Data BottomInfoDataFromMessage(not_null<Message*> message) {
|
BottomInfo::Data BottomInfoDataFromMessage(not_null<Message*> message) {
|
||||||
|
|
|
@ -76,13 +76,15 @@ public:
|
||||||
void animateReaction(
|
void animateReaction(
|
||||||
ReactionAnimationArgs &&args,
|
ReactionAnimationArgs &&args,
|
||||||
Fn<void()> repaint);
|
Fn<void()> repaint);
|
||||||
[[nodiscard]] auto takeSendReactionAnimation()
|
[[nodiscard]] auto takeReactionAnimations()
|
||||||
-> std::unique_ptr<Reactions::Animation>;
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>>;
|
||||||
void continueSendReactionAnimation(
|
void continueReactionAnimations(base::flat_map<
|
||||||
std::unique_ptr<Reactions::Animation> animation);
|
QString,
|
||||||
|
std::unique_ptr<Reactions::Animation>> animations);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Reaction {
|
struct Reaction {
|
||||||
|
mutable std::unique_ptr<Reactions::Animation> animation;
|
||||||
mutable QImage image;
|
mutable QImage image;
|
||||||
QString emoji;
|
QString emoji;
|
||||||
QString countText;
|
QString countText;
|
||||||
|
@ -124,7 +126,6 @@ private:
|
||||||
Ui::Text::String _replies;
|
Ui::Text::String _replies;
|
||||||
std::vector<Reaction> _reactions;
|
std::vector<Reaction> _reactions;
|
||||||
mutable ClickHandlerPtr _revokeLink;
|
mutable ClickHandlerPtr _revokeLink;
|
||||||
mutable std::unique_ptr<Reactions::Animation> _reactionAnimation;
|
|
||||||
int _reactionsMaxWidth = 0;
|
int _reactionsMaxWidth = 0;
|
||||||
int _dateWidth = 0;
|
int _dateWidth = 0;
|
||||||
bool _authorElided = false;
|
bool _authorElided = false;
|
||||||
|
|
|
@ -1072,9 +1072,9 @@ void Element::animateUnreadReactions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Element::takeSendReactionAnimation()
|
auto Element::takeReactionAnimations()
|
||||||
-> std::unique_ptr<Reactions::Animation> {
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>> {
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Element::~Element() {
|
Element::~Element() {
|
||||||
|
|
|
@ -423,8 +423,8 @@ public:
|
||||||
|
|
||||||
virtual void animateReaction(ReactionAnimationArgs &&args);
|
virtual void animateReaction(ReactionAnimationArgs &&args);
|
||||||
void animateUnreadReactions();
|
void animateUnreadReactions();
|
||||||
[[nodiscard]] virtual auto takeSendReactionAnimation()
|
[[nodiscard]] virtual auto takeReactionAnimations()
|
||||||
-> std::unique_ptr<Reactions::Animation>;
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>>;
|
||||||
|
|
||||||
virtual ~Element();
|
virtual ~Element();
|
||||||
|
|
||||||
|
|
|
@ -253,15 +253,18 @@ Message::Message(
|
||||||
initLogEntryOriginal();
|
initLogEntryOriginal();
|
||||||
initPsa();
|
initPsa();
|
||||||
refreshReactions();
|
refreshReactions();
|
||||||
auto animation = replacing
|
auto animations = replacing
|
||||||
? replacing->takeSendReactionAnimation()
|
? replacing->takeReactionAnimations()
|
||||||
: nullptr;
|
: base::flat_map<QString, std::unique_ptr<Reactions::Animation>>();
|
||||||
if (animation) {
|
if (!animations.empty()) {
|
||||||
animation->setRepaintCallback([=] { repaint(); });
|
const auto repainter = [=] { repaint(); };
|
||||||
|
for (const auto &[emoji, animation] : animations) {
|
||||||
|
animation->setRepaintCallback(repainter);
|
||||||
|
}
|
||||||
if (_reactions) {
|
if (_reactions) {
|
||||||
_reactions->continueSendAnimation(std::move(animation));
|
_reactions->continueAnimations(std::move(animations));
|
||||||
} else {
|
} else {
|
||||||
_bottomInfo.continueSendReactionAnimation(std::move(animation));
|
_bottomInfo.continueReactionAnimations(std::move(animations));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -424,11 +427,11 @@ void Message::animateReaction(ReactionAnimationArgs &&args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Message::takeSendReactionAnimation()
|
auto Message::takeReactionAnimations()
|
||||||
-> std::unique_ptr<Reactions::Animation> {
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>> {
|
||||||
return _reactions
|
return _reactions
|
||||||
? _reactions->takeSendAnimation()
|
? _reactions->takeAnimations()
|
||||||
: _bottomInfo.takeSendReactionAnimation();
|
: _bottomInfo.takeReactionAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Message::performCountOptimalSize() {
|
QSize Message::performCountOptimalSize() {
|
||||||
|
|
|
@ -136,8 +136,8 @@ public:
|
||||||
const base::flat_set<UserId> &changes) override;
|
const base::flat_set<UserId> &changes) override;
|
||||||
|
|
||||||
void animateReaction(ReactionAnimationArgs &&args) override;
|
void animateReaction(ReactionAnimationArgs &&args) override;
|
||||||
auto takeSendReactionAnimation()
|
auto takeReactionAnimations()
|
||||||
-> std::unique_ptr<Reactions::Animation> override;
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>> override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void refreshDataIdHook() override;
|
void refreshDataIdHook() override;
|
||||||
|
|
|
@ -27,11 +27,10 @@ Animation::Animation(
|
||||||
Fn<void()> repaint,
|
Fn<void()> repaint,
|
||||||
int size)
|
int size)
|
||||||
: _owner(owner)
|
: _owner(owner)
|
||||||
, _emoji(args.emoji)
|
|
||||||
, _repaint(std::move(repaint))
|
, _repaint(std::move(repaint))
|
||||||
, _flyFrom(args.flyFrom) {
|
, _flyFrom(args.flyFrom) {
|
||||||
const auto &list = owner->list(::Data::Reactions::Type::All);
|
const auto &list = owner->list(::Data::Reactions::Type::All);
|
||||||
const auto i = ranges::find(list, _emoji, &::Data::Reaction::emoji);
|
const auto i = ranges::find(list, args.emoji, &::Data::Reaction::emoji);
|
||||||
if (i == end(list) || !i->centerIcon) {
|
if (i == end(list) || !i->centerIcon) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -172,10 +171,9 @@ float64 Animation::flyingProgress() const {
|
||||||
return _fly.value(1.);
|
return _fly.value(1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Animation::playingAroundEmoji() const {
|
bool Animation::finished() const {
|
||||||
const auto finished = !_valid
|
return !_valid
|
||||||
|| (!_flyIcon && !_center->animating() && !_effect->animating());
|
|| (!_flyIcon && !_center->animating() && !_effect->animating());
|
||||||
return finished ? QString() : _emoji;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace HistoryView::Reactions
|
} // namespace HistoryView::Reactions
|
||||||
|
|
|
@ -35,9 +35,9 @@ public:
|
||||||
void setRepaintCallback(Fn<void()> repaint);
|
void setRepaintCallback(Fn<void()> repaint);
|
||||||
QRect paintGetArea(QPainter &p, QPoint origin, QRect target) const;
|
QRect paintGetArea(QPainter &p, QPoint origin, QRect target) const;
|
||||||
|
|
||||||
[[nodiscard]] QString playingAroundEmoji() const;
|
|
||||||
[[nodiscard]] bool flying() const;
|
[[nodiscard]] bool flying() const;
|
||||||
[[nodiscard]] float64 flyingProgress() const;
|
[[nodiscard]] float64 flyingProgress() const;
|
||||||
|
[[nodiscard]] bool finished() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void flyCallback();
|
void flyCallback();
|
||||||
|
@ -46,7 +46,6 @@ private:
|
||||||
int computeParabolicTop(int from, int to, float64 progress) const;
|
int computeParabolicTop(int from, int to, float64 progress) const;
|
||||||
|
|
||||||
const not_null<::Data::Reactions*> _owner;
|
const not_null<::Data::Reactions*> _owner;
|
||||||
const QString _emoji;
|
|
||||||
Fn<void()> _repaint;
|
Fn<void()> _repaint;
|
||||||
std::shared_ptr<Lottie::Icon> _flyIcon;
|
std::shared_ptr<Lottie::Icon> _flyIcon;
|
||||||
std::unique_ptr<Lottie::Icon> _center;
|
std::unique_ptr<Lottie::Icon> _center;
|
||||||
|
|
|
@ -268,29 +268,34 @@ void InlineList::paint(
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
const QRect &clip) const {
|
const QRect &clip) const {
|
||||||
|
struct SingleAnimation {
|
||||||
|
not_null<Reactions::Animation*> animation;
|
||||||
|
QRect target;
|
||||||
|
};
|
||||||
|
std::vector<SingleAnimation> animations;
|
||||||
|
|
||||||
const auto st = context.st;
|
const auto st = context.st;
|
||||||
const auto stm = context.messageStyle();
|
const auto stm = context.messageStyle();
|
||||||
const auto padding = st::reactionInlinePadding;
|
const auto padding = st::reactionInlinePadding;
|
||||||
const auto size = st::reactionInlineSize;
|
const auto size = st::reactionInlineSize;
|
||||||
const auto skip = (size - st::reactionInlineImage) / 2;
|
const auto skip = (size - st::reactionInlineImage) / 2;
|
||||||
const auto inbubble = (_data.flags & InlineListData::Flag::InBubble);
|
const auto inbubble = (_data.flags & InlineListData::Flag::InBubble);
|
||||||
const auto animated = (_animation && context.reactionInfo)
|
|
||||||
? _animation->playingAroundEmoji()
|
|
||||||
: QString();
|
|
||||||
const auto flipped = (_data.flags & Data::Flag::Flipped);
|
const auto flipped = (_data.flags & Data::Flag::Flipped);
|
||||||
if (_animation && context.reactionInfo && animated.isEmpty()) {
|
|
||||||
_animation = nullptr;
|
|
||||||
}
|
|
||||||
p.setFont(st::semiboldFont);
|
p.setFont(st::semiboldFont);
|
||||||
for (const auto &button : _buttons) {
|
for (const auto &button : _buttons) {
|
||||||
|
if (context.reactionInfo
|
||||||
|
&& button.animation
|
||||||
|
&& button.animation->finished()) {
|
||||||
|
button.animation = nullptr;
|
||||||
|
}
|
||||||
|
const auto animating = (button.animation != nullptr);
|
||||||
const auto &geometry = button.geometry;
|
const auto &geometry = button.geometry;
|
||||||
const auto mine = (_data.chosenReaction == button.emoji);
|
const auto mine = (_data.chosenReaction == button.emoji);
|
||||||
const auto withoutMine = button.count - (mine ? 1 : 0);
|
const auto withoutMine = button.count - (mine ? 1 : 0);
|
||||||
const auto animating = (animated == button.emoji);
|
|
||||||
const auto skipImage = animating
|
const auto skipImage = animating
|
||||||
&& (withoutMine < 1 || !_animation->flying());
|
&& (withoutMine < 1 || !button.animation->flying());
|
||||||
const auto bubbleProgress = skipImage
|
const auto bubbleProgress = skipImage
|
||||||
? _animation->flyingProgress()
|
? button.animation->flyingProgress()
|
||||||
: 1.;
|
: 1.;
|
||||||
const auto bubbleReady = (bubbleProgress == 1.);
|
const auto bubbleReady = (bubbleProgress == 1.);
|
||||||
const auto bubbleSkip = anim::interpolate(
|
const auto bubbleSkip = anim::interpolate(
|
||||||
|
@ -299,7 +304,7 @@ void InlineList::paint(
|
||||||
bubbleProgress);
|
bubbleProgress);
|
||||||
const auto inner = geometry.marginsRemoved(padding);
|
const auto inner = geometry.marginsRemoved(padding);
|
||||||
const auto chosen = mine
|
const auto chosen = mine
|
||||||
&& (!animating || !_animation->flying() || skipImage);
|
&& (!animating || !button.animation->flying() || skipImage);
|
||||||
if (bubbleProgress > 0.) {
|
if (bubbleProgress > 0.) {
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
|
@ -342,9 +347,10 @@ void InlineList::paint(
|
||||||
p.drawImage(image.topLeft(), button.image);
|
p.drawImage(image.topLeft(), button.image);
|
||||||
}
|
}
|
||||||
if (animating) {
|
if (animating) {
|
||||||
context.reactionInfo->effectPaint = [=](QPainter &p) {
|
animations.push_back({
|
||||||
return _animation->paintGetArea(p, QPoint(), image);
|
.animation = button.animation.get(),
|
||||||
};
|
.target = image,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (bubbleProgress == 0.) {
|
if (bubbleProgress == 0.) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -381,6 +387,19 @@ void InlineList::paint(
|
||||||
p.setOpacity(1.);
|
p.setOpacity(1.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!animations.empty()) {
|
||||||
|
context.reactionInfo->effectPaint = [=](QPainter &p) {
|
||||||
|
auto result = QRect();
|
||||||
|
for (const auto &single : animations) {
|
||||||
|
const auto area = single.animation->paintGetArea(
|
||||||
|
p,
|
||||||
|
QPoint(),
|
||||||
|
single.target);
|
||||||
|
result = result.isEmpty() ? area : result.united(area);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InlineList::getState(
|
bool InlineList::getState(
|
||||||
|
@ -411,7 +430,11 @@ bool InlineList::getState(
|
||||||
void InlineList::animate(
|
void InlineList::animate(
|
||||||
ReactionAnimationArgs &&args,
|
ReactionAnimationArgs &&args,
|
||||||
Fn<void()> repaint) {
|
Fn<void()> repaint) {
|
||||||
_animation = std::make_unique<Reactions::Animation>(
|
const auto i = ranges::find(_buttons, args.emoji, &Button::emoji);
|
||||||
|
if (i == end(_buttons)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i->animation = std::make_unique<Reactions::Animation>(
|
||||||
_owner,
|
_owner,
|
||||||
std::move(args),
|
std::move(args),
|
||||||
std::move(repaint),
|
std::move(repaint),
|
||||||
|
@ -447,13 +470,28 @@ void InlineList::resolveUserpicsImage(const Button &button) const {
|
||||||
kMaxRecentUserpics);
|
kMaxRecentUserpics);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Animation> InlineList::takeSendAnimation() {
|
auto InlineList::takeAnimations()
|
||||||
return std::move(_animation);
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>> {
|
||||||
|
auto result = base::flat_map<
|
||||||
|
QString,
|
||||||
|
std::unique_ptr<Reactions::Animation>>();
|
||||||
|
for (auto &button : _buttons) {
|
||||||
|
if (button.animation) {
|
||||||
|
result.emplace(button.emoji, std::move(button.animation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InlineList::continueSendAnimation(
|
void InlineList::continueAnimations(base::flat_map<
|
||||||
std::unique_ptr<Animation> animation) {
|
QString,
|
||||||
_animation = std::move(animation);
|
std::unique_ptr<Reactions::Animation>> animations) {
|
||||||
|
for (auto &[emoji, animation] : animations) {
|
||||||
|
const auto i = ranges::find(_buttons, emoji, &Button::emoji);
|
||||||
|
if (i != end(_buttons)) {
|
||||||
|
i->animation = std::move(animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineListData InlineListDataFromMessage(not_null<Message*> message) {
|
InlineListData InlineListDataFromMessage(not_null<Message*> message) {
|
||||||
|
|
|
@ -75,8 +75,11 @@ public:
|
||||||
void animate(
|
void animate(
|
||||||
ReactionAnimationArgs &&args,
|
ReactionAnimationArgs &&args,
|
||||||
Fn<void()> repaint);
|
Fn<void()> repaint);
|
||||||
[[nodiscard]] std::unique_ptr<Animation> takeSendAnimation();
|
[[nodiscard]] auto takeAnimations()
|
||||||
void continueSendAnimation(std::unique_ptr<Animation> animation);
|
-> base::flat_map<QString, std::unique_ptr<Reactions::Animation>>;
|
||||||
|
void continueAnimations(base::flat_map<
|
||||||
|
QString,
|
||||||
|
std::unique_ptr<Reactions::Animation>> animations);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Userpics {
|
struct Userpics {
|
||||||
|
@ -86,6 +89,7 @@ private:
|
||||||
};
|
};
|
||||||
struct Button {
|
struct Button {
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
|
mutable std::unique_ptr<Animation> animation;
|
||||||
mutable QImage image;
|
mutable QImage image;
|
||||||
mutable ClickHandlerPtr link;
|
mutable ClickHandlerPtr link;
|
||||||
std::unique_ptr<Userpics> userpics;
|
std::unique_ptr<Userpics> userpics;
|
||||||
|
@ -113,8 +117,6 @@ private:
|
||||||
std::vector<Button> _buttons;
|
std::vector<Button> _buttons;
|
||||||
QSize _skipBlock;
|
QSize _skipBlock;
|
||||||
|
|
||||||
mutable std::unique_ptr<Animation> _animation;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] InlineListData InlineListDataFromMessage(
|
[[nodiscard]] InlineListData InlineListDataFromMessage(
|
||||||
|
|
Loading…
Add table
Reference in a new issue