Path: blob/main/SignalServiceKit/Messages/Interactions/TSIncomingMessage.m
1 views
//1// Copyright 2017 Signal Messenger, LLC2// SPDX-License-Identifier: AGPL-3.0-only3//45#import "TSIncomingMessage.h"6#import <SignalServiceKit/SignalServiceKit-Swift.h>78NS_ASSUME_NONNULL_BEGIN910@interface TSIncomingMessage ()1112@property (nonatomic, getter=wasRead) BOOL read;13@property (nonatomic, getter=wasViewed) BOOL viewed;1415@property (nonatomic, nullable) NSNumber *serverTimestamp;1617@end1819#pragma mark -2021@implementation TSIncomingMessage2223- (NSUInteger)hash24{25NSUInteger result = [super hash];26result ^= self.authorPhoneNumber.hash;27result ^= self.authorUUID.hash;28result ^= self.deprecated_sourceDeviceId.hash;29result ^= self.read;30result ^= self.serverDeliveryTimestamp;31result ^= self.serverGuid.hash;32result ^= self.serverTimestamp.hash;33result ^= self.viewed;34result ^= self.wasReceivedByUD;35return result;36}3738- (BOOL)isEqual:(id)other39{40if (![super isEqual:other]) {41return NO;42}43TSIncomingMessage *typedOther = (TSIncomingMessage *)other;44if (![NSObject isObject:self.authorPhoneNumber equalToObject:typedOther.authorPhoneNumber]) {45return NO;46}47if (![NSObject isObject:self.authorUUID equalToObject:typedOther.authorUUID]) {48return NO;49}50if (![NSObject isObject:self.deprecated_sourceDeviceId equalToObject:typedOther.deprecated_sourceDeviceId]) {51return NO;52}53if (self.read != typedOther.read) {54return NO;55}56if (self.serverDeliveryTimestamp != typedOther.serverDeliveryTimestamp) {57return NO;58}59if (![NSObject isObject:self.serverGuid equalToObject:typedOther.serverGuid]) {60return NO;61}62if (![NSObject isObject:self.serverTimestamp equalToObject:typedOther.serverTimestamp]) {63return NO;64}65if (self.viewed != typedOther.viewed) {66return NO;67}68if (self.wasReceivedByUD != typedOther.wasReceivedByUD) {69return NO;70}71return YES;72}7374- (instancetype)initIncomingMessageWithBuilder:(TSIncomingMessageBuilder *)incomingMessageBuilder75{76self = [super initMessageWithBuilder:incomingMessageBuilder];7778if (!self) {79return self;80}8182_authorUUID = incomingMessageBuilder.authorAciObjC.serviceIdUppercaseString;83_authorPhoneNumber = incomingMessageBuilder.authorE164ObjC.stringValue;84_deprecated_sourceDeviceId = nil;85_read = incomingMessageBuilder.read;86if (incomingMessageBuilder.serverTimestamp > 0) {87_serverTimestamp = [NSNumber numberWithUnsignedLongLong:incomingMessageBuilder.serverTimestamp];88} else {89_serverTimestamp = nil;90}91_serverDeliveryTimestamp = incomingMessageBuilder.serverDeliveryTimestamp;92_serverGuid = incomingMessageBuilder.serverGuid;93_wasReceivedByUD = incomingMessageBuilder.wasReceivedByUD;9495return self;96}9798// --- CODE GENERATION MARKER99100// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run101// `sds_codegen.sh`.102103// clang-format off104105- (instancetype)initWithGrdbId:(int64_t)grdbId106uniqueId:(NSString *)uniqueId107receivedAtTimestamp:(uint64_t)receivedAtTimestamp108sortId:(uint64_t)sortId109timestamp:(uint64_t)timestamp110uniqueThreadId:(NSString *)uniqueThreadId111body:(nullable NSString *)body112bodyRanges:(nullable MessageBodyRanges *)bodyRanges113contactShare:(nullable OWSContact *)contactShare114deprecated_attachmentIds:(nullable NSArray<NSString *> *)deprecated_attachmentIds115editState:(TSEditState)editState116expireStartedAt:(uint64_t)expireStartedAt117expireTimerVersion:(nullable NSNumber *)expireTimerVersion118expiresAt:(uint64_t)expiresAt119expiresInSeconds:(unsigned int)expiresInSeconds120giftBadge:(nullable OWSGiftBadge *)giftBadge121isGroupStoryReply:(BOOL)isGroupStoryReply122isPoll:(BOOL)isPoll123isSmsMessageRestoredFromBackup:(BOOL)isSmsMessageRestoredFromBackup124isViewOnceComplete:(BOOL)isViewOnceComplete125isViewOnceMessage:(BOOL)isViewOnceMessage126linkPreview:(nullable OWSLinkPreview *)linkPreview127messageSticker:(nullable MessageSticker *)messageSticker128quotedMessage:(nullable TSQuotedMessage *)quotedMessage129storedShouldStartExpireTimer:(BOOL)storedShouldStartExpireTimer130storyAuthorUuidString:(nullable NSString *)storyAuthorUuidString131storyReactionEmoji:(nullable NSString *)storyReactionEmoji132storyTimestamp:(nullable NSNumber *)storyTimestamp133wasRemotelyDeleted:(BOOL)wasRemotelyDeleted134authorPhoneNumber:(nullable NSString *)authorPhoneNumber135authorUUID:(nullable NSString *)authorUUID136deprecated_sourceDeviceId:(nullable NSNumber *)deprecated_sourceDeviceId137read:(BOOL)read138serverDeliveryTimestamp:(uint64_t)serverDeliveryTimestamp139serverGuid:(nullable NSString *)serverGuid140serverTimestamp:(nullable NSNumber *)serverTimestamp141viewed:(BOOL)viewed142wasReceivedByUD:(BOOL)wasReceivedByUD143{144self = [super initWithGrdbId:grdbId145uniqueId:uniqueId146receivedAtTimestamp:receivedAtTimestamp147sortId:sortId148timestamp:timestamp149uniqueThreadId:uniqueThreadId150body:body151bodyRanges:bodyRanges152contactShare:contactShare153deprecated_attachmentIds:deprecated_attachmentIds154editState:editState155expireStartedAt:expireStartedAt156expireTimerVersion:expireTimerVersion157expiresAt:expiresAt158expiresInSeconds:expiresInSeconds159giftBadge:giftBadge160isGroupStoryReply:isGroupStoryReply161isPoll:isPoll162isSmsMessageRestoredFromBackup:isSmsMessageRestoredFromBackup163isViewOnceComplete:isViewOnceComplete164isViewOnceMessage:isViewOnceMessage165linkPreview:linkPreview166messageSticker:messageSticker167quotedMessage:quotedMessage168storedShouldStartExpireTimer:storedShouldStartExpireTimer169storyAuthorUuidString:storyAuthorUuidString170storyReactionEmoji:storyReactionEmoji171storyTimestamp:storyTimestamp172wasRemotelyDeleted:wasRemotelyDeleted];173174if (!self) {175return self;176}177178if (authorUUID != nil) {179_authorUUID = authorUUID;180} else if (authorPhoneNumber != nil) {181_authorPhoneNumber = authorPhoneNumber;182}183_deprecated_sourceDeviceId = deprecated_sourceDeviceId;184_read = read;185_serverDeliveryTimestamp = serverDeliveryTimestamp;186_serverGuid = serverGuid;187_serverTimestamp = serverTimestamp;188_viewed = viewed;189_wasReceivedByUD = wasReceivedByUD;190191return self;192}193194// clang-format on195196// --- CODE GENERATION MARKER197198- (OWSInteractionType)interactionType199{200return OWSInteractionType_IncomingMessage;201}202203#pragma mark - OWSReadTracking204205// This method will be called after every insert and update, so it needs206// to be cheap.207- (BOOL)shouldStartExpireTimer208{209if (self.hasPerConversationExpirationStarted) {210// Expiration already started.211return YES;212} else if (!self.hasPerConversationExpiration) {213return NO;214} else {215return self.wasRead && [super shouldStartExpireTimer];216}217}218219- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp220thread:(TSThread *)thread221circumstance:(OWSReceiptCircumstance)circumstance222shouldClearNotifications:(BOOL)shouldClearNotifications223transaction:(DBWriteTransaction *)transaction224{225OWSAssertDebug(transaction);226227if (self.read && readTimestamp >= self.expireStartedAt) {228return;229}230231[self anyUpdateIncomingMessageWithTransaction:transaction232block:^(TSIncomingMessage *message) {233message.read = YES;234// No need to update MessageAttachmentReferences table;235// this doesn's change isPastRevision state.236if (self.editState == TSEditState_LatestRevisionUnread) {237message.editState = TSEditState_LatestRevisionRead;238}239}];240241// readTimestamp may be earlier than now, so backdate the expiration if necessary.242[DisappearingMessagesExpirationJobObjcBridge startExpirationForMessage:self243expirationStartedAt:readTimestamp244tx:transaction];245246[SSKEnvironment.shared.receiptManagerRef messageWasRead:self247thread:thread248circumstance:circumstance249transaction:transaction];250251if (shouldClearNotifications) {252[NotificationPresenterObjC cancelNotificationsForMessageId:self.uniqueId];253}254}255256- (void)markAsViewedAtTimestamp:(uint64_t)viewedTimestamp257thread:(TSThread *)thread258circumstance:(OWSReceiptCircumstance)circumstance259transaction:(DBWriteTransaction *)transaction260{261OWSAssertDebug(transaction);262263if (self.viewed) {264return;265}266267[self anyUpdateIncomingMessageWithTransaction:transaction268block:^(TSIncomingMessage *message) { message.viewed = YES; }];269270[SSKEnvironment.shared.receiptManagerRef messageWasViewed:self271thread:thread272circumstance:circumstance273transaction:transaction];274}275276- (SignalServiceAddress *)authorAddress277{278return [SignalServiceAddress legacyAddressWithServiceIdString:self.authorUUID phoneNumber:self.authorPhoneNumber];279}280281@end282283NS_ASSUME_NONNULL_END284285286