mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 07:37:11 +02:00
Animate reactions when reading.
This commit is contained in:
parent
e509da8fd8
commit
4f1e04cf9e
17 changed files with 85 additions and 64 deletions
|
@ -1294,7 +1294,7 @@ void ApiWrap::markContentsRead(
|
|||
QVector<MTPint>>();
|
||||
markedIds.reserve(items.size());
|
||||
for (const auto &item : items) {
|
||||
if (!item->markContentsRead() || !item->isRegular() || true) {
|
||||
if (!item->markContentsRead(true) || !item->isRegular() || true) {
|
||||
AssertIsDebug();
|
||||
continue;
|
||||
}
|
||||
|
@ -1320,7 +1320,7 @@ void ApiWrap::markContentsRead(
|
|||
}
|
||||
|
||||
void ApiWrap::markContentsRead(not_null<HistoryItem*> item) {
|
||||
if (!item->markContentsRead() || !item->isRegular()) {
|
||||
if (!item->markContentsRead(true) || !item->isRegular()) {
|
||||
return;
|
||||
}
|
||||
const auto ids = MTP_vector<MTPint>(1, MTP_int(item->id));
|
||||
|
|
|
@ -1486,6 +1486,12 @@ void Session::requestAnimationPlayInline(not_null<HistoryItem*> item) {
|
|||
}
|
||||
}
|
||||
|
||||
void Session::requestUnreadReactionsAnimation(not_null<HistoryItem*> item) {
|
||||
enumerateItemViews(item, [&](not_null<ViewElement*> view) {
|
||||
view->animateUnreadReactions();
|
||||
});
|
||||
}
|
||||
|
||||
rpl::producer<not_null<HistoryItem*>> Session::animationPlayInlineRequest() const {
|
||||
return _animationPlayInlineRequest.events();
|
||||
}
|
||||
|
|
|
@ -253,6 +253,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<not_null<HistoryItem*>> itemViewRefreshRequest() const;
|
||||
void requestItemTextRefresh(not_null<HistoryItem*> item);
|
||||
void requestAnimationPlayInline(not_null<HistoryItem*> item);
|
||||
void requestUnreadReactionsAnimation(not_null<HistoryItem*> item);
|
||||
[[nodiscard]] rpl::producer<not_null<HistoryItem*>> animationPlayInlineRequest() const;
|
||||
void notifyHistoryUnloaded(not_null<const History*> history);
|
||||
[[nodiscard]] rpl::producer<not_null<const History*>> historyUnloaded() const;
|
||||
|
|
|
@ -386,7 +386,7 @@ HistoryInner::HistoryInner(
|
|||
return;
|
||||
} else if (const auto view = item->mainView()) {
|
||||
if (const auto top = itemTop(view); top >= 0) {
|
||||
view->animateSendReaction({
|
||||
view->animateReaction({
|
||||
.emoji = reaction.emoji,
|
||||
.flyIcon = reaction.icon,
|
||||
.flyFrom = reaction.geometry.translated(0, -top),
|
||||
|
|
|
@ -383,8 +383,11 @@ void HistoryItem::markReactionsRead() {
|
|||
history()->unreadReactions().erase(id);
|
||||
}
|
||||
|
||||
bool HistoryItem::markContentsRead() {
|
||||
bool HistoryItem::markContentsRead(bool fromThisClient) {
|
||||
if (hasUnreadReaction()) {
|
||||
if (fromThisClient) {
|
||||
history()->owner().requestUnreadReactionsAnimation(this);
|
||||
}
|
||||
markReactionsRead();
|
||||
return true;
|
||||
} else if (isUnreadMention() || isIncomingUnreadMedia()) {
|
||||
|
|
|
@ -150,7 +150,7 @@ public:
|
|||
[[nodiscard]] bool hasUnreadMediaFlag() const;
|
||||
void markReactionsRead();
|
||||
void markMediaAndMentionRead();
|
||||
bool markContentsRead();
|
||||
bool markContentsRead(bool fromThisClient = false);
|
||||
void setIsPinned(bool isPinned);
|
||||
|
||||
// For edit media in history_message.
|
||||
|
|
|
@ -512,10 +512,10 @@ void BottomInfo::setReactionCount(Reaction &reaction, int count) {
|
|||
: 0;
|
||||
}
|
||||
|
||||
void BottomInfo::animateReactionSend(
|
||||
SendReactionAnimationArgs &&args,
|
||||
void BottomInfo::animateReaction(
|
||||
ReactionAnimationArgs &&args,
|
||||
Fn<void()> repaint) {
|
||||
_reactionAnimation = std::make_unique<Reactions::SendAnimation>(
|
||||
_reactionAnimation = std::make_unique<Reactions::Animation>(
|
||||
_reactionsOwner,
|
||||
args.translated(QPoint(width(), height())),
|
||||
std::move(repaint),
|
||||
|
@ -523,12 +523,12 @@ void BottomInfo::animateReactionSend(
|
|||
}
|
||||
|
||||
auto BottomInfo::takeSendReactionAnimation()
|
||||
-> std::unique_ptr<Reactions::SendAnimation> {
|
||||
-> std::unique_ptr<Reactions::Animation> {
|
||||
return std::move(_reactionAnimation);
|
||||
}
|
||||
|
||||
void BottomInfo::continueSendReactionAnimation(
|
||||
std::unique_ptr<Reactions::SendAnimation> animation) {
|
||||
std::unique_ptr<Reactions::Animation> animation) {
|
||||
_reactionAnimation = std::move(animation);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,14 +21,14 @@ class Reactions;
|
|||
|
||||
namespace HistoryView {
|
||||
namespace Reactions {
|
||||
class SendAnimation;
|
||||
class Animation;
|
||||
} // namespace Reactions
|
||||
|
||||
using PaintContext = Ui::ChatPaintContext;
|
||||
|
||||
class Message;
|
||||
struct TextState;
|
||||
struct SendReactionAnimationArgs;
|
||||
struct ReactionAnimationArgs;
|
||||
|
||||
class BottomInfo final : public Object {
|
||||
public:
|
||||
|
@ -73,13 +73,13 @@ public:
|
|||
bool inverted,
|
||||
const PaintContext &context) const;
|
||||
|
||||
void animateReactionSend(
|
||||
SendReactionAnimationArgs &&args,
|
||||
void animateReaction(
|
||||
ReactionAnimationArgs &&args,
|
||||
Fn<void()> repaint);
|
||||
[[nodiscard]] auto takeSendReactionAnimation()
|
||||
-> std::unique_ptr<Reactions::SendAnimation>;
|
||||
-> std::unique_ptr<Reactions::Animation>;
|
||||
void continueSendReactionAnimation(
|
||||
std::unique_ptr<Reactions::SendAnimation> animation);
|
||||
std::unique_ptr<Reactions::Animation> animation);
|
||||
|
||||
private:
|
||||
struct Reaction {
|
||||
|
@ -124,7 +124,7 @@ private:
|
|||
Ui::Text::String _replies;
|
||||
std::vector<Reaction> _reactions;
|
||||
mutable ClickHandlerPtr _revokeLink;
|
||||
mutable std::unique_ptr<Reactions::SendAnimation> _reactionAnimation;
|
||||
mutable std::unique_ptr<Reactions::Animation> _reactionAnimation;
|
||||
int _reactionsMaxWidth = 0;
|
||||
int _dateWidth = 0;
|
||||
bool _authorElided = false;
|
||||
|
|
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_groups.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_sponsored_messages.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
|
@ -342,7 +343,7 @@ void DateBadge::paint(
|
|||
ServiceMessagePainter::PaintDate(p, st, text, width, y, w, chatWide);
|
||||
}
|
||||
|
||||
SendReactionAnimationArgs SendReactionAnimationArgs::translated(
|
||||
ReactionAnimationArgs ReactionAnimationArgs::translated(
|
||||
QPoint point) const {
|
||||
return {
|
||||
.emoji = emoji,
|
||||
|
@ -1059,11 +1060,20 @@ void Element::clickHandlerPressedChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void Element::animateSendReaction(SendReactionAnimationArgs &&args) {
|
||||
void Element::animateReaction(ReactionAnimationArgs &&args) {
|
||||
}
|
||||
|
||||
void Element::animateUnreadReactions() {
|
||||
const auto &recent = data()->recentReactions();
|
||||
for (const auto &[emoji, list] : recent) {
|
||||
if (ranges::contains(list, true, &Data::RecentReaction::unread)) {
|
||||
animateReaction({ .emoji = emoji });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Element::takeSendReactionAnimation()
|
||||
-> std::unique_ptr<Reactions::SendAnimation> {
|
||||
-> std::unique_ptr<Reactions::Animation> {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ using PaintContext = Ui::ChatPaintContext;
|
|||
|
||||
namespace Reactions {
|
||||
struct ButtonParameters;
|
||||
class SendAnimation;
|
||||
class Animation;
|
||||
} // namespace Reactions
|
||||
|
||||
enum class Context : char {
|
||||
|
@ -229,12 +229,12 @@ struct DateBadge : public RuntimeComponent<DateBadge, Element> {
|
|||
|
||||
};
|
||||
|
||||
struct SendReactionAnimationArgs {
|
||||
struct ReactionAnimationArgs {
|
||||
QString emoji;
|
||||
std::shared_ptr<Lottie::Icon> flyIcon;
|
||||
QRect flyFrom;
|
||||
|
||||
[[nodiscard]] SendReactionAnimationArgs translated(QPoint point) const;
|
||||
[[nodiscard]] ReactionAnimationArgs translated(QPoint point) const;
|
||||
};
|
||||
|
||||
class Element
|
||||
|
@ -421,9 +421,10 @@ public:
|
|||
|
||||
[[nodiscard]] bool markSponsoredViewed(int shownFromTop) const;
|
||||
|
||||
virtual void animateSendReaction(SendReactionAnimationArgs &&args);
|
||||
virtual void animateReaction(ReactionAnimationArgs &&args);
|
||||
void animateUnreadReactions();
|
||||
[[nodiscard]] virtual auto takeSendReactionAnimation()
|
||||
-> std::unique_ptr<Reactions::SendAnimation>;
|
||||
-> std::unique_ptr<Reactions::Animation>;
|
||||
|
||||
virtual ~Element();
|
||||
|
||||
|
@ -438,7 +439,7 @@ public:
|
|||
static void Moused(Element *view);
|
||||
[[nodiscard]] static Element *Moused();
|
||||
static void ClearGlobal();
|
||||
|
||||
|
||||
protected:
|
||||
void repaint() const;
|
||||
|
||||
|
|
|
@ -353,7 +353,7 @@ ListWidget::ListWidget(
|
|||
return;
|
||||
} else if (const auto view = viewForItem(item)) {
|
||||
if (const auto top = itemTop(view); top >= 0) {
|
||||
view->animateSendReaction({
|
||||
view->animateReaction({
|
||||
.emoji = reaction.emoji,
|
||||
.flyIcon = reaction.icon,
|
||||
.flyFrom = reaction.geometry.translated(0, -top),
|
||||
|
|
|
@ -326,7 +326,7 @@ void Message::applyGroupAdminChanges(
|
|||
}
|
||||
}
|
||||
|
||||
void Message::animateSendReaction(SendReactionAnimationArgs &&args) {
|
||||
void Message::animateReaction(ReactionAnimationArgs &&args) {
|
||||
const auto item = message();
|
||||
const auto media = this->media();
|
||||
|
||||
|
@ -353,12 +353,12 @@ void Message::animateSendReaction(SendReactionAnimationArgs &&args) {
|
|||
: 0;
|
||||
g.setHeight(g.height() - reactionsHeight);
|
||||
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
||||
_reactions->animateSend(args.translated(-reactionsPosition), repainter);
|
||||
_reactions->animate(args.translated(-reactionsPosition), repainter);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto animateInBottomInfo = [&](QPoint bottomRight) {
|
||||
_bottomInfo.animateReactionSend(args.translated(-bottomRight), repainter);
|
||||
_bottomInfo.animateReaction(args.translated(-bottomRight), repainter);
|
||||
};
|
||||
if (bubble) {
|
||||
auto entry = logEntryOriginal();
|
||||
|
@ -381,7 +381,7 @@ void Message::animateSendReaction(SendReactionAnimationArgs &&args) {
|
|||
if (reactionsInBubble) {
|
||||
trect.setHeight(trect.height() - reactionsHeight);
|
||||
const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + reactionsTop);
|
||||
_reactions->animateSend(args.translated(-reactionsPosition), repainter);
|
||||
_reactions->animate(args.translated(-reactionsPosition), repainter);
|
||||
return;
|
||||
}
|
||||
if (_viewButton) {
|
||||
|
@ -425,7 +425,7 @@ void Message::animateSendReaction(SendReactionAnimationArgs &&args) {
|
|||
}
|
||||
|
||||
auto Message::takeSendReactionAnimation()
|
||||
-> std::unique_ptr<Reactions::SendAnimation> {
|
||||
-> std::unique_ptr<Reactions::Animation> {
|
||||
return _reactions
|
||||
? _reactions->takeSendAnimation()
|
||||
: _bottomInfo.takeSendReactionAnimation();
|
||||
|
@ -2163,7 +2163,7 @@ void Message::refreshReactions() {
|
|||
strong->data()->toggleReaction(emoji);
|
||||
if (const auto now = weak.get()) {
|
||||
if (now->data()->chosenReaction() == emoji) {
|
||||
now->animateSendReaction({
|
||||
now->animateReaction({
|
||||
.emoji = emoji,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -135,9 +135,9 @@ public:
|
|||
void applyGroupAdminChanges(
|
||||
const base::flat_set<UserId> &changes) override;
|
||||
|
||||
void animateSendReaction(SendReactionAnimationArgs &&args) override;
|
||||
void animateReaction(ReactionAnimationArgs &&args) override;
|
||||
auto takeSendReactionAnimation()
|
||||
-> std::unique_ptr<Reactions::SendAnimation> override;
|
||||
-> std::unique_ptr<Reactions::Animation> override;
|
||||
|
||||
protected:
|
||||
void refreshDataIdHook() override;
|
||||
|
|
|
@ -21,9 +21,9 @@ constexpr auto kFlyDuration = crl::time(300);
|
|||
|
||||
} // namespace
|
||||
|
||||
SendAnimation::SendAnimation(
|
||||
Animation::Animation(
|
||||
not_null<::Data::Reactions*> owner,
|
||||
SendReactionAnimationArgs &&args,
|
||||
ReactionAnimationArgs &&args,
|
||||
Fn<void()> repaint,
|
||||
int size)
|
||||
: _owner(owner)
|
||||
|
@ -66,9 +66,9 @@ SendAnimation::SendAnimation(
|
|||
_valid = true;
|
||||
}
|
||||
|
||||
SendAnimation::~SendAnimation() = default;
|
||||
Animation::~Animation() = default;
|
||||
|
||||
QRect SendAnimation::paintGetArea(
|
||||
QRect Animation::paintGetArea(
|
||||
QPainter &p,
|
||||
QPoint origin,
|
||||
QRect target) const {
|
||||
|
@ -105,7 +105,7 @@ QRect SendAnimation::paintGetArea(
|
|||
return wide;
|
||||
}
|
||||
|
||||
int SendAnimation::computeParabolicTop(
|
||||
int Animation::computeParabolicTop(
|
||||
int from,
|
||||
int to,
|
||||
float64 progress) const {
|
||||
|
@ -141,12 +141,12 @@ int SendAnimation::computeParabolicTop(
|
|||
return int(base::SafeRound(_cachedA * t * t + _cachedB * t + from));
|
||||
}
|
||||
|
||||
void SendAnimation::startAnimations() {
|
||||
void Animation::startAnimations() {
|
||||
_center->animate([=] { callback(); }, 0, _center->framesCount() - 1);
|
||||
_effect->animate([=] { callback(); }, 0, _effect->framesCount() - 1);
|
||||
}
|
||||
|
||||
void SendAnimation::flyCallback() {
|
||||
void Animation::flyCallback() {
|
||||
if (!_fly.animating()) {
|
||||
_flyIcon = nullptr;
|
||||
startAnimations();
|
||||
|
@ -154,25 +154,25 @@ void SendAnimation::flyCallback() {
|
|||
callback();
|
||||
}
|
||||
|
||||
void SendAnimation::callback() {
|
||||
void Animation::callback() {
|
||||
if (_repaint) {
|
||||
_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void SendAnimation::setRepaintCallback(Fn<void()> repaint) {
|
||||
void Animation::setRepaintCallback(Fn<void()> repaint) {
|
||||
_repaint = std::move(repaint);
|
||||
}
|
||||
|
||||
bool SendAnimation::flying() const {
|
||||
bool Animation::flying() const {
|
||||
return (_flyIcon != nullptr);
|
||||
}
|
||||
|
||||
float64 SendAnimation::flyingProgress() const {
|
||||
float64 Animation::flyingProgress() const {
|
||||
return _fly.value(1.);
|
||||
}
|
||||
|
||||
QString SendAnimation::playingAroundEmoji() const {
|
||||
QString Animation::playingAroundEmoji() const {
|
||||
const auto finished = !_valid
|
||||
|| (!_flyIcon && !_center->animating() && !_effect->animating());
|
||||
return finished ? QString() : _emoji;
|
||||
|
|
|
@ -18,19 +18,19 @@ class Reactions;
|
|||
} // namespace Data
|
||||
|
||||
namespace HistoryView {
|
||||
struct SendReactionAnimationArgs;
|
||||
struct ReactionAnimationArgs;
|
||||
} // namespace HistoryView
|
||||
|
||||
namespace HistoryView::Reactions {
|
||||
|
||||
class SendAnimation final {
|
||||
class Animation final {
|
||||
public:
|
||||
SendAnimation(
|
||||
Animation(
|
||||
not_null<::Data::Reactions*> owner,
|
||||
SendReactionAnimationArgs &&args,
|
||||
ReactionAnimationArgs &&args,
|
||||
Fn<void()> repaint,
|
||||
int size);
|
||||
~SendAnimation();
|
||||
~Animation();
|
||||
|
||||
void setRepaintCallback(Fn<void()> repaint);
|
||||
QRect paintGetArea(QPainter &p, QPoint origin, QRect target) const;
|
||||
|
|
|
@ -408,10 +408,10 @@ bool InlineList::getState(
|
|||
return false;
|
||||
}
|
||||
|
||||
void InlineList::animateSend(
|
||||
SendReactionAnimationArgs &&args,
|
||||
void InlineList::animate(
|
||||
ReactionAnimationArgs &&args,
|
||||
Fn<void()> repaint) {
|
||||
_animation = std::make_unique<Reactions::SendAnimation>(
|
||||
_animation = std::make_unique<Reactions::Animation>(
|
||||
_owner,
|
||||
std::move(args),
|
||||
std::move(repaint),
|
||||
|
@ -447,12 +447,12 @@ void InlineList::resolveUserpicsImage(const Button &button) const {
|
|||
kMaxRecentUserpics);
|
||||
}
|
||||
|
||||
std::unique_ptr<SendAnimation> InlineList::takeSendAnimation() {
|
||||
std::unique_ptr<Animation> InlineList::takeSendAnimation() {
|
||||
return std::move(_animation);
|
||||
}
|
||||
|
||||
void InlineList::continueSendAnimation(
|
||||
std::unique_ptr<SendAnimation> animation) {
|
||||
std::unique_ptr<Animation> animation) {
|
||||
_animation = std::move(animation);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ namespace HistoryView {
|
|||
using PaintContext = Ui::ChatPaintContext;
|
||||
class Message;
|
||||
struct TextState;
|
||||
struct SendReactionAnimationArgs;
|
||||
struct ReactionAnimationArgs;
|
||||
struct UserpicInRow;
|
||||
} // namespace HistoryView
|
||||
|
||||
namespace HistoryView::Reactions {
|
||||
|
||||
class SendAnimation;
|
||||
class Animation;
|
||||
|
||||
struct InlineListData {
|
||||
enum class Flag : uchar {
|
||||
|
@ -72,11 +72,11 @@ public:
|
|||
QPoint point,
|
||||
not_null<TextState*> outResult) const;
|
||||
|
||||
void animateSend(
|
||||
SendReactionAnimationArgs &&args,
|
||||
void animate(
|
||||
ReactionAnimationArgs &&args,
|
||||
Fn<void()> repaint);
|
||||
[[nodiscard]] std::unique_ptr<SendAnimation> takeSendAnimation();
|
||||
void continueSendAnimation(std::unique_ptr<SendAnimation> animation);
|
||||
[[nodiscard]] std::unique_ptr<Animation> takeSendAnimation();
|
||||
void continueSendAnimation(std::unique_ptr<Animation> animation);
|
||||
|
||||
private:
|
||||
struct Userpics {
|
||||
|
@ -113,7 +113,7 @@ private:
|
|||
std::vector<Button> _buttons;
|
||||
QSize _skipBlock;
|
||||
|
||||
mutable std::unique_ptr<SendAnimation> _animation;
|
||||
mutable std::unique_ptr<Animation> _animation;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue