From e032dbf38345f085db050a4682ac114a72dbfa5a Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 10 Jan 2022 23:44:05 +0300 Subject: [PATCH] Cache reaction lottie in Window::SessionController. --- .../history/history_inner_widget.cpp | 3 +- .../history/view/history_view_list_widget.cpp | 3 +- .../view/history_view_react_button.cpp | 46 ++++++++++++------- .../history/view/history_view_react_button.h | 27 ++++++++++- .../window/window_session_controller.cpp | 4 +- .../window/window_session_controller.h | 12 +++++ 6 files changed, 75 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 951690655..6f25a2a81 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -323,7 +323,8 @@ HistoryInner::HistoryInner( std::make_unique( this, Data::UniqueReactionsLimitValue(&controller->session()), - [=](QRect updated) { update(updated); })) + [=](QRect updated) { update(updated); }, + controller->cachedReactionIconFactory().createMethod())) , _touchSelectTimer([=] { onTouchSelect(); }) , _touchScrollTimer([=] { onTouchScrollTimer(); }) , _scrollDateCheck([this] { scrollDateCheck(); }) diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 728eda911..3f6e962d5 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -269,7 +269,8 @@ ListWidget::ListWidget( std::make_unique( this, Data::UniqueReactionsLimitValue(&controller->session()), - [=](QRect updated) { update(updated); })) + [=](QRect updated) { update(updated); }, + controller->cachedReactionIconFactory().createMethod())) , _scrollDateCheck([this] { scrollDateCheck(); }) , _applyUpdatedScrollState([this] { applyUpdatedScrollState(); }) , _selectEnabled(_delegate->listAllowsMultiSelect()) diff --git a/Telegram/SourceFiles/history/view/history_view_react_button.cpp b/Telegram/SourceFiles/history/view/history_view_react_button.cpp index 4a7f84239..2f2dc59b2 100644 --- a/Telegram/SourceFiles/history/view/history_view_react_button.cpp +++ b/Telegram/SourceFiles/history/view/history_view_react_button.cpp @@ -70,18 +70,6 @@ constexpr auto kHoverScale = 1.24; return style::ConvertScale(kSizeForDownscale); } -[[nodiscard]] std::shared_ptr CreateIcon( - not_null media, - int size) { - Expects(media->loaded()); - - return std::make_shared(Lottie::IconDescriptor{ - .path = media->owner()->filepath(true), - .json = media->bytes(), - .sizeOverride = QSize(size, size), - }); -} - } // namespace Button::Button( @@ -332,8 +320,10 @@ float64 Button::currentOpacity() const { Manager::Manager( QWidget *wheelEventsTarget, rpl::producer uniqueLimitValue, - Fn buttonUpdate) -: _outer(CountOuterSize()) + Fn buttonUpdate, + IconFactory iconFactory) +: _iconFactory(std::move(iconFactory)) +, _outer(CountOuterSize()) , _inner(QRect({}, st::reactionCornerSize)) , _overlayFull( QRect(0, 0, _inner.width(), _inner.width()).marginsAdded( @@ -601,7 +591,7 @@ void Manager::setMainReactionIcon() { } } _mainReactionImage = QImage(); - _mainReactionIcon = CreateIcon( + _mainReactionIcon = DefaultIconFactory( _mainReactionMedia.get(), MainReactionSize()); } @@ -632,7 +622,7 @@ bool Manager::checkIconLoaded(ReactionDocument &entry) const { const auto size = (entry.media == _mainReactionMedia) ? MainReactionSize() : CornerImageSize(1.); - entry.icon = CreateIcon(entry.media.get(), size); + entry.icon = _iconFactory(entry.media.get(), size); entry.media = nullptr; return true; } @@ -1464,4 +1454,28 @@ void SetupManagerList( }, manager->lifetime()); } +IconFactory CachedIconFactory::createMethod() { + return [=](not_null media, int size) { + const auto owned = media->owner()->createMediaView(); + const auto i = _cache.find(owned); + return (i != end(_cache)) + ? i->second + : _cache.emplace( + owned, + DefaultIconFactory(media, size)).first->second; + }; +} + +std::shared_ptr DefaultIconFactory( + not_null media, + int size) { + Expects(media->loaded()); + + return std::make_shared(Lottie::IconDescriptor{ + .path = media->owner()->filepath(true), + .json = media->bytes(), + .sizeOverride = QSize(size, size), + }); +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_react_button.h b/Telegram/SourceFiles/history/view/history_view_react_button.h index 25d35ea10..cfb2518fd 100644 --- a/Telegram/SourceFiles/history/view/history_view_react_button.h +++ b/Telegram/SourceFiles/history/view/history_view_react_button.h @@ -127,12 +127,17 @@ private: }; +using IconFactory = Fn( + not_null, + int)>; + class Manager final : public base::has_weak_ptr { public: Manager( QWidget *wheelEventsTarget, rpl::producer uniqueLimitValue, - Fn buttonUpdate); + Fn buttonUpdate, + IconFactory iconFactory); ~Manager(); void applyList(const std::vector &list); @@ -273,6 +278,7 @@ private: void loadIcons(); void checkIcons(); + const IconFactory _iconFactory; rpl::event_stream _chosen; std::vector _list; std::optional> _filter; @@ -324,9 +330,28 @@ private: }; +class CachedIconFactory final { +public: + CachedIconFactory() = default; + CachedIconFactory(const CachedIconFactory &other) = delete; + CachedIconFactory &operator=(const CachedIconFactory &other) = delete; + + [[nodiscard]] IconFactory createMethod(); + +private: + base::flat_map< + std::shared_ptr, + std::shared_ptr> _cache; + +}; + void SetupManagerList( not_null manager, not_null session, rpl::producer>> filter); +[[nodiscard]] std::shared_ptr DefaultIconFactory( + not_null media, + int size); + } // namespace HistoryView diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 22444e448..fcde0abd3 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/history_item.h" #include "history/view/history_view_replies_section.h" +#include "history/view/history_view_react_button.h" #include "history/view/history_view_reactions.h" #include "media/player/media_player_instance.h" #include "media/view/media_view_open_common.h" @@ -530,7 +531,8 @@ SessionController::SessionController( this)) , _invitePeekTimer([=] { checkInvitePeek(); }) , _defaultChatTheme(std::make_shared()) -, _chatStyle(std::make_unique()) { +, _chatStyle(std::make_unique()) +, _cachedReactionIconFactory(std::make_unique()) { init(); _chatStyleTheme = _defaultChatTheme; diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 1beb15d3c..da7aaf04c 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -57,6 +57,10 @@ struct CloudTheme; enum class CloudThemeType; } // namespace Data +namespace HistoryView::Reactions { +class CachedIconFactory; +} // namespace HistoryView::Reactions + namespace Window { class MainWindow; @@ -450,6 +454,11 @@ public: return _chatStyle.get(); } + [[nodiscard]] auto cachedReactionIconFactory() const + -> HistoryView::Reactions::CachedIconFactory & { + return *_cachedReactionIconFactory; + } + rpl::lifetime &lifetime() { return _lifetime; } @@ -527,6 +536,9 @@ private: std::deque> _lastUsedCustomChatThemes; rpl::variable _peerThemeOverride; + using ReactionIconFactory = HistoryView::Reactions::CachedIconFactory; + std::unique_ptr _cachedReactionIconFactory; + rpl::lifetime _lifetime; };