diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 6c6991bd5..e0ff8ca26 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -38,6 +38,8 @@ constexpr auto kSavedPerPage = 100; constexpr auto kMaxPreloadSources = 10; constexpr auto kStillPreloadFromFirst = 3; constexpr auto kMaxSegmentsCount = 180; +constexpr auto kPollingIntervalChat = 5 * TimeId(60); +constexpr auto kPollingIntervalViewer = 1 * TimeId(60); using UpdateFlag = StoryUpdate::Flag; @@ -98,10 +100,12 @@ Stories::Stories(not_null owner) : _owner(owner) , _expireTimer([=] { processExpired(); }) , _markReadTimer([=] { sendMarkAsReadRequests(); }) -, _incrementViewsTimer([=] { sendIncrementViewsRequests(); }) { +, _incrementViewsTimer([=] { sendIncrementViewsRequests(); }) +, _pollingTimer([=] { sendPollingRequests(); }) { } Stories::~Stories() { + Expects(_pollingSettings.empty()); } Session &Stories::owner() const { @@ -348,7 +352,7 @@ Story *Stories::parseAndApply( const auto result = i->second.get(); const auto pinned = result->pinned(); const auto mediaChanged = (result->media() != *media); - if (result->applyChanges(*media, data)) { + if (result->applyChanges(*media, data, now)) { if (result->pinned() != pinned) { savedStateUpdated(result); } @@ -358,6 +362,11 @@ Story *Stories::parseAndApply( if (const auto item = lookupItem(result)) { item->applyChanges(result); } + _owner->refreshStoryItemViews(fullId); + } + const auto j = _pollingSettings.find(result); + if (j != end(_pollingSettings)) { + maybeSchedulePolling(result, j->second, now); } if (mediaChanged) { _preloaded.remove(fullId); @@ -378,7 +387,7 @@ Story *Stories::parseAndApply( StoryMedia{ *media }, data.vdate().v, data.vexpire_date().v)).first->second.get(); - result->applyChanges(*media, data); + result->applyChanges(*media, data, now); if (result->pinned()) { savedStateUpdated(result); } @@ -656,6 +665,7 @@ void Stories::applyDeleted(FullStoryId id) { preloadFinished(id); } _owner->refreshStoryItemViews(id); + Assert(!_pollingSettings.contains(story.get())); if (i->second.empty()) { _stories.erase(i); } @@ -818,13 +828,15 @@ base::expected, NoStory> Stories::lookup( _deleted.contains(id) ? NoStory::Deleted : NoStory::Unknown); } -void Stories::resolve(FullStoryId id, Fn done) { - const auto already = lookup(id); - if (already.has_value() || already.error() != NoStory::Unknown) { - if (done) { - done(); +void Stories::resolve(FullStoryId id, Fn done, bool force) { + if (!force) { + const auto already = lookup(id); + if (already.has_value() || already.error() != NoStory::Unknown) { + if (done) { + done(); + } + return; } - return; } if (const auto i = _resolveSent.find(id.peer); i != end(_resolveSent)) { if (const auto j = i->second.find(id.story); j != end(i->second)) { @@ -1493,6 +1505,84 @@ bool Stories::isUnread(not_null story) { return (story->id() > readTill); } +void Stories::registerPolling(not_null story, Polling polling) { + auto &settings = _pollingSettings[story]; + switch (polling) { + case Polling::Chat: ++settings.chat; break; + case Polling::Viewer: ++settings.viewer; break; + } + maybeSchedulePolling(story, settings, base::unixtime::now()); +} + +void Stories::unregisterPolling(not_null story, Polling polling) { + const auto i = _pollingSettings.find(story); + Assert(i != end(_pollingSettings)); + + switch (polling) { + case Polling::Chat: + Assert(i->second.chat > 0); + --i->second.chat; + break; + case Polling::Viewer: + Assert(i->second.viewer > 0); + --i->second.viewer; + break; + } + if (!i->second.chat && !i->second.viewer) { + _pollingSettings.erase(i); + } +} + +bool Stories::registerPolling(FullStoryId id, Polling polling) { + if (const auto maybeStory = lookup(id)) { + registerPolling(*maybeStory, polling); + return true; + } + return false; +} + +void Stories::unregisterPolling(FullStoryId id, Polling polling) { + const auto maybeStory = lookup(id); + Assert(maybeStory.has_value()); + unregisterPolling(*maybeStory, polling); +} + +int Stories::pollingInterval(const PollingSettings &settings) const { + return settings.viewer ? kPollingIntervalViewer : kPollingIntervalChat; +} + +void Stories::maybeSchedulePolling( + not_null story, + const PollingSettings &settings, + TimeId now) { + const auto last = story->lastUpdateTime(); + const auto next = last + pollingInterval(settings); + const auto left = std::max(next - now, 0) * crl::time(1000) + 1; + if (!_pollingTimer.isActive() || _pollingTimer.remainingTime() > left) { + _pollingTimer.callOnce(left); + } +} + +void Stories::sendPollingRequests() { + auto min = 0; + const auto now = base::unixtime::now(); + for (const auto &[story, settings] : _pollingSettings) { + const auto last = story->lastUpdateTime(); + const auto next = last + pollingInterval(settings); + if (now >= next) { + resolve(story->fullId(), nullptr, true); + } else { + const auto left = (next - now) * crl::time(1000) + 1; + if (!min || left < min) { + min = left; + } + } + } + if (min > 0) { + _pollingTimer.callOnce(min); + } +} + void Stories::updateUserStoriesState(not_null peer) { const auto till = _readTill.find(peer->id); const auto readTill = (till != end(_readTill)) ? till->second : 0; diff --git a/Telegram/SourceFiles/data/data_stories.h b/Telegram/SourceFiles/data/data_stories.h index e1bb0dcb6..579ec7b89 100644 --- a/Telegram/SourceFiles/data/data_stories.h +++ b/Telegram/SourceFiles/data/data_stories.h @@ -153,7 +153,7 @@ public: [[nodiscard]] base::expected, NoStory> lookup( FullStoryId id) const; - void resolve(FullStoryId id, Fn done); + void resolve(FullStoryId id, Fn done, bool force = false); [[nodiscard]] std::shared_ptr resolveItem(FullStoryId id); [[nodiscard]] std::shared_ptr resolveItem( not_null story); @@ -209,6 +209,16 @@ public: StoryId storyMaxId); [[nodiscard]] bool isUnread(not_null story); + enum class Polling { + Chat, + Viewer, + }; + void registerPolling(not_null story, Polling polling); + void unregisterPolling(not_null story, Polling polling); + + bool registerPolling(FullStoryId id, Polling polling); + void unregisterPolling(FullStoryId id, Polling polling); + private: struct Saved { StoriesIds ids; @@ -217,6 +227,10 @@ private: bool loaded = false; mtpRequestId requestId = 0; }; + struct PollingSettings { + int chat = 0; + int viewer = 0; + }; void parseAndApply(const MTPUserStories &stories); [[nodiscard]] Story *parseAndApply( @@ -265,6 +279,14 @@ private: void startPreloading(not_null story); void preloadFinished(FullStoryId id, bool markAsPreloaded = false); + [[nodiscard]] int pollingInterval( + const PollingSettings &settings) const; + void maybeSchedulePolling( + not_null story, + const PollingSettings &settings, + TimeId now); + void sendPollingRequests(); + const not_null _owner; std::unordered_map< PeerId, @@ -336,6 +358,9 @@ private: mtpRequestId _readTillsRequestId = 0; bool _readTillReceived = false; + base::flat_map, PollingSettings> _pollingSettings; + base::Timer _pollingTimer; + }; } // namespace Data diff --git a/Telegram/SourceFiles/data/data_story.cpp b/Telegram/SourceFiles/data/data_story.cpp index af8b50c8a..3a57400c0 100644 --- a/Telegram/SourceFiles/data/data_story.cpp +++ b/Telegram/SourceFiles/data/data_story.cpp @@ -371,7 +371,12 @@ void Story::applyViewsSlice( } } -bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) { +bool Story::applyChanges( + StoryMedia media, + const MTPDstoryItem &data, + TimeId now) { + _lastUpdateTime = now; + const auto pinned = data.is_pinned(); const auto edited = data.is_edited(); const auto isPublic = data.is_public(); @@ -424,6 +429,10 @@ bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) { return true; } +TimeId Story::lastUpdateTime() const { + return _lastUpdateTime; +} + StoryPreload::StoryPreload(not_null story, Fn done) : _story(story) , _done(std::move(done)) { diff --git a/Telegram/SourceFiles/data/data_story.h b/Telegram/SourceFiles/data/data_story.h index d80272e67..ed6254a09 100644 --- a/Telegram/SourceFiles/data/data_story.h +++ b/Telegram/SourceFiles/data/data_story.h @@ -113,7 +113,11 @@ public: const std::vector &slice, int total); - bool applyChanges(StoryMedia media, const MTPDstoryItem &data); + bool applyChanges( + StoryMedia media, + const MTPDstoryItem &data, + TimeId now); + [[nodiscard]] TimeId lastUpdateTime() const; private: const StoryId _id = 0; @@ -125,6 +129,7 @@ private: int _views = 0; const TimeId _date = 0; const TimeId _expires = 0; + TimeId _lastUpdateTime = 0; bool _pinned : 1 = false; bool _isPublic : 1 = false; bool _closeFriends : 1 = false; diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index e1c78f8b5..d3040ce07 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -42,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/path_shift_gradient.h" #include "ui/effects/spoiler_mess.h" #include "data/data_session.h" +#include "data/data_stories.h" #include "data/data_streaming.h" #include "data/data_document.h" #include "data/data_file_click_handler.h" @@ -134,6 +135,7 @@ Gif::~Gif() { _parent->checkHeavyPart(); } } + togglePollingStory(false); } bool Gif::CanPlayInline(not_null document) { @@ -1432,6 +1434,22 @@ void Gif::dataMediaCreated() const { _dataMedia->videoThumbnailWanted(_realParent->fullId()); } history()->owner().registerHeavyViewPart(_parent); + togglePollingStory(true); +} + +void Gif::togglePollingStory(bool enabled) const { + if (!_story || _pollingStory == enabled) { + return; + } + const auto polling = Data::Stories::Polling::Chat; + const auto media = _parent->data()->media(); + const auto id = media ? media->storyId() : FullStoryId(); + if (!enabled) { + _data->owner().stories().unregisterPolling(id, polling); + } else if (!_data->owner().stories().registerPolling(id, polling)) { + return; + } + _pollingStory = enabled; } bool Gif::uploading() const { @@ -1686,6 +1704,7 @@ void Gif::unloadHeavyPart() { _thumbCache = QImage(); _videoThumbnailFrame = nullptr; _caption.unloadPersistentAnimation(); + togglePollingStory(false); } void Gif::refreshParentId(not_null realParent) { @@ -1815,6 +1834,7 @@ void Gif::setStreamed(std::unique_ptr value) { _streamed = std::move(value); if (set) { history()->owner().registerHeavyViewPart(_parent); + togglePollingStory(true); } else if (removed) { _parent->checkHeavyPart(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.h b/Telegram/SourceFiles/history/view/media/history_view_gif.h index 6a8fca3b5..50c5583ac 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.h +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.h @@ -208,6 +208,8 @@ private: StateRequest request, QPoint position) const; + void togglePollingStory(bool enabled) const; + const not_null _data; Ui::Text::String _caption; std::unique_ptr _streamed; @@ -222,6 +224,7 @@ private: mutable bool _thumbCacheBlurred : 1 = false; mutable bool _thumbIsEllipse : 1 = false; mutable bool _story : 1 = false; + mutable bool _pollingStory : 1 = false; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index a7f08a50d..ed5c49ac9 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/power_saving.h" #include "data/data_session.h" +#include "data/data_stories.h" #include "data/data_streaming.h" #include "data/data_photo.h" #include "data/data_photo_media.h" @@ -101,6 +102,7 @@ Photo::~Photo() { _parent->checkHeavyPart(); } } + togglePollingStory(false); } void Photo::create(FullMsgId contextId, PeerData *chat) { @@ -145,6 +147,7 @@ void Photo::dataMediaCreated() const { _dataMedia->wanted(PhotoSize::Small, _realParent->fullId()); } history()->owner().registerHeavyViewPart(_parent); + togglePollingStory(true); } bool Photo::hasHeavyPart() const { @@ -160,6 +163,23 @@ void Photo::unloadHeavyPart() { } _imageCache = QImage(); _caption.unloadPersistentAnimation(); + togglePollingStory(false); +} + +void Photo::togglePollingStory(bool enabled) const { + const auto pollingStory = (enabled ? 1 : 0); + if (!_story || _pollingStory == pollingStory) { + return; + } + const auto polling = Data::Stories::Polling::Chat; + const auto media = _parent->data()->media(); + const auto id = media ? media->storyId() : FullStoryId(); + if (!enabled) { + _data->owner().stories().unregisterPolling(id, polling); + } else if (!_data->owner().stories().registerPolling(id, polling)) { + return; + } + _pollingStory = pollingStory; } QSize Photo::countOptimalSize() { @@ -926,6 +946,7 @@ void Photo::setStreamed(std::unique_ptr value) { _streamed = std::move(value); if (set) { history()->owner().registerHeavyViewPart(_parent); + togglePollingStory(true); } else if (removed) { _parent->checkHeavyPart(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.h b/Telegram/SourceFiles/history/view/media/history_view_photo.h index f6d7062f0..94404ddbe 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.h +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.h @@ -160,6 +160,8 @@ private: [[nodiscard]] QSize photoSize() const; + void togglePollingStory(bool enabled) const; + const not_null _data; Ui::Text::String _caption; mutable std::shared_ptr _dataMedia; @@ -167,10 +169,11 @@ private: const std::unique_ptr _spoiler; mutable QImage _imageCache; mutable std::optional _imageCacheRounding; - uint32 _serviceWidth : 29 = 0; + uint32 _serviceWidth : 28 = 0; mutable uint32 _imageCacheForum : 1 = 0; mutable uint32 _imageCacheBlurred : 1 = 0; mutable uint32 _story : 1 = 0; + mutable uint32 _pollingStory : 1 = 0; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_story_mention.cpp b/Telegram/SourceFiles/history/view/media/history_view_story_mention.cpp index a4d255fd2..15d8925b5 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_story_mention.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_story_mention.cpp @@ -52,7 +52,9 @@ StoryMention::StoryMention( , _unread(story->owner().stories().isUnread(story) ? 1 : 0) { } -StoryMention::~StoryMention() = default; +StoryMention::~StoryMention() { + changeSubscribedTo(0); +} int StoryMention::top() { return st::msgServiceGiftBoxButtonMargins.top(); @@ -105,13 +107,12 @@ void StoryMention::draw( ? history->session().user() : history->peer); _thumbnailFromStory = showStory; - _subscribed = 0; + changeSubscribedTo(0); } - if (!_subscribed) { + if (changeSubscribedTo(1)) { _thumbnail->subscribeToUpdates([=] { _parent->data()->history()->owner().requestViewRepaint(_parent); }); - _subscribed = 1; } const auto padding = (geometry.width() - st::storyMentionSize) / 2; @@ -164,10 +165,26 @@ bool StoryMention::hasHeavyPart() { } void StoryMention::unloadHeavyPart() { - if (_subscribed) { - _subscribed = 0; + if (changeSubscribedTo(0)) { _thumbnail->subscribeToUpdates(nullptr); } } +bool StoryMention::changeSubscribedTo(uint32 value) { + Expects(value == 0 || value == 1); + + if (_subscribed == value) { + return false; + } + _subscribed = value; + const auto stories = &_parent->history()->owner().stories(); + if (value) { + _parent->history()->owner().registerHeavyViewPart(_parent); + stories->registerPolling(_story, Data::Stories::Polling::Chat); + } else { + stories->unregisterPolling(_story, Data::Stories::Polling::Chat); + } + return true; +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_story_mention.h b/Telegram/SourceFiles/history/view/media/history_view_story_mention.h index fea24787f..51704d440 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_story_mention.h +++ b/Telegram/SourceFiles/history/view/media/history_view_story_mention.h @@ -55,6 +55,8 @@ public: private: using Thumbnail = Dialogs::Stories::Thumbnail; + bool changeSubscribedTo(uint32 value); + const not_null _parent; const not_null _story; std::shared_ptr _thumbnail; diff --git a/Telegram/SourceFiles/info/stories/info_stories_provider.cpp b/Telegram/SourceFiles/info/stories/info_stories_provider.cpp index b4cf680c6..fbe81ebc5 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_provider.cpp +++ b/Telegram/SourceFiles/info/stories/info_stories_provider.cpp @@ -56,6 +56,10 @@ Provider::Provider(not_null controller) }, _lifetime); } +Provider::~Provider() { + clear(); +} + Type Provider::type() { return Type::PhotoVideo; } @@ -90,11 +94,20 @@ std::optional Provider::fullCount() { return _slice.fullCount(); } -void Provider::restart() { +void Provider::clear() { + for (const auto &[storyId, _] : _layouts) { + _peer->owner().stories().unregisterPolling( + { _peer->id, storyId }, + Data::Stories::Polling::Chat); + } _layouts.clear(); _aroundId = kDefaultAroundId; _idsLimit = kMinimalIdsLimit; _slice = Data::StoriesIdsSlice(); +} + +void Provider::restart() { + clear(); refreshViewer(); } @@ -210,6 +223,9 @@ void Provider::markLayoutsStale() { void Provider::clearStaleLayouts() { for (auto i = _layouts.begin(); i != _layouts.end();) { if (i->second.stale) { + _peer->owner().stories().unregisterPolling( + { _peer->id, i->first }, + Data::Stories::Polling::Chat); _layoutRemoved.fire(i->second.item.get()); const auto taken = _items.take(i->first); i = _layouts.erase(i); @@ -240,6 +256,9 @@ bool Provider::isAfter( void Provider::itemRemoved(not_null item) { const auto id = StoryIdFromMsgId(item->id); if (const auto i = _layouts.find(id); i != end(_layouts)) { + _peer->owner().stories().unregisterPolling( + { _peer->id, id }, + Data::Stories::Polling::Chat); _layoutRemoved.fire(i->second.item.get()); _layouts.erase(i); } @@ -253,6 +272,9 @@ BaseLayout *Provider::getLayout( if (auto layout = createLayout(id, delegate)) { layout->initDimensions(); it = _layouts.emplace(id, std::move(layout)).first; + _peer->owner().stories().registerPolling( + { _peer->id, id }, + Data::Stories::Polling::Chat); } else { return nullptr; } diff --git a/Telegram/SourceFiles/info/stories/info_stories_provider.h b/Telegram/SourceFiles/info/stories/info_stories_provider.h index f1fb535d3..390234128 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_provider.h +++ b/Telegram/SourceFiles/info/stories/info_stories_provider.h @@ -30,6 +30,7 @@ class Provider final , public base::has_weak_ptr { public: explicit Provider(not_null controller); + ~Provider(); Media::Type type() override; bool hasSelectRestriction() override; @@ -99,6 +100,7 @@ private: void itemRemoved(not_null item); void markLayoutsStale(); void clearStaleLayouts(); + void clear(); [[nodiscard]] HistoryItem *ensureItem(StoryId id); [[nodiscard]] Media::BaseLayout *getLayout( diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index e1e6cc875..d05aa292c 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -302,7 +302,9 @@ Controller::Controller(not_null delegate) _contentFadeAnimation.stop(); } -Controller::~Controller() = default; +Controller::~Controller() { + changeShown(nullptr); +} void Controller::updateContentFaded() { if (_contentFaded == _replyActive) { @@ -480,6 +482,9 @@ void Controller::initLayout() { } Data::Story *Controller::story() const { + if (!_session) { + return nullptr; + } const auto maybeStory = _session->data().stories().lookup(_shown); return maybeStory ? maybeStory->get() : nullptr; } @@ -748,10 +753,9 @@ void Controller::show( .date = story->date(), .edited = story->edited(), }); - if (_shown == storyId && _session == &story->session()) { + if (!changeShown(story)) { return; } - _shown = storyId; _viewed = false; invalidate_weak_ptrs(&_viewsLoadGuard); _reactions->hide(); @@ -769,41 +773,72 @@ void Controller::show( .valid = user->isSelf(), }); - const auto session = &story->session(); - if (_session != session) { - _session = session; - _sessionLifetime = session->changes().storyUpdates( - Data::StoryUpdate::Flag::Destroyed - ) | rpl::start_with_next([=](Data::StoryUpdate update) { - if (update.story->fullId() == _shown) { - _delegate->storiesClose(); - } - }); - session->data().stories().itemsChanged( - ) | rpl::start_with_next([=](PeerId peerId) { - if (_waitingForId.peer == peerId) { - checkWaitingFor(); - } - }, _sessionLifetime); - session->changes().storyUpdates( - Data::StoryUpdate::Flag::Edited - ) | rpl::filter([=](const Data::StoryUpdate &update) { - return (update.story == this->story()); - }) | rpl::start_with_next([=](const Data::StoryUpdate &update) { - show(update.story, _context); - _delegate->storiesRedisplay(update.story); - }, _sessionLifetime); - _sessionLifetime.add([=] { - session->data().stories().setPreloadingInViewer({}); - }); - } - stories.loadAround(storyId, context); updatePlayingAllowed(); user->updateFull(); } +bool Controller::changeShown(Data::Story *story) { + const auto id = story ? story->fullId() : FullStoryId(); + const auto session = story ? &story->session() : nullptr; + const auto sessionChanged = (_session != session); + if (_shown == id && !sessionChanged) { + return false; + } + if (const auto now = this->story()) { + now->owner().stories().unregisterPolling( + now, + Data::Stories::Polling::Viewer); + } + if (sessionChanged) { + _sessionLifetime.destroy(); + } + _shown = id; + _session = session; + if (sessionChanged) { + subscribeToSession(); + } + if (story) { + story->owner().stories().registerPolling( + story, + Data::Stories::Polling::Viewer); + } + return true; +} + +void Controller::subscribeToSession() { + Expects(!_sessionLifetime); + + if (!_session) { + return; + } + _session->changes().storyUpdates( + Data::StoryUpdate::Flag::Destroyed + ) | rpl::start_with_next([=](Data::StoryUpdate update) { + if (update.story->fullId() == _shown) { + _delegate->storiesClose(); + } + }, _sessionLifetime); + _session->data().stories().itemsChanged( + ) | rpl::start_with_next([=](PeerId peerId) { + if (_waitingForId.peer == peerId) { + checkWaitingFor(); + } + }, _sessionLifetime); + _session->changes().storyUpdates( + Data::StoryUpdate::Flag::Edited + ) | rpl::filter([=](const Data::StoryUpdate &update) { + return (update.story == this->story()); + }) | rpl::start_with_next([=](const Data::StoryUpdate &update) { + show(update.story, _context); + _delegate->storiesRedisplay(update.story); + }, _sessionLifetime); + _sessionLifetime.add([=] { + _session->data().stories().setPreloadingInViewer({}); + }); +} + void Controller::updatePlayingAllowed() { if (!_shown) { return; diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index 5463cdc83..37d7b60fb 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -164,6 +164,8 @@ private: class Unsupported; void initLayout(); + bool changeShown(Data::Story *story); + void subscribeToSession(); void updatePhotoPlayback(const Player::TrackState &state); void updatePlayback(const Player::TrackState &state); void updatePowerSaveBlocker(const Player::TrackState &state);