mirror of https://github.com/procxx/kepka.git
				
				
				
			Use Lottie::MultiPlayer in StickersListWidget.
This commit is contained in:
		
							parent
							
								
									09c9f4ef9a
								
							
						
					
					
						commit
						ad1816cb7c
					
				|  | @ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | |||
| #include "ui/toast/toast.h" | ||||
| #include "ui/emoji_config.h" | ||||
| #include "lottie/lottie_single_player.h" | ||||
| #include "lottie/lottie_multi_player.h" | ||||
| #include "styles/style_chat_helpers.h" | ||||
| 
 | ||||
| namespace Stickers { | ||||
|  | @ -1092,7 +1093,9 @@ RecentStickerPack &GetRecentPack() { | |||
| 	return cRefRecentStickers(); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | ||||
| template <typename Method> | ||||
| auto LottieFromDocument( | ||||
| 		Method &&method, | ||||
| 		not_null<DocumentData*> document, | ||||
| 		LottieSize sizeTag, | ||||
| 		QSize box) { | ||||
|  | @ -1100,7 +1103,7 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | |||
| 	const auto filepath = document->filepath(); | ||||
| 	if (box.width() & box.height() > kDontCacheLottieAfterArea) { | ||||
| 		// Don't use frame caching for large stickers.
 | ||||
| 		return std::make_unique<Lottie::SinglePlayer>( | ||||
| 		return method( | ||||
| 			Lottie::ReadContent(data, filepath), | ||||
| 			Lottie::FrameRequest{ box }); | ||||
| 	} | ||||
|  | @ -1120,15 +1123,37 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | |||
| 				weak->data().cacheBigFile().put(key, std::move(data)); | ||||
| 			}); | ||||
| 		}; | ||||
| 		return std::make_unique<Lottie::SinglePlayer>( | ||||
| 		return method( | ||||
| 			get, | ||||
| 			put, | ||||
| 			Lottie::ReadContent(data, filepath), | ||||
| 			Lottie::FrameRequest{ box }); | ||||
| 	} | ||||
| 	return std::make_unique<Lottie::SinglePlayer>( | ||||
| 	return method( | ||||
| 		Lottie::ReadContent(data, filepath), | ||||
| 		Lottie::FrameRequest{ box }); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | ||||
| 		not_null<DocumentData*> document, | ||||
| 		LottieSize sizeTag, | ||||
| 		QSize box) { | ||||
| 	const auto method = [](auto &&...args) { | ||||
| 		return std::make_unique<Lottie::SinglePlayer>( | ||||
| 			std::forward<decltype(args)>(args)...); | ||||
| 	}; | ||||
| 	return LottieFromDocument(method, document, sizeTag, box); | ||||
| } | ||||
| 
 | ||||
| not_null<Lottie::Animation*> LottieAnimationFromDocument( | ||||
| 		not_null<Lottie::MultiPlayer*> player, | ||||
| 		not_null<DocumentData*> document, | ||||
| 		LottieSize sizeTag, | ||||
| 		QSize box) { | ||||
| 	const auto method = [&](auto &&...args) { | ||||
| 		return player->append(std::forward<decltype(args)>(args)...); | ||||
| 	}; | ||||
| 	return LottieFromDocument(method, document, sizeTag, box); | ||||
| } | ||||
| 
 | ||||
| } // namespace Stickers
 | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ class DocumentData; | |||
| 
 | ||||
| namespace Lottie { | ||||
| class SinglePlayer; | ||||
| class MultiPlayer; | ||||
| class Animation; | ||||
| } // namespace Lottie
 | ||||
| 
 | ||||
| namespace Stickers { | ||||
|  | @ -119,5 +121,10 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | |||
| 	not_null<DocumentData*> document, | ||||
| 	LottieSize sizeTag, | ||||
| 	QSize box); | ||||
| not_null<Lottie::Animation*> LottieAnimationFromDocument( | ||||
| 	not_null<Lottie::MultiPlayer*> player, | ||||
| 	not_null<DocumentData*> document, | ||||
| 	LottieSize sizeTag, | ||||
| 	QSize box); | ||||
| 
 | ||||
| } // namespace Stickers
 | ||||
