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>(
this,
Data::UniqueReactionsLimitValue(&controller->session()),
[=](QRect updated) { update(updated); }))
[=](QRect updated) { update(updated); },
controller->cachedReactionIconFactory().createMethod()))
, _touchSelectTimer([=] { onTouchSelect(); })
, _touchScrollTimer([=] { onTouchScrollTimer(); })
, _scrollDateCheck([this] { scrollDateCheck(); })

View file

@ -269,7 +269,8 @@ ListWidget::ListWidget(
std::make_unique<Reactions::Manager>(
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())

View file

@ -70,18 +70,6 @@ constexpr auto kHoverScale = 1.24;
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
Button::Button(
@ -332,8 +320,10 @@ float64 Button::currentOpacity() const {
Manager::Manager(
QWidget *wheelEventsTarget,
rpl::producer<int> uniqueLimitValue,
Fn<void(QRect)> buttonUpdate)
: _outer(CountOuterSize())
Fn<void(QRect)> 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<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

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 {
public:
Manager(
QWidget *wheelEventsTarget,
rpl::producer<int> uniqueLimitValue,
Fn<void(QRect)> buttonUpdate);
Fn<void(QRect)> buttonUpdate,
IconFactory iconFactory);
~Manager();
void applyList(const std::vector<Data::Reaction> &list);
@ -273,6 +278,7 @@ private:
void loadIcons();
void checkIcons();
const IconFactory _iconFactory;
rpl::event_stream<Chosen> _chosen;
std::vector<ReactionIcons> _list;
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(
not_null<Manager*> manager,
not_null<Main::Session*> session,
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

View file

@ -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<Ui::ChatTheme>())
, _chatStyle(std::make_unique<Ui::ChatStyle>()) {
, _chatStyle(std::make_unique<Ui::ChatStyle>())
, _cachedReactionIconFactory(std::make_unique<ReactionIconFactory>()) {
init();
_chatStyleTheme = _defaultChatTheme;

View file

@ -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<std::shared_ptr<Ui::ChatTheme>> _lastUsedCustomChatThemes;
rpl::variable<PeerThemeOverride> _peerThemeOverride;
using ReactionIconFactory = HistoryView::Reactions::CachedIconFactory;
std::unique_ptr<ReactionIconFactory> _cachedReactionIconFactory;
rpl::lifetime _lifetime;
};