/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "data/stickers/data_stickers_set.h" #include "ui/text/custom_emoji_instance.h" #include "base/timer.h" #include "base/weak_ptr.h" namespace Main { class Session; } // namespace Main namespace Data { class Session; class CustomEmojiLoader; enum class CustomEmojiSizeTag : uchar { Normal, Large, Isolated, SetIcon, kCount, }; class CustomEmojiManager final : public base::has_weak_ptr { public: using SizeTag = CustomEmojiSizeTag; CustomEmojiManager(not_null owner); ~CustomEmojiManager(); [[nodiscard]] std::unique_ptr create( QStringView data, Fn update, SizeTag tag = SizeTag::Normal, int sizeOverride = 0); [[nodiscard]] std::unique_ptr create( DocumentId documentId, Fn update, SizeTag tag = SizeTag::Normal, int sizeOverride = 0); [[nodiscard]] std::unique_ptr create( not_null document, Fn update, SizeTag tag = SizeTag::Normal, int sizeOverride = 0); [[nodiscard]] Ui::Text::CustomEmojiFactory factory( SizeTag tag = SizeTag::Normal, int sizeOverride = 0); class Listener { public: virtual void customEmojiResolveDone( not_null document) = 0; }; void resolve(QStringView data, not_null listener); void resolve(DocumentId documentId, not_null listener); void unregisterListener(not_null listener); [[nodiscard]] rpl::producer> resolve( DocumentId documentId); [[nodiscard]] std::unique_ptr createLoader( not_null document, SizeTag tag, int sizeOverride = 0); [[nodiscard]] std::unique_ptr createLoader( DocumentId documentId, SizeTag tag, int sizeOverride = 0); [[nodiscard]] QString lookupSetName(uint64 setId); [[nodiscard]] Main::Session &session() const; [[nodiscard]] Session &owner() const; [[nodiscard]] uint64 coloredSetId() const; private: static constexpr auto kSizeCount = int(SizeTag::kCount); struct RepaintBunch { crl::time when = 0; std::vector> instances; }; struct LoaderWithSetId { std::unique_ptr loader; uint64 setId = 0; bool colored = false; }; [[nodiscard]] LoaderWithSetId createLoaderWithSetId( not_null document, SizeTag tag, int sizeOverride = 0); [[nodiscard]] LoaderWithSetId createLoaderWithSetId( DocumentId documentId, SizeTag tag, int sizeOverride = 0); void request(); void requestFinished(); void repaintLater( not_null instance, Ui::CustomEmoji::RepaintRequest request); void scheduleRepaintTimer(); bool checkEmptyRepaints(); void invokeRepaints(); void fillColoredFlags(not_null document); void processLoaders(not_null document); void processListeners(not_null document); void requestSetFor(not_null document); [[nodiscard]] Ui::CustomEmoji::Preview prepareNonExactPreview( DocumentId documentId, SizeTag tag, int sizeOverride) const; template [[nodiscard]] std::unique_ptr create( DocumentId documentId, Fn update, SizeTag tag, int sizeOverride, LoaderFactory factory); [[nodiscard]] static int SizeIndex(SizeTag tag); const not_null _owner; std::array< base::flat_map< DocumentId, std::unique_ptr>, kSizeCount> _instances; std::array< base::flat_map< DocumentId, std::vector>>, kSizeCount> _loaders; base::flat_map< DocumentId, base::flat_set>> _resolvers; base::flat_map< not_null, base::flat_set> _listeners; base::flat_set _pendingForRequest; mtpRequestId _requestId = 0; uint64 _coloredSetId = 0; base::flat_map _repaints; crl::time _repaintNext = 0; base::Timer _repaintTimer; bool _repaintTimerScheduled = false; bool _requestSetsScheduled = false; #if 0 // inject-to-on_main crl::time _repaintsLastAdded = 0; rpl::lifetime _repaintsLifetime; #endif rpl::lifetime _lifetime; }; [[nodiscard]] int FrameSizeFromTag(CustomEmojiManager::SizeTag tag); [[nodiscard]] QString SerializeCustomEmojiId(DocumentId id); [[nodiscard]] QString SerializeCustomEmojiId( not_null document); [[nodiscard]] DocumentId ParseCustomEmojiData(QStringView data); [[nodiscard]] TextWithEntities SingleCustomEmoji(DocumentId id); [[nodiscard]] TextWithEntities SingleCustomEmoji( not_null document); [[nodiscard]] bool AllowEmojiWithoutPremium(not_null peer); void InsertCustomEmoji( not_null field, not_null document); [[nodiscard]] Ui::Text::CustomEmojiFactory ReactedMenuFactory( not_null session); } // namespace Data