Add effect animation for heart-like.
This commit is contained in:
		
							parent
							
								
									4bd925ac2c
								
							
						
					
					
						commit
						40b274e1b4
					
				
					 5 changed files with 33 additions and 23 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		
		Reference in a new issue