// // Copyright 2017 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // #import "TSOutgoingDeleteMessage.h" #import #import NS_ASSUME_NONNULL_BEGIN @interface TSOutgoingDeleteMessage () @property (nonatomic, readonly) uint64_t messageTimestamp; @property (nonatomic, readonly, nullable) NSString *messageUniqueId; @property (nonatomic, readonly) BOOL isDeletingStoryMessage; @end #pragma mark - @implementation TSOutgoingDeleteMessage - (instancetype)initWithThread:(TSThread *)thread message:(TSOutgoingMessage *)message transaction:(SDSAnyReadTransaction *)transaction { OWSAssertDebug([thread.uniqueId isEqualToString:message.uniqueThreadId]); TSOutgoingMessageBuilder *messageBuilder = [TSOutgoingMessageBuilder outgoingMessageBuilderWithThread:thread]; self = [super initOutgoingMessageWithBuilder:messageBuilder transaction:transaction]; if (!self) { return self; } _messageTimestamp = message.timestamp; _messageUniqueId = message.uniqueId; _isDeletingStoryMessage = NO; return self; } - (instancetype)initWithThread:(TSThread *)thread storyMessage:(StoryMessage *)storyMessage skippedRecipients:(nullable NSSet *)skippedRecipients transaction:(SDSAnyReadTransaction *)transaction { TSOutgoingMessageBuilder *messageBuilder = [TSOutgoingMessageBuilder outgoingMessageBuilderWithThread:thread]; messageBuilder.skippedRecipients = skippedRecipients; self = [super initOutgoingMessageWithBuilder:messageBuilder transaction:transaction]; if (!self) { return self; } _messageTimestamp = storyMessage.timestamp; _messageUniqueId = storyMessage.uniqueId; _isDeletingStoryMessage = YES; return self; } - (BOOL)shouldBeSaved { return NO; } - (BOOL)isStorySend { return self.isDeletingStoryMessage; } - (nullable SSKProtoDataMessageBuilder *)dataMessageBuilderWithThread:(TSThread *)thread transaction:(SDSAnyReadTransaction *)transaction { SSKProtoDataMessageDeleteBuilder *deleteBuilder = [SSKProtoDataMessageDelete builderWithTargetSentTimestamp:self.messageTimestamp]; NSError *error; SSKProtoDataMessageDelete *_Nullable deleteProto = [deleteBuilder buildAndReturnError:&error]; if (error || !deleteProto) { OWSFailDebug(@"could not build protobuf: %@", error); return nil; } SSKProtoDataMessageBuilder *builder = [super dataMessageBuilderWithThread:thread transaction:transaction]; [builder setTimestamp:self.timestamp]; [builder setDelete:deleteProto]; return builder; } - (void)anyUpdateOutgoingMessageWithTransaction:(SDSAnyWriteTransaction *)transaction block:(void(NS_NOESCAPE ^)(TSOutgoingMessage *_Nonnull))block { [super anyUpdateOutgoingMessageWithTransaction:transaction block:block]; // Some older outgoing delete messages didn't store the deleted message's unique id. // We want to mirror our sending state onto the original message, so it shows up // within the conversation. if (self.messageUniqueId) { TSOutgoingMessage *deletedMessage = [TSOutgoingMessage anyFetchOutgoingMessageWithUniqueId:self.messageUniqueId transaction:transaction]; [deletedMessage updateWithRecipientAddressStates:self.recipientAddressStates transaction:transaction]; } } - (NSSet *)relatedUniqueIds { return [[super relatedUniqueIds] setByAddingObjectsFromArray:@[ self.messageUniqueId ]]; } @end NS_ASSUME_NONNULL_END