Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/SignalServiceKit/Messages/Interactions/TSIncomingMessage.m
1 views
1
//
2
// Copyright 2017 Signal Messenger, LLC
3
// SPDX-License-Identifier: AGPL-3.0-only
4
//
5
6
#import "TSIncomingMessage.h"
7
#import <SignalServiceKit/SignalServiceKit-Swift.h>
8
9
NS_ASSUME_NONNULL_BEGIN
10
11
@interface TSIncomingMessage ()
12
13
@property (nonatomic, getter=wasRead) BOOL read;
14
@property (nonatomic, getter=wasViewed) BOOL viewed;
15
16
@property (nonatomic, nullable) NSNumber *serverTimestamp;
17
18
@end
19
20
#pragma mark -
21
22
@implementation TSIncomingMessage
23
24
- (NSUInteger)hash
25
{
26
NSUInteger result = [super hash];
27
result ^= self.authorPhoneNumber.hash;
28
result ^= self.authorUUID.hash;
29
result ^= self.deprecated_sourceDeviceId.hash;
30
result ^= self.read;
31
result ^= self.serverDeliveryTimestamp;
32
result ^= self.serverGuid.hash;
33
result ^= self.serverTimestamp.hash;
34
result ^= self.viewed;
35
result ^= self.wasReceivedByUD;
36
return result;
37
}
38
39
- (BOOL)isEqual:(id)other
40
{
41
if (![super isEqual:other]) {
42
return NO;
43
}
44
TSIncomingMessage *typedOther = (TSIncomingMessage *)other;
45
if (![NSObject isObject:self.authorPhoneNumber equalToObject:typedOther.authorPhoneNumber]) {
46
return NO;
47
}
48
if (![NSObject isObject:self.authorUUID equalToObject:typedOther.authorUUID]) {
49
return NO;
50
}
51
if (![NSObject isObject:self.deprecated_sourceDeviceId equalToObject:typedOther.deprecated_sourceDeviceId]) {
52
return NO;
53
}
54
if (self.read != typedOther.read) {
55
return NO;
56
}
57
if (self.serverDeliveryTimestamp != typedOther.serverDeliveryTimestamp) {
58
return NO;
59
}
60
if (![NSObject isObject:self.serverGuid equalToObject:typedOther.serverGuid]) {
61
return NO;
62
}
63
if (![NSObject isObject:self.serverTimestamp equalToObject:typedOther.serverTimestamp]) {
64
return NO;
65
}
66
if (self.viewed != typedOther.viewed) {
67
return NO;
68
}
69
if (self.wasReceivedByUD != typedOther.wasReceivedByUD) {
70
return NO;
71
}
72
return YES;
73
}
74
75
- (instancetype)initIncomingMessageWithBuilder:(TSIncomingMessageBuilder *)incomingMessageBuilder
76
{
77
self = [super initMessageWithBuilder:incomingMessageBuilder];
78
79
if (!self) {
80
return self;
81
}
82
83
_authorUUID = incomingMessageBuilder.authorAciObjC.serviceIdUppercaseString;
84
_authorPhoneNumber = incomingMessageBuilder.authorE164ObjC.stringValue;
85
_deprecated_sourceDeviceId = nil;
86
_read = incomingMessageBuilder.read;
87
if (incomingMessageBuilder.serverTimestamp > 0) {
88
_serverTimestamp = [NSNumber numberWithUnsignedLongLong:incomingMessageBuilder.serverTimestamp];
89
} else {
90
_serverTimestamp = nil;
91
}
92
_serverDeliveryTimestamp = incomingMessageBuilder.serverDeliveryTimestamp;
93
_serverGuid = incomingMessageBuilder.serverGuid;
94
_wasReceivedByUD = incomingMessageBuilder.wasReceivedByUD;
95
96
return self;
97
}
98
99
// --- CODE GENERATION MARKER
100
101
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run
102
// `sds_codegen.sh`.
103
104
// clang-format off
105
106
- (instancetype)initWithGrdbId:(int64_t)grdbId
107
uniqueId:(NSString *)uniqueId
108
receivedAtTimestamp:(uint64_t)receivedAtTimestamp
109
sortId:(uint64_t)sortId
110
timestamp:(uint64_t)timestamp
111
uniqueThreadId:(NSString *)uniqueThreadId
112
body:(nullable NSString *)body
113
bodyRanges:(nullable MessageBodyRanges *)bodyRanges
114
contactShare:(nullable OWSContact *)contactShare
115
deprecated_attachmentIds:(nullable NSArray<NSString *> *)deprecated_attachmentIds
116
editState:(TSEditState)editState
117
expireStartedAt:(uint64_t)expireStartedAt
118
expireTimerVersion:(nullable NSNumber *)expireTimerVersion
119
expiresAt:(uint64_t)expiresAt
120
expiresInSeconds:(unsigned int)expiresInSeconds
121
giftBadge:(nullable OWSGiftBadge *)giftBadge
122
isGroupStoryReply:(BOOL)isGroupStoryReply
123
isPoll:(BOOL)isPoll
124
isSmsMessageRestoredFromBackup:(BOOL)isSmsMessageRestoredFromBackup
125
isViewOnceComplete:(BOOL)isViewOnceComplete
126
isViewOnceMessage:(BOOL)isViewOnceMessage
127
linkPreview:(nullable OWSLinkPreview *)linkPreview
128
messageSticker:(nullable MessageSticker *)messageSticker
129
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
130
storedShouldStartExpireTimer:(BOOL)storedShouldStartExpireTimer
131
storyAuthorUuidString:(nullable NSString *)storyAuthorUuidString
132
storyReactionEmoji:(nullable NSString *)storyReactionEmoji
133
storyTimestamp:(nullable NSNumber *)storyTimestamp
134
wasRemotelyDeleted:(BOOL)wasRemotelyDeleted
135
authorPhoneNumber:(nullable NSString *)authorPhoneNumber
136
authorUUID:(nullable NSString *)authorUUID
137
deprecated_sourceDeviceId:(nullable NSNumber *)deprecated_sourceDeviceId
138
read:(BOOL)read
139
serverDeliveryTimestamp:(uint64_t)serverDeliveryTimestamp
140
serverGuid:(nullable NSString *)serverGuid
141
serverTimestamp:(nullable NSNumber *)serverTimestamp
142
viewed:(BOOL)viewed
143
wasReceivedByUD:(BOOL)wasReceivedByUD
144
{
145
self = [super initWithGrdbId:grdbId
146
uniqueId:uniqueId
147
receivedAtTimestamp:receivedAtTimestamp
148
sortId:sortId
149
timestamp:timestamp
150
uniqueThreadId:uniqueThreadId
151
body:body
152
bodyRanges:bodyRanges
153
contactShare:contactShare
154
deprecated_attachmentIds:deprecated_attachmentIds
155
editState:editState
156
expireStartedAt:expireStartedAt
157
expireTimerVersion:expireTimerVersion
158
expiresAt:expiresAt
159
expiresInSeconds:expiresInSeconds
160
giftBadge:giftBadge
161
isGroupStoryReply:isGroupStoryReply
162
isPoll:isPoll
163
isSmsMessageRestoredFromBackup:isSmsMessageRestoredFromBackup
164
isViewOnceComplete:isViewOnceComplete
165
isViewOnceMessage:isViewOnceMessage
166
linkPreview:linkPreview
167
messageSticker:messageSticker
168
quotedMessage:quotedMessage
169
storedShouldStartExpireTimer:storedShouldStartExpireTimer
170
storyAuthorUuidString:storyAuthorUuidString
171
storyReactionEmoji:storyReactionEmoji
172
storyTimestamp:storyTimestamp
173
wasRemotelyDeleted:wasRemotelyDeleted];
174
175
if (!self) {
176
return self;
177
}
178
179
if (authorUUID != nil) {
180
_authorUUID = authorUUID;
181
} else if (authorPhoneNumber != nil) {
182
_authorPhoneNumber = authorPhoneNumber;
183
}
184
_deprecated_sourceDeviceId = deprecated_sourceDeviceId;
185
_read = read;
186
_serverDeliveryTimestamp = serverDeliveryTimestamp;
187
_serverGuid = serverGuid;
188
_serverTimestamp = serverTimestamp;
189
_viewed = viewed;
190
_wasReceivedByUD = wasReceivedByUD;
191
192
return self;
193
}
194
195
// clang-format on
196
197
// --- CODE GENERATION MARKER
198
199
- (OWSInteractionType)interactionType
200
{
201
return OWSInteractionType_IncomingMessage;
202
}
203
204
#pragma mark - OWSReadTracking
205
206
// This method will be called after every insert and update, so it needs
207
// to be cheap.
208
- (BOOL)shouldStartExpireTimer
209
{
210
if (self.hasPerConversationExpirationStarted) {
211
// Expiration already started.
212
return YES;
213
} else if (!self.hasPerConversationExpiration) {
214
return NO;
215
} else {
216
return self.wasRead && [super shouldStartExpireTimer];
217
}
218
}
219
220
- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp
221
thread:(TSThread *)thread
222
circumstance:(OWSReceiptCircumstance)circumstance
223
shouldClearNotifications:(BOOL)shouldClearNotifications
224
transaction:(DBWriteTransaction *)transaction
225
{
226
OWSAssertDebug(transaction);
227
228
if (self.read && readTimestamp >= self.expireStartedAt) {
229
return;
230
}
231
232
[self anyUpdateIncomingMessageWithTransaction:transaction
233
block:^(TSIncomingMessage *message) {
234
message.read = YES;
235
// No need to update MessageAttachmentReferences table;
236
// this doesn's change isPastRevision state.
237
if (self.editState == TSEditState_LatestRevisionUnread) {
238
message.editState = TSEditState_LatestRevisionRead;
239
}
240
}];
241
242
// readTimestamp may be earlier than now, so backdate the expiration if necessary.
243
[DisappearingMessagesExpirationJobObjcBridge startExpirationForMessage:self
244
expirationStartedAt:readTimestamp
245
tx:transaction];
246
247
[SSKEnvironment.shared.receiptManagerRef messageWasRead:self
248
thread:thread
249
circumstance:circumstance
250
transaction:transaction];
251
252
if (shouldClearNotifications) {
253
[NotificationPresenterObjC cancelNotificationsForMessageId:self.uniqueId];
254
}
255
}
256
257
- (void)markAsViewedAtTimestamp:(uint64_t)viewedTimestamp
258
thread:(TSThread *)thread
259
circumstance:(OWSReceiptCircumstance)circumstance
260
transaction:(DBWriteTransaction *)transaction
261
{
262
OWSAssertDebug(transaction);
263
264
if (self.viewed) {
265
return;
266
}
267
268
[self anyUpdateIncomingMessageWithTransaction:transaction
269
block:^(TSIncomingMessage *message) { message.viewed = YES; }];
270
271
[SSKEnvironment.shared.receiptManagerRef messageWasViewed:self
272
thread:thread
273
circumstance:circumstance
274
transaction:transaction];
275
}
276
277
- (SignalServiceAddress *)authorAddress
278
{
279
return [SignalServiceAddress legacyAddressWithServiceIdString:self.authorUUID phoneNumber:self.authorPhoneNumber];
280
}
281
282
@end
283
284
NS_ASSUME_NONNULL_END
285
286