/* 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 "data/data_message_reaction_id.h" #include "data/data_search_controller.h" #include "info/statistics/info_statistics_tag.h" #include "window/window_session_controller.h" namespace Api { struct WhoReadList; } // namespace Api namespace Data { class ForumTopic; } // namespace Data namespace Ui { class SearchFieldController; } // namespace Ui namespace Info::Settings { struct Tag { explicit Tag(not_null self) : self(self) { } not_null self; }; } // namespace Info::Settings namespace Info::Downloads { struct Tag { }; } // namespace Info::Downloads namespace Info::GlobalMedia { struct Tag { explicit Tag(not_null self) : self(self) { } not_null self; }; } // namespace Info::GlobalMedia namespace Info::Stories { enum class Tab { Saved, Archive, }; struct Tag { explicit Tag(not_null peer, Tab tab = {}) : peer(peer) , tab(tab) { } not_null peer; Tab tab = {}; }; } // namespace Info::Stories namespace Info::BotStarRef { enum class Type : uchar { Setup, Join, }; struct Tag { Tag(not_null peer, Type type) : peer(peer), type(type) { } not_null peer; Type type = {}; }; } // namespace Info::BotStarRef namespace Info { class Key { public: explicit Key(not_null peer); explicit Key(not_null topic); Key(Settings::Tag settings); Key(Downloads::Tag downloads); Key(Stories::Tag stories); Key(Statistics::Tag statistics); Key(BotStarRef::Tag starref); Key(GlobalMedia::Tag global); Key(not_null poll, FullMsgId contextId); Key( std::shared_ptr whoReadIds, Data::ReactionId selected, FullMsgId contextId); PeerData *peer() const; Data::ForumTopic *topic() const; UserData *settingsSelf() const; bool isDownloads() const; bool isGlobalMedia() const; PeerData *storiesPeer() const; Stories::Tab storiesTab() const; Statistics::Tag statisticsTag() const; PeerData *starrefPeer() const; BotStarRef::Type starrefType() const; PollData *poll() const; FullMsgId pollContextId() const; std::shared_ptr reactionsWhoReadIds() const; Data::ReactionId reactionsSelected() const; FullMsgId reactionsContextId() const; private: struct PollKey { not_null poll; FullMsgId contextId; }; struct ReactionsKey { std::shared_ptr whoReadIds; Data::ReactionId selected; FullMsgId contextId; }; std::variant< not_null, not_null, Settings::Tag, Downloads::Tag, Stories::Tag, Statistics::Tag, BotStarRef::Tag, GlobalMedia::Tag, PollKey, ReactionsKey> _value; }; enum class Wrap; class WrapWidget; class Memento; class ContentMemento; class Section final { public: enum class Type { Profile, Media, GlobalMedia, CommonGroups, SimilarPeers, RequestsList, ReactionsList, SavedSublists, PeerGifts, Members, Settings, Downloads, Stories, PollResults, Statistics, BotStarRef, Boosts, ChannelEarn, BotEarn, }; using SettingsType = ::Settings::Type; using MediaType = Storage::SharedMediaType; Section(Type type) : _type(type) { Expects(type != Type::Media && type != Type::GlobalMedia && type != Type::Settings); } Section(MediaType mediaType, Type type = Type::Media) : _type(type) , _mediaType(mediaType) { } Section(SettingsType settingsType) : _type(Type::Settings) , _settingsType(settingsType) { } [[nodiscard]] Type type() const { return _type; } [[nodiscard]] MediaType mediaType() const { Expects(_type == Type::Media || _type == Type::GlobalMedia); return _mediaType; } [[nodiscard]] SettingsType settingsType() const { Expects(_type == Type::Settings); return _settingsType; } private: Type _type; MediaType _mediaType = MediaType(); SettingsType _settingsType = SettingsType(); }; class AbstractController : public Window::SessionNavigation { public: AbstractController(not_null parent); [[nodiscard]] virtual Key key() const = 0; [[nodiscard]] virtual PeerData *migrated() const = 0; [[nodiscard]] virtual Section section() const = 0; [[nodiscard]] PeerData *peer() const; [[nodiscard]] PeerId migratedPeerId() const; [[nodiscard]] Data::ForumTopic *topic() const { return key().topic(); } [[nodiscard]] UserData *settingsSelf() const { return key().settingsSelf(); } [[nodiscard]] bool isDownloads() const { return key().isDownloads(); } [[nodiscard]] bool isGlobalMedia() const { return key().isGlobalMedia(); } [[nodiscard]] PeerData *storiesPeer() const { return key().storiesPeer(); } [[nodiscard]] Stories::Tab storiesTab() const { return key().storiesTab(); } [[nodiscard]] Statistics::Tag statisticsTag() const { return key().statisticsTag(); } [[nodiscard]] PeerData *starrefPeer() const { return key().starrefPeer(); } [[nodiscard]] BotStarRef::Type starrefType() const { return key().starrefType(); } [[nodiscard]] PollData *poll() const; [[nodiscard]] FullMsgId pollContextId() const { return key().pollContextId(); } [[nodiscard]] auto reactionsWhoReadIds() const -> std::shared_ptr; [[nodiscard]] Data::ReactionId reactionsSelected() const; [[nodiscard]] FullMsgId reactionsContextId() const; virtual void setSearchEnabledByContent(bool enabled) { } virtual rpl::producer mediaSource( SparseIdsMergedSlice::UniversalMsgId aroundId, int limitBefore, int limitAfter) const; virtual rpl::producer mediaSourceQueryValue() const; virtual rpl::producer searchQueryValue() const; void showSection( std::shared_ptr memento, const Window::SectionShow ¶ms = Window::SectionShow()) override; void showBackFromStack( const Window::SectionShow ¶ms = Window::SectionShow()) override; void showPeerHistory( PeerId peerId, const Window::SectionShow ¶ms = Window::SectionShow::Way::ClearStack, MsgId msgId = ShowAtUnreadMsgId) override; not_null parentController() override { return _parent; } private: not_null _parent; }; class Controller : public AbstractController { public: Controller( not_null widget, not_null window, not_null memento); Key key() const override { return _key; } PeerData *migrated() const override { return _migrated; } Section section() const override { return _section; } [[nodiscard]] bool validateMementoPeer( not_null memento) const; [[nodiscard]] Wrap wrap() const; [[nodiscard]] rpl::producer wrapValue() const; [[nodiscard]] not_null wrapWidget() const; void setSection(not_null memento); Ui::SearchFieldController *searchFieldController() const { return _searchFieldController.get(); } void setSearchEnabledByContent(bool enabled) override { _seachEnabledByContent = enabled; } rpl::producer searchEnabledByContent() const; rpl::producer mediaSource( SparseIdsMergedSlice::UniversalMsgId aroundId, int limitBefore, int limitAfter) const override; rpl::producer mediaSourceQueryValue() const override; rpl::producer searchQueryValue() const override; bool takeSearchStartsFocused() { return base::take(_searchStartsFocused); } void saveSearchState(not_null memento); void showSection( std::shared_ptr memento, const Window::SectionShow ¶ms = Window::SectionShow()) override; void showBackFromStack( const Window::SectionShow ¶ms = Window::SectionShow()) override; void removeFromStack(const std::vector
§ions) const; void takeStepData(not_null another); std::any &stepDataReference(); rpl::lifetime &lifetime() { return _lifetime; } ~Controller(); private: using SearchQuery = Api::DelayedSearchController::Query; void updateSearchControllers(not_null memento); SearchQuery produceSearchQuery(const QString &query) const; void setupMigrationViewer(); void setupTopicViewer(); void replaceWith(std::shared_ptr memento); not_null _widget; Key _key; PeerData *_migrated = nullptr; rpl::variable _wrap; Section _section; std::unique_ptr _searchFieldController; std::unique_ptr _searchController; rpl::variable _seachEnabledByContent = false; bool _searchStartsFocused = false; // Data between sections based on steps. std::any _stepData; rpl::lifetime _lifetime; }; } // namespace Info