init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
This commit is contained in:
218
Telegram/SourceFiles/data/data_search_controller.h
Normal file
218
Telegram/SourceFiles/data/data_search_controller.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
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_sparse_ids.h"
|
||||
#include "storage/storage_sparse_ids_list.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/qt/qt_compare.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Data {
|
||||
enum class LoadDirection : char;
|
||||
struct MessagePosition;
|
||||
} // namespace Data
|
||||
|
||||
namespace Api {
|
||||
|
||||
struct SearchResult {
|
||||
std::vector<MsgId> messageIds;
|
||||
MsgRange noSkipRange;
|
||||
int fullCount = 0;
|
||||
};
|
||||
|
||||
using SearchRequest = MTPmessages_Search;
|
||||
using SearchRequestResult = MTPmessages_Messages;
|
||||
|
||||
using HistoryResult = SearchResult;
|
||||
using HistoryRequest = MTPmessages_GetHistory;
|
||||
using HistoryRequestResult = MTPmessages_Messages;
|
||||
|
||||
using GlobalMediaRequest = MTPmessages_SearchGlobal;
|
||||
struct GlobalMediaResult {
|
||||
std::vector<Data::MessagePosition> messageIds;
|
||||
int32 offsetRate = 0;
|
||||
int fullCount = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] MTPMessagesFilter PrepareSearchFilter(
|
||||
Storage::SharedMediaType type);
|
||||
|
||||
[[nodiscard]] std::optional<GlobalMediaRequest> PrepareGlobalMediaRequest(
|
||||
not_null<Main::Session*> session,
|
||||
int32 offsetRate,
|
||||
Data::MessagePosition offsetPosition,
|
||||
Storage::SharedMediaType type,
|
||||
const QString &query);
|
||||
|
||||
[[nodiscard]] GlobalMediaResult ParseGlobalMediaResult(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPmessages_Messages &data);
|
||||
|
||||
[[nodiscard]] std::optional<SearchRequest> PrepareSearchRequest(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
Storage::SharedMediaType type,
|
||||
const QString &query,
|
||||
MsgId messageId,
|
||||
Data::LoadDirection direction);
|
||||
|
||||
[[nodiscard]] SearchResult ParseSearchResult(
|
||||
not_null<PeerData*> peer,
|
||||
Storage::SharedMediaType type,
|
||||
MsgId messageId,
|
||||
Data::LoadDirection direction,
|
||||
const SearchRequestResult &data);
|
||||
|
||||
[[nodiscard]] HistoryRequest PrepareHistoryRequest(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId messageId,
|
||||
Data::LoadDirection direction);
|
||||
|
||||
[[nodiscard]] HistoryResult ParseHistoryResult(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId messageId,
|
||||
Data::LoadDirection direction,
|
||||
const HistoryRequestResult &data);
|
||||
|
||||
class SearchController final {
|
||||
public:
|
||||
using IdsList = Storage::SparseIdsList;
|
||||
struct Query {
|
||||
using MediaType = Storage::SharedMediaType;
|
||||
|
||||
PeerId peerId = 0;
|
||||
MsgId topicRootId = 0;
|
||||
PeerId monoforumPeerId = 0;
|
||||
PeerId migratedPeerId = 0;
|
||||
MediaType type = MediaType::kCount;
|
||||
QString query;
|
||||
// from_id, min_date, max_date
|
||||
|
||||
friend inline std::strong_ordering operator<=>(
|
||||
const Query &a,
|
||||
const Query &b) noexcept = default;
|
||||
|
||||
};
|
||||
struct SavedState {
|
||||
Query query;
|
||||
IdsList peerList;
|
||||
std::optional<IdsList> migratedList;
|
||||
};
|
||||
|
||||
explicit SearchController(not_null<Main::Session*> session);
|
||||
void setQuery(const Query &query);
|
||||
bool hasInCache(const Query &query) const;
|
||||
|
||||
Query query() const {
|
||||
Expects(_current != _cache.cend());
|
||||
|
||||
return _current->first;
|
||||
}
|
||||
|
||||
rpl::producer<SparseIdsMergedSlice> idsSlice(
|
||||
SparseIdsMergedSlice::UniversalMsgId aroundId,
|
||||
int limitBefore,
|
||||
int limitAfter);
|
||||
|
||||
SavedState saveState();
|
||||
void restoreState(SavedState &&state);
|
||||
|
||||
private:
|
||||
struct Data {
|
||||
explicit Data(not_null<PeerData*> peer) : peer(peer) {
|
||||
}
|
||||
|
||||
not_null<PeerData*> peer;
|
||||
IdsList list;
|
||||
base::flat_map<
|
||||
SparseIdsSliceBuilder::AroundData,
|
||||
rpl::lifetime> requests;
|
||||
};
|
||||
using SliceUpdate = Storage::SparseIdsSliceUpdate;
|
||||
|
||||
struct CacheEntry {
|
||||
CacheEntry(not_null<Main::Session*> session, const Query &query);
|
||||
|
||||
Data peerData;
|
||||
std::optional<Data> migratedData;
|
||||
};
|
||||
|
||||
using Cache = base::flat_map<Query, std::unique_ptr<CacheEntry>>;
|
||||
|
||||
rpl::producer<SparseIdsSlice> simpleIdsSlice(
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
MsgId aroundId,
|
||||
const Query &query,
|
||||
int limitBefore,
|
||||
int limitAfter);
|
||||
void requestMore(
|
||||
const SparseIdsSliceBuilder::AroundData &key,
|
||||
const Query &query,
|
||||
Data *listData);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
Cache _cache;
|
||||
Cache::iterator _current = _cache.end();
|
||||
|
||||
};
|
||||
|
||||
class DelayedSearchController {
|
||||
public:
|
||||
explicit DelayedSearchController(not_null<Main::Session*> session);
|
||||
|
||||
using Query = SearchController::Query;
|
||||
using SavedState = SearchController::SavedState;
|
||||
|
||||
void setQuery(const Query &query);
|
||||
void setQuery(const Query &query, crl::time delay);
|
||||
void setQueryFast(const Query &query);
|
||||
|
||||
Query currentQuery() const {
|
||||
return _controller.query();
|
||||
}
|
||||
|
||||
rpl::producer<SparseIdsMergedSlice> idsSlice(
|
||||
SparseIdsMergedSlice::UniversalMsgId aroundId,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
return _controller.idsSlice(
|
||||
aroundId,
|
||||
limitBefore,
|
||||
limitAfter);
|
||||
}
|
||||
|
||||
rpl::producer<QString> currentQueryValue() const {
|
||||
return _currentQueryChanges.events_starting_with(
|
||||
currentQuery().query);
|
||||
}
|
||||
|
||||
SavedState saveState() {
|
||||
return _controller.saveState();
|
||||
}
|
||||
|
||||
void restoreState(SavedState &&state) {
|
||||
_controller.restoreState(std::move(state));
|
||||
}
|
||||
|
||||
private:
|
||||
SearchController _controller;
|
||||
Query _nextQuery;
|
||||
base::Timer _timer;
|
||||
rpl::event_stream<QString> _currentQueryChanges;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
Reference in New Issue
Block a user