info_controller.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "data/data_message_reaction_id.h"
  9. #include "data/data_search_controller.h"
  10. #include "info/statistics/info_statistics_tag.h"
  11. #include "window/window_session_controller.h"
  12. namespace Api {
  13. struct WhoReadList;
  14. } // namespace Api
  15. namespace Data {
  16. class ForumTopic;
  17. } // namespace Data
  18. namespace Ui {
  19. class SearchFieldController;
  20. } // namespace Ui
  21. namespace Info::Settings {
  22. struct Tag {
  23. explicit Tag(not_null<UserData*> self) : self(self) {
  24. }
  25. not_null<UserData*> self;
  26. };
  27. } // namespace Info::Settings
  28. namespace Info::Downloads {
  29. struct Tag {
  30. };
  31. } // namespace Info::Downloads
  32. namespace Info::GlobalMedia {
  33. struct Tag {
  34. explicit Tag(not_null<UserData*> self) : self(self) {
  35. }
  36. not_null<UserData*> self;
  37. };
  38. } // namespace Info::GlobalMedia
  39. namespace Info::Stories {
  40. enum class Tab {
  41. Saved,
  42. Archive,
  43. };
  44. struct Tag {
  45. explicit Tag(not_null<PeerData*> peer, Tab tab = {})
  46. : peer(peer)
  47. , tab(tab) {
  48. }
  49. not_null<PeerData*> peer;
  50. Tab tab = {};
  51. };
  52. } // namespace Info::Stories
  53. namespace Info::BotStarRef {
  54. enum class Type : uchar {
  55. Setup,
  56. Join,
  57. };
  58. struct Tag {
  59. Tag(not_null<PeerData*> peer, Type type) : peer(peer), type(type) {
  60. }
  61. not_null<PeerData*> peer;
  62. Type type = {};
  63. };
  64. } // namespace Info::BotStarRef
  65. namespace Info {
  66. class Key {
  67. public:
  68. explicit Key(not_null<PeerData*> peer);
  69. explicit Key(not_null<Data::ForumTopic*> topic);
  70. Key(Settings::Tag settings);
  71. Key(Downloads::Tag downloads);
  72. Key(Stories::Tag stories);
  73. Key(Statistics::Tag statistics);
  74. Key(BotStarRef::Tag starref);
  75. Key(GlobalMedia::Tag global);
  76. Key(not_null<PollData*> poll, FullMsgId contextId);
  77. Key(
  78. std::shared_ptr<Api::WhoReadList> whoReadIds,
  79. Data::ReactionId selected,
  80. FullMsgId contextId);
  81. PeerData *peer() const;
  82. Data::ForumTopic *topic() const;
  83. UserData *settingsSelf() const;
  84. bool isDownloads() const;
  85. bool isGlobalMedia() const;
  86. PeerData *storiesPeer() const;
  87. Stories::Tab storiesTab() const;
  88. Statistics::Tag statisticsTag() const;
  89. PeerData *starrefPeer() const;
  90. BotStarRef::Type starrefType() const;
  91. PollData *poll() const;
  92. FullMsgId pollContextId() const;
  93. std::shared_ptr<Api::WhoReadList> reactionsWhoReadIds() const;
  94. Data::ReactionId reactionsSelected() const;
  95. FullMsgId reactionsContextId() const;
  96. private:
  97. struct PollKey {
  98. not_null<PollData*> poll;
  99. FullMsgId contextId;
  100. };
  101. struct ReactionsKey {
  102. std::shared_ptr<Api::WhoReadList> whoReadIds;
  103. Data::ReactionId selected;
  104. FullMsgId contextId;
  105. };
  106. std::variant<
  107. not_null<PeerData*>,
  108. not_null<Data::ForumTopic*>,
  109. Settings::Tag,
  110. Downloads::Tag,
  111. Stories::Tag,
  112. Statistics::Tag,
  113. BotStarRef::Tag,
  114. GlobalMedia::Tag,
  115. PollKey,
  116. ReactionsKey> _value;
  117. };
  118. enum class Wrap;
  119. class WrapWidget;
  120. class Memento;
  121. class ContentMemento;
  122. class Section final {
  123. public:
  124. enum class Type {
  125. Profile,
  126. Media,
  127. GlobalMedia,
  128. CommonGroups,
  129. SimilarPeers,
  130. RequestsList,
  131. ReactionsList,
  132. SavedSublists,
  133. PeerGifts,
  134. Members,
  135. Settings,
  136. Downloads,
  137. Stories,
  138. PollResults,
  139. Statistics,
  140. BotStarRef,
  141. Boosts,
  142. ChannelEarn,
  143. BotEarn,
  144. };
  145. using SettingsType = ::Settings::Type;
  146. using MediaType = Storage::SharedMediaType;
  147. Section(Type type) : _type(type) {
  148. Expects(type != Type::Media
  149. && type != Type::GlobalMedia
  150. && type != Type::Settings);
  151. }
  152. Section(MediaType mediaType, Type type = Type::Media)
  153. : _type(type)
  154. , _mediaType(mediaType) {
  155. }
  156. Section(SettingsType settingsType)
  157. : _type(Type::Settings)
  158. , _settingsType(settingsType) {
  159. }
  160. [[nodiscard]] Type type() const {
  161. return _type;
  162. }
  163. [[nodiscard]] MediaType mediaType() const {
  164. Expects(_type == Type::Media || _type == Type::GlobalMedia);
  165. return _mediaType;
  166. }
  167. [[nodiscard]] SettingsType settingsType() const {
  168. Expects(_type == Type::Settings);
  169. return _settingsType;
  170. }
  171. private:
  172. Type _type;
  173. MediaType _mediaType = MediaType();
  174. SettingsType _settingsType = SettingsType();
  175. };
  176. class AbstractController : public Window::SessionNavigation {
  177. public:
  178. AbstractController(not_null<Window::SessionController*> parent);
  179. [[nodiscard]] virtual Key key() const = 0;
  180. [[nodiscard]] virtual PeerData *migrated() const = 0;
  181. [[nodiscard]] virtual Section section() const = 0;
  182. [[nodiscard]] PeerData *peer() const;
  183. [[nodiscard]] PeerId migratedPeerId() const;
  184. [[nodiscard]] Data::ForumTopic *topic() const {
  185. return key().topic();
  186. }
  187. [[nodiscard]] UserData *settingsSelf() const {
  188. return key().settingsSelf();
  189. }
  190. [[nodiscard]] bool isDownloads() const {
  191. return key().isDownloads();
  192. }
  193. [[nodiscard]] bool isGlobalMedia() const {
  194. return key().isGlobalMedia();
  195. }
  196. [[nodiscard]] PeerData *storiesPeer() const {
  197. return key().storiesPeer();
  198. }
  199. [[nodiscard]] Stories::Tab storiesTab() const {
  200. return key().storiesTab();
  201. }
  202. [[nodiscard]] Statistics::Tag statisticsTag() const {
  203. return key().statisticsTag();
  204. }
  205. [[nodiscard]] PeerData *starrefPeer() const {
  206. return key().starrefPeer();
  207. }
  208. [[nodiscard]] BotStarRef::Type starrefType() const {
  209. return key().starrefType();
  210. }
  211. [[nodiscard]] PollData *poll() const;
  212. [[nodiscard]] FullMsgId pollContextId() const {
  213. return key().pollContextId();
  214. }
  215. [[nodiscard]] auto reactionsWhoReadIds() const
  216. -> std::shared_ptr<Api::WhoReadList>;
  217. [[nodiscard]] Data::ReactionId reactionsSelected() const;
  218. [[nodiscard]] FullMsgId reactionsContextId() const;
  219. virtual void setSearchEnabledByContent(bool enabled) {
  220. }
  221. virtual rpl::producer<SparseIdsMergedSlice> mediaSource(
  222. SparseIdsMergedSlice::UniversalMsgId aroundId,
  223. int limitBefore,
  224. int limitAfter) const;
  225. virtual rpl::producer<QString> mediaSourceQueryValue() const;
  226. virtual rpl::producer<QString> searchQueryValue() const;
  227. void showSection(
  228. std::shared_ptr<Window::SectionMemento> memento,
  229. const Window::SectionShow &params = Window::SectionShow()) override;
  230. void showBackFromStack(
  231. const Window::SectionShow &params = Window::SectionShow()) override;
  232. void showPeerHistory(
  233. PeerId peerId,
  234. const Window::SectionShow &params = Window::SectionShow::Way::ClearStack,
  235. MsgId msgId = ShowAtUnreadMsgId) override;
  236. not_null<Window::SessionController*> parentController() override {
  237. return _parent;
  238. }
  239. private:
  240. not_null<Window::SessionController*> _parent;
  241. };
  242. class Controller : public AbstractController {
  243. public:
  244. Controller(
  245. not_null<WrapWidget*> widget,
  246. not_null<Window::SessionController*> window,
  247. not_null<ContentMemento*> memento);
  248. Key key() const override {
  249. return _key;
  250. }
  251. PeerData *migrated() const override {
  252. return _migrated;
  253. }
  254. Section section() const override {
  255. return _section;
  256. }
  257. [[nodiscard]] bool validateMementoPeer(
  258. not_null<ContentMemento*> memento) const;
  259. [[nodiscard]] Wrap wrap() const;
  260. [[nodiscard]] rpl::producer<Wrap> wrapValue() const;
  261. [[nodiscard]] not_null<Ui::RpWidget*> wrapWidget() const;
  262. void setSection(not_null<ContentMemento*> memento);
  263. [[nodiscard]] bool hasBackButton() const;
  264. Ui::SearchFieldController *searchFieldController() const {
  265. return _searchFieldController.get();
  266. }
  267. void setSearchEnabledByContent(bool enabled) override {
  268. _seachEnabledByContent = enabled;
  269. }
  270. rpl::producer<bool> searchEnabledByContent() const;
  271. rpl::producer<SparseIdsMergedSlice> mediaSource(
  272. SparseIdsMergedSlice::UniversalMsgId aroundId,
  273. int limitBefore,
  274. int limitAfter) const override;
  275. rpl::producer<QString> mediaSourceQueryValue() const override;
  276. rpl::producer<QString> searchQueryValue() const override;
  277. bool takeSearchStartsFocused() {
  278. return base::take(_searchStartsFocused);
  279. }
  280. void saveSearchState(not_null<ContentMemento*> memento);
  281. void showSection(
  282. std::shared_ptr<Window::SectionMemento> memento,
  283. const Window::SectionShow &params = Window::SectionShow()) override;
  284. void showBackFromStack(
  285. const Window::SectionShow &params = Window::SectionShow()) override;
  286. void removeFromStack(const std::vector<Section> &sections) const;
  287. void takeStepData(not_null<Controller*> another);
  288. std::any &stepDataReference();
  289. rpl::lifetime &lifetime() {
  290. return _lifetime;
  291. }
  292. ~Controller();
  293. private:
  294. using SearchQuery = Api::DelayedSearchController::Query;
  295. void updateSearchControllers(not_null<ContentMemento*> memento);
  296. SearchQuery produceSearchQuery(const QString &query) const;
  297. void setupMigrationViewer();
  298. void setupTopicViewer();
  299. void replaceWith(std::shared_ptr<Memento> memento);
  300. not_null<WrapWidget*> _widget;
  301. Key _key;
  302. PeerData *_migrated = nullptr;
  303. rpl::variable<Wrap> _wrap;
  304. Section _section;
  305. std::unique_ptr<Ui::SearchFieldController> _searchFieldController;
  306. std::unique_ptr<Api::DelayedSearchController> _searchController;
  307. rpl::variable<bool> _seachEnabledByContent = false;
  308. bool _searchStartsFocused = false;
  309. // Data between sections based on steps.
  310. std::any _stepData;
  311. rpl::lifetime _lifetime;
  312. };
  313. } // namespace Info