Cache reaction lottie in Window::SessionController.

This commit is contained in:
John Preston 2022-01-10 23:44:05 +03:00
parent 3b4ed03105
commit e032dbf383
6 changed files with 75 additions and 20 deletions

View file

@ -323,7 +323,8 @@ HistoryInner::HistoryInner(
std::make_unique<HistoryView::Reactions::Manager>( std::make_unique<HistoryView::Reactions::Manager>(
this, this,
Data::UniqueReactionsLimitValue(&controller->session()), Data::UniqueReactionsLimitValue(&controller->session()),
[=](QRect updated) { update(updated); })) [=](QRect updated) { update(updated); },
controller->cachedReactionIconFactory().createMethod()))
, _touchSelectTimer([=] { onTouchSelect(); }) , _touchSelectTimer([=] { onTouchSelect(); })
, _touchScrollTimer([=] { onTouchScrollTimer(); }) , _touchScrollTimer([=] { onTouchScrollTimer(); })
, _scrollDateCheck([this] { scrollDateCheck(); }) , _scrollDateCheck([this] { scrollDateCheck(); })

View file

@ -269,7 +269,8 @@ ListWidget::ListWidget(
std::make_unique<Reactions::Manager>( std::make_unique<Reactions::Manager>(
this, this,
Data::UniqueReactionsLimitValue(&controller->session()), Data::UniqueReactionsLimitValue(&controller->session()),
[=](QRect updated) { update(updated); })) [=](QRect updated) { update(updated); },
controller->cachedReactionIconFactory().createMethod()))
, _scrollDateCheck([this] { scrollDateCheck(); }) , _scrollDateCheck([this] { scrollDateCheck(); })
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); }) , _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
, _selectEnabled(_delegate->listAllowsMultiSelect()) , _selectEnabled(_delegate->listAllowsMultiSelect())

View file

@ -70,18 +70,6 @@ constexpr auto kHoverScale = 1.24;
return style::ConvertScale(kSizeForDownscale); return style::ConvertScale(kSizeForDownscale);
} }
[[nodiscard]] std::shared_ptr<Lottie::Icon> CreateIcon(
not_null<Data::DocumentMedia*> media,
int size) {
Expects(media->loaded());
return std::make_shared<Lottie::Icon>(Lottie::IconDescriptor{
.path = media->owner()->filepath(true),
.json = media->bytes(),
.sizeOverride = QSize(size, size),
});
}
} // namespace } // namespace
Button::Button( Button::Button(
@ -332,8 +320,10 @@ float64 Button::currentOpacity() const {
Manager::Manager( Manager::Manager(
QWidget *wheelEventsTarget, QWidget *wheelEventsTarget,
rpl::producer<int> uniqueLimitValue, rpl::producer<int> uniqueLimitValue,
Fn<void(QRect)> buttonUpdate) Fn<void(QRect)> buttonUpdate,
: _outer(CountOuterSize()) IconFactory iconFactory)
: _iconFactory(std::move(iconFactory))
, _outer(CountOuterSize())
, _inner(QRect({}, st::reactionCornerSize)) , _inner(QRect({}, st::reactionCornerSize))
, _overlayFull( , _overlayFull(
QRect(0, 0, _inner.width(), _inner.width()).marginsAdded( QRect(0, 0, _inner.width(), _inner.width()).marginsAdded(
@ -601,7 +591,7 @@ void Manager::setMainReactionIcon() {
} }
} }
_mainReactionImage = QImage(); _mainReactionImage = QImage();
_mainReactionIcon = CreateIcon( _mainReactionIcon = DefaultIconFactory(
_mainReactionMedia.get(), _mainReactionMedia.get(),
MainReactionSize()); MainReactionSize());
} }
@ -632,7 +622,7 @@ bool Manager::checkIconLoaded(ReactionDocument &entry) const {
const auto size = (entry.media == _mainReactionMedia) const auto size = (entry.media == _mainReactionMedia)
? MainReactionSize() ? MainReactionSize()
: CornerImageSize(1.); : CornerImageSize(1.);
entry.icon = CreateIcon(entry.media.get(), size); entry.icon = _iconFactory(entry.media.get(), size);
entry.media = nullptr; entry.media = nullptr;
return true; return true;
} }
@ -1464,4 +1454,28 @@ void SetupManagerList(
}, manager->lifetime()); }, manager->lifetime());
} }
IconFactory CachedIconFactory::createMethod() {
return [=](not_null<Data::DocumentMedia*> 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<Lottie::Icon> DefaultIconFactory(
not_null<Data::DocumentMedia*> media,
int size) {
Expects(media->loaded());
return std::make_shared<Lottie::Icon>(Lottie::IconDescriptor{
.path = media->owner()->filepath(true),
.json = media->bytes(),
.sizeOverride = QSize(size, size),
});
}
} // namespace HistoryView } // namespace HistoryView

View file

@ -127,12 +127,17 @@ private:
}; };
using IconFactory = Fn<std::shared_ptr<Lottie::Icon>(
not_null<Data::DocumentMedia*>,
int)>;
class Manager final : public base::has_weak_ptr { class Manager final : public base::has_weak_ptr {
public: public:
Manager( Manager(
QWidget *wheelEventsTarget, QWidget *wheelEventsTarget,
rpl::producer<int> uniqueLimitValue, rpl::producer<int> uniqueLimitValue,
Fn<void(QRect)> buttonUpdate); Fn<void(QRect)> buttonUpdate,
IconFactory iconFactory);
~Manager(); ~Manager();
void applyList(const std::vector<Data::Reaction> &list); void applyList(const std::vector<Data::Reaction> &list);
@ -273,6 +278,7 @@ private:
void loadIcons(); void loadIcons();
void checkIcons(); void checkIcons();
const IconFactory _iconFactory;
rpl::event_stream<Chosen> _chosen; rpl::event_stream<Chosen> _chosen;
std::vector<ReactionIcons> _list; std::vector<ReactionIcons> _list;
std::optional<base::flat_set<QString>> _filter; std::optional<base::flat_set<QString>> _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<Data::DocumentMedia>,
std::shared_ptr<Lottie::Icon>> _cache;
};
void SetupManagerList( void SetupManagerList(
not_null<Manager*> manager, not_null<Manager*> manager,
not_null<Main::Session*> session, not_null<Main::Session*> session,
rpl::producer<std::optional<base::flat_set<QString>>> filter); rpl::producer<std::optional<base::flat_set<QString>>> filter);
[[nodiscard]] std::shared_ptr<Lottie::Icon> DefaultIconFactory(
not_null<Data::DocumentMedia*> media,
int size);
} // namespace HistoryView } // namespace HistoryView

