From c51837cfdfe25a0fecfde8130c52a8e4022fa02c Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 25 Jul 2022 11:30:38 +0300 Subject: [PATCH] Reuse SizeTag::Large emoji instances. --- .../SourceFiles/boxes/sticker_set_box.cpp | 35 ++- .../chat_helpers/emoji_list_widget.cpp | 216 +++++------------- .../chat_helpers/emoji_list_widget.h | 34 +-- .../chat_helpers/emoji_suggestions_widget.cpp | 29 ++- .../chat_helpers/emoji_suggestions_widget.h | 15 +- .../data/stickers/data_custom_emoji.cpp | 70 ++++-- .../data/stickers/data_custom_emoji.h | 23 +- .../ui/text/custom_emoji_instance.cpp | 80 ------- .../ui/text/custom_emoji_instance.h | 30 --- 9 files changed, 178 insertions(+), 354 deletions(-) diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index e2148ac39..d765dbf22 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -156,13 +156,12 @@ protected: void leaveEventHook(QEvent *e) override; private: - using CustomInstance = Ui::CustomEmoji::SeparateInstance; struct Element { not_null document; std::shared_ptr documentMedia; Lottie::Animation *lottie = nullptr; Media::Clip::ReaderPointer webm; - CustomInstance *emoji = nullptr; + Ui::Text::CustomEmoji *emoji = nullptr; Ui::Animations::Simple overAnimation; mutable QImage premiumLock; @@ -185,7 +184,7 @@ private: not_null document, int index); void setupEmoji(int index); - [[nodiscard]] not_null resolveCustomInstance( + [[nodiscard]] not_null resolveCustomEmoji( not_null document); void customEmojiRepaint(); @@ -213,8 +212,7 @@ private: base::flat_map< not_null, - std::unique_ptr> _instances; - std::unique_ptr _manager; + std::unique_ptr> _customEmoji; bool _repaintScheduled = false; StickersPack _pack; @@ -515,7 +513,6 @@ StickerSetBox::Inner::Inner( : RpWidget(parent) , _controller(controller) , _api(&_controller->session().mtp()) -, _manager(std::make_unique()) , _setId(set.id) , _setAccessHash(set.accessHash) , _setShortName(set.shortName) @@ -1098,24 +1095,22 @@ void StickerSetBox::Inner::clipCallback( void StickerSetBox::Inner::setupEmoji(int index) { auto &element = _elements[index]; - element.emoji = resolveCustomInstance(element.document); + element.emoji = resolveCustomEmoji(element.document); } -auto StickerSetBox::Inner::resolveCustomInstance( - not_null document) --> not_null { - const auto i = _instances.find(document); - if (i != end(_instances)) { +not_null StickerSetBox::Inner::resolveCustomEmoji( + not_null document) { + const auto i = _customEmoji.find(document); + if (i != end(_customEmoji)) { return i->second.get(); } - auto instance = _manager->make( - _controller->session().data().customEmojiManager().createLoader( - document, - Data::CustomEmojiManager::SizeTag::Large), - [=] { customEmojiRepaint(); }); - return _instances.emplace( + auto emoji = document->session().data().customEmojiManager().create( document, - std::move(instance) + [=] { customEmojiRepaint(); }, + Data::CustomEmojiManager::SizeTag::Large); + return _customEmoji.emplace( + document, + std::move(emoji) ).first->second.get(); } @@ -1167,7 +1162,7 @@ void StickerSetBox::Inner::paintSticker( (_singleSize.height() - size.height()) / 2); auto lottieFrame = QImage(); if (element.emoji) { - element.emoji->object.paint( + element.emoji->paint( p, ppos.x(), ppos.y(), diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index 941217613..ccb7d719b 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -100,14 +100,13 @@ private: }; -struct EmojiListWidget::CustomInstance : Ui::CustomEmoji::SeparateInstance { - using SeparateInstance::SeparateInstance; - +struct EmojiListWidget::CustomEmojiInstance { + std::unique_ptr emoji; bool recentOnly = false; }; struct EmojiListWidget::RecentOne { - CustomInstance *instance = nullptr; + Ui::Text::CustomEmoji *custom = nullptr; RecentEmojiId id; }; @@ -371,8 +370,7 @@ EmojiListWidget::EmojiListWidget( std::make_unique(&controller->session())) , _collapsedBg(st::emojiPanExpand.height / 2, st::emojiPanHeaderFg) , _picker(this) -, _showPickerTimer([=] { showPicker(); }) -, _repaintTimer([=] { invokeRepaints(); }) { +, _showPickerTimer([=] { showPicker(); }) { setMouseTracking(true); setAttribute(Qt::WA_OpaquePaintEvent); @@ -419,88 +417,20 @@ EmojiListWidget::EmojiListWidget( } EmojiListWidget::~EmojiListWidget() { - base::take(_instances); - base::take(_repaints); + base::take(_customEmoji); } -void EmojiListWidget::repaintLater( - DocumentId documentId, - uint64 setId, - Ui::CustomEmoji::RepaintRequest request) { - if (_instances.empty() || !request.when) { +void EmojiListWidget::repaintCustom(uint64 setId) { + if (!_repaintsScheduled.emplace(setId).second) { return; } - auto &repaint = _repaints[request.duration]; - if (repaint.when < request.when) { - repaint.when = request.when; - } - if (setId) { - repaint.ids.emplace(setId); - } - if (_recentCustomIds.contains(documentId)) { - repaint.ids.emplace(RecentEmojiSectionSetId()); - } - scheduleRepaintTimer(); -} - -void EmojiListWidget::scheduleRepaintTimer() { - if (_repaintTimerScheduled) { - return; - } - _repaintTimerScheduled = true; - Ui::PostponeCall(this, [=] { - _repaintTimerScheduled = false; - - auto next = crl::time(); - for (const auto &[duration, bunch] : _repaints) { - if (!next || next > bunch.when) { - next = bunch.when; - } - } - if (next && (!_repaintNext || _repaintNext > next)) { - const auto now = crl::now(); - if (now >= next) { - _repaintNext = 0; - _repaintTimer.cancel(); - invokeRepaints(); - } else { - _repaintNext = next; - _repaintTimer.callOnce(next - now); - } - } - }); -} - -void EmojiListWidget::invokeRepaints() { - _repaintNext = 0; - auto ids = base::flat_set(); - const auto now = crl::now(); - for (auto i = begin(_repaints); i != end(_repaints);) { - if (i->second.when > now) { - ++i; - continue; - } - if (ids.empty()) { - ids = std::move(i->second.ids); - } else { - for (const auto id : i->second.ids) { - ids.emplace(id); - } - } - i = _repaints.erase(i); - } - repaintCustom([&](uint64 id) { return ids.contains(id); }); - scheduleRepaintTimer(); -} - -template -void EmojiListWidget::repaintCustom(CheckId checkId) { + const auto repaintRecent = (setId == RecentEmojiSectionSetId()); enumerateSections([&](const SectionInfo &info) { - const auto repaint1 = (info.section == int(Section::Recent)) - && checkId(RecentEmojiSectionSetId()); + const auto repaint1 = repaintRecent + && (info.section == int(Section::Recent)); const auto repaint2 = !repaint1 && (info.section >= kEmojiSectionCount) - && checkId(_custom[info.section - kEmojiSectionCount].id); + && (setId == _custom[info.section - kEmojiSectionCount].id); if (repaint1 || repaint2) { update( 0, @@ -555,8 +485,8 @@ void EmojiListWidget::unloadCustomIn(const SectionInfo &info) { if (!info.section && _recentPainted) { _recentPainted = false; for (const auto &single : _recent) { - if (const auto instance = single.instance) { - instance->object.unload(); + if (const auto custom = single.custom) { + custom->unload(); } } return; @@ -569,7 +499,7 @@ void EmojiListWidget::unloadCustomIn(const SectionInfo &info) { } custom.painted = false; for (const auto &single : custom.list) { - single.instance->object.unload(); + single.custom->unload(); } } @@ -742,7 +672,7 @@ void EmojiListWidget::fillRecent() { continue; } _recent.push_back({ - .instance = resolveCustomInstance(one.id), + .custom = resolveCustomEmoji(one.id), .id = one.id, }); if (document) { @@ -756,7 +686,10 @@ void EmojiListWidget::fillRecent() { void EmojiListWidget::paintEvent(QPaintEvent *e) { Painter p(this); - QRect r = e ? e->rect() : rect(); + + _repaintsScheduled.clear(); + + const auto r = e ? e->rect() : rect(); if (r != rect()) { p.setClipRect(r); } @@ -897,9 +830,9 @@ void EmojiListWidget::drawRecent( if (const auto emoji = std::get_if(&_recent[index].id.data)) { drawEmoji(p, position, *emoji); } else { - Assert(_recent[index].instance != nullptr); + Assert(_recent[index].custom != nullptr); position += _innerPosition; - _recent[index].instance->object.paint( + _recent[index].custom->paint( p, position.x(), position.y(), @@ -931,7 +864,7 @@ void EmojiListWidget::drawCustom( int index) { position += _innerPosition; _custom[set].painted = true; - _custom[set].list[index].instance->object.paint( + _custom[set].list[index].custom->paint( p, position.x(), position.y(), @@ -1408,7 +1341,7 @@ void EmojiListWidget::refreshCustom() { for (const auto document : list) { if (document->sticker()) { set.push_back({ - .instance = resolveCustomInstance(document, setId), + .custom = resolveCustomEmoji(document, setId), .document = document, }); if (!premium && document->isPremiumEmoji()) { @@ -1443,98 +1376,75 @@ void EmojiListWidget::refreshCustom() { update(); } -auto EmojiListWidget::customInstanceWithLoader( - std::unique_ptr loader, - DocumentId documentId, - uint64 setId) --> std::unique_ptr { - const auto recentOnly = (setId == RecentEmojiSectionSetId()); - const auto repaintDelayedSetId = !recentOnly ? setId : uint64(0); - const auto repaintDelayed = [=]( - not_null instance, - Ui::CustomEmoji::RepaintRequest request) { - repaintLater(documentId, repaintDelayedSetId, request); - }; - const auto repaintNow = [=] { +Fn EmojiListWidget::repaintCallback( + DocumentId documentId, + uint64 setId) { + return [=] { + repaintCustom(setId); if (_recentCustomIds.contains(documentId)) { - const auto recentSetId = RecentEmojiSectionSetId(); - repaintCustom([&](uint64 id) { - return (id == setId) || (id == recentSetId); - }); - } else { - repaintCustom([&](uint64 id) { - return (id == setId); - }); + repaintCustom(RecentEmojiSectionSetId()); } }; - auto result = std::make_unique( - std::move(loader), - std::move(repaintDelayed), - std::move(repaintNow)); - result->recentOnly = recentOnly; - return result; } -auto EmojiListWidget::resolveCustomInstance( - not_null document, - uint64 setId) --> not_null { +not_null EmojiListWidget::resolveCustomEmoji( + not_null document, + uint64 setId) { Expects(document->sticker() != nullptr); const auto documentId = document->id; - const auto i = _instances.find(documentId); - const auto recentOnly = (i != end(_instances)) && i->second->recentOnly; - if (i != end(_instances) && !recentOnly) { - return i->second.get(); + const auto i = _customEmoji.find(documentId); + const auto recentOnly = (i != end(_customEmoji)) && i->second.recentOnly; + if (i != end(_customEmoji) && !recentOnly) { + return i->second.emoji.get(); } - auto instance = customInstanceWithLoader( - document->owner().customEmojiManager().createLoader( - document, - Data::CustomEmojiManager::SizeTag::Large), - documentId, - setId); + auto instance = document->owner().customEmojiManager().create( + document, + repaintCallback(documentId, setId), + Data::CustomEmojiManager::SizeTag::Large); if (recentOnly) { for (auto &recent : _recent) { - if (recent.instance && recent.instance == i->second.get()) { - recent.instance = instance.get(); + if (recent.custom && recent.custom == i->second.emoji.get()) { + recent.custom = instance.get(); } } - i->second = std::move(instance); - return i->second.get(); + i->second.emoji = std::move(instance); + i->second.recentOnly = false; + return i->second.emoji.get(); } - return _instances.emplace( + return _customEmoji.emplace( documentId, - std::move(instance)).first->second.get(); + CustomEmojiInstance{ .emoji = std::move(instance) } + ).first->second.emoji.get(); } -auto EmojiListWidget::resolveCustomInstance( - RecentEmojiId customId) --> CustomInstance* { +Ui::Text::CustomEmoji *EmojiListWidget::resolveCustomEmoji( + RecentEmojiId customId) { const auto &data = customId.data; if (const auto document = std::get_if(&data)) { - return resolveCustomInstance(document->id); + return resolveCustomEmoji(document->id); } else if (const auto emoji = std::get_if(&data)) { return nullptr; } Unexpected("Custom recent emoji id."); } -auto EmojiListWidget::resolveCustomInstance( - DocumentId documentId) --> not_null { - const auto i = _instances.find(documentId); - if (i != end(_instances)) { - return i->second.get(); +not_null EmojiListWidget::resolveCustomEmoji( + DocumentId documentId) { + const auto i = _customEmoji.find(documentId); + if (i != end(_customEmoji)) { + return i->second.emoji.get(); } - return _instances.emplace( + return _customEmoji.emplace( documentId, - customInstanceWithLoader( - session().data().customEmojiManager().createLoader( + CustomEmojiInstance{ + .emoji = session().data().customEmojiManager().create( documentId, + repaintCallback(documentId, RecentEmojiSectionSetId()), Data::CustomEmojiManager::SizeTag::Large), - documentId, - RecentEmojiSectionSetId()) - ).first->second.get(); + .recentOnly = true, + } + ).first->second.emoji.get(); } std::vector EmojiListWidget::fillIcons() { diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h index 16f956f7d..fe8b722f7 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h @@ -112,9 +112,8 @@ private: bool premiumRequired = false; bool collapsed = false; }; - struct CustomInstance; struct CustomOne { - not_null instance; + not_null custom; not_null document; }; struct CustomSet { @@ -129,6 +128,7 @@ private: bool canRemove = false; bool premiumRequired = false; }; + struct CustomEmojiInstance; struct RightButton { QImage back; QImage backOver; @@ -137,10 +137,6 @@ private: int textWidth = 0; }; struct RecentOne; - struct RepaintSet { - base::flat_set ids; - crl::time when = 0; - }; struct OverEmoji { int section = 0; int index = 0; @@ -253,25 +249,17 @@ private: int section); [[nodiscard]] QPoint buttonRippleTopLeft(int section) const; - void repaintLater( - DocumentId documentId, - uint64 setId, - Ui::CustomEmoji::RepaintRequest request); - template - void repaintCustom(CheckId checkId); - void scheduleRepaintTimer(); - void invokeRepaints(); + void repaintCustom(uint64 setId); void fillRecent(); - [[nodiscard]] not_null resolveCustomInstance( + [[nodiscard]] not_null resolveCustomEmoji( not_null document, uint64 setId); - [[nodiscard]] CustomInstance *resolveCustomInstance( + [[nodiscard]] Ui::Text::CustomEmoji *resolveCustomEmoji( Core::RecentEmojiId customId); - [[nodiscard]] not_null resolveCustomInstance( + [[nodiscard]] not_null resolveCustomEmoji( DocumentId documentId); - [[nodiscard]] std::unique_ptr customInstanceWithLoader( - std::unique_ptr loader, + [[nodiscard]] Fn repaintCallback( DocumentId documentId, uint64 setId); @@ -281,10 +269,11 @@ private: int _counts[kEmojiSectionCount]; std::vector _recent; base::flat_set _recentCustomIds; + base::flat_set _repaintsScheduled; bool _recentPainted = false; QVector _emoji[kEmojiSectionCount]; std::vector _custom; - base::flat_map> _instances; + base::flat_map _customEmoji; int _rowsLeft = 0; int _columnCount = 1; @@ -305,11 +294,6 @@ private: object_ptr _picker; base::Timer _showPickerTimer; - base::flat_map _repaints; - bool _repaintTimerScheduled = false; - base::Timer _repaintTimer; - crl::time _repaintNext = 0; - rpl::event_stream _chosen; rpl::event_stream _customChosen; diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index 44c1bd34b..3c63ab0bc 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -46,7 +46,6 @@ SuggestionsWidget::SuggestionsWidget( not_null session) : RpWidget(parent) , _session(session) -, _manager(std::make_unique()) , _oneWidth(st::emojiSuggestionSize) , _padding(st::emojiSuggestionsPadding) { resize( @@ -141,7 +140,7 @@ auto SuggestionsWidget::prependCustom(std::vector rows) for (const auto &[position, one] : custom) { result.push_back(Row(one.emoji, one.replacement)); result.back().document = one.document; - result.back().instance = resolveCustomInstance(one.document); + result.back().custom = resolveCustomEmoji(one.document); } for (auto &row : rows) { result.push_back(std::move(row)); @@ -149,21 +148,19 @@ auto SuggestionsWidget::prependCustom(std::vector rows) return result; } -auto SuggestionsWidget::resolveCustomInstance( - not_null document) --> not_null { - const auto i = _instances.find(document); - if (i != end(_instances)) { +not_null SuggestionsWidget::resolveCustomEmoji( + not_null document) { + const auto i = _customEmoji.find(document); + if (i != end(_customEmoji)) { return i->second.get(); } - auto instance = _manager->make( - _session->data().customEmojiManager().createLoader( - document, - Data::CustomEmojiManager::SizeTag::Large), - [=] { customEmojiRepaint(); }); - return _instances.emplace( + auto emoji = document->session().data().customEmojiManager().create( document, - std::move(instance) + [=] { customEmojiRepaint(); }, + Data::CustomEmojiManager::SizeTag::Large); + return _customEmoji.emplace( + document, + std::move(emoji) ).first->second.get(); } @@ -333,8 +330,8 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) { const auto size = esize / style::DevicePixelRatio(); const auto x = i * _oneWidth + (_oneWidth - size) / 2; const auto y = (_oneWidth - size) / 2; - if (row.instance) { - row.instance->object.paint(p, x, y, now, preview, false); + if (row.custom) { + row.custom->paint(p, x, y, now, preview, false); } else { Ui::Emoji::Draw(p, emoji, esize, x, y); } diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h index 1ca1adde6..5f6829c5c 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.h @@ -23,10 +23,9 @@ class InnerDropdown; class InputField; } // namespace Ui -namespace Ui::CustomEmoji { -struct SeparateInstance; -class SimpleManager; -} // namespace Ui::CustomEmoji +namespace Ui::Text { +class CustomEmoji; +} // namespace Ui::Text namespace Ui::Emoji { @@ -48,11 +47,10 @@ public: [[nodiscard]] rpl::producer triggered() const; private: - using CustomInstance = Ui::CustomEmoji::SeparateInstance; struct Row { Row(not_null emoji, const QString &replacement); - CustomInstance *instance = nullptr; + Ui::Text::CustomEmoji *custom = nullptr; DocumentData *document = nullptr; not_null emoji; QString replacement; @@ -92,7 +90,7 @@ private: void scrollTo(int value, anim::type animated = anim::type::instant); void stopAnimations(); - [[nodiscard]] not_null resolveCustomInstance( + [[nodiscard]] not_null resolveCustomEmoji( not_null document); void customEmojiRepaint(); @@ -102,8 +100,7 @@ private: base::flat_map< not_null, - std::unique_ptr> _instances; - std::unique_ptr _manager; + std::unique_ptr> _customEmoji; bool _repaintScheduled = false; std::optional _lastMousePosition; diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index 060ec770d..a4ca43419 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -361,35 +361,59 @@ CustomEmojiManager::CustomEmojiManager(not_null owner) CustomEmojiManager::~CustomEmojiManager() = default; +template std::unique_ptr CustomEmojiManager::create( - QStringView data, - Fn update) { - const auto parsed = ParseCustomEmojiData(data); - if (!parsed.id) { - return nullptr; - } - auto i = _instances.find(parsed.id); - if (i == end(_instances)) { + DocumentId documentId, + Fn update, + SizeTag tag, + LoaderFactory factory) { + auto &instances = _instances[SizeIndex(tag)]; + auto i = instances.find(documentId); + if (i == end(instances)) { using Loading = Ui::CustomEmoji::Loading; - auto loader = createLoader(parsed.id, SizeTag::Normal); const auto repaint = [=]( not_null instance, Ui::CustomEmoji::RepaintRequest request) { repaintLater(instance, request); }; - i = _instances.emplace( - parsed.id, + i = instances.emplace( + documentId, std::make_unique(Loading{ - std::move(loader), + factory(), Ui::CustomEmoji::Preview() }, std::move(repaint))).first; } - return std::make_unique( i->second.get(), std::move(update)); } +std::unique_ptr CustomEmojiManager::create( + QStringView data, + Fn update, + SizeTag tag) { + const auto parsed = ParseCustomEmojiData(data); + return parsed.id ? create(parsed.id, std::move(update), tag) : nullptr; +} + +std::unique_ptr CustomEmojiManager::create( + DocumentId documentId, + Fn update, + SizeTag tag) { + return create(documentId, std::move(update), tag, [&] { + return createLoader(documentId, tag); + }); +} + +std::unique_ptr CustomEmojiManager::create( + not_null document, + Fn update, + SizeTag tag) { + return create(document->id, std::move(update), tag, [&] { + return createLoader(document, tag); + }); +} + std::unique_ptr CustomEmojiManager::createLoader( not_null document, SizeTag tag) { @@ -405,7 +429,8 @@ std::unique_ptr CustomEmojiManager::createLoader( CustomEmojiId{ .selfId = selfId, .id = documentId }, tag); if (result->resolving()) { - _loaders[documentId].push_back(base::make_weak(result.get())); + const auto i = SizeIndex(tag); + _loaders[i][documentId].push_back(base::make_weak(result.get())); _pendingForRequest.emplace(documentId); if (!_requestId && _pendingForRequest.size() == 1) { crl::on_main(this, [=] { request(); }); @@ -439,10 +464,12 @@ void CustomEmojiManager::request() { for (const auto &entry : result.v) { const auto document = _owner->processDocument(entry); const auto id = document->id; - if (const auto loaders = _loaders.take(id)) { - for (const auto &weak : *loaders) { - if (const auto strong = weak.get()) { - strong->resolved(document); + for (auto &loaders : _loaders) { + if (const auto list = loaders.take(id)) { + for (const auto &weak : *list) { + if (const auto strong = weak.get()) { + strong->resolved(document); + } } } } @@ -479,6 +506,13 @@ void CustomEmojiManager::requestSetFor(not_null document) { }); } +int CustomEmojiManager::SizeIndex(SizeTag tag) { + const auto result = static_cast(tag); + + Ensures(result >= 0 && result < 2); + return result; +} + void CustomEmojiManager::requestFinished() { _requestId = 0; if (!_pendingForRequest.empty()) { diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h index 160c2be87..a203fb62e 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h @@ -40,7 +40,16 @@ public: [[nodiscard]] std::unique_ptr create( QStringView data, - Fn update); + Fn update, + SizeTag tag = SizeTag::Normal); + [[nodiscard]] std::unique_ptr create( + DocumentId documentId, + Fn update, + SizeTag tag = SizeTag::Normal); + [[nodiscard]] std::unique_ptr create( + not_null document, + Fn update, + SizeTag tag = SizeTag::Normal); [[nodiscard]] std::unique_ptr createLoader( not_null document, @@ -69,14 +78,22 @@ private: void invokeRepaints(); void requestSetFor(not_null document); + template + [[nodiscard]] std::unique_ptr create( + DocumentId documentId, + Fn update, + SizeTag tag, + LoaderFactory factory); + [[nodiscard]] static int SizeIndex(SizeTag tag); + const not_null _owner; base::flat_map< uint64, - std::unique_ptr> _instances; + std::unique_ptr> _instances[2]; base::flat_map< uint64, - std::vector>> _loaders; + std::vector>> _loaders[2]; base::flat_set _pendingForRequest; mtpRequestId _requestId = 0; diff --git a/Telegram/SourceFiles/ui/text/custom_emoji_instance.cpp b/Telegram/SourceFiles/ui/text/custom_emoji_instance.cpp index f82c289ac..f646f59ee 100644 --- a/Telegram/SourceFiles/ui/text/custom_emoji_instance.cpp +++ b/Telegram/SourceFiles/ui/text/custom_emoji_instance.cpp @@ -648,84 +648,4 @@ void Object::repaint() { _repaint(); } -SeparateInstance::SeparateInstance( - std::unique_ptr loader, - Fn, RepaintRequest)> repaintLater, - Fn repaint) -: emoji(Loading(std::move(loader), Preview()), std::move(repaintLater)) -, object(&emoji, std::move(repaint)) { -} - -SimpleManager::SimpleManager() -: _repaintTimer([=] { invokeRepaints(); }) { -} - -std::unique_ptr SimpleManager::make( - std::unique_ptr loader, - Fn repaint) { - auto repaintLater = [=]( - not_null instance, - RepaintRequest request) { - if (!request.when) { - return; - } - auto &when = _repaints[request.duration]; - if (when < request.when) { - when = request.when; - } - if (_repaintTimerScheduled) { - return; - } - scheduleRepaintTimer(); - }; - _simpleRepaint = repaint; - return std::make_unique( - std::move(loader), - std::move(repaintLater), - std::move(repaint)); -} - -void SimpleManager::scheduleRepaintTimer() { - _repaintTimerScheduled = true; - Ui::PostponeCall(this, [=] { - _repaintTimerScheduled = false; - - auto next = crl::time(); - for (const auto &[duration, when] : _repaints) { - if (!next || next > when) { - next = when; - } - } - if (next && (!_repaintNext || _repaintNext > next)) { - const auto now = crl::now(); - if (now >= next) { - _repaintNext = 0; - _repaintTimer.cancel(); - invokeRepaints(); - } else { - _repaintNext = next; - _repaintTimer.callOnce(next - now); - } - } - }); -} - -void SimpleManager::invokeRepaints() { - _repaintNext = 0; - auto invoke = false; - const auto now = crl::now(); - for (auto i = begin(_repaints); i != end(_repaints);) { - if (i->second > now) { - ++i; - continue; - } - invoke = true; - i = _repaints.erase(i); - } - if (invoke && _simpleRepaint) { - _simpleRepaint(); - } - scheduleRepaintTimer(); -} - } // namespace Ui::CustomEmoji diff --git a/Telegram/SourceFiles/ui/text/custom_emoji_instance.h b/Telegram/SourceFiles/ui/text/custom_emoji_instance.h index 3072b0f63..5722f0d22 100644 --- a/Telegram/SourceFiles/ui/text/custom_emoji_instance.h +++ b/Telegram/SourceFiles/ui/text/custom_emoji_instance.h @@ -267,34 +267,4 @@ private: }; -struct SeparateInstance { - SeparateInstance( - std::unique_ptr loader, - Fn, RepaintRequest)> repaintLater, - Fn repaint); - - Instance emoji; - Object object; -}; - -class SimpleManager final : public base::has_weak_ptr { -public: - SimpleManager(); - - [[nodiscard]] std::unique_ptr make( - std::unique_ptr loader, - Fn repaint); - -private: - void scheduleRepaintTimer(); - void invokeRepaints(); - - base::flat_map _repaints; - bool _repaintTimerScheduled = false; - crl::time _repaintNext = 0; - base::Timer _repaintTimer; - Fn _simpleRepaint; - -}; - } // namespace Ui::CustomEmoji