|  |  | |||
|  | @ -14,7 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | |||
| #include "ui/effects/animations.h" | ||||
| #include "ui/effects/ripple_animation.h" | ||||
| #include "ui/image/image.h" | ||||
| #include "lottie/lottie_single_player.h" | ||||
| #include "lottie/lottie_multi_player.h" | ||||
| #include "lottie/lottie_animation.h" | ||||
| #include "boxes/stickers_box.h" | ||||
| #include "inline_bots/inline_bot_result.h" | ||||
| #include "chat_helpers/stickers.h" | ||||
|  | @ -839,6 +840,7 @@ bool StickersListWidget::enumerateSections(Callback callback) const { | |||
| 
 | ||||
| StickersListWidget::SectionInfo StickersListWidget::sectionInfo(int section) const { | ||||
| 	Expects(section >= 0 && section < shownSets().size()); | ||||
| 
 | ||||
| 	auto result = SectionInfo(); | ||||
| 	enumerateSections([searchForSection = section, &result](const SectionInfo &info) { | ||||
| 		if (info.section == searchForSection) { | ||||
|  | @ -1200,6 +1202,13 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) { | |||
| 			return false; | ||||
| 		} | ||||
| 		auto &set = sets[info.section]; | ||||
| 		if (const auto player = set.lottiePlayer.get()) { | ||||
| 			const auto paused = controller()->isGifPausedAtLeastFor( | ||||
| 				Window::GifPauseReason::SavedGifs); | ||||
| 			if (!paused) { | ||||
| 				player->markFrameShown(); | ||||
| 			} | ||||
| 		} | ||||
| 		if (set.externalLayout) { | ||||
| 			const auto size = (set.flags | ||||
| 				& MTPDstickerSet_ClientFlag::f_not_loaded) | ||||
|  | @ -1364,21 +1373,41 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe | |||
| 	p.drawTextLeft(button.x() - (st::stickerGroupCategoryAdd.width / 2), button.y() + st::stickerGroupCategoryAdd.textTop, width(), _megagroupSetButtonText, _megagroupSetButtonTextWidth); | ||||
| } | ||||
| 
 | ||||
| void StickersListWidget::ensureLottiePlayer(Set &set) { | ||||
| 	if (set.lottiePlayer) { | ||||
| 		return; | ||||
| 	} | ||||
| 	set.lottiePlayer = std::make_unique<Lottie::MultiPlayer>( | ||||
| 		getLottieRenderer()); | ||||
| 	const auto raw = set.lottiePlayer.get(); | ||||
| 	set.lottiePlayer->updates( | ||||
| 	) | rpl::start_with_next([=] { | ||||
| 		const auto &sets = shownSets(); | ||||
| 
 | ||||
| 		enumerateSections([&](const SectionInfo &info) { | ||||
| 			if (shownSets()[info.section].lottiePlayer.get() == raw) { | ||||
| 				update( | ||||
| 					0, | ||||
| 					info.rowsTop, | ||||
| 					width(), | ||||
| 					info.rowsBottom - info.rowsTop); | ||||
| 				return false; | ||||
| 			} | ||||
| 			return true; | ||||
| 		}); | ||||
| 	}, lifetime()); | ||||
| } | ||||
| 
 | ||||
| void StickersListWidget::setupLottie(Set &set, int section, int index) { | ||||
| 	auto &sticker = set.stickers[index]; | ||||
| 	const auto document = sticker.document; | ||||
| 
 | ||||
| 	sticker.animated = Stickers::LottiePlayerFromDocument( | ||||
| 	ensureLottiePlayer(set); | ||||
| 	sticker.animated = Stickers::LottieAnimationFromDocument( | ||||
| 		set.lottiePlayer.get(), | ||||
| 		document, | ||||
| 		Stickers::LottieSize::StickersPanel, | ||||
| 		boundingBoxSize() * cIntRetinaFactor()); | ||||
| 	const auto animation = sticker.animated.get(); | ||||
| 
 | ||||
| 	animation->updates( | ||||
| 	) | rpl::start_with_next_error([=](Lottie::Update update) { | ||||
| 		rtlupdate(stickerRect(section, index)); | ||||
| 	}, [=](Lottie::Error error) { | ||||
| 	}, lifetime()); | ||||
| } | ||||
| 
 | ||||
| QSize StickersListWidget::boundingBoxSize() const { | ||||
|  | @ -1419,11 +1448,6 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, | |||
| 	if (sticker.animated && sticker.animated->ready()) { | ||||
| 		auto request = Lottie::FrameRequest(); | ||||
| 		request.box = boundingBoxSize() * cIntRetinaFactor(); | ||||
| 		const auto paused = controller()->isGifPausedAtLeastFor( | ||||
| 			Window::GifPauseReason::SavedGifs); | ||||
| 		if (!paused) { | ||||
| 			sticker.animated->markFrameShown(); | ||||
| 		} | ||||
| 		const auto frame = sticker.animated->frame(request); | ||||
| 		p.drawImage( | ||||
| 			QRect(ppos, frame.size() / cIntRetinaFactor()), | ||||
|  | @ -1787,7 +1811,7 @@ void StickersListWidget::refreshStickers() { | |||
| 	refreshFavedStickers(); | ||||
| 	refreshRecentStickers(false); | ||||
| 	refreshMegagroupStickers(GroupStickersPlace::Visible); | ||||
| 	for_const (auto setId, Auth().data().stickerSetsOrder()) { | ||||
| 	for (const auto setId : Auth().data().stickerSetsOrder()) { | ||||
| 		const auto externalLayout = false; | ||||
| 		appendSet(_mySets, setId, externalLayout, AppendSkip::Archived); | ||||
| 	} | ||||
|  | @ -1796,7 +1820,7 @@ void StickersListWidget::refreshStickers() { | |||
| 	_featuredSets.clear(); | ||||
| 	_featuredSets.reserve(Auth().data().featuredStickerSetsOrder().size()); | ||||
| 
 | ||||
| 	for_const (auto setId, Auth().data().featuredStickerSetsOrder()) { | ||||
| 	for (const auto setId : Auth().data().featuredStickerSetsOrder()) { | ||||
| 		const auto externalLayout = true; | ||||
| 		appendSet(_featuredSets, setId, externalLayout, AppendSkip::Installed); | ||||
| 	} | ||||
|  | @ -2311,6 +2335,16 @@ void StickersListWidget::showPreview() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| auto StickersListWidget::getLottieRenderer() | ||||
| -> std::shared_ptr<Lottie::FrameRenderer> { | ||||
| 	if (auto result = _lottieRenderer.lock()) { | ||||
| 		return result; | ||||
| 	} | ||||
| 	auto result = Lottie::MakeFrameRenderer(); | ||||
| 	_lottieRenderer = result; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| void StickersListWidget::showStickerSet(uint64 setId) { | ||||
| 	clearSelection(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,7 +22,9 @@ class RippleAnimation; | |||
| } // namespace Ui
 | ||||
| 
 | ||||
| namespace Lottie { | ||||
| class SinglePlayer; | ||||
| class Animation; | ||||
| class MultiPlayer; | ||||
| class FrameRenderer; | ||||
| } // namespace Lottie
 | ||||
| 
 | ||||
| namespace ChatHelpers { | ||||
|  | @ -141,7 +143,7 @@ private: | |||
| 
 | ||||
| 	struct Sticker { | ||||
| 		not_null<DocumentData*> document; | ||||
| 		std::unique_ptr<Lottie::SinglePlayer> animated; | ||||
| 		Lottie::Animation *animated = nullptr; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct Set { | ||||
|  | @ -165,6 +167,7 @@ private: | |||
| 		ImagePtr thumbnail; | ||||
| 		std::vector<Sticker> stickers; | ||||
| 		std::unique_ptr<Ui::RippleAnimation> ripple; | ||||
| 		std::unique_ptr<Lottie::MultiPlayer> lottiePlayer; | ||||
| 		bool externalLayout = false; | ||||
| 		int count = 0; | ||||
| 	}; | ||||
|  | @ -223,6 +226,8 @@ private: | |||
| 	void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected); | ||||
| 	void paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected); | ||||
| 	void paintEmptySearchResults(Painter &p); | ||||
| 
 | ||||
| 	void ensureLottiePlayer(Set &set); | ||||
| 	void setupLottie(Set &set, int section, int index); | ||||
| 
 | ||||
| 	int stickersRight() const; | ||||
|  | @ -265,6 +270,8 @@ private: | |||
| 
 | ||||
| 	void showPreview(); | ||||
| 
 | ||||
| 	std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer(); | ||||
| 
 | ||||
| 	ChannelData *_megagroupSet = nullptr; | ||||
| 	uint64 _megagroupSetIdRequested = 0; | ||||
| 	std::vector<Set> _mySets; | ||||
|  | @ -273,6 +280,7 @@ private: | |||
| 	base::flat_set<uint64> _installedLocallySets; | ||||
| 	std::vector<bool> _custom; | ||||
| 	base::flat_set<not_null<DocumentData*>> _favedStickersMap; | ||||
| 	std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer; | ||||
| 
 | ||||
| 	Section _section = Section::Stickers; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue