Merge branch 'charlesmchen/sentUpdates'

pull/2/head
Matthew Chen 6 years ago
commit c0ec9bfafe

@ -265,6 +265,7 @@ message SyncMessage {
optional DataMessage message = 3;
optional uint64 expirationStartTimestamp = 4;
repeated UnidentifiedDeliveryStatus unidentifiedStatus = 5;
optional bool isRecipientUpdate = 6 [default = false];
}
message Contacts {

@ -1,10 +1,11 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@class OWSIncomingSentMessageTranscript;
@class SSKProtoSyncMessageSentUpdate;
@class TSAttachmentStream;
@class YapDatabaseReadWriteTransaction;
@ -12,11 +13,11 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSRecordTranscriptJob : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithIncomingSentMessageTranscript:(OWSIncomingSentMessageTranscript *)incomingSentMessageTranscript
NS_DESIGNATED_INITIALIZER;
- (void)runWithAttachmentHandler:(void (^)(NSArray<TSAttachmentStream *> *attachmentStreams))attachmentHandler
transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (void)processIncomingSentMessageTranscript:(OWSIncomingSentMessageTranscript *)incomingSentMessageTranscript
attachmentHandler:(void (^)(
NSArray<TSAttachmentStream *> *attachmentStreams))attachmentHandler
transaction:(YapDatabaseReadWriteTransaction *)transaction;
@end

@ -10,79 +10,70 @@
#import "OWSReadReceiptManager.h"
#import "SSKEnvironment.h"
#import "TSAttachmentPointer.h"
#import "TSGroupThread.h"
#import "TSInfoMessage.h"
#import "TSNetworkManager.h"
#import "TSOutgoingMessage.h"
#import "TSQuotedMessage.h"
#import "TSThread.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWSRecordTranscriptJob ()
@property (nonatomic, readonly) OWSIncomingSentMessageTranscript *incomingSentMessageTranscript;
@end
#pragma mark -
@implementation OWSRecordTranscriptJob
- (instancetype)initWithIncomingSentMessageTranscript:(OWSIncomingSentMessageTranscript *)incomingSentMessageTranscript
{
self = [super init];
if (!self) {
return self;
}
_incomingSentMessageTranscript = incomingSentMessageTranscript;
return self;
}
#pragma mark - Dependencies
- (OWSPrimaryStorage *)primaryStorage
+ (OWSPrimaryStorage *)primaryStorage
{
OWSAssertDebug(SSKEnvironment.shared.primaryStorage);
return SSKEnvironment.shared.primaryStorage;
}
- (TSNetworkManager *)networkManager
+ (TSNetworkManager *)networkManager
{
OWSAssertDebug(SSKEnvironment.shared.networkManager);
return SSKEnvironment.shared.networkManager;
}
- (OWSReadReceiptManager *)readReceiptManager
+ (OWSReadReceiptManager *)readReceiptManager
{
OWSAssert(SSKEnvironment.shared.readReceiptManager);
return SSKEnvironment.shared.readReceiptManager;
}
- (id<ContactsManagerProtocol>)contactsManager
+ (id<ContactsManagerProtocol>)contactsManager
{
OWSAssertDebug(SSKEnvironment.shared.contactsManager);
return SSKEnvironment.shared.contactsManager;
}
- (OWSAttachmentDownloads *)attachmentDownloads
+ (OWSAttachmentDownloads *)attachmentDownloads
{
return SSKEnvironment.shared.attachmentDownloads;
}
#pragma mark -
- (void)runWithAttachmentHandler:(void (^)(NSArray<TSAttachmentStream *> *attachmentStreams))attachmentHandler
transaction:(YapDatabaseReadWriteTransaction *)transaction
+ (void)processIncomingSentMessageTranscript:(OWSIncomingSentMessageTranscript *)transcript
attachmentHandler:(void (^)(
NSArray<TSAttachmentStream *> *attachmentStreams))attachmentHandler
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(transcript);
OWSAssertDebug(transaction);
OWSIncomingSentMessageTranscript *transcript = self.incomingSentMessageTranscript;
if (transcript.isRecipientUpdate) {
// "Recipient updates" are processed completely separately in order
// to avoid resurrecting threads or messages.
[self processRecipientUpdateWithTranscript:transcript transaction:transaction];
return;
}
OWSLogInfo(@"Recording transcript in thread: %@ timestamp: %llu", transcript.thread.uniqueId, transcript.timestamp);
if (transcript.isEndSessionMessage) {
@ -170,6 +161,7 @@ NS_ASSUME_NONNULL_BEGIN
[outgoingMessage saveWithTransaction:transaction];
[outgoingMessage updateWithWasSentFromLinkedDeviceWithUDRecipientIds:transcript.udRecipientIds
nonUdRecipientIds:transcript.nonUdRecipientIds
isSentUpdate:NO
transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:outgoingMessage
expirationStartedAt:transcript.expirationStartedAt
@ -189,6 +181,95 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark -
+ (void)processRecipientUpdateWithTranscript:(OWSIncomingSentMessageTranscript *)transcript
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(transcript);
OWSAssertDebug(transaction);
if (!AreRecipientUpdatesEnabled()) {
OWSFailDebug(@"Ignoring 'recipient update' transcript; disabled.");
return;
}
if (transcript.udRecipientIds.count < 1 && transcript.nonUdRecipientIds.count < 1) {
OWSFailDebug(@"Ignoring empty 'recipient update' transcript.");
return;
}
uint64_t timestamp = transcript.timestamp;
if (timestamp < 1) {
OWSFailDebug(@"'recipient update' transcript has invalid timestamp.");
return;
}
if (!transcript.thread.isGroupThread) {
OWSFailDebug(@"'recipient update' has missing or invalid thread.");
return;
}
TSGroupThread *groupThread = (TSGroupThread *)transcript.thread;
NSData *groupId = groupThread.groupModel.groupId;
if (groupId.length < 1) {
OWSFailDebug(@"'recipient update' transcript has invalid groupId.");
return;
}
NSArray<TSOutgoingMessage *> *messages
= (NSArray<TSOutgoingMessage *> *)[TSInteraction interactionsWithTimestamp:timestamp
ofClass:[TSOutgoingMessage class]
withTransaction:transaction];
if (messages.count < 1) {
// This message may have disappeared.
OWSLogError(@"No matching message with timestamp: %llu.", timestamp);
return;
}
BOOL messageFound = NO;
for (TSOutgoingMessage *message in messages) {
if (!message.isFromLinkedDevice) {
// isFromLinkedDevice isn't always set for very old linked messages, but:
//
// a) We should never receive a "sent update" for a very old message.
// b) It's safe to discard suspicious "sent updates."
continue;
}
TSThread *thread = [message threadWithTransaction:transaction];
if (!thread.isGroupThread) {
continue;
}
TSGroupThread *groupThread = (TSGroupThread *)thread;
if (![groupThread.groupModel.groupId isEqual:groupId]) {
continue;
}
if (!message.isFromLinkedDevice) {
OWSFailDebug(@"Ignoring 'recipient update' for message which was sent locally.");
continue;
}
OWSLogInfo(@"Processing 'recipient update' transcript in thread: %@, timestamp: %llu, nonUdRecipientIds: %d, "
@"udRecipientIds: %d.",
thread.uniqueId,
timestamp,
(int)transcript.nonUdRecipientIds.count,
(int)transcript.udRecipientIds.count);
[message updateWithWasSentFromLinkedDeviceWithUDRecipientIds:transcript.udRecipientIds
nonUdRecipientIds:transcript.nonUdRecipientIds
isSentUpdate:YES
transaction:transaction];
messageFound = YES;
}
if (!messageFound) {
// This message may have disappeared.
OWSLogError(@"No matching message with timestamp: %llu.", timestamp);
}
}
@end
NS_ASSUME_NONNULL_END

@ -33,10 +33,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly, nullable) NSData *groupId;
@property (nonatomic, readonly) NSString *body;
@property (nonatomic, readonly) NSArray<SSKProtoAttachmentPointer *> *attachmentPointerProtos;
@property (nonatomic, readonly) TSThread *thread;
@property (nonatomic, readonly, nullable) TSThread *thread;
@property (nonatomic, readonly, nullable) TSQuotedMessage *quotedMessage;
@property (nonatomic, readonly, nullable) OWSContact *contact;
@property (nonatomic, readonly, nullable) OWSLinkPreview *linkPreview;
@property (nonatomic, readonly) BOOL isRecipientUpdate;
// If either nonUdRecipientIds or udRecipientIds is nil,
// this is either a legacy transcript or it reflects a legacy sync message.

@ -36,23 +36,35 @@ NS_ASSUME_NONNULL_BEGIN
_isGroupUpdate = _dataMessage.group != nil && (_dataMessage.group.type == SSKProtoGroupContextTypeUpdate);
_isExpirationTimerUpdate = (_dataMessage.flags & SSKProtoDataMessageFlagsExpirationTimerUpdate) != 0;
_isEndSessionMessage = (_dataMessage.flags & SSKProtoDataMessageFlagsEndSession) != 0;
_isRecipientUpdate = sentProto.isRecipientUpdate;
if (self.dataMessage.group) {
_thread = [TSGroupThread getOrCreateThreadWithGroupId:_dataMessage.group.id transaction:transaction];
if (self.isRecipientUpdate) {
// Fetch, don't create. We don't want recipient updates to resurrect messages or threads.
if (self.dataMessage.group) {
_thread = [TSGroupThread threadWithGroupId:_dataMessage.group.id transaction:transaction];
} else {
OWSFailDebug(@"We should never receive a 'recipient update' for messages in contact threads.");
}
// Skip the other processing for recipient updates.
} else {
_thread = [TSContactThread getOrCreateThreadWithContactId:_recipientId transaction:transaction];
}
if (self.dataMessage.group) {
_thread = [TSGroupThread getOrCreateThreadWithGroupId:_dataMessage.group.id transaction:transaction];
} else {
_thread = [TSContactThread getOrCreateThreadWithContactId:_recipientId transaction:transaction];
}
_quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread transaction:transaction];
_contact = [OWSContacts contactForDataMessage:_dataMessage transaction:transaction];
_quotedMessage =
[TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread transaction:transaction];
_contact = [OWSContacts contactForDataMessage:_dataMessage transaction:transaction];
NSError *linkPreviewError;
_linkPreview = [OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:_dataMessage
body:_body
transaction:transaction
error:&linkPreviewError];
if (linkPreviewError && ![OWSLinkPreview isNoPreviewError:linkPreviewError]) {
OWSLogError(@"linkPreviewError: %@", linkPreviewError);
NSError *linkPreviewError;
_linkPreview = [OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:_dataMessage
body:_body
transaction:transaction
error:&linkPreviewError];
if (linkPreviewError && ![OWSLinkPreview isNoPreviewError:linkPreviewError]) {
OWSLogError(@"linkPreviewError: %@", linkPreviewError);
}
}
if (sentProto.unidentifiedStatus.count > 0) {

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWSOutgoingSyncMessage.h"
@ -16,7 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithOutgoingMessage:(TSOutgoingMessage *)message NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithOutgoingMessage:(TSOutgoingMessage *)message
isRecipientUpdate:(BOOL)isRecipientUpdate NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
@end

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWSOutgoingSentMessageTranscript.h"
@ -22,18 +22,25 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark -
@interface OWSOutgoingSentMessageTranscript ()
@property (nonatomic, readonly) TSOutgoingMessage *message;
// sentRecipientId is the recipient of message, for contact thread messages.
// It is used to identify the thread/conversation to desktop.
@property (nonatomic, readonly, nullable) NSString *sentRecipientId;
@property (nonatomic, readonly) BOOL isRecipientUpdate;
@end
#pragma mark -
@implementation OWSOutgoingSentMessageTranscript
- (instancetype)initWithOutgoingMessage:(TSOutgoingMessage *)message
- (instancetype)initWithOutgoingMessage:(TSOutgoingMessage *)message isRecipientUpdate:(BOOL)isRecipientUpdate
{
self = [super init];
@ -44,6 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
_message = message;
// This will be nil for groups.
_sentRecipientId = message.thread.contactIdentifier;
_isRecipientUpdate = isRecipientUpdate;
return self;
}
@ -58,6 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
SSKProtoSyncMessageSentBuilder *sentBuilder = [SSKProtoSyncMessageSent builder];
[sentBuilder setTimestamp:self.message.timestamp];
[sentBuilder setDestination:self.sentRecipientId];
[sentBuilder setIsRecipientUpdate:self.isRecipientUpdate];
SSKProtoDataMessage *_Nullable dataMessage = [self.message buildDataMessage:self.sentRecipientId];
if (!dataMessage) {

@ -6,6 +6,11 @@
NS_ASSUME_NONNULL_BEGIN
// Feature flag.
//
// TODO: Remove.
BOOL AreRecipientUpdatesEnabled(void);
typedef NS_ENUM(NSInteger, TSOutgoingMessageState) {
// The message is either:
// a) Enqueued for sending.
@ -220,6 +225,7 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
- (void)updateWithWasSentFromLinkedDeviceWithUDRecipientIds:(nullable NSArray<NSString *> *)udRecipientIds
nonUdRecipientIds:(nullable NSArray<NSString *> *)nonUdRecipientIds
isSentUpdate:(BOOL)isSentUpdate
transaction:(YapDatabaseReadWriteTransaction *)transaction;
// This method is used to rewrite the recipient list with a single recipient.

@ -23,6 +23,11 @@
NS_ASSUME_NONNULL_BEGIN
BOOL AreRecipientUpdatesEnabled(void)
{
return NO;
}
NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRecipientAll";
NSString *NSStringForOutgoingMessageState(TSOutgoingMessageState value)
@ -753,7 +758,9 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
- (void)updateWithWasSentFromLinkedDeviceWithUDRecipientIds:(nullable NSArray<NSString *> *)udRecipientIds
nonUdRecipientIds:(nullable NSArray<NSString *> *)nonUdRecipientIds
transaction:(YapDatabaseReadWriteTransaction *)transaction {
isSentUpdate:(BOOL)isSentUpdate
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(transaction);
[self
@ -788,6 +795,20 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
recipientState.wasSentByUD = NO;
recipientStateMap[recipientId] = recipientState;
}
if (isSentUpdate) {
// If this is a "sent update", make sure that:
//
// a) "Sent updates" should never remove any recipients. We end up with the
// union of the existing and new recipients.
// b) "Sent updates" should never downgrade the "recipient state" for any
// recipients. Prefer existing "recipient state"; "sent updates" only
// add new recipients at the "sent" state.
//
// Therefore we retain all existing entries in the recipient state map.
[recipientStateMap addEntriesFromDictionary:self.recipientStateMap];
}
[message setRecipientStateMap:recipientStateMap];
} else {
// Otherwise assume this is a legacy message before UD was introduced, and mark
@ -800,7 +821,10 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
}
}
}
[message setIsFromLinkedDevice:YES];
if (!isSentUpdate) {
[message setIsFromLinkedDevice:YES];
}
}];
}
@ -1089,7 +1113,7 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
- (BOOL)shouldSyncTranscript
{
return !self.hasSyncedTranscript;
return YES;
}
- (NSString *)statusDescription

