1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9 
10 #include "base/timer.h"
11 
12 class History;
13 class HistoryItem;
14 
15 namespace Main {
16 class Session;
17 } // namespace Main
18 
19 namespace Data {
20 
21 class Session;
22 class Folder;
23 
24 class Histories final {
25 public:
26 	enum class RequestType : uchar {
27 		None,
28 		History,
29 		ReadInbox,
30 		Delete,
31 		Send,
32 	};
33 
34 	explicit Histories(not_null<Session*> owner);
35 
36 	[[nodiscard]] Session &owner() const;
37 	[[nodiscard]] Main::Session &session() const;
38 
39 	[[nodiscard]] History *find(PeerId peerId);
40 	[[nodiscard]] not_null<History*> findOrCreate(PeerId peerId);
41 
42 	void applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs);
43 
44 	void unloadAll();
45 	void clearAll();
46 
47 	void readInbox(not_null<History*> history);
48 	void readInboxTill(not_null<HistoryItem*> item);
49 	void readInboxTill(not_null<History*> history, MsgId tillId);
50 	void readInboxOnNewMessage(not_null<HistoryItem*> item);
51 	void readClientSideMessage(not_null<HistoryItem*> item);
52 	void sendPendingReadInbox(not_null<History*> history);
53 
54 	void requestDialogEntry(not_null<Data::Folder*> folder);
55 	void requestDialogEntry(
56 		not_null<History*> history,
57 		Fn<void()> callback = nullptr);
58 	void dialogEntryApplied(not_null<History*> history);
59 	void changeDialogUnreadMark(not_null<History*> history, bool unread);
60 	void requestFakeChatListMessage(not_null<History*> history);
61 
62 	void requestGroupAround(not_null<HistoryItem*> item);
63 
64 	void deleteMessages(
65 		not_null<History*> history,
66 		const QVector<MTPint> &ids,
67 		bool revoke);
68 	void deleteAllMessages(
69 		not_null<History*> history,
70 		MsgId deleteTillId,
71 		bool justClear,
72 		bool revoke);
73 
74 	void deleteMessages(const MessageIdsList &ids, bool revoke);
75 
76 	int sendRequest(
77 		not_null<History*> history,
78 		RequestType type,
79 		Fn<mtpRequestId(Fn<void()> finish)> generator);
80 	void cancelRequest(int id);
81 
82 private:
83 	struct PostponedHistoryRequest {
84 		Fn<mtpRequestId(Fn<void()> finish)> generator;
85 	};
86 	struct SentRequest {
87 		Fn<mtpRequestId(Fn<void()> finish)> generator;
88 		mtpRequestId id = 0;
89 		RequestType type = RequestType::None;
90 	};
91 	struct State {
92 		base::flat_map<int, PostponedHistoryRequest> postponed;
93 		base::flat_map<int, SentRequest> sent;
94 		MsgId willReadTill = 0;
95 		MsgId sentReadTill = 0;
96 		crl::time willReadWhen = 0;
97 		bool sentReadDone = false;
98 		bool postponedRequestEntry = false;
99 	};
100 	struct ChatListGroupRequest {
101 		MsgId aroundId = 0;
102 		mtpRequestId requestId = 0;
103 	};
104 
105 	void readInboxTill(not_null<History*> history, MsgId tillId, bool force);
106 	void sendReadRequests();
107 	void sendReadRequest(not_null<History*> history, State &state);
108 	[[nodiscard]] State *lookup(not_null<History*> history);
109 	void checkEmptyState(not_null<History*> history);
110 	void checkPostponed(not_null<History*> history, int id);
111 	void finishSentRequest(
112 		not_null<History*> history,
113 		not_null<State*> state,
114 		int id);
115 	[[nodiscard]] bool postponeHistoryRequest(const State &state) const;
116 	[[nodiscard]] bool postponeEntryRequest(const State &state) const;
117 	void postponeRequestDialogEntries();
118 
119 	void sendDialogRequests();
120 
121 	const not_null<Session*> _owner;
122 
123 	std::unordered_map<PeerId, std::unique_ptr<History>> _map;
124 	base::flat_map<not_null<History*>, State> _states;
125 	base::flat_map<int, not_null<History*>> _historyByRequest;
126 	int _requestAutoincrement = 0;
127 	base::Timer _readRequestsTimer;
128 
129 	base::flat_set<not_null<Data::Folder*>> _dialogFolderRequests;
130 	base::flat_map<
131 		not_null<History*>,
132 		std::vector<Fn<void()>>> _dialogRequests;
133 	base::flat_map<
134 		not_null<History*>,
135 		std::vector<Fn<void()>>> _dialogRequestsPending;
136 
137 	base::flat_set<not_null<History*>> _fakeChatListRequests;
138 
139 	base::flat_map<
140 		not_null<History*>,
141 		ChatListGroupRequest> _chatListGroupRequests;
142 
143 };
144 
145 } // namespace Data
146