Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/SignalServiceKit/Messages/Interactions/Quotes/TSQuotedMessage.m
1 views
1
//
2
// Copyright 2018 Signal Messenger, LLC
3
// SPDX-License-Identifier: AGPL-3.0-only
4
//
5
6
#import "TSQuotedMessage.h"
7
#import "OWSPaymentMessage.h"
8
#import "TSIncomingMessage.h"
9
#import "TSInteraction.h"
10
#import "TSOutgoingMessage.h"
11
#import <SignalServiceKit/SignalServiceKit-Swift.h>
12
13
NS_ASSUME_NONNULL_BEGIN
14
15
// MARK: -
16
17
@interface TSQuotedMessage ()
18
@property (nonatomic, readonly) uint64_t timestamp;
19
@property (nonatomic, nullable) OWSAttachmentInfo *quotedAttachment;
20
@end
21
22
@implementation TSQuotedMessage
23
24
// Public
25
- (instancetype)initWithTimestamp:(uint64_t)timestamp
26
authorAddress:(SignalServiceAddress *)authorAddress
27
body:(nullable NSString *)body
28
bodyRanges:(nullable MessageBodyRanges *)bodyRanges
29
bodySource:(TSQuotedMessageContentSource)bodySource
30
receivedQuotedAttachmentInfo:(nullable OWSAttachmentInfo *)attachmentInfo
31
isGiftBadge:(BOOL)isGiftBadge
32
isTargetMessageViewOnce:(BOOL)isTargetMessageViewOnce
33
isPoll:(BOOL)isPoll
34
{
35
OWSAssertDebug(authorAddress.isValid);
36
37
self = [super init];
38
if (!self) {
39
return nil;
40
}
41
42
_timestamp = timestamp;
43
_authorAddress = authorAddress;
44
_body = body;
45
_bodyRanges = bodyRanges;
46
_bodySource = bodySource;
47
_quotedAttachment = attachmentInfo;
48
_isGiftBadge = isGiftBadge;
49
_isTargetMessageViewOnce = isTargetMessageViewOnce;
50
_isPoll = isPoll;
51
52
return self;
53
}
54
55
// Public
56
- (instancetype)initWithTimestamp:(nullable NSNumber *)timestamp
57
authorAddress:(SignalServiceAddress *)authorAddress
58
body:(nullable NSString *)body
59
bodyRanges:(nullable MessageBodyRanges *)bodyRanges
60
quotedAttachmentForSending:(nullable OWSAttachmentInfo *)attachmentInfo
61
isGiftBadge:(BOOL)isGiftBadge
62
isTargetMessageViewOnce:(BOOL)isTargetMessageViewOnce
63
isPoll:(BOOL)isPoll
64
{
65
OWSAssertDebug(authorAddress.isValid);
66
67
self = [super init];
68
if (!self) {
69
return nil;
70
}
71
72
_timestamp = [timestamp unsignedLongLongValue];
73
_authorAddress = authorAddress;
74
_body = body;
75
_bodyRanges = bodyRanges;
76
_bodySource = TSQuotedMessageContentSourceLocal;
77
_quotedAttachment = attachmentInfo;
78
_isGiftBadge = isGiftBadge;
79
_isTargetMessageViewOnce = isTargetMessageViewOnce;
80
_isPoll = isPoll;
81
82
return self;
83
}
84
85
+ (BOOL)supportsSecureCoding
86
{
87
return YES;
88
}
89
90
- (void)encodeWithCoder:(NSCoder *)coder
91
{
92
SignalServiceAddress *authorAddress = self.authorAddress;
93
if (authorAddress != nil) {
94
[coder encodeObject:authorAddress forKey:@"authorAddress"];
95
}
96
NSString *body = self.body;
97
if (body != nil) {
98
[coder encodeObject:body forKey:@"body"];
99
}
100
MessageBodyRanges *bodyRanges = self.bodyRanges;
101
if (bodyRanges != nil) {
102
[coder encodeObject:bodyRanges forKey:@"bodyRanges"];
103
}
104
[coder encodeObject:[self valueForKey:@"bodySource"] forKey:@"bodySource"];
105
[coder encodeObject:[self valueForKey:@"isGiftBadge"] forKey:@"isGiftBadge"];
106
[coder encodeObject:[self valueForKey:@"isPoll"] forKey:@"isPoll"];
107
[coder encodeObject:[self valueForKey:@"isTargetMessageViewOnce"] forKey:@"isTargetMessageViewOnce"];
108
OWSAttachmentInfo *quotedAttachment = self.quotedAttachment;
109
if (quotedAttachment != nil) {
110
[coder encodeObject:quotedAttachment forKey:@"quotedAttachment"];
111
}
112
[coder encodeObject:[self valueForKey:@"timestamp"] forKey:@"timestamp"];
113
}
114
115
- (nullable instancetype)initWithCoder:(NSCoder *)coder
116
{
117
self = [super init];
118
if (!self) {
119
return self;
120
}
121
self->_authorAddress = [coder decodeObjectOfClass:[SignalServiceAddress class] forKey:@"authorAddress"];
122
self->_body = [coder decodeObjectOfClass:[NSString class] forKey:@"body"];
123
self->_bodyRanges = [coder decodeObjectOfClass:[MessageBodyRanges class] forKey:@"bodyRanges"];
124
self->_bodySource = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
125
forKey:@"bodySource"] unsignedIntegerValue];
126
self->_isGiftBadge = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class] forKey:@"isGiftBadge"] boolValue];
127
self->_isPoll = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class] forKey:@"isPoll"] boolValue];
128
self->_isTargetMessageViewOnce = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
129
forKey:@"isTargetMessageViewOnce"] boolValue];
130
self->_quotedAttachment = [coder decodeObjectOfClass:[OWSAttachmentInfo class] forKey:@"quotedAttachment"];
131
self->_timestamp = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
132
forKey:@"timestamp"] unsignedLongLongValue];
133
134
if (_authorAddress == nil) {
135
NSString *phoneNumber = [coder decodeObjectOfClass:[NSString class] forKey:@"authorId"];
136
_authorAddress = [SignalServiceAddress legacyAddressWithServiceIdString:nil phoneNumber:phoneNumber];
137
OWSAssertDebug(_authorAddress.isValid);
138
}
139
140
if (_quotedAttachment == nil) {
141
NSSet *expectedClasses = [NSSet setWithArray:@[ [NSArray class], [OWSAttachmentInfo class] ]];
142
NSArray *_Nullable attachmentInfos = [coder decodeObjectOfClasses:expectedClasses forKey:@"quotedAttachments"];
143
144
if ([attachmentInfos.firstObject isKindOfClass:[OWSAttachmentInfo class]]) {
145
// In practice, we only used the first item of this array
146
OWSAssertDebug(attachmentInfos.count <= 1);
147
_quotedAttachment = attachmentInfos.firstObject;
148
}
149
}
150
151
return self;
152
}
153
154
- (NSUInteger)hash
155
{
156
NSUInteger result = 0;
157
result ^= self.authorAddress.hash;
158
result ^= self.body.hash;
159
result ^= self.bodyRanges.hash;
160
result ^= self.bodySource;
161
result ^= self.isGiftBadge;
162
result ^= self.isPoll;
163
result ^= self.isTargetMessageViewOnce;
164
result ^= self.quotedAttachment.hash;
165
result ^= self.timestamp;
166
return result;
167
}
168
169
- (BOOL)isEqual:(id)other
170
{
171
if (![other isMemberOfClass:self.class]) {
172
return NO;
173
}
174
TSQuotedMessage *typedOther = (TSQuotedMessage *)other;
175
if (![NSObject isObject:self.authorAddress equalToObject:typedOther.authorAddress]) {
176
return NO;
177
}
178
if (![NSObject isObject:self.body equalToObject:typedOther.body]) {
179
return NO;
180
}
181
if (![NSObject isObject:self.bodyRanges equalToObject:typedOther.bodyRanges]) {
182
return NO;
183
}
184
if (self.bodySource != typedOther.bodySource) {
185
return NO;
186
}
187
if (self.isGiftBadge != typedOther.isGiftBadge) {
188
return NO;
189
}
190
if (self.isPoll != typedOther.isPoll) {
191
return NO;
192
}
193
if (self.isTargetMessageViewOnce != typedOther.isTargetMessageViewOnce) {
194
return NO;
195
}
196
if (![NSObject isObject:self.quotedAttachment equalToObject:typedOther.quotedAttachment]) {
197
return NO;
198
}
199
if (self.timestamp != typedOther.timestamp) {
200
return NO;
201
}
202
return YES;
203
}
204
205
- (id)copyWithZone:(nullable NSZone *)zone
206
{
207
TSQuotedMessage *result = [[[self class] allocWithZone:zone] init];
208
result->_authorAddress = self.authorAddress;
209
result->_body = self.body;
210
result->_bodyRanges = self.bodyRanges;
211
result->_bodySource = self.bodySource;
212
result->_isGiftBadge = self.isGiftBadge;
213
result->_isPoll = self.isPoll;
214
result->_isTargetMessageViewOnce = self.isTargetMessageViewOnce;
215
result->_quotedAttachment = self.quotedAttachment;
216
result->_timestamp = self.timestamp;
217
return result;
218
}
219
220
+ (instancetype)quotedMessageFromBackupWithTargetMessageTimestamp:(nullable NSNumber *)timestamp
221
authorAddress:(SignalServiceAddress *)authorAddress
222
body:(nullable NSString *)body
223
bodyRanges:(nullable MessageBodyRanges *)bodyRanges
224
bodySource:(TSQuotedMessageContentSource)bodySource
225
quotedAttachmentInfo:(nullable OWSAttachmentInfo *)attachmentInfo
226
isGiftBadge:(BOOL)isGiftBadge
227
isTargetMessageViewOnce:(BOOL)isTargetMessageViewOnce
228
isPoll:(BOOL)isPoll
229
{
230
OWSAssertDebug(authorAddress.isValid);
231
232
uint64_t rawTimestamp;
233
rawTimestamp = [timestamp unsignedLongLongValue];
234
235
return [[TSQuotedMessage alloc] initWithTimestamp:rawTimestamp
236
authorAddress:authorAddress
237
body:body
238
bodyRanges:bodyRanges
239
bodySource:bodySource
240
receivedQuotedAttachmentInfo:attachmentInfo
241
isGiftBadge:isGiftBadge
242
isTargetMessageViewOnce:isTargetMessageViewOnce
243
isPoll:isPoll];
244
}
245
246
- (nullable NSNumber *)getTimestampValue
247
{
248
return [self timestampValue];
249
}
250
251
- (nullable NSNumber *)timestampValue
252
{
253
if (_timestamp == 0) {
254
return nil;
255
}
256
return [[NSNumber alloc] initWithUnsignedLongLong:_timestamp];
257
}
258
259
#pragma mark - Attachment (not necessarily with a thumbnail)
260
261
- (nullable OWSAttachmentInfo *)attachmentInfo
262
{
263
return _quotedAttachment;
264
}
265
266
@end
267
268
NS_ASSUME_NONNULL_END
269
270