data_search_controller.h 5.0 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 "data/data_sparse_ids.h"
  9. #include "storage/storage_sparse_ids_list.h"
  10. #include "storage/storage_shared_media.h"
  11. #include "base/timer.h"
  12. #include "base/qt/qt_compare.h"
  13. namespace Main {
  14. class Session;
  15. } // namespace Main
  16. namespace Data {
  17. enum class LoadDirection : char;
  18. struct MessagePosition;
  19. } // namespace Data
  20. namespace Api {
  21. struct SearchResult {
  22. std::vector<MsgId> messageIds;
  23. MsgRange noSkipRange;
  24. int fullCount = 0;
  25. };
  26. using SearchRequest = MTPmessages_Search;
  27. using SearchRequestResult = MTPmessages_Messages;
  28. using HistoryResult = SearchResult;
  29. using HistoryRequest = MTPmessages_GetHistory;
  30. using HistoryRequestResult = MTPmessages_Messages;
  31. using GlobalMediaRequest = MTPmessages_SearchGlobal;
  32. struct GlobalMediaResult {
  33. std::vector<Data::MessagePosition> messageIds;
  34. int32 offsetRate = 0;
  35. int fullCount = 0;
  36. };
  37. [[nodiscard]] MTPMessagesFilter PrepareSearchFilter(
  38. Storage::SharedMediaType type);
  39. [[nodiscard]] std::optional<GlobalMediaRequest> PrepareGlobalMediaRequest(
  40. not_null<Main::Session*> session,
  41. int32 offsetRate,
  42. Data::MessagePosition offsetPosition,
  43. Storage::SharedMediaType type,
  44. const QString &query);
  45. [[nodiscard]] GlobalMediaResult ParseGlobalMediaResult(
  46. not_null<Main::Session*> session,
  47. const MTPmessages_Messages &data);
  48. [[nodiscard]] std::optional<SearchRequest> PrepareSearchRequest(
  49. not_null<PeerData*> peer,
  50. MsgId topicRootId,
  51. Storage::SharedMediaType type,
  52. const QString &query,
  53. MsgId messageId,
  54. Data::LoadDirection direction);
  55. [[nodiscard]] SearchResult ParseSearchResult(
  56. not_null<PeerData*> peer,
  57. Storage::SharedMediaType type,
  58. MsgId messageId,
  59. Data::LoadDirection direction,
  60. const SearchRequestResult &data);
  61. [[nodiscard]] HistoryRequest PrepareHistoryRequest(
  62. not_null<PeerData*> peer,
  63. MsgId messageId,
  64. Data::LoadDirection direction);
  65. [[nodiscard]] HistoryResult ParseHistoryResult(
  66. not_null<PeerData*> peer,
  67. MsgId messageId,
  68. Data::LoadDirection direction,
  69. const HistoryRequestResult &data);
  70. class SearchController final {
  71. public:
  72. using IdsList = Storage::SparseIdsList;
  73. struct Query {
  74. using MediaType = Storage::SharedMediaType;
  75. PeerId peerId = 0;
  76. MsgId topicRootId = 0;
  77. PeerId migratedPeerId = 0;
  78. MediaType type = MediaType::kCount;
  79. QString query;
  80. // from_id, min_date, max_date
  81. friend inline std::strong_ordering operator<=>(
  82. const Query &a,
  83. const Query &b) noexcept = default;
  84. };
  85. struct SavedState {
  86. Query query;
  87. IdsList peerList;
  88. std::optional<IdsList> migratedList;
  89. };
  90. explicit SearchController(not_null<Main::Session*> session);
  91. void setQuery(const Query &query);
  92. bool hasInCache(const Query &query) const;
  93. Query query() const {
  94. Expects(_current != _cache.cend());
  95. return _current->first;
  96. }
  97. rpl::producer<SparseIdsMergedSlice> idsSlice(
  98. SparseIdsMergedSlice::UniversalMsgId aroundId,
  99. int limitBefore,
  100. int limitAfter);
  101. SavedState saveState();
  102. void restoreState(SavedState &&state);
  103. private:
  104. struct Data {
  105. explicit Data(not_null<PeerData*> peer) : peer(peer) {
  106. }
  107. not_null<PeerData*> peer;
  108. IdsList list;
  109. base::flat_map<
  110. SparseIdsSliceBuilder::AroundData,
  111. rpl::lifetime> requests;
  112. };
  113. using SliceUpdate = Storage::SparseIdsSliceUpdate;
  114. struct CacheEntry {
  115. CacheEntry(not_null<Main::Session*> session, const Query &query);
  116. Data peerData;
  117. std::optional<Data> migratedData;
  118. };
  119. using Cache = base::flat_map<Query, std::unique_ptr<CacheEntry>>;
  120. rpl::producer<SparseIdsSlice> simpleIdsSlice(
  121. PeerId peerId,
  122. MsgId topicRootId,
  123. MsgId aroundId,
  124. const Query &query,
  125. int limitBefore,
  126. int limitAfter);
  127. void requestMore(
  128. const SparseIdsSliceBuilder::AroundData &key,
  129. const Query &query,
  130. Data *listData);
  131. const not_null<Main::Session*> _session;
  132. Cache _cache;
  133. Cache::iterator _current = _cache.end();
  134. };
  135. class DelayedSearchController {
  136. public:
  137. explicit DelayedSearchController(not_null<Main::Session*> session);
  138. using Query = SearchController::Query;
  139. using SavedState = SearchController::SavedState;
  140. void setQuery(const Query &query);
  141. void setQuery(const Query &query, crl::time delay);
  142. void setQueryFast(const Query &query);
  143. Query currentQuery() const {
  144. return _controller.query();
  145. }
  146. rpl::producer<SparseIdsMergedSlice> idsSlice(
  147. SparseIdsMergedSlice::UniversalMsgId aroundId,
  148. int limitBefore,
  149. int limitAfter) {
  150. return _controller.idsSlice(
  151. aroundId,
  152. limitBefore,
  153. limitAfter);
  154. }
  155. rpl::producer<QString> currentQueryValue() const {
  156. return _currentQueryChanges.events_starting_with(
  157. currentQuery().query);
  158. }
  159. SavedState saveState() {
  160. return _controller.saveState();
  161. }
  162. void restoreState(SavedState &&state) {
  163. _controller.restoreState(std::move(state));
  164. }
  165. private:
  166. SearchController _controller;
  167. Query _nextQuery;
  168. base::Timer _timer;
  169. rpl::event_stream<QString> _currentQueryChanges;
  170. };
  171. } // namespace Api