mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Merge branch 'charlesmchen/dontResurrectZombies'
This commit is contained in:
commit
adca3f5d18
|
@ -30,9 +30,9 @@ class SessionResetJob: NSObject {
|
|||
self.storageManager.deleteAllSessions(forContact: self.recipientId)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
let endSessionMessage = EndSessionMessage(timestamp:NSDate.ows_millisecondTimeStamp(), in: self.thread)
|
||||
let endSessionMessage = EndSessionMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: self.thread)
|
||||
|
||||
self.messageSender.send(endSessionMessage, success: {
|
||||
self.messageSender.enqueue(endSessionMessage, success: {
|
||||
Logger.info("\(self.TAG) successfully sent EndSession<essage.")
|
||||
let message = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
in: self.thread,
|
||||
|
|
|
@ -12,7 +12,7 @@ public extension MessageSender {
|
|||
*/
|
||||
public func sendPromise(message: TSOutgoingMessage) -> Promise<Void> {
|
||||
let promise: Promise<Void> = Promise { fulfill, reject in
|
||||
self.send(message, success: fulfill, failure: reject)
|
||||
self.enqueue(message, success: fulfill, failure: reject)
|
||||
}
|
||||
|
||||
// Ensure sends complete before they're GC'd.
|
||||
|
|
|
@ -43,8 +43,8 @@ import PromiseKit
|
|||
identityManager: self.identityManager,
|
||||
profileManager: self.profileManager)
|
||||
|
||||
let dataSource = DataSourceValue.dataSource(withSyncMessage:syncContactsMessage.buildPlainTextAttachmentData())
|
||||
self.messageSender.sendTemporaryAttachmentData(dataSource,
|
||||
let dataSource = DataSourceValue.dataSource(withSyncMessage: syncContactsMessage.buildPlainTextAttachmentData())
|
||||
self.messageSender.enqueueTemporaryAttachment(dataSource,
|
||||
contentType: OWSMimeTypeApplicationOctetStream,
|
||||
in: syncContactsMessage,
|
||||
success: {
|
||||
|
|
|
@ -1465,7 +1465,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
|
|||
return;
|
||||
}
|
||||
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent profile key message to thread: %@", self.logTag, thread);
|
||||
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];
|
||||
|
|
|
@ -1654,7 +1654,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
[UIAlertAction actionWithTitle:NSLocalizedString(@"SEND_AGAIN_BUTTON", @"")
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully resent failed message.", self.logTag);
|
||||
}
|
||||
|
@ -3391,7 +3391,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
if (newGroupModel.groupImage) {
|
||||
NSData *data = UIImagePNGRepresentation(newGroupModel.groupImage);
|
||||
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
[self.messageSender sendAttachmentData:dataSource
|
||||
[self.messageSender enqueueAttachment:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
|
@ -3405,7 +3405,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
DDLogError(@"%@ Failed to send group avatar update with error: %@", self.logTag, error);
|
||||
}];
|
||||
} else {
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogDebug(@"%@ Successfully sent group update", self.logTag);
|
||||
if (successCompletion) {
|
||||
|
|
|
@ -219,7 +219,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
|
||||
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread
|
||||
groupId:[Randomness generateRandomBytes:16]];
|
||||
[[Environment getCurrent].messageSender sendMessage:syncGroupsRequestMessage
|
||||
[[Environment getCurrent].messageSender enqueueMessage:syncGroupsRequestMessage
|
||||
success:^{
|
||||
DDLogWarn(@"%@ Successfully sent Request Group Info message.", self.logTag);
|
||||
}
|
||||
|
@ -1055,7 +1055,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
groupMetaMessage:TSGroupMessageNew];
|
||||
// This will save the message.
|
||||
[message updateWithCustomMessage:NSLocalizedString(@"GROUP_CREATED", nil)];
|
||||
|
||||
OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
|
||||
|
@ -1067,11 +1066,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
});
|
||||
});
|
||||
};
|
||||
[messageSender sendMessage:message
|
||||
success:completion
|
||||
failure:^(NSError *error) {
|
||||
completion();
|
||||
}];
|
||||
[messageSender enqueueMessage:message
|
||||
success:completion
|
||||
failure:^(NSError *error) {
|
||||
completion();
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)injectFakeIncomingMessages:(int)counter thread:(TSThread *)thread
|
||||
|
|
|
@ -437,7 +437,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssert(message);
|
||||
|
||||
OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
|
||||
[messageSender sendMessage:message
|
||||
[messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent message.", self.logTag);
|
||||
}
|
||||
|
|
|
@ -526,7 +526,11 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
|
|||
}
|
||||
|
||||
public func addViewController(experienceUpgrade: ExperienceUpgrade) {
|
||||
guard let identifier = ExperienceUpgradeId(rawValue: experienceUpgrade.uniqueId) else {
|
||||
guard let uniqueId = experienceUpgrade.uniqueId else {
|
||||
Logger.error("\(self.TAG) experienceUpgrade is missing uniqueId.")
|
||||
return
|
||||
}
|
||||
guard let identifier = ExperienceUpgradeId(rawValue: uniqueId) else {
|
||||
owsFail("\(TAG) unknown experience upgrade. skipping")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -679,7 +679,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
groupMetaMessage:TSGroupMessageQuit];
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
[self dismissViewControllerAnimated:YES
|
||||
completion:^{
|
||||
|
|
|
@ -551,7 +551,11 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate {
|
|||
AssertIsOnMainThread()
|
||||
|
||||
self.databaseConnection.read { transaction in
|
||||
guard let newMessage = TSInteraction.fetch(uniqueId: self.message.uniqueId, transaction: transaction) as? TSMessage else {
|
||||
guard let uniqueId = self.message.uniqueId else {
|
||||
Logger.error("\(self.TAG) Message is missing uniqueId.")
|
||||
return
|
||||
}
|
||||
guard let newMessage = TSInteraction.fetch(uniqueId: uniqueId, transaction: transaction) as? TSMessage else {
|
||||
Logger.error("\(self.TAG) Couldn't reload message.")
|
||||
return
|
||||
}
|
||||
|
@ -564,7 +568,11 @@ class MessageDetailViewController: OWSViewController, UIScrollViewDelegate {
|
|||
|
||||
let notifications = self.databaseConnection.beginLongLivedReadTransaction()
|
||||
|
||||
guard self.databaseConnection.hasChange(forKey: message.uniqueId,
|
||||
guard let uniqueId = self.message.uniqueId else {
|
||||
Logger.error("\(self.TAG) Message is missing uniqueId.")
|
||||
return
|
||||
}
|
||||
guard self.databaseConnection.hasChange(forKey: uniqueId,
|
||||
inCollection: TSInteraction.collection(),
|
||||
in: notifications) else {
|
||||
Logger.debug("\(TAG) No relevant changes.")
|
||||
|
|
|
@ -493,7 +493,6 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
|
|||
inThread:thread
|
||||
groupMetaMessage:TSGroupMessageNew];
|
||||
|
||||
// This will save the message.
|
||||
[message updateWithCustomMessage:NSLocalizedString(@"GROUP_CREATED", nil)];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
@ -501,14 +500,14 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
|
|||
NSData *data = UIImagePNGRepresentation(model.groupImage);
|
||||
DataSource *_Nullable dataSource =
|
||||
[DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
[self.messageSender sendAttachmentData:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
[self.messageSender enqueueAttachment:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
} else {
|
||||
[self.messageSender sendMessage:message success:successHandler failure:failureHandler];
|
||||
[self.messageSender enqueueMessage:message success:successHandler failure:failureHandler];
|
||||
}
|
||||
});
|
||||
}];
|
||||
|
|
|
@ -885,7 +885,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:gThread
|
||||
groupMetaMessage:TSGroupMessageQuit];
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully left group.", self.logTag);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class ExperienceUpgradeFinder: NSObject {
|
|||
// MARK: - Instance Methods
|
||||
|
||||
public func allUnseen(transaction: YapDatabaseReadTransaction) -> [ExperienceUpgrade] {
|
||||
return allExperienceUpgrades.filter { ExperienceUpgrade.fetch(uniqueId: $0.uniqueId, transaction: transaction) == nil }
|
||||
return allExperienceUpgrades.filter { ExperienceUpgrade.fetch(uniqueId: $0.uniqueId!, transaction: transaction) == nil }
|
||||
}
|
||||
|
||||
public func markAllAsSeen(transaction: YapDatabaseReadWriteTransaction) {
|
||||
|
|
|
@ -16,7 +16,7 @@ class ExperienceUpgrade: TSYapDatabaseObject {
|
|||
super.init(uniqueId: uniqueId)
|
||||
}
|
||||
|
||||
override required init(uniqueId: String) {
|
||||
override required init(uniqueId: String?) {
|
||||
// This is the unfortunate seam between strict swift and fast-and-loose objc
|
||||
// we can't leave these properties nil, since we really "don't know" that the superclass
|
||||
// will assign them.
|
||||
|
|
|
@ -115,7 +115,7 @@ NSString *const kTSStorageManagerOWSContactsSyncingLastMessageKey =
|
|||
|
||||
DataSource *dataSource =
|
||||
[DataSourceValue dataSourceWithSyncMessage:[syncContactsMessage buildPlainTextAttachmentData]];
|
||||
[self.messageSender sendTemporaryAttachmentData:dataSource
|
||||
[self.messageSender enqueueTemporaryAttachment:dataSource
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
inMessage:syncContactsMessage
|
||||
success:^{
|
||||
|
|
|
@ -86,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
|
||||
|
||||
[messageSender sendMessage:message success:successHandler failure:failureHandler];
|
||||
[messageSender enqueueMessage:message success:successHandler failure:failureHandler];
|
||||
|
||||
return message;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
inThread:thread
|
||||
isVoiceMessage:[attachment isVoiceMessage]
|
||||
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
|
||||
[messageSender sendAttachmentData:attachment.dataSource
|
||||
[messageSender enqueueAttachment:attachment.dataSource
|
||||
contentType:attachment.mimeType
|
||||
sourceFilename:attachment.filenameOrDefault
|
||||
inMessage:message
|
||||
|
|
|
@ -27,7 +27,7 @@ const uint32_t OWSDisappearingMessagesConfigurationDefaultExpirationDuration = k
|
|||
durationSeconds:OWSDisappearingMessagesConfigurationDefaultExpirationDuration];
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
|
||||
|
|
|
@ -156,27 +156,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (atomic, readonly) BOOL isMuted;
|
||||
@property (atomic, readonly, nullable) NSDate *mutedUntilDate;
|
||||
|
||||
// This model may be updated from many threads. We don't want to save
|
||||
// our local copy (this instance) since it may be out of date. Instead, we
|
||||
// use these "updateWith..." methods to:
|
||||
//
|
||||
// a) Update a property of this instance.
|
||||
// b) Load an up-to-date instance of this model from from the data store.
|
||||
// c) Update and save that fresh instance.
|
||||
// d) If this instance hasn't yet been saved, save this local instance.
|
||||
//
|
||||
// After "updateWith...":
|
||||
//
|
||||
// a) An updated copy of this instance will always have been saved in the
|
||||
// data store.
|
||||
// b) The local property on this instance will always have been updated.
|
||||
// c) Other properties on this instance may be out of date.
|
||||
//
|
||||
// All mutable properties of this class have been made read-only to
|
||||
// prevent accidentally modifying them directly.
|
||||
//
|
||||
// This isn't a perfect arrangement, but in practice this will prevent
|
||||
// data loss and will resolve all known issues.
|
||||
#pragma mark - Update With... Methods
|
||||
|
||||
- (void)updateWithMutedUntilDate:(NSDate *)mutedUntilDate;
|
||||
|
||||
@end
|
||||
|
|
|
@ -34,7 +34,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return @"TSThread";
|
||||
}
|
||||
|
||||
- (instancetype)initWithUniqueId:(NSString *)uniqueId {
|
||||
- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId
|
||||
{
|
||||
self = [super initWithUniqueId:uniqueId];
|
||||
|
||||
if (self) {
|
||||
|
@ -382,33 +383,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[mutedUntilDate timeIntervalSinceDate:now] > 0);
|
||||
}
|
||||
|
||||
// This method does the work for the "updateWith..." methods. Please see
|
||||
// the header for a discussion of those methods.
|
||||
- (void)applyChangeToSelfAndLatestThread:(YapDatabaseReadWriteTransaction *)transaction
|
||||
changeBlock:(void (^)(TSThread *))changeBlock
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
changeBlock(self);
|
||||
|
||||
NSString *collection = [[self class] collection];
|
||||
TSThread *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestInstance) {
|
||||
changeBlock(latestInstance);
|
||||
[latestInstance saveWithTransaction:transaction];
|
||||
} else {
|
||||
// This message has not yet been saved.
|
||||
[self saveWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
#pragma mark - Update With... Methods
|
||||
|
||||
- (void)updateWithMutedUntilDate:(NSDate *)mutedUntilDate
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestThread:transaction
|
||||
changeBlock:^(TSThread *thread) {
|
||||
[thread setMutedUntilDate:mutedUntilDate];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSThread *thread) {
|
||||
[thread setMutedUntilDate:mutedUntilDate];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return;
|
||||
}
|
||||
|
||||
[outgoingMessage saveWithTransaction:transaction];
|
||||
[outgoingMessage updateWithWasSentFromLinkedDeviceWithTransaction:transaction];
|
||||
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:outgoingMessage
|
||||
contactsManager:self.contactsManager];
|
||||
|
@ -138,6 +139,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
expiresInSeconds:transcript.expirationDuration
|
||||
expireStartedAt:transcript.expirationStartedAt];
|
||||
// Since textMessage is a new message, updateWithWasSentAndDelivered will save it.
|
||||
[textMessage saveWithTransaction:transaction];
|
||||
[textMessage updateWithWasSentFromLinkedDeviceWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@interface TSMessage : TSInteraction
|
||||
|
||||
@property (nonatomic, readonly) NSMutableArray<NSString *> *attachmentIds;
|
||||
@property (nullable, nonatomic) NSString *body;
|
||||
@property (nonatomic) uint32_t expiresInSeconds;
|
||||
@property (nonatomic) uint64_t expireStartedAt;
|
||||
@property (nonatomic, readonly, nullable) NSString *body;
|
||||
@property (nonatomic, readonly) uint32_t expiresInSeconds;
|
||||
@property (nonatomic, readonly) uint64_t expireStartedAt;
|
||||
@property (nonatomic, readonly) uint64_t expiresAt;
|
||||
@property (nonatomic, readonly) BOOL isExpiringMessage;
|
||||
|
||||
|
@ -56,6 +56,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (BOOL)shouldStartExpireTimer;
|
||||
- (BOOL)shouldStartExpireTimer:(YapDatabaseReadTransaction *)transaction;
|
||||
|
||||
#pragma mark - Update With... Methods
|
||||
|
||||
- (void)updateWithExpireStartedAt:(uint64_t)expireStartedAt transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -16,6 +16,10 @@ static const NSUInteger OWSMessageSchemaVersion = 3;
|
|||
|
||||
@interface TSMessage ()
|
||||
|
||||
@property (nonatomic, nullable) NSString *body;
|
||||
@property (nonatomic) uint32_t expiresInSeconds;
|
||||
@property (nonatomic) uint64_t expireStartedAt;
|
||||
|
||||
/**
|
||||
* The version of the model class's schema last used to serialize this model. Use this to manage data migrations during
|
||||
* object de/serialization.
|
||||
|
@ -277,6 +281,18 @@ static const NSUInteger OWSMessageSchemaVersion = 3;
|
|||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Update With... Methods
|
||||
|
||||
- (void)updateWithExpireStartedAt:(uint64_t)expireStartedAt transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssert(expireStartedAt > 0);
|
||||
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSMessage *message) {
|
||||
[message setExpireStartedAt:expireStartedAt];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -148,32 +148,14 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
|
|||
- (OWSSignalServiceProtosAttachmentPointer *)buildAttachmentProtoForAttachmentId:(NSString *)attachmentId
|
||||
filename:(nullable NSString *)filename;
|
||||
|
||||
// TSOutgoingMessage are updated from many threads. We don't want to save
|
||||
// our local copy (this instance) since it may be out of date. Instead, we
|
||||
// use these "updateWith..." methods to:
|
||||
//
|
||||
// a) Update a property of this instance.
|
||||
// b) Load an up-to-date instance of this model from from the data store.
|
||||
// c) Update and save that fresh instance.
|
||||
// d) If this message hasn't yet been saved, save this local instance.
|
||||
//
|
||||
// After "updateWith...":
|
||||
//
|
||||
// a) An updated copy of this message will always have been saved in the
|
||||
// data store.
|
||||
// b) The local property on this instance will always have been updated.
|
||||
// c) Other properties on this instance may be out of date.
|
||||
//
|
||||
// All mutable properties of this class have been made read-only to
|
||||
// prevent accidentally modifying them directly.
|
||||
//
|
||||
// This isn't a perfect arrangement, but in practice this will prevent
|
||||
// data loss and will resolve all known issues.
|
||||
#pragma mark - Update With... Methods
|
||||
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState;
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (void)updateWithSendingError:(NSError *)error;
|
||||
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript;
|
||||
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (void)updateWithCustomMessage:(NSString *)customMessage transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (void)updateWithCustomMessage:(NSString *)customMessage;
|
||||
// deliveryTimestamp is an optional parameter, since legacy
|
||||
|
@ -196,7 +178,6 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
|
|||
- (NSUInteger)sentRecipientsCount;
|
||||
- (BOOL)wasSentToRecipient:(NSString *)contactId;
|
||||
- (void)updateWithSentRecipient:(NSString *)contactId transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (void)updateWithSentRecipient:(NSString *)contactId;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -238,38 +238,18 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
return OWSInteractionType_OutgoingMessage;
|
||||
}
|
||||
|
||||
#pragma mark - Update Methods
|
||||
|
||||
// This method does the work for the "updateWith..." methods. Please see
|
||||
// the header for a discussion of those methods.
|
||||
- (void)applyChangeToSelfAndLatestOutgoingMessage:(YapDatabaseReadWriteTransaction *)transaction
|
||||
changeBlock:(void (^)(TSOutgoingMessage *))changeBlock
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
changeBlock(self);
|
||||
|
||||
NSString *collection = [[self class] collection];
|
||||
TSOutgoingMessage *latestMessage = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestMessage) {
|
||||
changeBlock(latestMessage);
|
||||
[latestMessage saveWithTransaction:transaction];
|
||||
} else {
|
||||
// This message has not yet been saved.
|
||||
[self saveWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
#pragma mark - Update With... Methods
|
||||
|
||||
- (void)updateWithSendingError:(NSError *)error
|
||||
{
|
||||
OWSAssert(error);
|
||||
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:TSOutgoingMessageStateUnsent];
|
||||
[message setMostRecentFailureText:error.localizedDescription];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:TSOutgoingMessageStateUnsent];
|
||||
[message setMostRecentFailureText:error.localizedDescription];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -285,20 +265,19 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:messageState];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:messageState];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setHasSyncedTranscript:hasSyncedTranscript];
|
||||
}];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setHasSyncedTranscript:hasSyncedTranscript];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithCustomMessage:(NSString *)customMessage transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
|
@ -306,10 +285,10 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
OWSAssert(customMessage);
|
||||
OWSAssert(transaction);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setCustomMessage:customMessage];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setCustomMessage:customMessage];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithCustomMessage:(NSString *)customMessage
|
||||
|
@ -326,32 +305,31 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
OWSAssert(recipientId.length > 0);
|
||||
OWSAssert(transaction);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
|
||||
if (deliveryTimestamp) {
|
||||
NSMutableDictionary<NSString *, NSNumber *> *recipientDeliveryMap
|
||||
= (message.recipientDeliveryMap
|
||||
? [message.recipientDeliveryMap mutableCopy]
|
||||
: [NSMutableDictionary new]);
|
||||
recipientDeliveryMap[recipientId] = deliveryTimestamp;
|
||||
message.recipientDeliveryMap = [recipientDeliveryMap copy];
|
||||
}
|
||||
if (deliveryTimestamp) {
|
||||
NSMutableDictionary<NSString *, NSNumber *> *recipientDeliveryMap
|
||||
= (message.recipientDeliveryMap ? [message.recipientDeliveryMap mutableCopy]
|
||||
: [NSMutableDictionary new]);
|
||||
recipientDeliveryMap[recipientId] = deliveryTimestamp;
|
||||
message.recipientDeliveryMap = [recipientDeliveryMap copy];
|
||||
}
|
||||
|
||||
[message setWasDelivered:YES];
|
||||
}];
|
||||
[message setWasDelivered:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithWasSentFromLinkedDeviceWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:TSOutgoingMessageStateSentToService];
|
||||
[message setWasDelivered:YES];
|
||||
[message setIsFromLinkedDevice:YES];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:TSOutgoingMessageStateSentToService];
|
||||
[message setWasDelivered:YES];
|
||||
[message setIsFromLinkedDevice:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithSingleGroupRecipient:(NSString *)singleGroupRecipient
|
||||
|
@ -360,10 +338,10 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
OWSAssert(transaction);
|
||||
OWSAssert(singleGroupRecipient.length > 0);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setSingleGroupRecipient:singleGroupRecipient];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setSingleGroupRecipient:singleGroupRecipient];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Sent Recipients
|
||||
|
@ -415,17 +393,10 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
- (void)updateWithSentRecipient:(NSString *)contactId transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message addSentRecipient:contactId];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithSentRecipient:(NSString *)contactId
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self updateWithSentRecipient:contactId transaction:transaction];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message addSentRecipient:contactId];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithReadRecipientId:(NSString *)recipientId
|
||||
|
@ -435,14 +406,14 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
OWSAssert(recipientId.length > 0);
|
||||
OWSAssert(transaction);
|
||||
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
NSMutableDictionary<NSString *, NSNumber *> *recipientReadMap
|
||||
= (message.recipientReadMap ? [message.recipientReadMap mutableCopy]
|
||||
: [NSMutableDictionary new]);
|
||||
recipientReadMap[recipientId] = @(readTimestamp);
|
||||
message.recipientReadMap = [recipientReadMap copy];
|
||||
}];
|
||||
[self applyChangeToSelfAndLatestCopy:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
NSMutableDictionary<NSString *, NSNumber *> *recipientReadMap
|
||||
= (message.recipientReadMap ? [message.recipientReadMap mutableCopy]
|
||||
: [NSMutableDictionary new]);
|
||||
recipientReadMap[recipientId] = @(readTimestamp);
|
||||
message.recipientReadMap = [recipientReadMap copy];
|
||||
}];
|
||||
}
|
||||
|
||||
- (nullable NSNumber *)firstRecipientReadTimestamp
|
||||
|
|
|
@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (instancetype)initWithEnvelopeData:(NSData *)envelopeData
|
||||
plaintextData:(NSData *_Nullable)plaintextData NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_UNAVAILABLE;
|
||||
- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId NS_UNAVAILABLE;
|
||||
- (OWSSignalServiceProtosEnvelope *)envelopeProto;
|
||||
|
||||
@end
|
||||
|
|
|
@ -258,7 +258,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
OWSBlockedPhoneNumbersMessage *message =
|
||||
[[OWSBlockedPhoneNumbersMessage alloc] initWithPhoneNumbers:blockedPhoneNumbers];
|
||||
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent blocked phone numbers sync message", self.logTag);
|
||||
|
||||
|
|
|
@ -184,8 +184,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
// Don't clobber if multiple actions simultaneously triggered expiration.
|
||||
if (message.expireStartedAt == 0 || message.expireStartedAt > expirationStartedAt) {
|
||||
message.expireStartedAt = expirationStartedAt;
|
||||
[message saveWithTransaction:transaction];
|
||||
[message updateWithExpireStartedAt:expirationStartedAt transaction:transaction];
|
||||
}
|
||||
|
||||
// Necessary that the async expiration run happens *after* the message is saved with expiration configuration.
|
||||
|
|
|
@ -517,10 +517,10 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
|||
// subsequently
|
||||
OWSOutgoingNullMessage *nullMessage = [[OWSOutgoingNullMessage alloc] initWithContactThread:contactThread
|
||||
verificationStateSyncMessage:message];
|
||||
[self.messageSender sendMessage:nullMessage
|
||||
[self.messageSender enqueueMessage:nullMessage
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent verification state NullMessage", self.logTag);
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent verification state sync message", self.logTag);
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
|
||||
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread groupId:groupId];
|
||||
[self.messageSender sendMessage:syncGroupsRequestMessage
|
||||
[self.messageSender enqueueMessage:syncGroupsRequestMessage
|
||||
success:^{
|
||||
DDLogWarn(@"%@ Successfully sent Request Group Info message.", self.logTag);
|
||||
}
|
||||
|
@ -609,7 +609,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
profileManager:self.profileManager];
|
||||
DataSource *dataSource =
|
||||
[DataSourceValue dataSourceWithSyncMessage:[syncContactsMessage buildPlainTextAttachmentData]];
|
||||
[self.messageSender sendTemporaryAttachmentData:dataSource
|
||||
[self.messageSender enqueueTemporaryAttachment:dataSource
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
inMessage:syncContactsMessage
|
||||
success:^{
|
||||
|
@ -622,7 +622,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
|
||||
DataSource *dataSource = [DataSourceValue
|
||||
dataSourceWithSyncMessage:[syncGroupsMessage buildPlainTextAttachmentDataWithTransaction:transaction]];
|
||||
[self.messageSender sendTemporaryAttachmentData:dataSource
|
||||
[self.messageSender enqueueTemporaryAttachment:dataSource
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
inMessage:syncGroupsMessage
|
||||
success:^{
|
||||
|
@ -639,7 +639,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[[OWSReadReceiptManager sharedManager] areReadReceiptsEnabledWithTransaction:transaction];
|
||||
OWSSyncConfigurationMessage *syncConfigurationMessage =
|
||||
[[OWSSyncConfigurationMessage alloc] initWithReadReceiptsEnabled:areReadReceiptsEnabled];
|
||||
[self.messageSender sendMessage:syncConfigurationMessage
|
||||
[self.messageSender enqueueMessage:syncConfigurationMessage
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent Configuration response syncMessage.", self.logTag);
|
||||
}
|
||||
|
@ -774,7 +774,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
if (gThread.groupModel.groupImage) {
|
||||
NSData *data = UIImagePNGRepresentation(gThread.groupModel.groupImage);
|
||||
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
||||
[self.messageSender sendAttachmentData:dataSource
|
||||
[self.messageSender enqueueAttachment:dataSource
|
||||
contentType:OWSMimeTypeImagePng
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
|
@ -785,7 +785,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
DDLogError(@"%@ Failed to send group avatar update with error: %@", self.logTag, error);
|
||||
}];
|
||||
} else {
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogDebug(@"%@ Successfully sent group update", self.logTag);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (instancetype)initWithEnvelope:(OWSSignalServiceProtosEnvelope *)envelope NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_UNAVAILABLE;
|
||||
- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId NS_UNAVAILABLE;
|
||||
- (OWSSignalServiceProtosEnvelope *)envelopeProto;
|
||||
|
||||
@end
|
||||
|
|
|
@ -63,33 +63,33 @@ NS_SWIFT_NAME(MessageSender)
|
|||
|
||||
/**
|
||||
* Send and resend text messages or resend messages with existing attachments.
|
||||
* If you haven't yet created the attachment, see the `sendAttachmentData:` variants.
|
||||
* If you haven't yet created the attachment, see the ` enqueueAttachment:` variants.
|
||||
*/
|
||||
// TODO: make transaction nonnull and remove `sendMessage:success:failure`
|
||||
- (void)sendMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler;
|
||||
- (void)enqueueMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler;
|
||||
|
||||
/**
|
||||
* Takes care of allocating and uploading the attachment, then sends the message.
|
||||
* Only necessary to call once. If sending fails, retry with `sendMessage:`.
|
||||
*/
|
||||
- (void)sendAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
inMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler;
|
||||
- (void)enqueueAttachment:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
inMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler;
|
||||
|
||||
/**
|
||||
* Same as `sendAttachmentData:`, but deletes the local copy of the attachment after sending.
|
||||
* Same as ` enqueueAttachment:`, but deletes the local copy of the attachment after sending.
|
||||
* Used for sending sync request data, not for user visible attachments.
|
||||
*/
|
||||
- (void)sendTemporaryAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
inMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler;
|
||||
- (void)enqueueTemporaryAttachment:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
inMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler;
|
||||
|
||||
/**
|
||||
* Set local configuration to match that of the of `outgoingMessage`'s sender
|
||||
|
|
|
@ -155,7 +155,7 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
|
|||
|
||||
@property (nonatomic, readonly) TSOutgoingMessage *message;
|
||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||
@property (nonatomic, readonly) void (^successHandler)();
|
||||
@property (nonatomic, readonly) void (^successHandler)(void);
|
||||
@property (nonatomic, readonly) void (^failureHandler)(NSError *_Nonnull error);
|
||||
@property (nonatomic) OWSSendMessageOperationState operationState;
|
||||
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
|
||||
|
@ -280,6 +280,15 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
|
|||
|
||||
- (void)tryWithRemainingRetries:(NSUInteger)remainingRetries
|
||||
{
|
||||
// If the message has been deleted, abort send.
|
||||
if (![TSOutgoingMessage fetchObjectWithUniqueID:self.message.uniqueId]) {
|
||||
DDLogInfo(@"%@ aborting message send; message deleted.", self.logTag);
|
||||
NSError *error = OWSErrorWithCodeDescription(
|
||||
OWSErrorCodeMessageDeletedBeforeSent, @"Message was deleted before it could be sent.");
|
||||
self.failureHandler(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use this flag to ensure a given operation only succeeds or fails once.
|
||||
__block BOOL onceFlag = NO;
|
||||
RetryableFailureHandler retryableFailureHandler = ^(NSError *_Nonnull error) {
|
||||
|
@ -410,9 +419,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
}
|
||||
}
|
||||
|
||||
- (void)sendMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler
|
||||
- (void)enqueueMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler
|
||||
{
|
||||
OWSAssert(message);
|
||||
|
||||
|
@ -429,7 +438,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
//
|
||||
// So we're using YDB behavior to ensure this invariant, which is a bit
|
||||
// unorthodox.
|
||||
[message updateWithMessageState:TSOutgoingMessageStateAttemptingOut];
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
// All outgoing messages should be saved at the time they are enqueued.
|
||||
[message saveWithTransaction:transaction];
|
||||
[message updateWithMessageState:TSOutgoingMessageStateAttemptingOut transaction:transaction];
|
||||
}];
|
||||
|
||||
OWSSendMessageOperation *sendMessageOperation =
|
||||
[[OWSSendMessageOperation alloc] initWithMessage:message
|
||||
|
@ -457,12 +470,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
{
|
||||
[self ensureAnyAttachmentsUploaded:message
|
||||
success:^() {
|
||||
[self deliverMessage:message
|
||||
success:successHandler
|
||||
failure:^(NSError *error) {
|
||||
DDLogDebug(@"%@ Message send attempt failed: %@", self.logTag, message.debugDescription);
|
||||
failureHandler(error);
|
||||
}];
|
||||
[self sendMessageToService:message
|
||||
success:successHandler
|
||||
failure:^(NSError *error) {
|
||||
DDLogDebug(
|
||||
@"%@ Message send attempt failed: %@", self.logTag, message.debugDescription);
|
||||
failureHandler(error);
|
||||
}];
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
DDLogDebug(@"%@ Attachment upload attempt failed: %@", self.logTag, message.debugDescription);
|
||||
|
@ -495,15 +509,15 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
failure:failureHandler];
|
||||
}
|
||||
|
||||
- (void)sendTemporaryAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
inMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler
|
||||
- (void)enqueueTemporaryAttachment:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
inMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler
|
||||
{
|
||||
OWSAssert(dataSource);
|
||||
|
||||
void (^successWithDeleteHandler)() = ^() {
|
||||
void (^successWithDeleteHandler)(void) = ^() {
|
||||
successHandler();
|
||||
|
||||
DDLogDebug(@"Removing temporary attachment message.");
|
||||
|
@ -517,20 +531,20 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
[message remove];
|
||||
};
|
||||
|
||||
[self sendAttachmentData:dataSource
|
||||
contentType:contentType
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:successWithDeleteHandler
|
||||
failure:failureWithDeleteHandler];
|
||||
[self enqueueAttachment:dataSource
|
||||
contentType:contentType
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:successWithDeleteHandler
|
||||
failure:failureWithDeleteHandler];
|
||||
}
|
||||
|
||||
- (void)sendAttachmentData:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
inMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler
|
||||
- (void)enqueueAttachment:(DataSource *)dataSource
|
||||
contentType:(NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
inMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(void (^)(NSError *error))failureHandler
|
||||
{
|
||||
OWSAssert(dataSource);
|
||||
|
||||
|
@ -554,9 +568,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
if (sourceFilename) {
|
||||
message.attachmentFilenameMap[attachmentStream.uniqueId] = sourceFilename;
|
||||
}
|
||||
[message save];
|
||||
|
||||
[self sendMessage:message success:successHandler failure:failureHandler];
|
||||
[self enqueueMessage:message success:successHandler failure:failureHandler];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -586,9 +599,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
return [recipients copy];
|
||||
}
|
||||
|
||||
- (void)deliverMessage:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
- (void)sendMessageToService:(TSOutgoingMessage *)message
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
{
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
TSThread *thread = message.thread;
|
||||
|
@ -674,12 +687,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
return;
|
||||
}
|
||||
|
||||
[self sendMessage:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:OWSMessageSenderRetryAttempts
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
[self sendMessageToService:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:OWSMessageSenderRetryAttempts
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
} else {
|
||||
// Neither a group nor contact thread? This should never happen.
|
||||
OWSFail(@"%@ Unknown message type: %@", self.logTag, NSStringFromClass([message class]));
|
||||
|
@ -698,13 +711,15 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
{
|
||||
TOCFutureSource *futureSource = [[TOCFutureSource alloc] init];
|
||||
|
||||
[self sendMessage:message
|
||||
[self sendMessageToService:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:OWSMessageSenderRetryAttempts
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Marking group message as sent to recipient: %@", self.logTag, recipient.uniqueId);
|
||||
[message updateWithSentRecipient:recipient.uniqueId];
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[message updateWithSentRecipient:recipient.uniqueId transaction:transaction];
|
||||
}];
|
||||
[futureSource trySetResult:@1];
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
|
@ -826,12 +841,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)sendMessage:(TSOutgoingMessage *)message
|
||||
recipient:(SignalRecipient *)recipient
|
||||
thread:(TSThread *)thread
|
||||
attempts:(int)remainingAttempts
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
- (void)sendMessageToService:(TSOutgoingMessage *)message
|
||||
recipient:(SignalRecipient *)recipient
|
||||
thread:(TSThread *)thread
|
||||
attempts:(int)remainingAttempts
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
{
|
||||
DDLogInfo(@"%@ attempting to send message: %@, timestamp: %llu, recipient: %@",
|
||||
self.logTag,
|
||||
|
@ -1022,7 +1037,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
long statuscode = response.statusCode;
|
||||
NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
|
||||
|
||||
void (^retrySend)() = ^void() {
|
||||
void (^retrySend)(void) = ^void() {
|
||||
if (remainingAttempts <= 0) {
|
||||
// Since we've already repeatedly failed to send to the messaging API,
|
||||
// it's unlikely that repeating the whole process will succeed.
|
||||
|
@ -1032,12 +1047,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
DDLogDebug(@"%@ Retrying: %@", self.logTag, message.debugDescription);
|
||||
[self sendMessage:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:remainingAttempts
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
[self sendMessageToService:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:remainingAttempts
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1146,7 +1161,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
if (message.shouldSyncTranscript) {
|
||||
// TODO: I suspect we shouldn't optimistically set hasSyncedTranscript.
|
||||
// We could set this in a success handler for [sendSyncTranscriptForMessage:].
|
||||
[message updateWithHasSyncedTranscript:YES];
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[message updateWithHasSyncedTranscript:YES transaction:transaction];
|
||||
}];
|
||||
[self sendSyncTranscriptForMessage:message];
|
||||
}
|
||||
|
||||
|
@ -1226,7 +1243,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
OWSOutgoingSentMessageTranscript *sentMessageTranscript =
|
||||
[[OWSOutgoingSentMessageTranscript alloc] initWithOutgoingMessage:message];
|
||||
|
||||
[self sendMessage:sentMessageTranscript
|
||||
[self sendMessageToService:sentMessageTranscript
|
||||
recipient:[SignalRecipient selfRecipient]
|
||||
thread:message.thread
|
||||
attempts:OWSMessageSenderRetryAttempts
|
||||
|
|
|
@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[[OWSDisappearingMessagesConfigurationMessage alloc] initWithConfiguration:self.configuration
|
||||
thread:self.thread];
|
||||
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogDebug(
|
||||
@"%@ Successfully notified %@ of new disappearing messages configuration", self.logTag, self.thread);
|
||||
|
|
|
@ -229,7 +229,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
|
|||
OWSReadReceiptsForLinkedDevicesMessage *message =
|
||||
[[OWSReadReceiptsForLinkedDevicesMessage alloc] initWithReadReceipts:readReceiptsForLinkedDevices];
|
||||
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent %zd read receipt to linked devices.",
|
||||
self.logTag,
|
||||
|
@ -253,7 +253,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
|
|||
[[OWSReadReceiptsForSenderMessage alloc] initWithThread:thread
|
||||
messageTimestamps:timestamps.allObjects];
|
||||
|
||||
[self.messageSender sendMessage:message
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent %zd read receipts to sender.", self.logTag, timestamps.count);
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
|
|||
|
||||
OWSSyncConfigurationMessage *syncConfigurationMessage =
|
||||
[[OWSSyncConfigurationMessage alloc] initWithReadReceiptsEnabled:value];
|
||||
[self.messageSender sendMessage:syncConfigurationMessage
|
||||
[self.messageSender enqueueMessage:syncConfigurationMessage
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent Configuration syncMessage.", self.logTag);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerifica
|
|||
|
||||
#pragma mark - Initializers
|
||||
|
||||
- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_UNAVAILABLE;
|
||||
- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#import <Mantle/MTLModel+NSCoding.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class TSStorageManager;
|
||||
@class YapDatabaseConnection;
|
||||
@class YapDatabaseReadTransaction;
|
||||
|
@ -18,8 +20,8 @@
|
|||
*
|
||||
* @return Initialized object
|
||||
*/
|
||||
- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Returns the collection to which the object belongs.
|
||||
|
@ -77,8 +79,10 @@
|
|||
*
|
||||
* @return Instance of the object or nil if non-existent
|
||||
*/
|
||||
+ (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID transaction:(YapDatabaseReadTransaction *)transaction NS_SWIFT_NAME(fetch(uniqueId:transaction:));
|
||||
+ (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID NS_SWIFT_NAME(fetch(uniqueId:));
|
||||
+ (nullable instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID
|
||||
transaction:(YapDatabaseReadTransaction *)transaction
|
||||
NS_SWIFT_NAME(fetch(uniqueId:transaction:));
|
||||
+ (nullable instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID NS_SWIFT_NAME(fetch(uniqueId:));
|
||||
|
||||
/**
|
||||
* Saves the object with the shared readWrite connection.
|
||||
|
@ -113,9 +117,40 @@
|
|||
/**
|
||||
* The unique identifier of the stored object
|
||||
*/
|
||||
@property (nonatomic) NSString *uniqueId;
|
||||
@property (nonatomic, nullable) NSString *uniqueId;
|
||||
|
||||
- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (void)remove;
|
||||
|
||||
#pragma mark Update With...
|
||||
|
||||
// This method is used by "updateWith..." methods.
|
||||
//
|
||||
// This model may be updated from many threads. We don't want to save
|
||||
// our local copy (this instance) since it may be out of date. We also
|
||||
// want to avoid re-saving a model that has been deleted. Therefore, we
|
||||
// use "updateWith..." methods to:
|
||||
//
|
||||
// a) Update a property of this instance.
|
||||
// b) If a copy of this model exists in the database, load an up-to-date copy,
|
||||
// and update and save that copy.
|
||||
// b) If a copy of this model _DOES NOT_ exist in the database, do _NOT_ save
|
||||
// this local instance.
|
||||
//
|
||||
// After "updateWith...":
|
||||
//
|
||||
// a) Any copy of this model in the database will have been updated.
|
||||
// b) The local property on this instance will always have been updated.
|
||||
// c) Other properties on this instance may be out of date.
|
||||
//
|
||||
// All mutable properties of this class have been made read-only to
|
||||
// prevent accidentally modifying them directly.
|
||||
//
|
||||
// This isn't a perfect arrangement, but in practice this will prevent
|
||||
// data loss and will resolve all known issues.
|
||||
- (void)applyChangeToSelfAndLatestCopy:(YapDatabaseReadWriteTransaction *)transaction
|
||||
changeBlock:(void (^)(id))changeBlock;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#import "TSStorageManager.h"
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation TSYapDatabaseObject
|
||||
|
||||
- (instancetype)init
|
||||
|
@ -13,7 +15,7 @@
|
|||
return [self initWithUniqueId:[[NSUUID UUID] UUIDString]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithUniqueId:(NSString *)aUniqueId
|
||||
- (instancetype)initWithUniqueId:(NSString *_Nullable)aUniqueId
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
|
@ -25,6 +27,11 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
return [super initWithCoder:coder];
|
||||
}
|
||||
|
||||
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
[transaction setObject:self forKey:self.uniqueId inCollection:[[self class] collection]];
|
||||
|
@ -176,18 +183,40 @@
|
|||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID transaction:(YapDatabaseReadTransaction *)transaction
|
||||
+ (nullable instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID
|
||||
transaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
return [transaction objectForKey:uniqueID inCollection:[self collection]];
|
||||
}
|
||||
|
||||
+ (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID
|
||||
+ (nullable instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID
|
||||
{
|
||||
__block id object;
|
||||
__block id _Nullable object = nil;
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
object = [transaction objectForKey:uniqueID inCollection:[self collection]];
|
||||
}];
|
||||
return object;
|
||||
}
|
||||
|
||||
#pragma mark Update With...
|
||||
|
||||
// This method does the work for the "updateWith..." methods. Please see
|
||||
// the header for a discussion of those methods.
|
||||
- (void)applyChangeToSelfAndLatestCopy:(YapDatabaseReadWriteTransaction *)transaction
|
||||
changeBlock:(void (^)(id))changeBlock
|
||||
{
|
||||
OWSAssert(transaction);
|
||||
|
||||
changeBlock(self);
|
||||
|
||||
NSString *collection = [[self class] collection];
|
||||
id latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestInstance) {
|
||||
changeBlock(latestInstance);
|
||||
[latestInstance saveWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
|
|||
OWSErrorCodeMessageSendNoValidRecipients = 777407,
|
||||
OWSErrorCodeContactsUpdaterRateLimit = 777408,
|
||||
OWSErrorCodeCouldNotWriteAttachmentData = 777409,
|
||||
OWSErrorCodeMessageDeletedBeforeSent = 777410,
|
||||
};
|
||||
|
||||
extern NSError *OWSErrorWithCodeDescription(OWSErrorCode code, NSString *description);
|
||||
|
|
Loading…
Reference in a new issue