/* 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 "base/timer.h" class History; class HistoryItem; namespace Main { class Session; } // namespace Main namespace MTP { class Error; struct Response; } // namespace MTP namespace Data { class Session; class Folder; [[nodiscard]] MTPInputReplyTo ReplyToForMTP( not_null owner, FullReplyTo replyTo); class Histories final { public: enum class RequestType : uchar { None, History, ReadInbox, Delete, Send, }; explicit Histories(not_null owner); [[nodiscard]] Session &owner() const; [[nodiscard]] Main::Session &session() const; [[nodiscard]] History *find(PeerId peerId); [[nodiscard]] not_null findOrCreate(PeerId peerId); void applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs); void unloadAll(); void clearAll(); void readInbox(not_null history); void readInboxTill(not_null item); void readInboxTill(not_null history, MsgId tillId); void readInboxOnNewMessage(not_null item); void readClientSideMessage(not_null item); void sendPendingReadInbox(not_null history); void requestDialogEntry(not_null folder); void requestDialogEntry( not_null history, Fn callback = nullptr); void dialogEntryApplied(not_null history); void changeDialogUnreadMark(not_null history, bool unread); void requestFakeChatListMessage(not_null history); void requestGroupAround(not_null item); void deleteMessages( not_null history, const QVector &ids, bool revoke); void deleteAllMessages( not_null history, MsgId deleteTillId, bool justClear, bool revoke); void deleteMessagesByDates( not_null history, QDate firstDayToDelete, QDate lastDayToDelete, bool revoke); void deleteMessagesByDates( not_null history, TimeId minDate, TimeId maxDate, bool revoke); void deleteMessages(const MessageIdsList &ids, bool revoke); int sendRequest( not_null history, RequestType type, Fn finish)> generator); void cancelRequest(int id); using PreparedMessage = std::variant< MTPmessages_SendMessage, MTPmessages_SendMedia, MTPmessages_SendInlineBotResult, MTPmessages_SendMultiMedia>; int sendPreparedMessage( not_null history, FullReplyTo replyTo, uint64 randomId, Fn, FullReplyTo)> message, Fn done, Fn fail); struct ReplyToPlaceholder { }; template static auto PrepareMessage(const Args &...args) -> Fn, FullReplyTo)> { return [=](not_null owner, FullReplyTo replyTo) -> RequestType { return { ReplaceReplyIds(owner, args, replyTo)... }; }; } void checkTopicCreated(FullMsgId rootId, MsgId realRoot); [[nodiscard]] MsgId convertTopicReplyToId( not_null history, MsgId replyToId) const; private: struct PostponedHistoryRequest { Fn finish)> generator; }; struct SentRequest { Fn finish)> generator; mtpRequestId id = 0; RequestType type = RequestType::None; }; struct State { base::flat_map postponed; base::flat_map sent; MsgId willReadTill = 0; MsgId sentReadTill = 0; crl::time willReadWhen = 0; bool sentReadDone = false; bool postponedRequestEntry = false; }; struct ChatListGroupRequest { MsgId aroundId = 0; mtpRequestId requestId = 0; }; struct DelayedByTopicMessage { uint64 randomId = 0; MsgId replyTo = 0; Fn, FullReplyTo)> message; Fn done; Fn fail; int requestId = 0; }; struct GroupRequestKey { not_null history; MsgId rootId = 0; friend inline auto operator<=>( GroupRequestKey, GroupRequestKey) = default; }; template static auto ReplaceReplyIds( not_null owner, Arg arg, FullReplyTo replyTo) { if constexpr (std::is_same_v) { return ReplyToForMTP(owner, replyTo); } else { return arg; } } void readInboxTill(not_null history, MsgId tillId, bool force); void sendReadRequests(); void sendReadRequest(not_null history, State &state); [[nodiscard]] State *lookup(not_null history); void checkEmptyState(not_null history); void checkPostponed(not_null history, int id); void finishSentRequest( not_null history, not_null state, int id); [[nodiscard]] bool postponeHistoryRequest(const State &state) const; [[nodiscard]] bool postponeEntryRequest(const State &state) const; void postponeRequestDialogEntries(); void sendDialogRequests(); [[nodiscard]] bool isCreatingTopic( not_null history, MsgId rootId) const; void sendCreateTopicRequest(not_null history, MsgId rootId); void cancelDelayedByTopicRequest(int id); const not_null _owner; std::unordered_map> _map; base::flat_map, State> _states; base::flat_map> _historyByRequest; int _requestAutoincrement = 0; base::Timer _readRequestsTimer; base::flat_set> _dialogFolderRequests; base::flat_map< not_null, std::vector>> _dialogRequests; base::flat_map< not_null, std::vector>> _dialogRequestsPending; base::flat_set> _fakeChatListRequests; base::flat_map< GroupRequestKey, ChatListGroupRequest> _chatListGroupRequests; base::flat_map< FullMsgId, std::vector> _creatingTopics; base::flat_map _createdTopicIds; base::flat_set _creatingTopicRequests; }; } // namespace Data