That fuck shit the fascists are using
1package org.tm.archive.conversation;
2
3import androidx.annotation.NonNull;
4
5import org.tm.archive.conversation.mutiselect.MultiselectPart;
6import org.tm.archive.database.model.MmsMessageRecord;
7import org.tm.archive.database.model.MessageRecord;
8import org.tm.archive.recipients.Recipient;
9import org.tm.archive.util.MessageRecordUtil;
10import org.tm.archive.util.MessageConstraintsUtil;
11
12import java.util.Set;
13import java.util.stream.Collectors;
14
15public final class MenuState {
16
17 private static final int MAX_FORWARDABLE_COUNT = 32;
18
19 private final boolean forward;
20 private final boolean reply;
21 private final boolean details;
22 private final boolean saveAttachment;
23 private final boolean resend;
24 private final boolean copy;
25 private final boolean delete;
26 private final boolean reactions;
27 private final boolean paymentDetails;
28 private final boolean edit;
29
30 private MenuState(@NonNull Builder builder) {
31 forward = builder.forward;
32 reply = builder.reply;
33 details = builder.details;
34 saveAttachment = builder.saveAttachment;
35 resend = builder.resend;
36 copy = builder.copy;
37 delete = builder.delete;
38 reactions = builder.reactions;
39 paymentDetails = builder.paymentDetails;
40 edit = builder.edit;
41 }
42
43 public boolean shouldShowForwardAction() {
44 return forward;
45 }
46
47 public boolean shouldShowReplyAction() {
48 return reply;
49 }
50
51 public boolean shouldShowDetailsAction() {
52 return details;
53 }
54
55 public boolean shouldShowSaveAttachmentAction() {
56 return saveAttachment;
57 }
58
59 public boolean shouldShowResendAction() {
60 return resend;
61 }
62
63 public boolean shouldShowCopyAction() {
64 return copy;
65 }
66
67 public boolean shouldShowDeleteAction() {
68 return delete;
69 }
70
71 public boolean shouldShowReactions() {
72 return reactions;
73 }
74
75 public boolean shouldShowPaymentDetails() {
76 return paymentDetails;
77 }
78
79 public boolean shouldShowEditAction() {
80 return edit;
81 }
82
83 public static MenuState getMenuState(@NonNull Recipient conversationRecipient,
84 @NonNull Set<MultiselectPart> selectedParts,
85 boolean shouldShowMessageRequest,
86 boolean isNonAdminInAnnouncementGroup)
87 {
88
89 Builder builder = new Builder();
90 boolean actionMessage = false;
91 boolean hasText = false;
92 boolean sharedContact = false;
93 boolean viewOnce = false;
94 boolean remoteDelete = false;
95 boolean hasInMemory = false;
96 boolean hasPendingMedia = false;
97 boolean mediaIsSelected = false;
98 boolean hasGift = false;
99 boolean hasPayment = false;
100
101 for (MultiselectPart part : selectedParts) {
102 MessageRecord messageRecord = part.getMessageRecord();
103
104 if (isActionMessage(messageRecord)) {
105 actionMessage = true;
106 if (messageRecord.isInMemoryMessageRecord()) {
107 hasInMemory = true;
108 }
109 }
110
111 if (!(part instanceof MultiselectPart.Attachments)) {
112 if (messageRecord.getBody().length() > 0) {
113 hasText = true;
114 }
115 } else {
116 mediaIsSelected = true;
117 if (messageRecord.isMediaPending()) {
118 hasPendingMedia = true;
119 }
120 }
121
122 if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getSharedContacts().isEmpty()) {
123 sharedContact = true;
124 }
125
126 if (messageRecord.isViewOnce()) {
127 viewOnce = true;
128 }
129
130 if (messageRecord.isRemoteDelete()) {
131 remoteDelete = true;
132 }
133
134 if (MessageRecordUtil.hasGiftBadge(messageRecord)) {
135 hasGift = true;
136 }
137
138 if (messageRecord.isPaymentNotification()) {
139 hasPayment = true;
140 }
141 }
142
143 boolean shouldShowForwardAction = !actionMessage &&
144 !viewOnce &&
145 !remoteDelete &&
146 !hasPendingMedia &&
147 !hasGift &&
148 !hasPayment &&
149 selectedParts.size() <= MAX_FORWARDABLE_COUNT;
150
151 int uniqueRecords = selectedParts.stream()
152 .map(MultiselectPart::getMessageRecord)
153 .collect(Collectors.toSet())
154 .size();
155
156 if (uniqueRecords > 1) {
157 builder.shouldShowForwardAction(shouldShowForwardAction)
158 .shouldShowReplyAction(false)
159 .shouldShowDetailsAction(false)
160 .shouldShowSaveAttachmentAction(false)
161 .shouldShowResendAction(false)
162 .shouldShowEdit(false);
163 } else {
164 MultiselectPart multiSelectRecord = selectedParts.iterator().next();
165
166 MessageRecord messageRecord = multiSelectRecord.getMessageRecord();
167
168 builder.shouldShowResendAction(messageRecord.isFailed())
169 .shouldShowSaveAttachmentAction(mediaIsSelected &&
170 !actionMessage &&
171 !viewOnce &&
172 messageRecord.isMms() &&
173 !hasPendingMedia &&
174 !hasGift &&
175 !messageRecord.isMmsNotification() &&
176 ((MmsMessageRecord)messageRecord).containsMediaSlide() &&
177 ((MmsMessageRecord)messageRecord).getSlideDeck().getStickerSlide() == null)
178 .shouldShowForwardAction(shouldShowForwardAction)
179 .shouldShowDetailsAction(!actionMessage && !conversationRecipient.isReleaseNotes())
180 .shouldShowReplyAction(canReplyToMessage(conversationRecipient, actionMessage, messageRecord, shouldShowMessageRequest, isNonAdminInAnnouncementGroup));
181
182 builder.shouldShowEdit(!actionMessage &&
183 hasText &&
184 !multiSelectRecord.getConversationMessage().getOriginalMessage().isFailed() &&
185 MessageConstraintsUtil.isValidEditMessageSend(multiSelectRecord.getConversationMessage().getOriginalMessage(), System.currentTimeMillis()));
186 }
187
188 return builder.shouldShowCopyAction(!actionMessage && !remoteDelete && hasText && !hasGift && !hasPayment)
189 .shouldShowDeleteAction(!hasInMemory && onlyContainsCompleteMessages(selectedParts))
190 .shouldShowReactions(!conversationRecipient.isReleaseNotes())
191 .shouldShowPaymentDetails(hasPayment)
192 .build();
193 }
194
195 private static boolean onlyContainsCompleteMessages(@NonNull Set<MultiselectPart> multiselectParts) {
196 return multiselectParts.stream()
197 .map(MultiselectPart::getConversationMessage)
198 .map(ConversationMessage::getMultiselectCollection)
199 .allMatch(collection -> multiselectParts.containsAll(collection.toSet()));
200 }
201
202 public static boolean canReplyToMessage(@NonNull Recipient conversationRecipient,
203 boolean actionMessage,
204 @NonNull MessageRecord messageRecord,
205 boolean isDisplayingMessageRequest,
206 boolean isNonAdminInAnnouncementGroup)
207 {
208 return !actionMessage &&
209 !isNonAdminInAnnouncementGroup &&
210 !messageRecord.isRemoteDelete() &&
211 !messageRecord.isPending() &&
212 !messageRecord.isFailed() &&
213 !isDisplayingMessageRequest &&
214 messageRecord.isSecure() &&
215 (!conversationRecipient.isGroup() || conversationRecipient.isActiveGroup()) &&
216 !messageRecord.getFromRecipient().isBlocked() &&
217 !conversationRecipient.isReleaseNotes();
218 }
219
220 public static boolean isActionMessage(@NonNull MessageRecord messageRecord) {
221 return messageRecord.isInMemoryMessageRecord() || messageRecord.isUpdate();
222 }
223
224 private final static class Builder {
225
226 private boolean forward;
227 private boolean reply;
228 private boolean details;
229 private boolean saveAttachment;
230 private boolean resend;
231 private boolean copy;
232 private boolean delete;
233 private boolean reactions;
234 private boolean paymentDetails;
235 private boolean edit;
236
237 @NonNull Builder shouldShowForwardAction(boolean forward) {
238 this.forward = forward;
239 return this;
240 }
241
242 @NonNull Builder shouldShowReplyAction(boolean reply) {
243 this.reply = reply;
244 return this;
245 }
246
247 @NonNull Builder shouldShowDetailsAction(boolean details) {
248 this.details = details;
249 return this;
250 }
251
252 @NonNull Builder shouldShowSaveAttachmentAction(boolean saveAttachment) {
253 this.saveAttachment = saveAttachment;
254 return this;
255 }
256
257 @NonNull Builder shouldShowResendAction(boolean resend) {
258 this.resend = resend;
259 return this;
260 }
261
262 @NonNull Builder shouldShowCopyAction(boolean copy) {
263 this.copy = copy;
264 return this;
265 }
266
267 @NonNull Builder shouldShowDeleteAction(boolean delete) {
268 this.delete = delete;
269 return this;
270 }
271
272 @NonNull Builder shouldShowReactions(boolean reactions) {
273 this.reactions = reactions;
274 return this;
275 }
276
277 @NonNull Builder shouldShowPaymentDetails(boolean paymentDetails) {
278 this.paymentDetails = paymentDetails;
279 return this;
280 }
281
282 @NonNull Builder shouldShowEdit(boolean edit) {
283 this.edit = edit;
284 return this;
285 }
286
287 @NonNull
288 MenuState build() {
289 return new MenuState(this);
290 }
291 }
292}