dialogs_entry.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 "base/flat_map.h"
  9. #include "base/weak_ptr.h"
  10. #include "base/flags.h"
  11. #include "dialogs/dialogs_common.h"
  12. #include "ui/unread_badge.h"
  13. class HistoryItem;
  14. class History;
  15. class UserData;
  16. namespace Main {
  17. class Session;
  18. } // namespace Main
  19. namespace Data {
  20. class Session;
  21. class Forum;
  22. class Folder;
  23. class ForumTopic;
  24. class SavedSublist;
  25. class Thread;
  26. } // namespace Data
  27. namespace Ui {
  28. struct PeerUserpicView;
  29. } // namespace Ui
  30. namespace Dialogs::Ui {
  31. using namespace ::Ui;
  32. struct PaintContext;
  33. } // namespace Dialogs::Ui
  34. namespace Dialogs {
  35. struct UnreadState;
  36. class Row;
  37. class IndexedList;
  38. class MainList;
  39. [[nodiscard]] BadgesState BadgesForUnread(
  40. const UnreadState &state,
  41. CountInBadge count = CountInBadge::Default,
  42. IncludeInBadge include = IncludeInBadge::Default);
  43. class Entry : public base::has_weak_ptr {
  44. public:
  45. enum class Type : uchar {
  46. History,
  47. Folder,
  48. ForumTopic,
  49. SavedSublist,
  50. };
  51. Entry(not_null<Data::Session*> owner, Type type);
  52. virtual ~Entry();
  53. [[nodiscard]] Data::Session &owner() const;
  54. [[nodiscard]] Main::Session &session() const;
  55. History *asHistory();
  56. Data::Forum *asForum();
  57. Data::Folder *asFolder();
  58. Data::Thread *asThread();
  59. Data::ForumTopic *asTopic();
  60. Data::SavedSublist *asSublist();
  61. const History *asHistory() const;
  62. const Data::Forum *asForum() const;
  63. const Data::Folder *asFolder() const;
  64. const Data::Thread *asThread() const;
  65. const Data::ForumTopic *asTopic() const;
  66. const Data::SavedSublist *asSublist() const;
  67. PositionChange adjustByPosInChatList(
  68. FilterId filterId,
  69. not_null<MainList*> list);
  70. [[nodiscard]] bool inChatList(FilterId filterId = 0) const {
  71. return _chatListLinks.contains(filterId);
  72. }
  73. RowsByLetter *chatListLinks(FilterId filterId);
  74. const RowsByLetter *chatListLinks(FilterId filterId) const;
  75. [[nodiscard]] int posInChatList(FilterId filterId) const;
  76. not_null<Row*> addToChatList(
  77. FilterId filterId,
  78. not_null<MainList*> list);
  79. void setColorIndexForFilterId(FilterId, std::optional<uint8>);
  80. void removeFromChatList(
  81. FilterId filterId,
  82. not_null<MainList*> list);
  83. void removeChatListEntryByLetter(FilterId filterId, QChar letter);
  84. void addChatListEntryByLetter(
  85. FilterId filterId,
  86. QChar letter,
  87. not_null<Row*> row);
  88. void updateChatListEntry();
  89. void updateChatListEntryPostponed();
  90. void updateChatListEntryHeight();
  91. [[nodiscard]] bool isPinnedDialog(FilterId filterId) const {
  92. return lookupPinnedIndex(filterId) != 0;
  93. }
  94. void cachePinnedIndex(FilterId filterId, int index);
  95. [[nodiscard]] uint64 sortKeyInChatList(FilterId filterId) const {
  96. return filterId
  97. ? computeSortPosition(filterId)
  98. : _sortKeyInChatList;
  99. }
  100. void updateChatListSortPosition();
  101. void setChatListTimeId(TimeId date);
  102. virtual void updateChatListExistence();
  103. bool needUpdateInChatList() const;
  104. [[nodiscard]] virtual TimeId adjustedChatListTimeId() const;
  105. [[nodiscard]] virtual int fixedOnTopIndex() const = 0;
  106. static constexpr auto kArchiveFixOnTopIndex = 1;
  107. static constexpr auto kTopPromotionFixOnTopIndex = 2;
  108. [[nodiscard]] virtual bool shouldBeInChatList() const = 0;
  109. [[nodiscard]] virtual UnreadState chatListUnreadState() const = 0;
  110. [[nodiscard]] virtual BadgesState chatListBadgesState() const = 0;
  111. [[nodiscard]] virtual HistoryItem *chatListMessage() const = 0;
  112. [[nodiscard]] virtual bool chatListMessageKnown() const = 0;
  113. [[nodiscard]] virtual const QString &chatListName() const = 0;
  114. [[nodiscard]] virtual const QString &chatListNameSortKey() const = 0;
  115. [[nodiscard]] virtual int chatListNameVersion() const = 0;
  116. [[nodiscard]] virtual auto chatListNameWords() const
  117. -> const base::flat_set<QString> & = 0;
  118. [[nodiscard]] virtual auto chatListFirstLetters() const
  119. -> const base::flat_set<QChar> & = 0;
  120. [[nodiscard]] virtual bool folderKnown() const {
  121. return true;
  122. }
  123. [[nodiscard]] virtual Data::Folder *folder() const {
  124. return nullptr;
  125. }
  126. virtual void chatListPreloadData() = 0;
  127. virtual void paintUserpic(
  128. Painter &p,
  129. Ui::PeerUserpicView &view,
  130. const Ui::PaintContext &context) const = 0;
  131. [[nodiscard]] TimeId chatListTimeId() const {
  132. return _timeId;
  133. }
  134. [[nodiscard]] const Ui::Text::String &chatListNameText() const;
  135. [[nodiscard]] Ui::PeerBadge &chatListPeerBadge() const {
  136. return _chatListPeerBadge;
  137. }
  138. [[nodiscard]] bool hasChatsFilterTags(FilterId exclude) const;
  139. protected:
  140. void notifyUnreadStateChange(const UnreadState &wasState);
  141. inline auto unreadStateChangeNotifier(bool required);
  142. [[nodiscard]] int lookupPinnedIndex(FilterId filterId) const;
  143. private:
  144. enum class Flag : uchar {
  145. IsThread = (1 << 0),
  146. IsHistory = (1 << 1),
  147. IsSavedSublist = (1 << 2),
  148. UpdatePostponed = (1 << 3),
  149. InUnreadChangeBlock = (1 << 4),
  150. };
  151. friend inline constexpr bool is_flag_type(Flag) { return true; }
  152. using Flags = base::flags<Flag>;
  153. virtual void changedChatListPinHook();
  154. void pinnedIndexChanged(FilterId filterId, int was, int now);
  155. [[nodiscard]] uint64 computeSortPosition(FilterId filterId) const;
  156. void setChatListExistence(bool exists);
  157. not_null<Row*> mainChatListLink(FilterId filterId) const;
  158. Row *maybeMainChatListLink(FilterId filterId) const;
  159. const not_null<Data::Session*> _owner;
  160. base::flat_map<FilterId, RowsByLetter> _chatListLinks;
  161. uint64 _sortKeyInChatList = 0;
  162. uint64 _sortKeyByDate = 0;
  163. base::flat_map<FilterId, int> _pinnedIndex;
  164. base::flat_map<FilterId, uint8> _tagColors;
  165. mutable Ui::PeerBadge _chatListPeerBadge;
  166. mutable Ui::Text::String _chatListNameText;
  167. mutable int _chatListNameVersion = 0;
  168. TimeId _timeId = 0;
  169. Flags _flags;
  170. };
  171. auto Entry::unreadStateChangeNotifier(bool required) {
  172. Expects(!(_flags & Flag::InUnreadChangeBlock));
  173. _flags |= Flag::InUnreadChangeBlock;
  174. const auto notify = required && inChatList();
  175. const auto wasState = notify ? chatListUnreadState() : UnreadState();
  176. return gsl::finally([=, this] {
  177. _flags &= ~Flag::InUnreadChangeBlock;
  178. if (notify) {
  179. Assert(inChatList());
  180. notifyUnreadStateChange(wasState);
  181. }
  182. });
  183. }
  184. } // namespace Dialogs