diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 4f35f40808..3faf62904c 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_folder.h" #include "data/data_forum.h" +#include "data/data_forum_icons.h" #include "data/data_location.h" #include "data/data_histories.h" #include "data/data_group_call.h" @@ -164,8 +165,9 @@ void ChannelData::setFlags(ChannelDataFlags which) { const auto taken = ((diff & Flag::Forum) && !(which & Flag::Forum)) ? mgInfo->takeForumData() : nullptr; - - if ((diff & Flag::Forum) && (which & Flag::Forum)) { + if (const auto raw = taken.get()) { + owner().forumIcons().clearUserpicsReset(taken.get()); + } else if ((diff & Flag::Forum) && (which & Flag::Forum)) { mgInfo->ensureForum(this); } _flags.set(which); diff --git a/Telegram/SourceFiles/data/data_forum_icons.cpp b/Telegram/SourceFiles/data/data_forum_icons.cpp index e2ced07cf0..346e40881a 100644 --- a/Telegram/SourceFiles/data/data_forum_icons.cpp +++ b/Telegram/SourceFiles/data/data_forum_icons.cpp @@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "data/data_session.h" #include "data/data_document.h" +#include "data/data_forum.h" +#include "data/data_forum_topic.h" #include "apiwrap.h" namespace Data { @@ -22,7 +24,8 @@ constexpr auto kMaxTimeout = 6 * 60 * 60 * crl::time(1000); } // namespace ForumIcons::ForumIcons(not_null owner) -: _owner(owner) { +: _owner(owner) +, _resetUserpicsTimer([=] { resetUserpics(); }) { } ForumIcons::~ForumIcons() = default; @@ -79,4 +82,45 @@ void ForumIcons::updateDefault(const MTPDmessages_stickerSet &data) { _defaultUpdated.fire({}); } +void ForumIcons::scheduleUserpicsReset(not_null forum) { + const auto duration = crl::time(st::slideDuration); + _resetUserpicsWhen[forum] = crl::now() + duration; + if (!_resetUserpicsTimer.isActive()) { + _resetUserpicsTimer.callOnce(duration); + } +} + +void ForumIcons::clearUserpicsReset(not_null forum) { + _resetUserpicsWhen.remove(forum); +} + +void ForumIcons::resetUserpics() { + auto nearest = crl::time(); + auto now = crl::now(); + for (auto i = begin(_resetUserpicsWhen); i != end(_resetUserpicsWhen);) { + if (i->second > now) { + if (!nearest || nearest > i->second) { + nearest = i->second; + } + ++i; + } else { + const auto forum = i->first; + i = _resetUserpicsWhen.erase(i); + resetUserpicsFor(forum); + } + } + if (nearest) { + _resetUserpicsTimer.callOnce( + std::min(nearest - now, 86400 * crl::time(1000))); + } else { + _resetUserpicsTimer.cancel(); + } +} + +void ForumIcons::resetUserpicsFor(not_null forum) { + forum->enumerateTopics([](not_null topic) { + topic->clearUserpicLoops(); + }); +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_forum_icons.h b/Telegram/SourceFiles/data/data_forum_icons.h index cc0bdd9a67..54f03a366b 100644 --- a/Telegram/SourceFiles/data/data_forum_icons.h +++ b/Telegram/SourceFiles/data/data_forum_icons.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/timer.h" + namespace Main { class Session; } // namespace Main @@ -15,6 +17,7 @@ namespace Data { class DocumentMedia; class Session; +class Forum; class ForumIcons final { public: @@ -33,8 +36,13 @@ public: [[nodiscard]] rpl::producer<> defaultUpdates() const; + void scheduleUserpicsReset(not_null forum); + void clearUserpicsReset(not_null forum); + private: void requestDefault(); + void resetUserpics(); + void resetUserpicsFor(not_null forum); void updateDefault(const MTPDmessages_stickerSet &data); @@ -45,6 +53,9 @@ private: mtpRequestId _defaultRequestId = 0; + base::flat_map, crl::time> _resetUserpicsWhen; + base::Timer _resetUserpicsTimer; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index ae1a2757ea..82ac881b95 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "ui/painter.h" #include "ui/color_int_conversion.h" +#include "ui/text/text_custom_emoji.h" #include "styles/style_dialogs.h" #include "styles/style_chat_helpers.h" @@ -41,6 +42,8 @@ namespace { using UpdateFlag = TopicUpdate::Flag; +constexpr auto kUserpicLoopsCount = 2; + } // namespace const base::flat_map &ForumTopicIcons() { @@ -544,6 +547,12 @@ void ForumTopic::paintUserpic( } } +void ForumTopic::clearUserpicLoops() { + if (_icon) { + _icon->unload(); + } +} + void ForumTopic::validateDefaultIcon() const { if (_defaultIcon.isNull()) { _defaultIcon = ForumTopicIconFrame( @@ -629,10 +638,12 @@ void ForumTopic::applyIconId(DocumentId iconId) { } _iconId = iconId; _icon = iconId - ? owner().customEmojiManager().create( - _iconId, - [=] { updateChatListEntry(); }, - Data::CustomEmojiManager::SizeTag::Normal) + ? std::make_unique( + owner().customEmojiManager().create( + _iconId, + [=] { updateChatListEntry(); }, + Data::CustomEmojiManager::SizeTag::Normal), + kUserpicLoopsCount) : nullptr; if (iconId) { _defaultIcon = QImage(); diff --git a/Telegram/SourceFiles/data/data_forum_topic.h b/Telegram/SourceFiles/data/data_forum_topic.h index 86c2f7d02c..2bb335c63d 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.h +++ b/Telegram/SourceFiles/data/data_forum_topic.h @@ -138,6 +138,7 @@ public: Painter &p, std::shared_ptr &view, const Dialogs::Ui::PaintContext &context) const override; + void clearUserpicLoops(); [[nodiscard]] bool isServerSideUnread( not_null item) const override; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 2fa7135dec..78f01fe1c3 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_drafts.h" #include "data/data_folder.h" #include "data/data_forum.h" +#include "data/data_forum_icons.h" #include "data/data_session.h" #include "data/data_channel.h" #include "data/data_forum_topic.h" @@ -428,6 +429,10 @@ void InnerWidget::changeOpenedForum(ChannelData *forum) { _filterId = forum ? 0 : _controller->activeChatsFilterCurrent(); + if (const auto old = now ? now->forum() : nullptr) { + // If we close it inside forum destruction we should not schedule. + old->owner().forumIcons().scheduleUserpicsReset(old); + } _openedForum = forum ? forum->forum() : nullptr; _st = forum ? &st::forumTopicRow : &st::defaultDialogRow;