/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/expected.h" class Image; class PhotoData; class DocumentData; namespace Main { class Session; } // namespace Main namespace Data { class Session; struct StoryMedia { std::variant, not_null> data; friend inline bool operator==(StoryMedia, StoryMedia) = default; }; class Story { public: Story( StoryId id, not_null peer, StoryMedia media, TimeId date); [[nodiscard]] Session &owner() const; [[nodiscard]] Main::Session &session() const; [[nodiscard]] not_null peer() const; [[nodiscard]] StoryId id() const; [[nodiscard]] FullStoryId fullId() const; [[nodiscard]] TimeId date() const; [[nodiscard]] const StoryMedia &media() const; [[nodiscard]] PhotoData *photo() const; [[nodiscard]] DocumentData *document() const; [[nodiscard]] bool hasReplyPreview() const; [[nodiscard]] Image *replyPreview() const; [[nodiscard]] TextWithEntities inReplyText() const; void setPinned(bool pinned); [[nodiscard]] bool pinned() const; void setCaption(TextWithEntities &&caption); [[nodiscard]] const TextWithEntities &caption() const; bool applyChanges(StoryMedia media, const MTPDstoryItem &data); private: const StoryId _id = 0; const not_null _peer; StoryMedia _media; TextWithEntities _caption; const TimeId _date = 0; bool _pinned = false; }; struct StoriesList { not_null user; std::vector ids; StoryId readTill = 0; int total = 0; [[nodiscard]] bool unread() const; friend inline bool operator==(StoriesList, StoriesList) = default; }; enum class NoStory : uchar { Unknown, Deleted, }; class Stories final { public: explicit Stories(not_null owner); ~Stories(); [[nodiscard]] Session &owner() const; [[nodiscard]] Main::Session &session() const; void updateDependentMessages(not_null story); void registerDependentMessage( not_null dependent, not_null dependency); void unregisterDependentMessage( not_null dependent, not_null dependency); void loadMore(); void apply(const MTPDupdateStories &data); [[nodiscard]] const std::vector &all(); [[nodiscard]] bool allLoaded() const; [[nodiscard]] rpl::producer<> allChanged() const; [[nodiscard]] base::expected, NoStory> lookup( FullStoryId id) const; void resolve(FullStoryId id, Fn done); private: [[nodiscard]] StoriesList parse(const MTPUserStories &stories); [[nodiscard]] Story *parseAndApply( not_null peer, const MTPDstoryItem &data); void processResolvedStories( not_null peer, const QVector &list); void sendResolveRequests(); void finalizeResolve(FullStoryId id); void pushToBack(StoriesList &&list); void applyChanges(StoriesList &&list); void applyDeleted(FullStoryId id); void removeDependencyStory(not_null story); const not_null _owner; base::flat_map< PeerId, base::flat_map>> _stories; base::flat_set _deleted; base::flat_map< PeerId, base::flat_map>>> _resolves; base::flat_map>> _resolveRequests; std::map< not_null, base::flat_set>> _dependentMessages; std::vector _all; rpl::event_stream<> _allChanged; QString _state; bool _allLoaded = false; mtpRequestId _loadMoreRequestId = 0; }; } // namespace Data