diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index ac5476a1b..1367970fc 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -1991,7 +1991,10 @@ MediaStory::MediaStory( : Media(parent) , _storyId(storyId) , _mention(mention) { - const auto stories = &parent->history()->owner().stories(); + const auto owner = &parent->history()->owner(); + owner->registerStoryItem(storyId, parent); + + const auto stories = &owner->stories(); if (const auto maybeStory = stories->lookup(storyId)) { if (!_mention) { parent->setText((*maybeStory)->caption()); @@ -2017,6 +2020,11 @@ MediaStory::MediaStory( } } +MediaStory::~MediaStory() { + const auto owner = &parent()->history()->owner(); + owner->unregisterStoryItem(_storyId, parent()); +} + std::unique_ptr MediaStory::clone(not_null parent) { return std::make_unique(parent, _storyId, false); } diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index f60bc82a1..81e034c02 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -575,6 +575,7 @@ public: not_null parent, FullStoryId storyId, bool mention); + ~MediaStory(); std::unique_ptr clone(not_null parent) override; diff --git a/Telegram/SourceFiles/data/data_msg_id.h b/Telegram/SourceFiles/data/data_msg_id.h index aa3bf1785..49357d88f 100644 --- a/Telegram/SourceFiles/data/data_msg_id.h +++ b/Telegram/SourceFiles/data/data_msg_id.h @@ -194,4 +194,13 @@ struct hash : private hash { } }; +template <> +struct hash { + size_t operator()(FullStoryId value) const { + return QtPrivate::QHashCombine().operator()( + std::hash()(value.peer.value), + value.story); + } +}; + } // namespace std diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 6c3100d4d..02437c67c 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -3881,6 +3881,33 @@ void Session::destroyAllCallItems() { } } +void Session::registerStoryItem( + FullStoryId id, + not_null item) { + _storyItems[id].emplace(item); +} + +void Session::unregisterStoryItem( + FullStoryId id, + not_null item) { + const auto i = _storyItems.find(id); + if (i != _storyItems.end()) { + auto &items = i->second; + if (items.remove(item) && items.empty()) { + _storyItems.erase(i); + } + } +} + +void Session::refreshStoryItemViews(FullStoryId id) { + const auto i = _storyItems.find(id); + if (i != _storyItems.end()) { + for (const auto item : i->second) { + requestItemViewRefresh(item); + } + } +} + void Session::documentMessageRemoved(not_null document) { if (_documentItems.find(document) != _documentItems.end()) { return; diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index c287713d3..9ba13d1a9 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -637,6 +637,9 @@ public: not_null item); void registerCallItem(not_null item); void unregisterCallItem(not_null item); + void registerStoryItem(FullStoryId id, not_null item); + void unregisterStoryItem(FullStoryId id, not_null item); + void refreshStoryItemViews(FullStoryId id); void documentMessageRemoved(not_null document); @@ -949,6 +952,9 @@ private: UserId, base::flat_set>> _contactViews; std::unordered_set> _callItems; + std::unordered_map< + FullStoryId, + base::flat_set>> _storyItems; base::flat_set> _webpagesUpdated; base::flat_set> _gamesUpdated; diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 86ee493e6..15710d021 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -331,6 +331,7 @@ Story *Stories::parseAndApply( return nullptr; } const auto id = data.vid().v; + const auto fullId = FullStoryId{ peer->id, id }; auto &stories = _stories[peer->id]; const auto i = stories.find(id); if (i != end(stories)) { @@ -349,7 +350,6 @@ Story *Stories::parseAndApply( } } if (mediaChanged) { - const auto fullId = result->fullId(); _preloaded.remove(fullId); if (_preloading && _preloading->id() == fullId) { _preloading = nullptr; @@ -357,9 +357,11 @@ Story *Stories::parseAndApply( rebuildPreloadSources(StorySourcesList::Hidden); continuePreloading(); } + _owner->refreshStoryItemViews(fullId); } return result; } + const auto wasDeleted = _deleted.remove(fullId); const auto result = stories.emplace(id, std::make_unique( id, peer, @@ -382,10 +384,14 @@ Story *Stories::parseAndApply( } if (expired) { - _expiring.remove(expires, result->fullId()); - applyExpired(result->fullId()); + _expiring.remove(expires, fullId); + applyExpired(fullId); } else { - registerExpiring(expires, result->fullId()); + registerExpiring(expires, fullId); + } + + if (wasDeleted) { + _owner->refreshStoryItemViews(fullId); } return result; @@ -605,7 +611,7 @@ void Stories::finalizeResolve(FullStoryId id) { void Stories::applyDeleted(FullStoryId id) { applyRemovedFromActive(id); - _deleted.emplace(id); + _deleted.emplace(id).second; const auto i = _stories.find(id.peer); if (i != end(_stories)) { const auto j = i->second.find(id.story); @@ -639,6 +645,7 @@ void Stories::applyDeleted(FullStoryId id) { if (_preloading && _preloading->id() == id) { preloadFinished(id); } + _owner->refreshStoryItemViews(id); if (i->second.empty()) { _stories.erase(i); }