diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 32eae7905..9e74b82b8 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -114,6 +114,10 @@ struct SameDayRange { return result; } +[[nodiscard]] Data::ReactionId HeartReactionId() { + return { QString() + QChar(10084) }; +} + } // namespace class Controller::PhotoPlayback final { @@ -309,10 +313,11 @@ Controller::Controller(not_null delegate) _reactions->chosen( ) | rpl::start_with_next([=](HistoryView::Reactions::ChosenReaction id) { - startReactionAnimation(id.id, { - .type = Ui::MessageSendingAnimationFrom::Type::Emoji, - .globalStartGeometry = id.globalGeometry, - .frame = id.icon, + startReactionAnimation({ + .id = id.id, + .flyIcon = id.icon, + .flyFrom = _wrap->mapFromGlobal(id.globalGeometry), + .scaleOutDuration = st::fadeWrapDuration * 2, }, _wrap.get()); _replyArea->sendReaction(id.id); unfocusReply(); @@ -597,6 +602,13 @@ rpl::producer Controller::likedValue() const { void Controller::toggleLiked(bool liked) { _liked = liked; + if (liked) { + startReactionAnimation({ + .id = HeartReactionId(), + .scaleOutDuration = st::fadeWrapDuration * 2, + .effectOnly = true, + }, _replyArea->likeAnimationTarget()); + } } void Controller::showFullCaption() { @@ -1045,6 +1057,8 @@ void Controller::ready() { } _started = true; updatePlayingAllowed(); + uiShow()->session().data().reactions().preloadAnimationsFor( + HeartReactionId()); } void Controller::updateVideoPlayback(const Player::TrackState &state) { @@ -1563,17 +1577,10 @@ void Controller::updatePowerSaveBlocker(const Player::TrackState &state) { } void Controller::startReactionAnimation( - Data::ReactionId id, - Ui::MessageSendingAnimationFrom from, + Ui::ReactionFlyAnimationArgs args, not_null target) { Expects(shown()); - auto args = Ui::ReactionFlyAnimationArgs{ - .id = id, - .flyIcon = from.frame, - .flyFrom = _wrap->mapFromGlobal(from.globalStartGeometry), - .scaleOutDuration = st::fadeWrapDuration * 2, - }; _reactionAnimation = std::make_unique( _wrap, &shownUser()->owner().reactions(), diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index 115e7e80a..997590929 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -35,7 +35,7 @@ class CachedIconFactory; namespace Ui { class RpWidget; -struct MessageSendingAnimationFrom; +struct ReactionFlyAnimationArgs; class EmojiFlyAnimation; class BoxContent; } // namespace Ui @@ -238,8 +238,7 @@ private: int index); void startReactionAnimation( - Data::ReactionId id, - Ui::MessageSendingAnimationFrom from, + Ui::ReactionFlyAnimationArgs from, not_null target); const not_null _delegate; diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 119604e1c..1c010e0f0 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -1031,8 +1031,8 @@ QSize OverlayWidget::flipSizeByRotation(QSize size) const { bool OverlayWidget::hasCopyMediaRestriction(bool skipPremiumCheck) const { if (const auto story = _stories ? _stories->story() : nullptr) { return skipPremiumCheck - ? story->canDownloadIfPremium() - : story->canDownloadChecked(); + ? !story->canDownloadIfPremium() + : !story->canDownloadChecked(); } return (_history && !_history->peer->allowsForwarding()) || (_message && _message->forbidsSaving()); @@ -1261,9 +1261,12 @@ void OverlayWidget::showPremiumDownloadPromo() { .text = tr::lng_stories_save_promo( tr::now, 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), .duration = kStorySavePromoDuration, + .adaptive = true, .filter = filter, }); } diff --git a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp index 361eb3b7b..e46820573 100644 --- a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp @@ -111,11 +111,13 @@ ReactionFlyAnimation::ReactionFlyAnimation( }); 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; } resolve(_effect, aroundAnimation, size * 2); - generateMiniCopies(size + size / 2); if (!args.flyIcon.isNull()) { _flyIcon = std::move(args.flyIcon); _fly.start(flyCallback(), 0., 1., kFlyDuration); @@ -210,8 +212,6 @@ void ReactionFlyAnimation::paintCenterFrame( QRect target, const QColor &colored, crl::time now) const { - Expects(_center || _custom); - const auto size = QSize( int(base::SafeRound(target.width() * _centerSizeMultiplier)), int(base::SafeRound(target.height() * _centerSizeMultiplier))); @@ -222,7 +222,7 @@ void ReactionFlyAnimation::paintCenterFrame( size.width(), size.height()); p.drawImage(rect, _center->frame(st::windowFg->c)); - } else { + } else if (_custom) { const auto scaled = (size.width() != _customSize); _custom->paint(p, { .textColor = colored, diff --git a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h index 595e11e86..00d9d2e8d 100644 --- a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h +++ b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h @@ -28,6 +28,7 @@ struct ReactionFlyAnimationArgs { QImage flyIcon; QRect flyFrom; crl::time scaleOutDuration = 0; + bool effectOnly = false; [[nodiscard]] ReactionFlyAnimationArgs translated(QPoint point) const; };