Play select animations in reactions.
This commit is contained in:
		
							parent
							
								
									7f27ce6dee
								
							
						
					
					
						commit
						c56a22c8d5
					
				
					 2 changed files with 80 additions and 13 deletions
				
			
		| 
						 | 
					@ -363,6 +363,7 @@ Manager::~Manager() = default;
 | 
				
			||||||
void Manager::updateButton(ButtonParameters parameters) {
 | 
					void Manager::updateButton(ButtonParameters parameters) {
 | 
				
			||||||
	const auto contextChanged = (_buttonContext != parameters.context);
 | 
						const auto contextChanged = (_buttonContext != parameters.context);
 | 
				
			||||||
	if (contextChanged) {
 | 
						if (contextChanged) {
 | 
				
			||||||
 | 
							setSelectedIcon(-1);
 | 
				
			||||||
		if (_button) {
 | 
							if (_button) {
 | 
				
			||||||
			_button->applyState(ButtonState::Hidden);
 | 
								_button->applyState(ButtonState::Hidden);
 | 
				
			||||||
			_buttonHiding.push_back(std::move(_button));
 | 
								_buttonHiding.push_back(std::move(_button));
 | 
				
			||||||
| 
						 | 
					@ -498,6 +499,12 @@ bool Manager::checkIconLoaded(ReactionDocument &entry) const {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Manager::updateCurrentButton() const {
 | 
				
			||||||
 | 
						if (const auto button = _button.get()) {
 | 
				
			||||||
 | 
							_buttonUpdate(button->geometry());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::loadIcons() {
 | 
					void Manager::loadIcons() {
 | 
				
			||||||
	const auto load = [&](not_null<DocumentData*> document, int frame) {
 | 
						const auto load = [&](not_null<DocumentData*> document, int frame) {
 | 
				
			||||||
		if (const auto i = _loadCache.find(document); i != end(_loadCache)) {
 | 
							if (const auto i = _loadCache.find(document); i != end(_loadCache)) {
 | 
				
			||||||
| 
						 | 
					@ -521,7 +528,7 @@ void Manager::loadIcons() {
 | 
				
			||||||
	for (const auto &reaction : _list) {
 | 
						for (const auto &reaction : _list) {
 | 
				
			||||||
		_icons.push_back({
 | 
							_icons.push_back({
 | 
				
			||||||
			.appear = load(reaction.appearAnimation, main ? -1 : 0),
 | 
								.appear = load(reaction.appearAnimation, main ? -1 : 0),
 | 
				
			||||||
			.select = load(reaction.selectAnimation, -1),
 | 
								.select = load(reaction.selectAnimation, 0),
 | 
				
			||||||
			.appearAnimated = main,
 | 
								.appearAnimated = main,
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		main = false;
 | 
							main = false;
 | 
				
			||||||
| 
						 | 
					@ -592,11 +599,25 @@ void Manager::setSelectedIcon(int index) const {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		icon.selected = selected;
 | 
							icon.selected = selected;
 | 
				
			||||||
		icon.selectedScale.start(
 | 
							icon.selectedScale.start(
 | 
				
			||||||
			[=] { if (_button) _buttonUpdate(_button->geometry()); },
 | 
								[=] { updateCurrentButton(); },
 | 
				
			||||||
			selected ? 1. : kHoverScale,
 | 
								selected ? 1. : kHoverScale,
 | 
				
			||||||
			selected ? kHoverScale : 1.,
 | 
								selected ? kHoverScale : 1.,
 | 
				
			||||||
			kHoverScaleDuration,
 | 
								kHoverScaleDuration,
 | 
				
			||||||
			anim::sineInOut);
 | 
								anim::sineInOut);
 | 
				
			||||||
 | 
							if (selected) {
 | 
				
			||||||
 | 
								const auto skipAnimation = icon.selectAnimated
 | 
				
			||||||
 | 
									|| !icon.appearAnimated
 | 
				
			||||||
 | 
									|| (icon.select && icon.select->animating())
 | 
				
			||||||
 | 
									|| (icon.appear && icon.appear->animating());
 | 
				
			||||||
 | 
								const auto select = skipAnimation ? nullptr : icon.select.get();
 | 
				
			||||||
 | 
								if (select && !icon.selectAnimated) {
 | 
				
			||||||
 | 
									icon.selectAnimated = true;
 | 
				
			||||||
 | 
									select->animate(
 | 
				
			||||||
 | 
										[=] { updateCurrentButton(); },
 | 
				
			||||||
 | 
										0,
 | 
				
			||||||
 | 
										select->framesCount() - 1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	if (_selectedIcon != index) {
 | 
						if (_selectedIcon != index) {
 | 
				
			||||||
		setSelected(_selectedIcon, false);
 | 
							setSelected(_selectedIcon, false);
 | 
				
			||||||
| 
						 | 
					@ -694,17 +715,16 @@ void Manager::paintButton(
 | 
				
			||||||
	const auto mainEmojiPosition = position + (button->expandUp()
 | 
						const auto mainEmojiPosition = position + (button->expandUp()
 | 
				
			||||||
		? QPoint(0, size.height() - _outer.height())
 | 
							? QPoint(0, size.height() - _outer.height())
 | 
				
			||||||
		: QPoint());
 | 
							: QPoint());
 | 
				
			||||||
	if (size.height() > _outer.height()
 | 
						if (onlyMainEmojiVisible(button)) {
 | 
				
			||||||
		|| (!_icons.empty() && _icons.front().selected)) {
 | 
							const auto source = validateEmoji(frameIndex, scale);
 | 
				
			||||||
 | 
							p.drawImage(mainEmojiPosition, _cacheParts, source);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		p.save();
 | 
							p.save();
 | 
				
			||||||
		paintAllEmoji(p, button, scale, mainEmojiPosition);
 | 
							paintAllEmoji(p, button, scale, mainEmojiPosition);
 | 
				
			||||||
		p.restore();
 | 
							p.restore();
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		const auto source = validateEmoji(frameIndex, scale);
 | 
					 | 
				
			||||||
		p.drawImage(mainEmojiPosition, _cacheParts, source);
 | 
					 | 
				
			||||||
		if (button == _button.get()) {
 | 
					 | 
				
			||||||
			clearAppearAnimations();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (button == _button.get() && button->hasInitialView()) {
 | 
				
			||||||
 | 
							clearAppearAnimations();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opacity != 1.) {
 | 
						if (opacity != 1.) {
 | 
				
			||||||
| 
						 | 
					@ -712,6 +732,22 @@ void Manager::paintButton(
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Manager::onlyMainEmojiVisible(not_null<Button*> button) const {
 | 
				
			||||||
 | 
						if (!button->hasInitialView()) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						} else if (button != _button.get() || _icons.empty()) {
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const auto &icon = _icons.front();
 | 
				
			||||||
 | 
						if (icon.selected
 | 
				
			||||||
 | 
							|| icon.selectedScale.animating()
 | 
				
			||||||
 | 
							|| (icon.select && icon.select->animating())) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						icon.selectAnimated = false;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::clearAppearAnimations() {
 | 
					void Manager::clearAppearAnimations() {
 | 
				
			||||||
	if (!_showingAll) {
 | 
						if (!_showingAll) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -719,10 +755,20 @@ void Manager::clearAppearAnimations() {
 | 
				
			||||||
	_showingAll = false;
 | 
						_showingAll = false;
 | 
				
			||||||
	auto main = true;
 | 
						auto main = true;
 | 
				
			||||||
	for (auto &icon : _icons) {
 | 
						for (auto &icon : _icons) {
 | 
				
			||||||
 | 
							if (!main) {
 | 
				
			||||||
 | 
								if (icon.selected) {
 | 
				
			||||||
 | 
									setSelectedIcon(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								icon.selectedScale.stop();
 | 
				
			||||||
 | 
								if (const auto select = icon.select.get()) {
 | 
				
			||||||
 | 
									select->jumpTo(0, nullptr);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								icon.selectAnimated = false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (icon.appearAnimated != main) {
 | 
							if (icon.appearAnimated != main) {
 | 
				
			||||||
			if (const auto appear = icon.appear.get()) {
 | 
								if (const auto appear = icon.appear.get()) {
 | 
				
			||||||
				appear->jumpTo(
 | 
									appear->jumpTo(
 | 
				
			||||||
					main ? (appear->framesCount() - 1) : 1,
 | 
										main ? (appear->framesCount() - 1) : 0,
 | 
				
			||||||
					nullptr);
 | 
										nullptr);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			icon.appearAnimated = main;
 | 
								icon.appearAnimated = main;
 | 
				
			||||||
| 
						 | 
					@ -811,7 +857,7 @@ void Manager::paintAllEmoji(
 | 
				
			||||||
	auto emojiPosition = mainEmojiPosition
 | 
						auto emojiPosition = mainEmojiPosition
 | 
				
			||||||
		+ QPoint(0, button->scroll() * (expandUp ? 1 : -1));
 | 
							+ QPoint(0, button->scroll() * (expandUp ? 1 : -1));
 | 
				
			||||||
	const auto update = [=] {
 | 
						const auto update = [=] {
 | 
				
			||||||
		if (_button) _buttonUpdate(_button->geometry());
 | 
							updateCurrentButton();
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	for (auto &icon : _icons) {
 | 
						for (auto &icon : _icons) {
 | 
				
			||||||
		const auto target = countTarget(icon).translated(emojiPosition);
 | 
							const auto target = countTarget(icon).translated(emojiPosition);
 | 
				
			||||||
| 
						 | 
					@ -820,10 +866,22 @@ void Manager::paintAllEmoji(
 | 
				
			||||||
		if (!target.intersects(clip)) {
 | 
							if (!target.intersects(clip)) {
 | 
				
			||||||
			if (current) {
 | 
								if (current) {
 | 
				
			||||||
				if (const auto appear = icon.appear.get()) {
 | 
									if (const auto appear = icon.appear.get()) {
 | 
				
			||||||
					appear->jumpTo(1, nullptr);
 | 
										appear->jumpTo(0, nullptr);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (icon.selected) {
 | 
				
			||||||
 | 
										setSelectedIcon(-1);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				icon.appearAnimated = false;
 | 
									icon.appearAnimated = false;
 | 
				
			||||||
 | 
									icon.selectAnimated = false;
 | 
				
			||||||
 | 
									if (const auto select = icon.select.get()) {
 | 
				
			||||||
 | 
										select->jumpTo(0, nullptr);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									icon.selectedScale.stop();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (icon.select && icon.select->animating()) {
 | 
				
			||||||
 | 
								const auto size = int(base::SafeRound(target.width()));
 | 
				
			||||||
 | 
								const auto frame = icon.select->frame({ size, size }, update);
 | 
				
			||||||
 | 
								p.drawImage(target, frame.image);
 | 
				
			||||||
		} else if (const auto appear = icon.appear.get()) {
 | 
							} else if (const auto appear = icon.appear.get()) {
 | 
				
			||||||
			if (current
 | 
								if (current
 | 
				
			||||||
				&& !icon.appearAnimated
 | 
									&& !icon.appearAnimated
 | 
				
			||||||
| 
						 | 
					@ -835,6 +893,12 @@ void Manager::paintAllEmoji(
 | 
				
			||||||
			const auto frame = appear->frame({ size, size }, update);
 | 
								const auto frame = appear->frame({ size, size }, update);
 | 
				
			||||||
			p.drawImage(target, frame.image);
 | 
								p.drawImage(target, frame.image);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (current
 | 
				
			||||||
 | 
								&& icon.selectAnimated
 | 
				
			||||||
 | 
								&& !icon.select->animating()
 | 
				
			||||||
 | 
								&& !icon.selected) {
 | 
				
			||||||
 | 
								icon.selectAnimated = false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,6 +150,7 @@ private:
 | 
				
			||||||
		mutable Ui::Animations::Simple selectedScale;
 | 
							mutable Ui::Animations::Simple selectedScale;
 | 
				
			||||||
		bool appearAnimated = false;
 | 
							bool appearAnimated = false;
 | 
				
			||||||
		mutable bool selected = false;
 | 
							mutable bool selected = false;
 | 
				
			||||||
 | 
							mutable bool selectAnimated = false;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	static constexpr auto kFramesCount = 30;
 | 
						static constexpr auto kFramesCount = 30;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,6 +206,8 @@ private:
 | 
				
			||||||
	[[nodiscard]] ClickHandlerPtr resolveButtonLink(
 | 
						[[nodiscard]] ClickHandlerPtr resolveButtonLink(
 | 
				
			||||||
		const Data::Reaction &reaction) const;
 | 
							const Data::Reaction &reaction) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void updateCurrentButton() const;
 | 
				
			||||||
 | 
						[[nodiscard]] bool onlyMainEmojiVisible(not_null<Button*> button) const;
 | 
				
			||||||
	[[nodiscard]] bool checkIconLoaded(ReactionDocument &entry) const;
 | 
						[[nodiscard]] bool checkIconLoaded(ReactionDocument &entry) const;
 | 
				
			||||||
	void loadIcons();
 | 
						void loadIcons();
 | 
				
			||||||
	void checkIcons();
 | 
						void checkIcons();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue