Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/SignalServiceKit/Messages/Interactions/TSInteraction.m
1 views
1
//
2
// Copyright 2017 Signal Messenger, LLC
3
// SPDX-License-Identifier: AGPL-3.0-only
4
//
5
6
#import "TSInteraction.h"
7
#import <SignalServiceKit/SignalServiceKit-Swift.h>
8
9
NS_ASSUME_NONNULL_BEGIN
10
11
NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
12
{
13
switch (value) {
14
case OWSInteractionType_Unknown:
15
return @"OWSInteractionType_Unknown";
16
case OWSInteractionType_IncomingMessage:
17
return @"OWSInteractionType_IncomingMessage";
18
case OWSInteractionType_OutgoingMessage:
19
return @"OWSInteractionType_OutgoingMessage";
20
case OWSInteractionType_Error:
21
return @"OWSInteractionType_Error";
22
case OWSInteractionType_Call:
23
return @"OWSInteractionType_Call";
24
case OWSInteractionType_Info:
25
return @"OWSInteractionType_Info";
26
case OWSInteractionType_ThreadDetails:
27
return @"OWSInteractionType_ThreadDetails";
28
case OWSInteractionType_TypingIndicator:
29
return @"OWSInteractionType_TypingIndicator";
30
case OWSInteractionType_UnreadIndicator:
31
return @"OWSInteractionType_UnreadIndicator";
32
case OWSInteractionType_DateHeader:
33
return @"OWSInteractionType_DateHeader";
34
case OWSInteractionType_UnknownThreadWarning:
35
return @"OWSInteractionType_UnknownThreadWarning";
36
case OWSInteractionType_DefaultDisappearingMessageTimer:
37
return @"OWSInteractionType_DefaultDisappearingMessageTimer";
38
case OWSInteractionType_CollapseSet:
39
return @"OWSInteractionType_CollapseSet";
40
}
41
}
42
43
// MARK: -
44
45
@interface TSInteraction ()
46
47
@property (nonatomic) uint64_t sortId;
48
@property (nonatomic) uint64_t receivedAtTimestamp;
49
@property (nonatomic) uint64_t timestamp;
50
51
@end
52
53
// MARK: -
54
55
@implementation TSInteraction
56
57
- (instancetype)initWithCustomUniqueId:(NSString *)uniqueId
58
timestamp:(uint64_t)timestamp
59
receivedAtTimestamp:(uint64_t)receivedAtTimestamp
60
thread:(TSThread *)thread
61
{
62
self = [super initWithUniqueId:uniqueId];
63
64
if (!self) {
65
return self;
66
}
67
68
_timestamp = timestamp;
69
_receivedAtTimestamp = receivedAtTimestamp;
70
_uniqueThreadId = thread.uniqueId;
71
72
return self;
73
}
74
75
- (instancetype)initWithTimestamp:(uint64_t)timestamp
76
receivedAtTimestamp:(uint64_t)receivedAtTimestamp
77
thread:(TSThread *)thread
78
{
79
// Use a sequential UUID for interaction inserts, as an optimization for the
80
// corresponding insert into the index on `uniqueId`. See comments about
81
// UUIDv7 for more.
82
NSString *uniqueId = [[NSUUID sequential] UUIDString];
83
self = [super initWithUniqueId:uniqueId];
84
85
if (!self) {
86
return self;
87
}
88
89
_timestamp = timestamp;
90
_receivedAtTimestamp = receivedAtTimestamp;
91
_uniqueThreadId = thread.uniqueId;
92
93
return self;
94
}
95
96
// --- CODE GENERATION MARKER
97
98
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run
99
// `sds_codegen.sh`.
100
101
// clang-format off
102
103
- (instancetype)initWithGrdbId:(int64_t)grdbId
104
uniqueId:(NSString *)uniqueId
105
receivedAtTimestamp:(uint64_t)receivedAtTimestamp
106
sortId:(uint64_t)sortId
107
timestamp:(uint64_t)timestamp
108
uniqueThreadId:(NSString *)uniqueThreadId
109
{
110
self = [super initWithGrdbId:grdbId
111
uniqueId:uniqueId];
112
113
if (!self) {
114
return self;
115
}
116
117
_receivedAtTimestamp = receivedAtTimestamp;
118
_sortId = sortId;
119
_timestamp = timestamp;
120
_uniqueThreadId = uniqueThreadId;
121
122
return self;
123
}
124
125
// clang-format on
126
127
// --- CODE GENERATION MARKER
128
129
- (void)encodeWithCoder:(NSCoder *)coder
130
{
131
[self encodeIdsWithCoder:coder];
132
[coder encodeObject:[self valueForKey:@"receivedAtTimestamp"] forKey:@"receivedAtTimestamp"];
133
[coder encodeObject:[self valueForKey:@"sortId"] forKey:@"sortId"];
134
[coder encodeObject:[self valueForKey:@"timestamp"] forKey:@"timestamp"];
135
NSString *uniqueThreadId = self.uniqueThreadId;
136
if (uniqueThreadId != nil) {
137
[coder encodeObject:uniqueThreadId forKey:@"uniqueThreadId"];
138
}
139
}
140
141
- (nullable instancetype)initWithCoder:(NSCoder *)coder
142
{
143
self = [super initWithCoder:coder];
144
if (!self) {
145
return self;
146
}
147
self->_receivedAtTimestamp = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
148
forKey:@"receivedAtTimestamp"] unsignedLongLongValue];
149
self->_sortId = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class] forKey:@"sortId"] unsignedLongValue];
150
self->_timestamp = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
151
forKey:@"timestamp"] unsignedLongLongValue];
152
self->_uniqueThreadId = [coder decodeObjectOfClass:[NSString class] forKey:@"uniqueThreadId"];
153
154
// Previously the receivedAtTimestamp field lived on TSMessage, but we've moved it up
155
// to the TSInteraction superclass.
156
if (_receivedAtTimestamp == 0) {
157
// Upgrade from the older "TSMessage.receivedAtDate" and "TSMessage.receivedAt" properties if
158
// necessary.
159
NSDate *receivedAtDate = [coder decodeObjectOfClass:[NSDate class] forKey:@"receivedAtDate"];
160
if (!receivedAtDate) {
161
receivedAtDate = [coder decodeObjectOfClass:[NSDate class] forKey:@"receivedAt"];
162
}
163
164
if (receivedAtDate) {
165
_receivedAtTimestamp = [NSDate ows_millisecondsSince1970ForDate:receivedAtDate];
166
}
167
168
// For TSInteractions which are not TSMessage's, the timestamp *is* the receivedAtTimestamp
169
if (_receivedAtTimestamp == 0) {
170
_receivedAtTimestamp = _timestamp;
171
}
172
}
173
174
return self;
175
}
176
177
- (NSUInteger)hash
178
{
179
NSUInteger result = [super hash];
180
result ^= self.receivedAtTimestamp;
181
result ^= self.sortId;
182
result ^= self.timestamp;
183
result ^= self.uniqueThreadId.hash;
184
return result;
185
}
186
187
- (BOOL)isEqual:(id)other
188
{
189
if (![super isEqual:other]) {
190
return NO;
191
}
192
TSInteraction *typedOther = (TSInteraction *)other;
193
if (self.receivedAtTimestamp != typedOther.receivedAtTimestamp) {
194
return NO;
195
}
196
if (self.sortId != typedOther.sortId) {
197
return NO;
198
}
199
if (self.timestamp != typedOther.timestamp) {
200
return NO;
201
}
202
if (![NSObject isObject:self.uniqueThreadId equalToObject:typedOther.uniqueThreadId]) {
203
return NO;
204
}
205
return YES;
206
}
207
208
#pragma mark Thread
209
210
- (nullable TSThread *)threadWithTx:(DBReadTransaction *)tx
211
{
212
if (self.uniqueThreadId == nil) {
213
// This might be true for a few legacy interactions enqueued in the message
214
// sender. The message sender will handle this case.
215
return nil;
216
}
217
218
// However, it's also possible that the thread doesn't exist.
219
return [TSThread fetchViaCacheObjCWithUniqueId:self.uniqueThreadId transaction:tx];
220
}
221
222
#pragma mark Date operations
223
224
- (NSDate *)receivedAtDate
225
{
226
return [NSDate ows_dateWithMillisecondsSince1970:self.receivedAtTimestamp];
227
}
228
229
- (NSDate *)timestampDate
230
{
231
return [NSDate ows_dateWithMillisecondsSince1970:self.timestamp];
232
}
233
234
- (OWSInteractionType)interactionType
235
{
236
OWSFailDebug(@"unknown interaction type.");
237
238
return OWSInteractionType_Unknown;
239
}
240
241
- (NSString *)description
242
{
243
return [NSString
244
stringWithFormat:@"%@ in thread: %@ timestamp: %llu", [super description], self.uniqueThreadId, self.timestamp];
245
}
246
247
#pragma mark -
248
249
- (BOOL)isDynamicInteraction
250
{
251
return NO;
252
}
253
254
#pragma mark - sorting migration
255
256
- (void)replaceSortId:(uint64_t)sortId
257
{
258
_sortId = sortId;
259
}
260
261
#if TESTABLE_BUILD
262
263
- (void)replaceTimestamp:(uint64_t)timestamp transaction:(DBWriteTransaction *)transaction
264
{
265
[self anyUpdateWithTransaction:transaction
266
block:^(TSInteraction *interaction) { interaction.timestamp = timestamp; }];
267
}
268
269
- (void)replaceReceivedAtTimestamp:(uint64_t)receivedAtTimestamp
270
{
271
self.receivedAtTimestamp = receivedAtTimestamp;
272
}
273
274
- (void)replaceReceivedAtTimestamp:(uint64_t)receivedAtTimestamp transaction:(DBWriteTransaction *)transaction
275
{
276
[self anyUpdateWithTransaction:transaction
277
block:^(TSInteraction *interaction) {
278
interaction.receivedAtTimestamp = receivedAtTimestamp;
279
}];
280
}
281
#endif
282
283
@end
284
285
NS_ASSUME_NONNULL_END
286
287