Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/SignalServiceKit/Messages/Interactions/TSInfoMessage.m
1 views
1
//
2
// Copyright 2017 Signal Messenger, LLC
3
// SPDX-License-Identifier: AGPL-3.0-only
4
//
5
6
#import "TSInfoMessage.h"
7
#import <SignalServiceKit/SignalServiceKit-Swift.h>
8
9
NS_ASSUME_NONNULL_BEGIN
10
11
const InfoMessageUserInfoKey InfoMessageUserInfoKeyLegacyGroupUpdateItems = @"InfoMessageUserInfoKeyUpdateMessages";
12
const InfoMessageUserInfoKey InfoMessageUserInfoKeyGroupUpdateItems = @"InfoMessageUserInfoKeyUpdateMessagesV2";
13
const InfoMessageUserInfoKey InfoMessageUserInfoKeyOldGroupModel = @"InfoMessageUserInfoKeyOldGroupModel";
14
const InfoMessageUserInfoKey InfoMessageUserInfoKeyNewGroupModel = @"InfoMessageUserInfoKeyNewGroupModel";
15
const InfoMessageUserInfoKey InfoMessageUserInfoKeyOldDisappearingMessageToken
16
= @"InfoMessageUserInfoKeyOldDisappearingMessageToken";
17
const InfoMessageUserInfoKey InfoMessageUserInfoKeyNewDisappearingMessageToken
18
= @"InfoMessageUserInfoKeyNewDisappearingMessageToken";
19
const InfoMessageUserInfoKey InfoMessageUserInfoKeyGroupUpdateSourceLegacyAddress
20
= @"InfoMessageUserInfoKeyGroupUpdateSourceAddress";
21
const InfoMessageUserInfoKey InfoMessageUserInfoKeyLegacyUpdaterKnownToBeLocalUser
22
= @"InfoMessageUserInfoKeyUpdaterWasLocalUser";
23
const InfoMessageUserInfoKey InfoMessageUserInfoKeyProfileChanges = @"InfoMessageUserInfoKeyProfileChanges";
24
const InfoMessageUserInfoKey InfoMessageUserInfoKeyChangePhoneNumberAciString
25
= @"InfoMessageUserInfoKeyChangePhoneNumberUuid";
26
const InfoMessageUserInfoKey InfoMessageUserInfoKeyChangePhoneNumberOld = @"InfoMessageUserInfoKeyChangePhoneNumberOld";
27
const InfoMessageUserInfoKey InfoMessageUserInfoKeyChangePhoneNumberNew = @"InfoMessageUserInfoKeyChangePhoneNumberNew";
28
const InfoMessageUserInfoKey InfoMessageUserInfoKeyPaymentActivationRequestSenderAci
29
= @"InfoMessageUserInfoKeyPaymentActivationRequestSenderAci";
30
const InfoMessageUserInfoKey InfoMessageUserInfoKeyPaymentActivatedAci = @"InfoMessageUserInfoKeyPaymentActivatedAci";
31
const InfoMessageUserInfoKey InfoMessageUserInfoKeyThreadMergePhoneNumber
32
= @"InfoMessageUserInfoKeyThreadMergePhoneNumber";
33
const InfoMessageUserInfoKey InfoMessageUserInfoKeySessionSwitchoverPhoneNumber
34
= @"InfoMessageUserInfoKeySessionSwitchoverPhoneNumber";
35
const InfoMessageUserInfoKey InfoMessageUserInfoKeyPhoneNumberDisplayNameBeforeLearningProfileName
36
= @"InfoMessageUserInfoKeyPhoneNumberDisplayNameBeforeLearningProfileName";
37
const InfoMessageUserInfoKey InfoMessageUserInfoKeyUsernameDisplayNameBeforeLearningProfileName
38
= @"InfoMessageUserInfoKeyUsernameDisplayNameBeforeLearningProfileName";
39
const InfoMessageUserInfoKey InfoMessageUserInfoKeyEndPoll = @"InfoMessageUserInfoKeyEndPoll";
40
const InfoMessageUserInfoKey InfoMessageUserInfoKeyPinnedMessage = @"InfoMessageUserInfoKeyPinnedMessage";
41
42
@interface TSInfoMessage ()
43
44
@property (nonatomic, getter=wasRead) BOOL read;
45
46
@end
47
48
#pragma mark -
49
50
@implementation TSInfoMessage
51
52
+ (NSArray<Class> *)infoMessageUserInfoObjectClasses
53
{
54
return @[
55
[DisappearingMessageToken class],
56
[NSDictionary class],
57
[NSNull class],
58
[NSNumber class],
59
[NSString class],
60
[PersistableEndPollItem class],
61
[PersistablePinnedMessageItem class],
62
[ProfileChanges class],
63
[SignalServiceAddress class],
64
[TSGroupModel class],
65
[TSInfoMessageUpdateMessages class],
66
[TSInfoMessageUpdateMessagesV2 class]
67
];
68
}
69
70
- (NSUInteger)hash
71
{
72
NSUInteger result = [super hash];
73
result ^= self.customMessage.hash;
74
result ^= self.infoMessageUserInfo.hash;
75
result ^= (NSUInteger)self.messageType;
76
result ^= self.read;
77
result ^= self.serverGuid.hash;
78
result ^= self.unregisteredAddress.hash;
79
return result;
80
}
81
82
- (BOOL)isEqual:(id)other
83
{
84
if (![super isEqual:other]) {
85
return NO;
86
}
87
TSInfoMessage *typedOther = (TSInfoMessage *)other;
88
if (![NSObject isObject:self.customMessage equalToObject:typedOther.customMessage]) {
89
return NO;
90
}
91
if (![NSObject isObject:self.infoMessageUserInfo equalToObject:typedOther.infoMessageUserInfo]) {
92
return NO;
93
}
94
if (self.messageType != typedOther.messageType) {
95
return NO;
96
}
97
if (self.read != typedOther.read) {
98
return NO;
99
}
100
if (![NSObject isObject:self.serverGuid equalToObject:typedOther.serverGuid]) {
101
return NO;
102
}
103
if (![NSObject isObject:self.unregisteredAddress equalToObject:typedOther.unregisteredAddress]) {
104
return NO;
105
}
106
return YES;
107
}
108
109
- (instancetype)initWithThread:(TSThread *)thread
110
timestamp:(uint64_t)timestamp
111
serverGuid:(nullable NSString *)serverGuid
112
messageType:(TSInfoMessageType)messageType
113
expireTimerVersion:(nullable NSNumber *)expireTimerVersion
114
expiresInSeconds:(unsigned int)expiresInSeconds
115
infoMessageUserInfo:(nullable NSDictionary<InfoMessageUserInfoKey, id> *)infoMessageUserInfo
116
{
117
TSMessageBuilder *builder;
118
if (timestamp > 0) {
119
builder = [TSMessageBuilder messageBuilderWithThread:thread timestamp:timestamp];
120
} else {
121
builder = [TSMessageBuilder messageBuilderWithThread:thread];
122
}
123
124
if (expiresInSeconds > 0 && expireTimerVersion != nil) {
125
builder.expiresInSeconds = expiresInSeconds;
126
builder.expireTimerVersion = expireTimerVersion;
127
}
128
129
self = [super initMessageWithBuilder:builder];
130
if (!self) {
131
return self;
132
}
133
134
_serverGuid = serverGuid;
135
_messageType = messageType;
136
_infoMessageUserInfo = infoMessageUserInfo;
137
138
if (self.isDynamicInteraction) {
139
self.read = YES;
140
}
141
142
if (_messageType == TSInfoMessageTypeGroupQuit) {
143
self.read = YES;
144
}
145
146
return self;
147
}
148
149
// --- CODE GENERATION MARKER
150
151
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run
152
// `sds_codegen.sh`.
153
154
// clang-format off
155
156
- (instancetype)initWithGrdbId:(int64_t)grdbId
157
uniqueId:(NSString *)uniqueId
158
receivedAtTimestamp:(uint64_t)receivedAtTimestamp
159
sortId:(uint64_t)sortId
160
timestamp:(uint64_t)timestamp
161
uniqueThreadId:(NSString *)uniqueThreadId
162
body:(nullable NSString *)body
163
bodyRanges:(nullable MessageBodyRanges *)bodyRanges
164
contactShare:(nullable OWSContact *)contactShare
165
deprecated_attachmentIds:(nullable NSArray<NSString *> *)deprecated_attachmentIds
166
editState:(TSEditState)editState
167
expireStartedAt:(uint64_t)expireStartedAt
168
expireTimerVersion:(nullable NSNumber *)expireTimerVersion
169
expiresAt:(uint64_t)expiresAt
170
expiresInSeconds:(unsigned int)expiresInSeconds
171
giftBadge:(nullable OWSGiftBadge *)giftBadge
172
isGroupStoryReply:(BOOL)isGroupStoryReply
173
isPoll:(BOOL)isPoll
174
isSmsMessageRestoredFromBackup:(BOOL)isSmsMessageRestoredFromBackup
175
isViewOnceComplete:(BOOL)isViewOnceComplete
176
isViewOnceMessage:(BOOL)isViewOnceMessage
177
linkPreview:(nullable OWSLinkPreview *)linkPreview
178
messageSticker:(nullable MessageSticker *)messageSticker
179
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
180
storedShouldStartExpireTimer:(BOOL)storedShouldStartExpireTimer
181
storyAuthorUuidString:(nullable NSString *)storyAuthorUuidString
182
storyReactionEmoji:(nullable NSString *)storyReactionEmoji
183
storyTimestamp:(nullable NSNumber *)storyTimestamp
184
wasRemotelyDeleted:(BOOL)wasRemotelyDeleted
185
customMessage:(nullable NSString *)customMessage
186
infoMessageUserInfo:(nullable NSDictionary<InfoMessageUserInfoKey, id> *)infoMessageUserInfo
187
messageType:(TSInfoMessageType)messageType
188
read:(BOOL)read
189
serverGuid:(nullable NSString *)serverGuid
190
unregisteredAddress:(nullable SignalServiceAddress *)unregisteredAddress
191
{
192
self = [super initWithGrdbId:grdbId
193
uniqueId:uniqueId
194
receivedAtTimestamp:receivedAtTimestamp
195
sortId:sortId
196
timestamp:timestamp
197
uniqueThreadId:uniqueThreadId
198
body:body
199
bodyRanges:bodyRanges
200
contactShare:contactShare
201
deprecated_attachmentIds:deprecated_attachmentIds
202
editState:editState
203
expireStartedAt:expireStartedAt
204
expireTimerVersion:expireTimerVersion
205
expiresAt:expiresAt
206
expiresInSeconds:expiresInSeconds
207
giftBadge:giftBadge
208
isGroupStoryReply:isGroupStoryReply
209
isPoll:isPoll
210
isSmsMessageRestoredFromBackup:isSmsMessageRestoredFromBackup
211
isViewOnceComplete:isViewOnceComplete
212
isViewOnceMessage:isViewOnceMessage
213
linkPreview:linkPreview
214
messageSticker:messageSticker
215
quotedMessage:quotedMessage
216
storedShouldStartExpireTimer:storedShouldStartExpireTimer
217
storyAuthorUuidString:storyAuthorUuidString
218
storyReactionEmoji:storyReactionEmoji
219
storyTimestamp:storyTimestamp
220
wasRemotelyDeleted:wasRemotelyDeleted];
221
222
if (!self) {
223
return self;
224
}
225
226
_customMessage = customMessage;
227
_infoMessageUserInfo = infoMessageUserInfo;
228
_messageType = messageType;
229
_read = read;
230
_serverGuid = serverGuid;
231
_unregisteredAddress = unregisteredAddress;
232
233
return self;
234
}
235
236
// clang-format on
237
238
// --- CODE GENERATION MARKER
239
240
- (OWSInteractionType)interactionType
241
{
242
return OWSInteractionType_Info;
243
}
244
245
- (NSString *)conversationSystemMessageComponentTextWithTransaction:(DBReadTransaction *)transaction
246
{
247
switch (self.messageType) {
248
case TSInfoMessageSyncedThread:
249
// This particular string is here, and not in `infoMessagePreviewTextWithTransaction`,
250
// because we want it to be excluded from everywhere except chat list rendering.
251
// e.g. not in the conversation list preview.
252
return OWSLocalizedString(@"INFO_MESSAGE_SYNCED_THREAD",
253
@"Shown in inbox and conversation after syncing as a placeholder indicating why your message history "
254
@"is missing.");
255
default:
256
return [self infoMessagePreviewTextWithTransaction:transaction];
257
}
258
}
259
260
- (NSString *)infoMessagePreviewTextWithTransaction:(DBReadTransaction *)transaction
261
{
262
return [self _infoMessagePreviewTextWithTx:transaction];
263
}
264
265
#pragma mark - OWSReadTracking
266
267
- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp
268
thread:(TSThread *)thread
269
circumstance:(OWSReceiptCircumstance)circumstance
270
shouldClearNotifications:(BOOL)shouldClearNotifications
271
transaction:(DBWriteTransaction *)transaction
272
{
273
OWSAssertDebug(transaction);
274
275
if (self.read) {
276
return;
277
}
278
279
[self anyUpdateInfoMessageWithTransaction:transaction block:^(TSInfoMessage *message) { message.read = YES; }];
280
281
// Ignore `circumstance` - we never send read receipts for info messages.
282
}
283
284
@end
285
286
NS_ASSUME_NONNULL_END
287
288