Add effect animation for heart-like.
This commit is contained in:
parent
4bd925ac2c
commit
40b274e1b4
|
@ -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(),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user