View file

@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/view/history_view_replies_section.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 "history/view/history_view_reactions.h"
#include "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
#include "media/view/media_view_open_common.h" #include "media/view/media_view_open_common.h"
@ -530,7 +531,8 @@ SessionController::SessionController(
this)) this))
, _invitePeekTimer([=] { checkInvitePeek(); }) , _invitePeekTimer([=] { checkInvitePeek(); })
, _defaultChatTheme(std::make_shared<Ui::ChatTheme>()) , _defaultChatTheme(std::make_shared<Ui::ChatTheme>())
, _chatStyle(std::make_unique<Ui::ChatStyle>()) { , _chatStyle(std::make_unique<Ui::ChatStyle>())
, _cachedReactionIconFactory(std::make_unique<ReactionIconFactory>()) {
init(); init();
_chatStyleTheme = _defaultChatTheme; _chatStyleTheme = _defaultChatTheme;

View file

@ -57,6 +57,10 @@ struct CloudTheme;
enum class CloudThemeType; enum class CloudThemeType;
} // namespace Data } // namespace Data
namespace HistoryView::Reactions {
class CachedIconFactory;
} // namespace HistoryView::Reactions
namespace Window { namespace Window {
class MainWindow; class MainWindow;
@ -450,6 +454,11 @@ public:
return _chatStyle.get(); return _chatStyle.get();
} }
[[nodiscard]] auto cachedReactionIconFactory() const
-> HistoryView::Reactions::CachedIconFactory & {
return *_cachedReactionIconFactory;
}
rpl::lifetime &lifetime() { rpl::lifetime &lifetime() {
return _lifetime; return _lifetime;
} }
@ -527,6 +536,9 @@ private:
std::deque<std::shared_ptr<Ui::ChatTheme>> _lastUsedCustomChatThemes; std::deque<std::shared_ptr<Ui::ChatTheme>> _lastUsedCustomChatThemes;
rpl::variable<PeerThemeOverride> _peerThemeOverride; rpl::variable<PeerThemeOverride> _peerThemeOverride;
using ReactionIconFactory = HistoryView::Reactions::CachedIconFactory;
std::unique_ptr<ReactionIconFactory> _cachedReactionIconFactory;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
}; };