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 "mtproto/sender.h"
11 #include "data/stickers/data_stickers_set.h"
12 #include "settings.h"
13 
14 class HistoryItem;
15 class DocumentData;
16 
17 namespace Main {
18 class Session;
19 } // namespace Main
20 
21 namespace Data {
22 
23 class Session;
24 class DocumentMedia;
25 
26 class Stickers final {
27 public:
28 	explicit Stickers(not_null<Session*> owner);
29 
30 	[[nodiscard]] Session &owner() const;
31 	[[nodiscard]] Main::Session &session() const;
32 
33 	// for backward compatibility
34 	static constexpr auto DefaultSetId = 0;
35 	static constexpr auto CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
36 
37 	// For stickers panel, should not appear in Sets.
38 	static constexpr auto RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
39 	static constexpr auto NoneSetId = 0xFFFFFFFFFFFFFFFDULL;
40 	static constexpr auto FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL;
41 
42 	// For cloud-stored recent stickers.
43 	static constexpr auto CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL;
44 	static constexpr auto CloudRecentAttachedSetId = 0xFFFFFFFFFFFFFFF9ULL;
45 
46 	// For cloud-stored faved stickers.
47 	static constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL;
48 
49 	// For setting up megagroup sticker set.
50 	static constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL;
51 
52 	enum Recent {
53 		Regular,
54 		Attached,
55 	};
56 
57 	void notifyUpdated();
58 	[[nodiscard]] rpl::producer<> updated() const;
59 	void notifyRecentUpdated(Recent recent = Recent::Regular);
60 	[[nodiscard]] rpl::producer<Recent> recentUpdated() const;
61 	void notifySavedGifsUpdated();
62 	[[nodiscard]] rpl::producer<> savedGifsUpdated() const;
63 	void notifyStickerSetInstalled(uint64 setId);
64 	[[nodiscard]] rpl::producer<uint64> stickerSetInstalled() const;
65 
66 	void incrementSticker(not_null<DocumentData*> document);
67 
updateNeeded(crl::time now)68 	bool updateNeeded(crl::time now) const {
69 		return updateNeeded(_lastUpdate, now);
70 	}
setLastUpdate(crl::time update)71 	void setLastUpdate(crl::time update) {
72 		_lastUpdate = update;
73 	}
recentUpdateNeeded(crl::time now)74 	bool recentUpdateNeeded(crl::time now) const {
75 		return updateNeeded(_lastRecentUpdate, now);
76 	}
setLastRecentUpdate(crl::time update)77 	void setLastRecentUpdate(crl::time update) {
78 		if (update) {
79 			notifyRecentUpdated();
80 		}
81 		_lastRecentUpdate = update;
82 	}
masksUpdateNeeded(crl::time now)83 	bool masksUpdateNeeded(crl::time now) const {
84 		return updateNeeded(_lastMasksUpdate, now);
85 	}
setLastMasksUpdate(crl::time update)86 	void setLastMasksUpdate(crl::time update) {
87 		_lastMasksUpdate = update;
88 	}
recentAttachedUpdateNeeded(crl::time now)89 	bool recentAttachedUpdateNeeded(crl::time now) const {
90 		return updateNeeded(_lastRecentAttachedUpdate, now);
91 	}
setLastRecentAttachedUpdate(crl::time update)92 	void setLastRecentAttachedUpdate(crl::time update) {
93 		if (update) {
94 			notifyRecentUpdated(Recent::Attached);
95 		}
96 		_lastRecentAttachedUpdate = update;
97 	}
favedUpdateNeeded(crl::time now)98 	bool favedUpdateNeeded(crl::time now) const {
99 		return updateNeeded(_lastFavedUpdate, now);
100 	}
setLastFavedUpdate(crl::time update)101 	void setLastFavedUpdate(crl::time update) {
102 		_lastFavedUpdate = update;
103 	}
featuredUpdateNeeded(crl::time now)104 	bool featuredUpdateNeeded(crl::time now) const {
105 		return updateNeeded(_lastFeaturedUpdate, now);
106 	}
setLastFeaturedUpdate(crl::time update)107 	void setLastFeaturedUpdate(crl::time update) {
108 		_lastFeaturedUpdate = update;
109 	}
savedGifsUpdateNeeded(crl::time now)110 	bool savedGifsUpdateNeeded(crl::time now) const {
111 		return updateNeeded(_lastSavedGifsUpdate, now);
112 	}
setLastSavedGifsUpdate(crl::time update)113 	void setLastSavedGifsUpdate(crl::time update) {
114 		_lastSavedGifsUpdate = update;
115 	}
featuredSetsUnreadCount()116 	int featuredSetsUnreadCount() const {
117 		return _featuredSetsUnreadCount.current();
118 	}
setFeaturedSetsUnreadCount(int count)119 	void setFeaturedSetsUnreadCount(int count) {
120 		_featuredSetsUnreadCount = count;
121 	}
featuredSetsUnreadCountValue()122 	[[nodiscard]] rpl::producer<int> featuredSetsUnreadCountValue() const {
123 		return _featuredSetsUnreadCount.value();
124 	}
sets()125 	const StickersSets &sets() const {
126 		return _sets;
127 	}
setsRef()128 	StickersSets &setsRef() {
129 		return _sets;
130 	}
setsOrder()131 	const StickersSetsOrder &setsOrder() const {
132 		return _setsOrder;
133 	}
setsOrderRef()134 	StickersSetsOrder &setsOrderRef() {
135 		return _setsOrder;
136 	}
maskSetsOrder()137 	const StickersSetsOrder &maskSetsOrder() const {
138 		return _maskSetsOrder;
139 	}
maskSetsOrderRef()140 	StickersSetsOrder &maskSetsOrderRef() {
141 		return _maskSetsOrder;
142 	}
featuredSetsOrder()143 	const StickersSetsOrder &featuredSetsOrder() const {
144 		return _featuredSetsOrder;
145 	}
featuredSetsOrderRef()146 	StickersSetsOrder &featuredSetsOrderRef() {
147 		return _featuredSetsOrder;
148 	}
archivedSetsOrder()149 	const StickersSetsOrder &archivedSetsOrder() const {
150 		return _archivedSetsOrder;
151 	}
archivedSetsOrderRef()152 	StickersSetsOrder &archivedSetsOrderRef() {
153 		return _archivedSetsOrder;
154 	}
archivedMaskSetsOrder()155 	const StickersSetsOrder &archivedMaskSetsOrder() const {
156 		return _archivedMaskSetsOrder;
157 	}
archivedMaskSetsOrderRef()158 	StickersSetsOrder &archivedMaskSetsOrderRef() {
159 		return _archivedMaskSetsOrder;
160 	}
savedGifs()161 	const SavedGifs &savedGifs() const {
162 		return _savedGifs;
163 	}
savedGifsRef()164 	SavedGifs &savedGifsRef() {
165 		return _savedGifs;
166 	}
167 	void removeFromRecentSet(not_null<DocumentData*> document);
168 
169 	void addSavedGif(not_null<DocumentData*> document);
170 	void checkSavedGif(not_null<HistoryItem*> item);
171 
172 	void applyArchivedResult(
173 		const MTPDmessages_stickerSetInstallResultArchive &d);
174 	void installLocally(uint64 setId);
175 	void undoInstallLocally(uint64 setId);
176 	bool isFaved(not_null<const DocumentData*> document);
177 	void setFaved(not_null<DocumentData*> document, bool faved);
178 
179 	void setsReceived(const QVector<MTPStickerSet> &data, uint64 hash);
180 	void masksReceived(const QVector<MTPStickerSet> &data, uint64 hash);
181 	void specialSetReceived(
182 		uint64 setId,
183 		const QString &setTitle,
184 		const QVector<MTPDocument> &items,
185 		uint64 hash,
186 		const QVector<MTPStickerPack> &packs = QVector<MTPStickerPack>(),
187 		const QVector<MTPint> &usageDates = QVector<MTPint>());
188 	void featuredSetsReceived(
189 		const QVector<MTPStickerSetCovered> &list,
190 		const QVector<MTPlong> &unread,
191 		uint64 hash);
192 	void gifsReceived(const QVector<MTPDocument> &items, uint64 hash);
193 
194 	std::vector<not_null<DocumentData*>> getListByEmoji(
195 		not_null<EmojiPtr> emoji,
196 		uint64 seed);
197 	std::optional<std::vector<not_null<EmojiPtr>>> getEmojiListFromSet(
198 		not_null<DocumentData*> document);
199 
200 	StickersSet *feedSet(const MTPDstickerSet &data);
201 	StickersSet *feedSetFull(const MTPmessages_StickerSet &data);
202 	void newSetReceived(const MTPmessages_StickerSet &data);
203 
204 	QString getSetTitle(const MTPDstickerSet &s);
205 
206 	RecentStickerPack &getRecentPack() const;
207 
208 private:
updateNeeded(crl::time lastUpdate,crl::time now)209 	bool updateNeeded(crl::time lastUpdate, crl::time now) const {
210 		constexpr auto kUpdateTimeout = crl::time(3600'000);
211 		return (lastUpdate == 0)
212 			|| (now >= lastUpdate + kUpdateTimeout);
213 	}
214 	void checkFavedLimit(StickersSet &set);
215 	void setIsFaved(
216 		not_null<DocumentData*> document,
217 		std::optional<std::vector<not_null<EmojiPtr>>> emojiList
218 			= std::nullopt);
219 	void setIsNotFaved(not_null<DocumentData*> document);
220 	void pushFavedToFront(
221 		StickersSet &set,
222 		not_null<DocumentData*> document,
223 		const std::vector<not_null<EmojiPtr>> &emojiList);
224 	void moveFavedToFront(StickersSet &set, int index);
225 	void requestSetToPushFaved(not_null<DocumentData*> document);
226 	void setPackAndEmoji(
227 		StickersSet &set,
228 		StickersPack &&pack,
229 		const std::vector<TimeId> &&dates,
230 		const QVector<MTPStickerPack> &packs);
231 	void setsOrMasksReceived(
232 		const QVector<MTPStickerSet> &data,
233 		uint64 hash,
234 		bool masks);
235 
236 	const not_null<Session*> _owner;
237 	rpl::event_stream<> _updated;
238 	rpl::event_stream<Recent> _recentUpdated;
239 	rpl::event_stream<> _savedGifsUpdated;
240 	rpl::event_stream<uint64> _stickerSetInstalled;
241 	crl::time _lastUpdate = 0;
242 	crl::time _lastRecentUpdate = 0;
243 	crl::time _lastFavedUpdate = 0;
244 	crl::time _lastFeaturedUpdate = 0;
245 	crl::time _lastSavedGifsUpdate = 0;
246 	crl::time _lastMasksUpdate = 0;
247 	crl::time _lastRecentAttachedUpdate = 0;
248 	rpl::variable<int> _featuredSetsUnreadCount = 0;
249 	StickersSets _sets;
250 	StickersSetsOrder _setsOrder;
251 	StickersSetsOrder _maskSetsOrder;
252 	StickersSetsOrder _featuredSetsOrder;
253 	StickersSetsOrder _archivedSetsOrder;
254 	StickersSetsOrder _archivedMaskSetsOrder;
255 	SavedGifs _savedGifs;
256 
257 };
258 
259 } // namespace Data
260