Path: blob/main/SignalServiceKit/Messages/Interactions/Quotes/TSQuotedMessage.m
1 views
//1// Copyright 2018 Signal Messenger, LLC2// SPDX-License-Identifier: AGPL-3.0-only3//45#import "TSQuotedMessage.h"6#import "OWSPaymentMessage.h"7#import "TSIncomingMessage.h"8#import "TSInteraction.h"9#import "TSOutgoingMessage.h"10#import <SignalServiceKit/SignalServiceKit-Swift.h>1112NS_ASSUME_NONNULL_BEGIN1314// MARK: -1516@interface TSQuotedMessage ()17@property (nonatomic, readonly) uint64_t timestamp;18@property (nonatomic, nullable) OWSAttachmentInfo *quotedAttachment;19@end2021@implementation TSQuotedMessage2223// Public24- (instancetype)initWithTimestamp:(uint64_t)timestamp25authorAddress:(SignalServiceAddress *)authorAddress26body:(nullable NSString *)body27bodyRanges:(nullable MessageBodyRanges *)bodyRanges28bodySource:(TSQuotedMessageContentSource)bodySource29receivedQuotedAttachmentInfo:(nullable OWSAttachmentInfo *)attachmentInfo30isGiftBadge:(BOOL)isGiftBadge31isTargetMessageViewOnce:(BOOL)isTargetMessageViewOnce32isPoll:(BOOL)isPoll33{34OWSAssertDebug(authorAddress.isValid);3536self = [super init];37if (!self) {38return nil;39}4041_timestamp = timestamp;42_authorAddress = authorAddress;43_body = body;44_bodyRanges = bodyRanges;45_bodySource = bodySource;46_quotedAttachment = attachmentInfo;47_isGiftBadge = isGiftBadge;48_isTargetMessageViewOnce = isTargetMessageViewOnce;49_isPoll = isPoll;5051return self;52}5354// Public55- (instancetype)initWithTimestamp:(nullable NSNumber *)timestamp56authorAddress:(SignalServiceAddress *)authorAddress57body:(nullable NSString *)body58bodyRanges:(nullable MessageBodyRanges *)bodyRanges59quotedAttachmentForSending:(nullable OWSAttachmentInfo *)attachmentInfo60isGiftBadge:(BOOL)isGiftBadge61isTargetMessageViewOnce:(BOOL)isTargetMessageViewOnce62isPoll:(BOOL)isPoll63{64OWSAssertDebug(authorAddress.isValid);6566self = [super init];67if (!self) {68return nil;69}7071_timestamp = [timestamp unsignedLongLongValue];72_authorAddress = authorAddress;73_body = body;74_bodyRanges = bodyRanges;75_bodySource = TSQuotedMessageContentSourceLocal;76_quotedAttachment = attachmentInfo;77_isGiftBadge = isGiftBadge;78_isTargetMessageViewOnce = isTargetMessageViewOnce;79_isPoll = isPoll;8081return self;82}8384+ (BOOL)supportsSecureCoding85{86return YES;87}8889- (void)encodeWithCoder:(NSCoder *)coder90{91SignalServiceAddress *authorAddress = self.authorAddress;92if (authorAddress != nil) {93[coder encodeObject:authorAddress forKey:@"authorAddress"];94}95NSString *body = self.body;96if (body != nil) {97[coder encodeObject:body forKey:@"body"];98}99MessageBodyRanges *bodyRanges = self.bodyRanges;100if (bodyRanges != nil) {101[coder encodeObject:bodyRanges forKey:@"bodyRanges"];102}103[coder encodeObject:[self valueForKey:@"bodySource"] forKey:@"bodySource"];104[coder encodeObject:[self valueForKey:@"isGiftBadge"] forKey:@"isGiftBadge"];105[coder encodeObject:[self valueForKey:@"isPoll"] forKey:@"isPoll"];106[coder encodeObject:[self valueForKey:@"isTargetMessageViewOnce"] forKey:@"isTargetMessageViewOnce"];107OWSAttachmentInfo *quotedAttachment = self.quotedAttachment;108if (quotedAttachment != nil) {109[coder encodeObject:quotedAttachment forKey:@"quotedAttachment"];110}111[coder encodeObject:[self valueForKey:@"timestamp"] forKey:@"timestamp"];112}113114- (nullable instancetype)initWithCoder:(NSCoder *)coder115{116self = [super init];117if (!self) {118return self;119}120self->_authorAddress = [coder decodeObjectOfClass:[SignalServiceAddress class] forKey:@"authorAddress"];121self->_body = [coder decodeObjectOfClass:[NSString class] forKey:@"body"];122self->_bodyRanges = [coder decodeObjectOfClass:[MessageBodyRanges class] forKey:@"bodyRanges"];123self->_bodySource = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]124forKey:@"bodySource"] unsignedIntegerValue];125self->_isGiftBadge = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class] forKey:@"isGiftBadge"] boolValue];126self->_isPoll = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class] forKey:@"isPoll"] boolValue];127self->_isTargetMessageViewOnce = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]128forKey:@"isTargetMessageViewOnce"] boolValue];129self->_quotedAttachment = [coder decodeObjectOfClass:[OWSAttachmentInfo class] forKey:@"quotedAttachment"];130self->_timestamp = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]131forKey:@"timestamp"] unsignedLongLongValue];132133if (_authorAddress == nil) {134NSString *phoneNumber = [coder decodeObjectOfClass:[NSString class] forKey:@"authorId"];135_authorAddress = [SignalServiceAddress legacyAddressWithServiceIdString:nil phoneNumber:phoneNumber];136OWSAssertDebug(_authorAddress.isValid);137}138139if (_quotedAttachment == nil) {140NSSet *expectedClasses = [NSSet setWithArray:@[ [NSArray class], [OWSAttachmentInfo class] ]];141NSArray *_Nullable attachmentInfos = [coder decodeObjectOfClasses:expectedClasses forKey:@"quotedAttachments"];142143if ([attachmentInfos.firstObject isKindOfClass:[OWSAttachmentInfo class]]) {144// In practice, we only used the first item of this array145OWSAssertDebug(attachmentInfos.count <= 1);146_quotedAttachment = attachmentInfos.firstObject;147}148}149150return self;151}152153- (NSUInteger)hash154{155NSUInteger result = 0;156result ^= self.authorAddress.hash;157result ^= self.body.hash;158result ^= self.bodyRanges.hash;159result ^= self.bodySource;160result ^= self.isGiftBadge;161result ^= self.isPoll;162result ^= self.isTargetMessageViewOnce;163result ^= self.quotedAttachment.hash;164result ^= self.timestamp;165return result;166}167168- (BOOL)isEqual:(id)other169{170if (![other isMemberOfClass:self.class]) {171return NO;172}173TSQuotedMessage *typedOther = (TSQuotedMessage *)other;174if (![NSObject isObject:self.authorAddress equalToObject:typedOther.authorAddress]) {175return NO;176}177if (![NSObject isObject:self.body equalToObject:typedOther.body]) {178return NO;179}180if (![NSObject isObject:self.bodyRanges equalToObject:typedOther.bodyRanges]) {181return NO;182}183if (self.bodySource != typedOther.bodySource) {184return NO;185}186if (self.isGiftBadge != typedOther.isGiftBadge) {187return NO;188}189if (self.isPoll != typedOther.isPoll) {190return NO;191}192if (self.isTargetMessageViewOnce != typedOther.isTargetMessageViewOnce) {193return NO;194}195if (![NSObject isObject:self.quotedAttachment equalToObject:typedOther.quotedAttachment]) {196return NO;197}198if (self.timestamp != typedOther.timestamp) {199return NO;200}201return YES;202}203204- (id)copyWithZone:(nullable NSZone *)zone205{206TSQuotedMessage *result = [[[self class] allocWithZone:zone] init];207result->_authorAddress = self.authorAddress;208result->_body = self.body;209result->_bodyRanges = self.bodyRanges;210result->_bodySource = self.bodySource;211result->_isGiftBadge = self.isGiftBadge;212result->_isPoll = self.isPoll;213result->_isTargetMessageViewOnce = self.isTargetMessageViewOnce;214result->_quotedAttachment = self.quotedAttachment;215result->_timestamp = self.timestamp;216return result;217}218219+ (instancetype)quotedMessageFromBackupWithTargetMessageTimestamp:(nullable NSNumber *)timestamp220authorAddress:(SignalServiceAddress *)authorAddress221body:(nullable NSString *)body222bodyRanges:(nullable MessageBodyRanges *)bodyRanges223bodySource:(TSQuotedMessageContentSource)bodySource224quotedAttachmentInfo:(nullable OWSAttachmentInfo *)attachmentInfo225isGiftBadge:(BOOL)isGiftBadge226isTargetMessageViewOnce:(BOOL)isTargetMessageViewOnce227isPoll:(BOOL)isPoll228{229OWSAssertDebug(authorAddress.isValid);230231uint64_t rawTimestamp;232rawTimestamp = [timestamp unsignedLongLongValue];233234return [[TSQuotedMessage alloc] initWithTimestamp:rawTimestamp235authorAddress:authorAddress236body:body237bodyRanges:bodyRanges238bodySource:bodySource239receivedQuotedAttachmentInfo:attachmentInfo240isGiftBadge:isGiftBadge241isTargetMessageViewOnce:isTargetMessageViewOnce242isPoll:isPoll];243}244245- (nullable NSNumber *)getTimestampValue246{247return [self timestampValue];248}249250- (nullable NSNumber *)timestampValue251{252if (_timestamp == 0) {253return nil;254}255return [[NSNumber alloc] initWithUnsignedLongLong:_timestamp];256}257258#pragma mark - Attachment (not necessarily with a thumbnail)259260- (nullable OWSAttachmentInfo *)attachmentInfo261{262return _quotedAttachment;263}264265@end266267NS_ASSUME_NONNULL_END268269270