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 "history/history_item.h"
11 
12 namespace HistoryView {
13 class Service;
14 } // namespace HistoryView
15 
16 struct HistoryServiceDependentData {
17 	PeerId peerId = 0;
18 	MsgId msgId = 0;
19 	HistoryItem *msg = nullptr;
20 	ClickHandlerPtr lnk;
21 };
22 
23 struct HistoryServicePinned
24 : public RuntimeComponent<HistoryServicePinned, HistoryItem>
25 , public HistoryServiceDependentData {
26 };
27 
28 struct HistoryServiceGameScore
29 : public RuntimeComponent<HistoryServiceGameScore, HistoryItem>
30 , public HistoryServiceDependentData {
31 	int score = 0;
32 };
33 
34 struct HistoryServicePayment
35 : public RuntimeComponent<HistoryServicePayment, HistoryItem>
36 , public HistoryServiceDependentData {
37 	QString amount;
38 	ClickHandlerPtr invoiceLink;
39 };
40 
41 struct HistoryServiceSelfDestruct
42 : public RuntimeComponent<HistoryServiceSelfDestruct, HistoryItem> {
43 	enum class Type {
44 		Photo,
45 		Video,
46 	};
47 	Type type = Type::Photo;
48 	crl::time timeToLive = 0;
49 	crl::time destructAt = 0;
50 };
51 
52 struct HistoryServiceOngoingCall
53 : public RuntimeComponent<HistoryServiceOngoingCall, HistoryItem> {
54 	CallId id = 0;
55 	ClickHandlerPtr link;
56 	rpl::lifetime lifetime;
57 };
58 
59 namespace HistoryView {
60 class ServiceMessagePainter;
61 } // namespace HistoryView
62 
63 class HistoryService : public HistoryItem {
64 public:
65 	struct PreparedText {
66 		QString text;
67 		QList<ClickHandlerPtr> links;
68 	};
69 
70 	HistoryService(
71 		not_null<History*> history,
72 		MsgId id,
73 		const MTPDmessage &data,
74 		MessageFlags localFlags);
75 	HistoryService(
76 		not_null<History*> history,
77 		MsgId id,
78 		const MTPDmessageService &data,
79 		MessageFlags localFlags);
80 	HistoryService(
81 		not_null<History*> history,
82 		MsgId id,
83 		MessageFlags flags,
84 		TimeId date,
85 		const PreparedText &message,
86 		PeerId from = 0,
87 		PhotoData *photo = nullptr);
88 
89 	bool updateDependencyItem() override;
dependencyMsgId()90 	MsgId dependencyMsgId() const override {
91 		if (auto dependent = GetDependentData()) {
92 			return dependent->msgId;
93 		}
94 		return 0;
95 	}
notificationReady()96 	bool notificationReady() const override {
97 		if (auto dependent = GetDependentData()) {
98 			return (dependent->msg || !dependent->msgId);
99 		}
100 		return true;
101 	}
102 
103 	void applyEdition(const MTPDmessageService &message) override;
104 	crl::time getSelfDestructIn(crl::time now) override;
105 
106 	Storage::SharedMediaTypesMask sharedMediaTypes() const override;
107 
108 	void dependencyItemRemoved(HistoryItem *dependency) override;
109 
110 	bool needCheck() const override;
isService()111 	bool isService() const override {
112 		return true;
113 	}
114 	ItemPreview toPreview(ToPreviewOptions options) const override;
115 	QString inReplyText() const override;
116 
117 	std::unique_ptr<HistoryView::Element> createView(
118 		not_null<HistoryView::ElementDelegate*> delegate,
119 		HistoryView::Element *replacing = nullptr) override;
120 
121 	void setServiceText(const PreparedText &prepared);
122 
123 	~HistoryService();
124 
125 protected:
126 	friend class HistoryView::ServiceMessagePainter;
127 
128 	void markMediaAsReadHook() override;
129 
130 	QString fromLinkText() const;
131 	ClickHandlerPtr fromLink() const;
132 
133 	void removeMedia();
134 
135 private:
GetDependentData()136 	HistoryServiceDependentData *GetDependentData() {
137 		if (auto pinned = Get<HistoryServicePinned>()) {
138 			return pinned;
139 		} else if (auto gamescore = Get<HistoryServiceGameScore>()) {
140 			return gamescore;
141 		} else if (auto payment = Get<HistoryServicePayment>()) {
142 			return payment;
143 		}
144 		return nullptr;
145 	}
GetDependentData()146 	const HistoryServiceDependentData *GetDependentData() const {
147 		return const_cast<HistoryService*>(this)->GetDependentData();
148 	}
149 	bool updateDependent(bool force = false);
150 	void updateDependentText();
151 	void updateText(PreparedText &&text);
152 	void clearDependency();
153 
154 	void createFromMtp(const MTPDmessage &message);
155 	void createFromMtp(const MTPDmessageService &message);
156 	void setMessageByAction(const MTPmessageAction &action);
157 	void setSelfDestruct(
158 		HistoryServiceSelfDestruct::Type type,
159 		int ttlSeconds);
160 	void applyAction(const MTPMessageAction &action);
161 
162 	PreparedText preparePinnedText();
163 	PreparedText prepareGameScoreText();
164 	PreparedText preparePaymentSentText();
165 	PreparedText prepareInvitedToCallText(
166 		const QVector<MTPlong> &users,
167 		CallId linkCallId);
168 	PreparedText prepareCallScheduledText(
169 		TimeId scheduleDate);
170 
171 	friend class HistoryView::Service;
172 
173 };
174 
175 [[nodiscard]] not_null<HistoryService*> GenerateJoinedMessage(
176 	not_null<History*> history,
177 	TimeId inviteDate,
178 	not_null<UserData*> inviter,
179 	bool viaRequest);
180 [[nodiscard]] std::optional<bool> PeerHasThisCall(
181 	not_null<PeerData*> peer,
182 	CallId id);
183