peer_list_controllers.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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 "boxes/peer_list_box.h"
  9. #include "base/flat_set.h"
  10. #include "base/weak_ptr.h"
  11. #include "base/timer.h"
  12. #include "mtproto/sender.h"
  13. class History;
  14. namespace style {
  15. struct PeerListItem;
  16. } // namespace style
  17. namespace Api {
  18. struct MessageMoneyRestriction;
  19. } // namespace Api
  20. namespace Data {
  21. class Thread;
  22. class Forum;
  23. class ForumTopic;
  24. } // namespace Data
  25. namespace Ui {
  26. struct OutlineSegment;
  27. } // namespace Ui
  28. namespace Window {
  29. class SessionController;
  30. } // namespace Window
  31. [[nodiscard]] object_ptr<Ui::BoxContent> PrepareContactsBox(
  32. not_null<Window::SessionController*> sessionController);
  33. [[nodiscard]] QBrush PeerListStoriesGradient(const style::PeerList &st);
  34. [[nodiscard]] std::vector<Ui::OutlineSegment> PeerListStoriesSegments(
  35. int count,
  36. int unread,
  37. const QBrush &unreadBrush);
  38. class PeerListRowWithLink : public PeerListRow {
  39. public:
  40. using PeerListRow::PeerListRow;
  41. void setActionLink(const QString &action);
  42. void lazyInitialize(const style::PeerListItem &st) override;
  43. protected:
  44. QSize rightActionSize() const override;
  45. QMargins rightActionMargins() const override;
  46. void rightActionPaint(
  47. Painter &p,
  48. int x,
  49. int y,
  50. int outerWidth,
  51. bool selected,
  52. bool actionSelected) override;
  53. private:
  54. void refreshActionLink();
  55. QString _action;
  56. int _actionWidth = 0;
  57. };
  58. class PeerListGlobalSearchController : public PeerListSearchController {
  59. public:
  60. explicit PeerListGlobalSearchController(not_null<Main::Session*> session);
  61. void searchQuery(const QString &query) override;
  62. bool isLoading() override;
  63. bool loadMoreRows() override {
  64. return false;
  65. }
  66. private:
  67. bool searchInCache();
  68. void searchOnServer();
  69. void searchDone(const MTPcontacts_Found &result, mtpRequestId requestId);
  70. const not_null<Main::Session*> _session;
  71. MTP::Sender _api;
  72. base::Timer _timer;
  73. QString _query;
  74. mtpRequestId _requestId = 0;
  75. std::map<QString, MTPcontacts_Found> _cache;
  76. std::map<mtpRequestId, QString> _queries;
  77. };
  78. struct RecipientMoneyRestrictionError {
  79. TextWithEntities text;
  80. };
  81. [[nodiscard]] RecipientMoneyRestrictionError WriteMoneyRestrictionError(
  82. not_null<UserData*> user);
  83. struct RestrictionBadgeCache {
  84. int paletteVersion = 0;
  85. int stars = 0;
  86. QImage badge;
  87. };
  88. void PaintRestrictionBadge(
  89. Painter &p,
  90. not_null<const style::PeerListItem*> st,
  91. int stars,
  92. RestrictionBadgeCache &cache,
  93. int x,
  94. int y,
  95. int outerWidth,
  96. int size);
  97. class RecipientRow : public PeerListRow {
  98. public:
  99. explicit RecipientRow(
  100. not_null<PeerData*> peer,
  101. const style::PeerListItem *maybeLockedSt = nullptr,
  102. History *maybeHistory = nullptr);
  103. bool refreshLock(not_null<const style::PeerListItem*> maybeLockedSt);
  104. [[nodiscard]] static bool ShowLockedError(
  105. not_null<PeerListController*> controller,
  106. not_null<PeerListRow*> row,
  107. Fn<RecipientMoneyRestrictionError(not_null<UserData*>)> error);
  108. [[nodiscard]] History *maybeHistory() const {
  109. return _maybeHistory;
  110. }
  111. void paintUserpicOverlay(
  112. Painter &p,
  113. const style::PeerListItem &st,
  114. int x,
  115. int y,
  116. int outerWidth) override;
  117. void preloadUserpic() override;
  118. [[nodiscard]] Api::MessageMoneyRestriction restriction() const;
  119. void setRestriction(Api::MessageMoneyRestriction restriction);
  120. private:
  121. struct Restriction;
  122. History *_maybeHistory = nullptr;
  123. const style::PeerListItem *_maybeLockedSt = nullptr;
  124. std::shared_ptr<Restriction> _restriction;
  125. };
  126. void TrackMessageMoneyRestrictionsChanges(
  127. not_null<PeerListController*> controller,
  128. rpl::lifetime &lifetime);
  129. class ChatsListBoxController : public PeerListController {
  130. public:
  131. class Row : public RecipientRow {
  132. public:
  133. Row(
  134. not_null<History*> history,
  135. const style::PeerListItem *maybeLockedSt = nullptr);
  136. [[nodiscard]] not_null<History*> history() const {
  137. return maybeHistory();
  138. }
  139. };
  140. ChatsListBoxController(not_null<Main::Session*> session);
  141. ChatsListBoxController(
  142. std::unique_ptr<PeerListSearchController> searchController);
  143. void prepare() override final;
  144. std::unique_ptr<PeerListRow> createSearchRow(
  145. not_null<PeerData*> peer) override final;
  146. protected:
  147. virtual std::unique_ptr<Row> createRow(not_null<History*> history) = 0;
  148. virtual void prepareViewHook() = 0;
  149. virtual void updateRowHook(not_null<Row*> row) {
  150. }
  151. virtual QString emptyBoxText() const;
  152. private:
  153. void rebuildRows();
  154. void checkForEmptyRows();
  155. bool appendRow(not_null<History*> history);
  156. };
  157. class PeerListStories final {
  158. public:
  159. PeerListStories(
  160. not_null<PeerListController*> controller,
  161. not_null<Main::Session*> session);
  162. void prepare(not_null<PeerListDelegate*> delegate);
  163. void process(not_null<PeerListRow*> row);
  164. bool handleClick(not_null<PeerData*> peer);
  165. private:
  166. struct Counts {
  167. int count = 0;
  168. int unread = 0;
  169. };
  170. void updateColors();
  171. void updateFor(uint64 id, int count, int unread);
  172. void applyForRow(
  173. not_null<PeerListRow*> row,
  174. int count,
  175. int unread,
  176. bool force = false);
  177. const not_null<PeerListController*> _controller;
  178. const not_null<Main::Session*> _session;
  179. PeerListDelegate *_delegate = nullptr;
  180. QBrush _unreadBrush;
  181. base::flat_map<uint64, Counts> _counts;
  182. rpl::lifetime _lifetime;
  183. };
  184. class ContactsBoxController : public PeerListController {
  185. public:
  186. explicit ContactsBoxController(not_null<Main::Session*> session);
  187. ContactsBoxController(
  188. not_null<Main::Session*> session,
  189. std::unique_ptr<PeerListSearchController> searchController);
  190. [[nodiscard]] Main::Session &session() const override;
  191. void prepare() override final;
  192. [[nodiscard]] std::unique_ptr<PeerListRow> createSearchRow(
  193. not_null<PeerData*> peer) override final;
  194. void rowClicked(not_null<PeerListRow*> row) override;
  195. bool trackSelectedList() override {
  196. return !_stories;
  197. }
  198. enum class SortMode {
  199. Alphabet,
  200. Online,
  201. };
  202. void setSortMode(SortMode mode);
  203. void setStoriesShown(bool shown);
  204. protected:
  205. virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
  206. virtual void prepareViewHook() {
  207. }
  208. virtual void updateRowHook(not_null<PeerListRow*> row) {
  209. }
  210. private:
  211. void sort();
  212. void sortByOnline();
  213. void rebuildRows();
  214. void checkForEmptyRows();
  215. bool appendRow(not_null<UserData*> user);
  216. const not_null<Main::Session*> _session;
  217. SortMode _sortMode = SortMode::Alphabet;
  218. base::Timer _sortByOnlineTimer;
  219. rpl::lifetime _sortByOnlineLifetime;
  220. std::unique_ptr<PeerListStories> _stories;
  221. };
  222. struct ChooseRecipientArgs {
  223. not_null<Main::Session*> session;
  224. FnMut<void(not_null<Data::Thread*>)> callback;
  225. Fn<bool(not_null<Data::Thread*>)> filter;
  226. using MoneyRestrictionError = RecipientMoneyRestrictionError;
  227. Fn<MoneyRestrictionError(not_null<UserData*>)> moneyRestrictionError;
  228. };
  229. class ChooseRecipientBoxController
  230. : public ChatsListBoxController
  231. , public base::has_weak_ptr {
  232. public:
  233. ChooseRecipientBoxController(
  234. not_null<Main::Session*> session,
  235. FnMut<void(not_null<Data::Thread*>)> callback,
  236. Fn<bool(not_null<Data::Thread*>)> filter = nullptr);
  237. explicit ChooseRecipientBoxController(ChooseRecipientArgs &&args);
  238. Main::Session &session() const override;
  239. void rowClicked(not_null<PeerListRow*> row) override;
  240. QString savedMessagesChatStatus() const override;
  241. protected:
  242. void prepareViewHook() override;
  243. std::unique_ptr<Row> createRow(not_null<History*> history) override;
  244. bool showLockedError(not_null<PeerListRow*> row);
  245. private:
  246. const not_null<Main::Session*> _session;
  247. FnMut<void(not_null<Data::Thread*>)> _callback;
  248. Fn<bool(not_null<Data::Thread*>)> _filter;
  249. Fn<RecipientMoneyRestrictionError(
  250. not_null<UserData*>)> _moneyRestrictionError;
  251. };
  252. class ChooseTopicSearchController : public PeerListSearchController {
  253. public:
  254. explicit ChooseTopicSearchController(not_null<Data::Forum*> forum);
  255. void searchQuery(const QString &query) override;
  256. bool isLoading() override;
  257. bool loadMoreRows() override;
  258. private:
  259. void searchOnServer();
  260. void searchDone(const MTPcontacts_Found &result, mtpRequestId requestId);
  261. const not_null<Data::Forum*> _forum;
  262. MTP::Sender _api;
  263. base::Timer _timer;
  264. QString _query;
  265. mtpRequestId _requestId = 0;
  266. TimeId _offsetDate = 0;
  267. MsgId _offsetId = 0;
  268. MsgId _offsetTopicId = 0;
  269. bool _allLoaded = false;
  270. };
  271. class ChooseTopicBoxController final
  272. : public PeerListController
  273. , public base::has_weak_ptr {
  274. public:
  275. ChooseTopicBoxController(
  276. not_null<Data::Forum*> forum,
  277. FnMut<void(not_null<Data::ForumTopic*>)> callback,
  278. Fn<bool(not_null<Data::ForumTopic*>)> filter = nullptr);
  279. Main::Session &session() const override;
  280. void rowClicked(not_null<PeerListRow*> row) override;
  281. void prepare() override;
  282. void loadMoreRows() override;
  283. std::unique_ptr<PeerListRow> createSearchRow(PeerListRowId id) override;
  284. [[nodiscard]] static std::unique_ptr<PeerListRow> MakeRow(
  285. not_null<Data::ForumTopic*> topic);
  286. private:
  287. class Row final : public PeerListRow {
  288. public:
  289. explicit Row(not_null<Data::ForumTopic*> topic);
  290. [[nodiscard]] not_null<Data::ForumTopic*> topic() const {
  291. return _topic;
  292. }
  293. QString generateName() override;
  294. QString generateShortName() override;
  295. PaintRoundImageCallback generatePaintUserpicCallback(
  296. bool forceRound) override;
  297. auto generateNameFirstLetters() const
  298. -> const base::flat_set<QChar> & override;
  299. auto generateNameWords() const
  300. -> const base::flat_set<QString> & override;
  301. private:
  302. const not_null<Data::ForumTopic*> _topic;
  303. };
  304. void refreshRows(bool initial = false);
  305. [[nodiscard]] std::unique_ptr<Row> createRow(
  306. not_null<Data::ForumTopic*> topic);
  307. const not_null<Data::Forum*> _forum;
  308. FnMut<void(not_null<Data::ForumTopic*>)> _callback;
  309. Fn<bool(not_null<Data::ForumTopic*>)> _filter;
  310. };