Add effect animation for heart-like.

This commit is contained in:
John Preston 2023-08-03 15:28:38 +02:00
parent 4bd925ac2c
commit 40b274e1b4
5 changed files with 33 additions and 23 deletions

View File

@ -114,6 +114,10 @@ struct SameDayRange {
return result; return result;
} }
[[nodiscard]] Data::ReactionId HeartReactionId() {
return { QString() + QChar(10084) };
}
} // namespace } // namespace
class Controller::PhotoPlayback final { class Controller::PhotoPlayback final {
@ -309,10 +313,11 @@ Controller::Controller(not_null<Delegate*> delegate)
_reactions->chosen( _reactions->chosen(
) | rpl::start_with_next([=](HistoryView::Reactions::ChosenReaction id) { ) | rpl::start_with_next([=](HistoryView::Reactions::ChosenReaction id) {
startReactionAnimation(id.id, { startReactionAnimation({
.type = Ui::MessageSendingAnimationFrom::Type::Emoji, .id = id.id,
.globalStartGeometry = id.globalGeometry, .flyIcon = id.icon,
.frame = id.icon, .flyFrom = _wrap->mapFromGlobal(id.globalGeometry),
.scaleOutDuration = st::fadeWrapDuration * 2,
}, _wrap.get()); }, _wrap.get());
_replyArea->sendReaction(id.id); _replyArea->sendReaction(id.id);
unfocusReply(); unfocusReply();
@ -597,6 +602,13 @@ rpl::producer<bool> Controller::likedValue() const {
void Controller::toggleLiked(bool liked) { void Controller::toggleLiked(bool liked) {
_liked = liked; _liked = liked;
if (liked) {
startReactionAnimation({
.id = HeartReactionId(),
.scaleOutDuration = st::fadeWrapDuration * 2,
.effectOnly = true,
}, _replyArea->likeAnimationTarget());
}
} }
void Controller::showFullCaption() { void Controller::showFullCaption() {
@ -1045,6 +1057,8 @@ void Controller::ready() {
} }
_started = true; _started = true;
updatePlayingAllowed(); updatePlayingAllowed();
uiShow()->session().data().reactions().preloadAnimationsFor(
HeartReactionId());
} }
void Controller::updateVideoPlayback(const Player::TrackState &state) { void Controller::updateVideoPlayback(const Player::TrackState &state) {
@ -1563,17 +1577,10 @@ void Controller::updatePowerSaveBlocker(const Player::TrackState &state) {
} }
void Controller::startReactionAnimation( void Controller::startReactionAnimation(
Data::ReactionId id, Ui::ReactionFlyAnimationArgs args,
Ui::MessageSendingAnimationFrom from,
not_null<QWidget*> target) { not_null<QWidget*> target) {
Expects(shown()); Expects(shown());
auto args = Ui::ReactionFlyAnimationArgs{
.id = id,
.flyIcon = from.frame,
.flyFrom = _wrap->mapFromGlobal(from.globalStartGeometry),
.scaleOutDuration = st::fadeWrapDuration * 2,
};
_reactionAnimation = std::make_unique<Ui::EmojiFlyAnimation>( _reactionAnimation = std::make_unique<Ui::EmojiFlyAnimation>(
_wrap, _wrap,
&shownUser()->owner().reactions(), &shownUser()->owner().reactions(),

View File

@ -35,7 +35,7 @@ class CachedIconFactory;
namespace Ui { namespace Ui {
class RpWidget; class RpWidget;
struct MessageSendingAnimationFrom; struct ReactionFlyAnimationArgs;
class EmojiFlyAnimation; class EmojiFlyAnimation;
class BoxContent; class BoxContent;
} // namespace Ui } // namespace Ui
@ -238,8 +238,7 @@ private:
int index); int index);
void startReactionAnimation( void startReactionAnimation(
Data::ReactionId id, Ui::ReactionFlyAnimationArgs from,
Ui::MessageSendingAnimationFrom from,
not_null<QWidget*> target); not_null<QWidget*> target);
const not_null<Delegate*> _delegate; const not_null<Delegate*> _delegate;

View File

@ -1031,8 +1031,8 @@ QSize OverlayWidget::flipSizeByRotation(QSize size) const {
bool OverlayWidget::hasCopyMediaRestriction(bool skipPremiumCheck) const { bool OverlayWidget::hasCopyMediaRestriction(bool skipPremiumCheck) const {
if (const auto story = _stories ? _stories->story() : nullptr) { if (const auto story = _stories ? _stories->story() : nullptr) {
return skipPremiumCheck return skipPremiumCheck
? story->canDownloadIfPremium() ? !story->canDownloadIfPremium()
: story->canDownloadChecked(); : !story->canDownloadChecked();
} }
return (_history && !_history->peer->allowsForwarding()) return (_history && !_history->peer->allowsForwarding())
|| (_message && _message->forbidsSaving()); || (_message && _message->forbidsSaving());
@ -1261,9 +1261,12 @@ void OverlayWidget::showPremiumDownloadPromo() {
.text = tr::lng_stories_save_promo( .text = tr::lng_stories_save_promo(
tr::now, tr::now,
lt_link, lt_link,
Ui::Text::Bold(tr::lng_send_as_premium_required_link(tr::now)), Ui::Text::Link(
Ui::Text::Bold(
tr::lng_send_as_premium_required_link(tr::now))),
Ui::Text::WithEntities), Ui::Text::WithEntities),
.duration = kStorySavePromoDuration, .duration = kStorySavePromoDuration,
.adaptive = true,
.filter = filter, .filter = filter,
}); });
} }

View File

@ -111,11 +111,13 @@ ReactionFlyAnimation::ReactionFlyAnimation(
}); });
return true; return true;
}; };
if (!_custom && !resolve(_center, centerIcon, size)) { generateMiniCopies(size + size / 2);
if (args.effectOnly) {
_custom = nullptr;
} else if (!_custom && !resolve(_center, centerIcon, size)) {
return; return;
} }
resolve(_effect, aroundAnimation, size * 2); resolve(_effect, aroundAnimation, size * 2);
generateMiniCopies(size + size / 2);
if (!args.flyIcon.isNull()) { if (!args.flyIcon.isNull()) {
_flyIcon = std::move(args.flyIcon); _flyIcon = std::move(args.flyIcon);
_fly.start(flyCallback(), 0., 1., kFlyDuration); _fly.start(flyCallback(), 0., 1., kFlyDuration);
@ -210,8 +212,6 @@ void ReactionFlyAnimation::paintCenterFrame(
QRect target, QRect target,
const QColor &colored, const QColor &colored,
crl::time now) const { crl::time now) const {
Expects(_center || _custom);
const auto size = QSize( const auto size = QSize(
int(base::SafeRound(target.width() * _centerSizeMultiplier)), int(base::SafeRound(target.width() * _centerSizeMultiplier)),
int(base::SafeRound(target.height() * _centerSizeMultiplier))); int(base::SafeRound(target.height() * _centerSizeMultiplier)));
@ -222,7 +222,7 @@ void ReactionFlyAnimation::paintCenterFrame(
size.width(), size.width(),
size.height()); size.height());
p.drawImage(rect, _center->frame(st::windowFg->c)); p.drawImage(rect, _center->frame(st::windowFg->c));
} else { } else if (_custom) {
const auto scaled = (size.width() != _customSize); const auto scaled = (size.width() != _customSize);
_custom->paint(p, { _custom->paint(p, {
.textColor = colored, .textColor = colored,

View File

@ -28,6 +28,7 @@ struct ReactionFlyAnimationArgs {
QImage flyIcon; QImage flyIcon;
QRect flyFrom; QRect flyFrom;
crl::time scaleOutDuration = 0; crl::time scaleOutDuration = 0;
bool effectOnly = false;
[[nodiscard]] ReactionFlyAnimationArgs translated(QPoint point) const; [[nodiscard]] ReactionFlyAnimationArgs translated(QPoint point) const;
}; };