@ -860,11 +860,7 @@ NS_ASSUME_NONNULL_BEGIN
if (syncMessage.sent) {
OWSIncomingSentMessageTranscript *transcript =
[[OWSIncomingSentMessageTranscript alloc] initWithProto:syncMessage.sent
transaction:transaction];
OWSRecordTranscriptJob *recordJob =
[[OWSRecordTranscriptJob alloc] initWithIncomingSentMessageTranscript:transcript];
[[OWSIncomingSentMessageTranscript alloc] initWithProto:syncMessage.sent transaction:transaction];
SSKProtoDataMessage *_Nullable dataMessage = syncMessage.sent.message;
if (!dataMessage) {
@ -882,30 +878,35 @@ NS_ASSUME_NONNULL_BEGIN
}
}
if ([self isDataMessageGroupAvatarUpdate:syncMessage.sent.message]) {
[recordJob
runWithAttachmentHandler:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSAssertDebug(attachmentStreams.count == 1);
TSAttachmentStream *attachmentStream = attachmentStreams.firstObject;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSGroupThread *_Nullable groupThread =
[TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
if (!groupThread) {
OWSFailDebug(@"ignoring sync group avatar update for unknown group.");
return;
}
[groupThread updateAvatarWithAttachmentStream:attachmentStream transaction:transaction];
}];
}
transaction:transaction];
if ([self isDataMessageGroupAvatarUpdate:syncMessage.sent.message] && !syncMessage.sent.isRecipientUpdate) {
[OWSRecordTranscriptJob
processIncomingSentMessageTranscript:transcript
attachmentHandler:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSAssertDebug(attachmentStreams.count == 1);
TSAttachmentStream *attachmentStream = attachmentStreams.firstObject;
[self.dbConnection readWriteWithBlock:^(
YapDatabaseReadWriteTransaction *transaction) {
TSGroupThread *_Nullable groupThread =
[TSGroupThread threadWithGroupId:dataMessage.group.id
transaction:transaction];
if (!groupThread) {
OWSFailDebug(@"ignoring sync group avatar update for unknown group.");
return;
}
[groupThread updateAvatarWithAttachmentStream:attachmentStream
transaction:transaction];
}];
}
transaction:transaction];
} else {
[recordJob
runWithAttachmentHandler:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSLogDebug(
@"successfully fetched transcript attachments: %lu", (unsigned long)attachmentStreams.count);
}
transaction:transaction];
[OWSRecordTranscriptJob
processIncomingSentMessageTranscript:transcript
attachmentHandler:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSLogDebug(@"successfully fetched transcript attachments: %lu",
(unsigned long)attachmentStreams.count);
}
transaction:transaction];
}
} else if (syncMessage.request) {
if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeContacts) {

@ -1391,13 +1391,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return success();
}
BOOL shouldSendTranscript = (AreRecipientUpdatesEnabled() || !message.hasSyncedTranscript);
if (!shouldSendTranscript) {
return success();
}
BOOL isRecipientUpdate = message.hasSyncedTranscript;
[self
sendSyncTranscriptForMessage:message
isRecipientUpdate:isRecipientUpdate
success:^{
// TODO: We might send to a recipient, then to another recipient on retry.
// To ensure desktop receives all "delivery status" info, we might
// want to send a transcript after every send that reaches _any_
// new recipients.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message updateWithHasSyncedTranscript:YES transaction:transaction];
}];
@ -1408,11 +1411,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
- (void)sendSyncTranscriptForMessage:(TSOutgoingMessage *)message
isRecipientUpdate:(BOOL)isRecipientUpdate
success:(void (^)(void))success
failure:(RetryableFailureHandler)failure
{
OWSOutgoingSentMessageTranscript *sentMessageTranscript =
[[OWSOutgoingSentMessageTranscript alloc] initWithOutgoingMessage:message];
[[OWSOutgoingSentMessageTranscript alloc] initWithOutgoingMessage:message isRecipientUpdate:isRecipientUpdate];
NSString *recipientId = self.tsAccountManager.localNumber;
__block SignalRecipient *recipient;

@ -3602,6 +3602,9 @@ extension SSKProtoSyncMessageSentUnidentifiedDeliveryStatus.SSKProtoSyncMessageS
builder.setExpirationStartTimestamp(expirationStartTimestamp)
}
builder.setUnidentifiedStatus(unidentifiedStatus)
if hasIsRecipientUpdate {
builder.setIsRecipientUpdate(isRecipientUpdate)
}
return builder
}
@ -3637,6 +3640,10 @@ extension SSKProtoSyncMessageSentUnidentifiedDeliveryStatus.SSKProtoSyncMessageS
proto.unidentifiedStatus = wrappedItems.map { $0.proto }
}
@objc public func setIsRecipientUpdate(_ valueParam: Bool) {
proto.isRecipientUpdate = valueParam
}
@objc public func build() throws -> SSKProtoSyncMessageSent {
return try SSKProtoSyncMessageSent.parseProto(proto)
}
@ -3676,6 +3683,13 @@ extension SSKProtoSyncMessageSentUnidentifiedDeliveryStatus.SSKProtoSyncMessageS
return proto.hasExpirationStartTimestamp
}
@objc public var isRecipientUpdate: Bool {
return proto.isRecipientUpdate
}
@objc public var hasIsRecipientUpdate: Bool {
return proto.hasIsRecipientUpdate
}
private init(proto: SignalServiceProtos_SyncMessage.Sent,
message: SSKProtoDataMessage?,
unidentifiedStatus: [SSKProtoSyncMessageSentUnidentifiedDeliveryStatus]) {

@ -1568,6 +1568,15 @@ struct SignalServiceProtos_SyncMessage {
set {_uniqueStorage()._unidentifiedStatus = newValue}
}
var isRecipientUpdate: Bool {
get {return _storage._isRecipientUpdate ?? false}
set {_uniqueStorage()._isRecipientUpdate = newValue}
}
/// Returns true if `isRecipientUpdate` has been explicitly set.
var hasIsRecipientUpdate: Bool {return _storage._isRecipientUpdate != nil}
/// Clears the value of `isRecipientUpdate`. Subsequent reads from it will return its default value.
mutating func clearIsRecipientUpdate() {_uniqueStorage()._isRecipientUpdate = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
struct UnidentifiedDeliveryStatus {
@ -3844,6 +3853,7 @@ extension SignalServiceProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProt
3: .same(proto: "message"),
4: .same(proto: "expirationStartTimestamp"),
5: .same(proto: "unidentifiedStatus"),
6: .same(proto: "isRecipientUpdate"),
]
fileprivate class _StorageClass {
@ -3852,6 +3862,7 @@ extension SignalServiceProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProt
var _message: SignalServiceProtos_DataMessage? = nil
var _expirationStartTimestamp: UInt64? = nil
var _unidentifiedStatus: [SignalServiceProtos_SyncMessage.Sent.UnidentifiedDeliveryStatus] = []
var _isRecipientUpdate: Bool? = nil
static let defaultInstance = _StorageClass()
@ -3863,6 +3874,7 @@ extension SignalServiceProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProt
_message = source._message
_expirationStartTimestamp = source._expirationStartTimestamp
_unidentifiedStatus = source._unidentifiedStatus
_isRecipientUpdate = source._isRecipientUpdate
}
}
@ -3883,6 +3895,7 @@ extension SignalServiceProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProt
case 3: try decoder.decodeSingularMessageField(value: &_storage._message)
case 4: try decoder.decodeSingularUInt64Field(value: &_storage._expirationStartTimestamp)
case 5: try decoder.decodeRepeatedMessageField(value: &_storage._unidentifiedStatus)
case 6: try decoder.decodeSingularBoolField(value: &_storage._isRecipientUpdate)
default: break
}
}
@ -3906,6 +3919,9 @@ extension SignalServiceProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProt
if !_storage._unidentifiedStatus.isEmpty {
try visitor.visitRepeatedMessageField(value: _storage._unidentifiedStatus, fieldNumber: 5)
}
if let v = _storage._isRecipientUpdate {
try visitor.visitSingularBoolField(value: v, fieldNumber: 6)
}
}
try unknownFields.traverse(visitor: &visitor)
}
@ -3920,6 +3936,7 @@ extension SignalServiceProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProt
if _storage._message != rhs_storage._message {return false}
if _storage._expirationStartTimestamp != rhs_storage._expirationStartTimestamp {return false}
if _storage._unidentifiedStatus != rhs_storage._unidentifiedStatus {return false}
if _storage._isRecipientUpdate != rhs_storage._isRecipientUpdate {return false}
return true
}
if !storagesAreEqual {return false}

Loading…
Cancel
Save