diff --git a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp index 4706014c5..915dd6d1d 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp @@ -15,34 +15,35 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_session.h" #include "data/data_document.h" -#include "base/concurrent_timer.h" #include "apiwrap.h" #include "styles/style_history.h" namespace Stickers { namespace details { +using UniversalImages = Ui::Emoji::UniversalImages; + class EmojiImageLoader { public: EmojiImageLoader( crl::weak_on_queue weak, - int id); + std::shared_ptr images, + bool largeEnabled); [[nodiscard]] QImage prepare(EmojiPtr emoji); - void switchTo(int id); + void switchTo(std::shared_ptr images); + std::shared_ptr releaseImages(); private: crl::weak_on_queue _weak; - std::optional _images; - - base::ConcurrentTimer _unloadTimer; + std::shared_ptr _images; }; namespace { constexpr auto kRefreshTimeout = TimeId(7200); -constexpr auto kUnloadTimeout = 86400 * crl::time(1000); +constexpr auto kClearSourceTimeout = 10 * crl::time(1000); [[nodiscard]] QSize SingleSize() { const auto single = st::largeEmojiSize; @@ -245,15 +246,18 @@ QByteArray ImageSource::bytesForCache() { EmojiImageLoader::EmojiImageLoader( crl::weak_on_queue weak, - int id) + std::shared_ptr images, + bool largeEnabled) : _weak(std::move(weak)) -, _images(std::in_place, id) -, _unloadTimer(_weak.runner(), [=] { _images->clear(); }) { +, _images(std::move(images)) { + Expects(_images != nullptr); + + if (largeEnabled) { + _images->ensureLoaded(); + } } QImage EmojiImageLoader::prepare(EmojiPtr emoji) { - Expects(_images.has_value()); - _images->ensureLoaded(); const auto factor = cIntRetinaFactor(); const auto side = st::largeEmojiSize + 2 * st::largeEmojiOutline; @@ -300,19 +304,25 @@ QImage EmojiImageLoader::prepare(EmojiPtr emoji) { delta, delta); } - _unloadTimer.callOnce(kUnloadTimeout); return result; } -void EmojiImageLoader::switchTo(int id) { - _images.emplace(id); +void EmojiImageLoader::switchTo(std::shared_ptr images) { + _images = std::move(images); +} + +std::shared_ptr EmojiImageLoader::releaseImages() { + return std::exchange( + _images, + std::make_shared(_images->id())); } } // namespace details EmojiPack::EmojiPack(not_null session) : _session(session) -, _imageLoader(Ui::Emoji::CurrentSetId()) { +, _imageLoader(prepareSourceImages(), session->settings().largeEmoji()) +, _clearTimer([=] { clearSourceImages(); }) { refresh(); session->data().itemRemoved( @@ -322,17 +332,23 @@ EmojiPack::EmojiPack(not_null session) remove(item); }, _lifetime); - session->settings().largeEmojiChanges( - ) | rpl::start_with_next([=] { + _session->settings().largeEmojiChanges( + ) | rpl::start_with_next([=](bool large) { + if (large) { + _clearTimer.cancel(); + } else { + _clearTimer.callOnce(details::kClearSourceTimeout); + } refreshAll(); }, _lifetime); Ui::Emoji::Updated( ) | rpl::start_with_next([=] { - const auto id = Ui::Emoji::CurrentSetId(); _images.clear(); - _imageLoader.with([=](details::EmojiImageLoader &loader) { - loader.switchTo(id); + _imageLoader.with([ + source = prepareSourceImages() + ](details::EmojiImageLoader &loader) mutable { + loader.switchTo(std::move(source)); }); refreshAll(); }, _lifetime); @@ -450,6 +466,24 @@ void EmojiPack::refreshItems( } } +auto EmojiPack::prepareSourceImages() +-> std::shared_ptr { + const auto &images = Ui::Emoji::SourceImages(); + if (_session->settings().largeEmoji()) { + return images; + } + Ui::Emoji::ClearSourceImages(images); + return std::make_shared(images->id()); +} + +void EmojiPack::clearSourceImages() { + _imageLoader.with([](details::EmojiImageLoader &loader) { + crl::on_main([images = loader.releaseImages()]{ + Ui::Emoji::ClearSourceImages(images); + }); + }); +} + void EmojiPack::applyPack( const MTPDstickerPack &data, const base::flat_map> &map) { diff --git a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h index b098b0775..68ed3c3e3 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/text/text_isolated_emoji.h" +#include "base/timer.h" #include @@ -22,6 +23,9 @@ namespace Ui { namespace Text { class String; } // namespace Text +namespace Emoji { +class UniversalImages; +} // namespace Emoji } // namespace Ui namespace Stickers { @@ -56,6 +60,8 @@ private: void refreshAll(); void refreshItems(EmojiPtr emoji); void refreshItems(const base::flat_set> &list); + std::shared_ptr prepareSourceImages(); + void clearSourceImages(); not_null _session; base::flat_map> _map; @@ -66,6 +72,7 @@ private: mtpRequestId _requestId = 0; crl::object_on_queue _imageLoader; + base::Timer _clearTimer; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp index d4a0662c2..3f76336e2 100644 --- a/Telegram/SourceFiles/main/main_session.cpp +++ b/Telegram/SourceFiles/main/main_session.cpp @@ -481,6 +481,10 @@ bool Settings::largeEmoji() const { return _variables.largeEmoji.current(); } +rpl::producer Settings::largeEmojiValue() const { + return _variables.largeEmoji.value(); +} + rpl::producer Settings::largeEmojiChanges() const { return _variables.largeEmoji.changes(); } diff --git a/Telegram/SourceFiles/main/main_session.h b/Telegram/SourceFiles/main/main_session.h index c75848753..7f6afc3dd 100644 --- a/Telegram/SourceFiles/main/main_session.h +++ b/Telegram/SourceFiles/main/main_session.h @@ -249,6 +249,7 @@ public: } void setLargeEmoji(bool value); [[nodiscard]] bool largeEmoji() const; + [[nodiscard]] rpl::producer largeEmojiValue() const; [[nodiscard]] rpl::producer largeEmojiChanges() const; void setReplaceEmoji(bool value); [[nodiscard]] bool replaceEmoji() const; diff --git a/Telegram/SourceFiles/ui/emoji_config.cpp b/Telegram/SourceFiles/ui/emoji_config.cpp index 9f123ae78..e1e105b81 100644 --- a/Telegram/SourceFiles/ui/emoji_config.cpp +++ b/Telegram/SourceFiles/ui/emoji_config.cpp @@ -68,6 +68,7 @@ auto SpritesCount = -1; auto InstanceNormal = std::unique_ptr(); auto InstanceLarge = std::unique_ptr(); auto Universal = std::shared_ptr(); +auto CanClearUniversal = false; auto Updates = rpl::event_stream<>(); auto UpdatesRecent = rpl::event_stream<>(); @@ -148,6 +149,7 @@ void SwitchToSetPrepared(int id, std::shared_ptr images) { stream << qint32(id); } Universal = std::move(images); + CanClearUniversal = false; MainEmojiMap.clear(); OtherEmojiMap.clear(); Updates.fire({}); @@ -383,7 +385,10 @@ EmojiPtr FindReplacement(const QChar *start, const QChar *end, int *outLength) { void ClearUniversalChecked() { Expects(InstanceNormal != nullptr && InstanceLarge != nullptr); - if (InstanceNormal->cached() && InstanceLarge->cached() && Universal) { + if (CanClearUniversal + && Universal + && InstanceNormal->cached() + && InstanceLarge->cached()) { Universal->clear(); } } @@ -507,6 +512,7 @@ void Init() { SizeNormal = ConvertScale(18, cScale() * cIntRetinaFactor()); SizeLarge = int(ConvertScale(18 * 4 / 3., cScale() * cIntRetinaFactor())); Universal = std::make_shared(ReadCurrentSetId()); + CanClearUniversal = false; InstanceNormal = std::make_unique(SizeNormal); InstanceLarge = std::make_unique(SizeLarge); @@ -1007,5 +1013,24 @@ void Instance::pushSprite(QImage &&data) { _sprites.back().setDevicePixelRatio(cRetinaFactor()); } +const std::shared_ptr &SourceImages() { + return Universal; +} + +void ClearSourceImages(const std::shared_ptr &images) { + if (images == Universal) { + CanClearUniversal = true; + ClearUniversalChecked(); + } +} + +void ReplaceSourceImages(std::shared_ptr images) { + Expects(images != nullptr); + + if (Universal->id() == images->id()) { + Universal = std::move(images); + } +} + } // namespace Emoji } // namespace Ui diff --git a/Telegram/SourceFiles/ui/emoji_config.h b/Telegram/SourceFiles/ui/emoji_config.h index fb056e6a9..e4eeaf0d3 100644 --- a/Telegram/SourceFiles/ui/emoji_config.h +++ b/Telegram/SourceFiles/ui/emoji_config.h @@ -182,10 +182,13 @@ public: QImage generate(int size, int index) const; private: - int _id = 0; + const int _id = 0; std::vector _sprites; }; +const std::shared_ptr &SourceImages(); +void ClearSourceImages(const std::shared_ptr &images); + } // namespace Emoji } // namespace Ui diff --git a/Telegram/gyp/generate.py b/Telegram/gyp/generate.py index cf7b44707..4194e1666 100644 --- a/Telegram/gyp/generate.py +++ b/Telegram/gyp/generate.py @@ -96,7 +96,7 @@ if sys.platform == 'win32': elif sys.platform == 'darwin': # use patched gyp with Xcode project generator gypScript = '../../../Libraries/gyp/gyp' - gypArguments.append('-Gxcode_upgrade_check_project_version=1020') + gypArguments.append('-Gxcode_upgrade_check_project_version=1030') gypFormats.append('xcode') else: gypScript = '../../../Libraries/gyp/gyp'