From 17511749de3a74edcb93b7598e9015accf46b76f Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 19 Sep 2021 18:15:46 +0300 Subject: [PATCH] Hold only last 5 custom themes in memory. --- .../window/window_session_controller.cpp | 61 +++++++++++++++---- .../window/window_session_controller.h | 2 + 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 3960c4e05..839ed2e12 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -75,6 +75,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Window { namespace { +constexpr auto kCustomThemesInMemory = 5; constexpr auto kMaxChatEntryHistorySize = 50; constexpr auto kDayBaseFile = ":/gui/day-custom-base.tdesktop-theme"_cs; constexpr auto kNightBaseFile = ":/gui/night-custom-base.tdesktop-theme"_cs; @@ -505,9 +506,10 @@ void SessionNavigation::showPollResults( } struct SessionController::CachedTheme { - std::shared_ptr theme; + std::weak_ptr theme; std::shared_ptr media; Data::WallPaper paper; + bool caching = false; rpl::lifetime lifetime; }; @@ -1393,10 +1395,13 @@ auto SessionController::cachedChatThemeValue( return rpl::single(_defaultChatTheme); } const auto i = _customChatThemes.find(key); - if (i != end(_customChatThemes) && i->second.theme) { - return rpl::single(i->second.theme); + if (i != end(_customChatThemes)) { + if (auto strong = i->second.theme.lock()) { + pushToLastUsed(strong); + return rpl::single(std::move(strong)); + } } - if (i == end(_customChatThemes)) { + if (i == end(_customChatThemes) || !i->second.caching) { cacheChatTheme(data); } const auto limit = Data::CloudThemes::TestingColors() ? (1 << 20) : 1; @@ -1405,10 +1410,27 @@ auto SessionController::cachedChatThemeValue( _defaultChatTheme ) | rpl::then(_cachedThemesStream.events( ) | rpl::filter([=](const std::shared_ptr &theme) { - return (theme->key() == key); + if (theme->key() != key) { + return false; + } + pushToLastUsed(theme); + return true; }) | rpl::take(limit)); } +void SessionController::pushToLastUsed( + const std::shared_ptr &theme) { + const auto i = ranges::find(_lastUsedCustomChatThemes, theme); + if (i == end(_lastUsedCustomChatThemes)) { + if (_lastUsedCustomChatThemes.size() >= kCustomThemesInMemory) { + _lastUsedCustomChatThemes.pop_back(); + } + _lastUsedCustomChatThemes.push_front(theme); + } else if (i != begin(_lastUsedCustomChatThemes)) { + std::rotate(begin(_lastUsedCustomChatThemes), i, i + 1); + } +} + void SessionController::setChatStyleTheme( const std::shared_ptr &theme) { if (_chatStyleTheme.lock() == theme) { @@ -1447,9 +1469,22 @@ void SessionController::cacheChatTheme(const Data::CloudTheme &data) { const auto document = data.paper->document(); const auto media = document ? document->createMediaView() : nullptr; data.paper->loadDocument(); - auto &theme = _customChatThemes.emplace( - key, - CachedTheme{ .media = media, .paper = *data.paper }).first->second; + auto &theme = [&]() -> CachedTheme& { + const auto i = _customChatThemes.find(key); + if (i != end(_customChatThemes)) { + i->second.media = media; + i->second.paper = *data.paper; + i->second.caching = true; + return i->second; + } + return _customChatThemes.emplace( + key, + CachedTheme{ + .media = media, + .paper = *data.paper, + .caching = true, + }).first->second; + }(); auto descriptor = Ui::ChatThemeDescriptor{ .id = key, .preparePalette = PreparePaletteCallback( @@ -1485,6 +1520,7 @@ void SessionController::cacheChatThemeDone( if (i == end(_customChatThemes)) { return; } + i->second.caching = false; i->second.theme = result; if (i->second.media) { if (i->second.media->loaded(true)) { @@ -1510,10 +1546,11 @@ void SessionController::updateCustomThemeBackground(CachedTheme &theme) { theme.lifetime.destroy(); theme.media = nullptr; }); - if (!theme.media || !theme.theme || !theme.media->loaded(true)) { + const auto strong = theme.theme.lock(); + if (!theme.media || !strong || !theme.media->loaded(true)) { return; } - const auto key = theme.theme->key(); + const auto key = strong->key(); const auto weak = base::make_weak(this); crl::async([=, data = backgroundData(theme, false)] { crl::on_main(weak, [ @@ -1522,7 +1559,9 @@ void SessionController::updateCustomThemeBackground(CachedTheme &theme) { ]() mutable { const auto i = _customChatThemes.find(key); if (i != end(_customChatThemes)) { - i->second.theme->updateBackgroundImageFrom(std::move(result)); + if (const auto strong = i->second.theme.lock()) { + strong->updateBackgroundImageFrom(std::move(result)); + } } }); }); diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 35c79a856..81d6697d6 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -464,6 +464,7 @@ private: [[nodiscard]] Ui::ChatThemeBackgroundData backgroundData( CachedTheme &theme, bool generateGradient = true) const; + void pushToLastUsed(const std::shared_ptr &theme); const not_null _window; const std::unique_ptr _emojiInteractions; @@ -498,6 +499,7 @@ private: rpl::event_stream> _cachedThemesStream; const std::unique_ptr _chatStyle; std::weak_ptr _chatStyleTheme; + std::deque> _lastUsedCustomChatThemes; rpl::lifetime _lifetime;