From 1ddb8ac50ec3dec103cdc31b13d64ee2653cab4b Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Thu, 26 Nov 2020 14:01:24 +1100 Subject: [PATCH] Resolve more TODOs --- Session/Signal/AppNotifications.swift | 27 ++- .../ConversationViewController.m | 67 +----- .../OWSConversationSettingsViewController.m | 2 +- .../Read Tracking/OWSOutgoingReceiptManager.m | 2 +- .../Read Tracking/OWSReadReceiptManager.m | 38 --- .../MessageSender+Handling.swift | 60 +++-- SignalUtilitiesKit/OWSRecordTranscriptJob.m | 216 ------------------ SignalUtilitiesKit/UI/BlockListUIUtils.m | 4 +- .../UI/SharingThreadPickerViewController.m | 98 ++++---- 9 files changed, 102 insertions(+), 412 deletions(-) diff --git a/Session/Signal/AppNotifications.swift b/Session/Signal/AppNotifications.swift index 960dca597..4bf251056 100644 --- a/Session/Signal/AppNotifications.swift +++ b/Session/Signal/AppNotifications.swift @@ -434,18 +434,21 @@ class NotificationActionHandler { } return markAsRead(thread: thread).then { () -> Promise in - // TODO TODO TODO - -// let sendPromise = ThreadUtil.sendMessageNonDurably(text: replyText, -// thread: thread, -// quotedReplyModel: nil, -// messageSender: self.messageSender) - -// return sendPromise.recover { error in -// Logger.warn("Failed to send reply message from notification with error: \(error)") -// self.notificationPresenter.notifyForFailedSend(inThread: thread) -// } - return Promise.value(()) + let message = VisibleMessage() + message.sentTimestamp = NSDate.millisecondTimestamp() + message.text = replyText + let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread) + Storage.write { transaction in + tsMessage.save(with: transaction) + } + var promise: Promise! + Storage.writeSync { transaction in + promise = MessageSender.sendNonDurably(message, in: thread, using: transaction) + } + promise.catch { [weak self] error in + self?.notificationPresenter.notifyForFailedSend(inThread: thread) + } + return promise } } diff --git a/Session/Signal/ConversationView/ConversationViewController.m b/Session/Signal/ConversationView/ConversationViewController.m index 9326faa60..f9849191e 100644 --- a/Session/Signal/ConversationView/ConversationViewController.m +++ b/Session/Signal/ConversationView/ConversationViewController.m @@ -1480,8 +1480,6 @@ typedef enum : NSUInteger { [message remove]; }]; [actionSheet addAction:deleteMessageAction]; - - // TODO TODO TODO // UIAlertAction *resendMessageAction = [UIAlertAction // actionWithTitle:NSLocalizedString(@"SEND_AGAIN_BUTTON", @"") @@ -2992,68 +2990,7 @@ typedef enum : NSUInteger { - (void)updateGroupModelTo:(TSGroupModel *)newGroupModel successCompletion:(void (^_Nullable)(void))successCompletion { - __block TSGroupThread *groupThread; - __block TSOutgoingMessage *message; - - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - groupThread = [TSGroupThread getOrCreateThreadWithGroupModel:newGroupModel transaction:transaction]; - - NSString *updateGroupInfo = - [groupThread.groupModel getInfoStringAboutUpdateTo:newGroupModel]; - - groupThread.groupModel = newGroupModel; - [groupThread saveWithTransaction:transaction]; - - uint32_t expiresInSeconds = [groupThread disappearingMessagesDurationWithTransaction:transaction]; - message = [TSOutgoingMessage outgoingMessageInThread:groupThread - groupMetaMessage:TSGroupMetaMessageUpdate - expiresInSeconds:expiresInSeconds]; - [message updateWithCustomMessage:updateGroupInfo transaction:transaction]; - }]; - - [groupThread fireAvatarChangedNotification]; - - if (newGroupModel.groupImage) { - NSData *data = UIImagePNGRepresentation(newGroupModel.groupImage); - DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"]; - // DURABLE CLEANUP - currently one caller uses the completion handler to delete the tappable error message - // which causes this code to be called. Once we're more aggressive about durable sending retry, - // we could get rid of this "retryable tappable error message". - - // TODO TODO TODO - -// [self.messageSender sendTemporaryAttachment:dataSource -// contentType:OWSMimeTypeImagePng -// inMessage:message -// success:^{ -// OWSLogDebug(@"Successfully sent group update with avatar"); -// if (successCompletion) { -// successCompletion(); -// } -// } -// failure:^(NSError *error) { -// OWSLogError(@"Failed to send group avatar update with error: %@", error); -// }]; - } else { - // DURABLE CLEANUP - currently one caller uses the completion handler to delete the tappable error message - // which causes this code to be called. Once we're more aggressive about durable sending retry, - // we could get rid of this "retryable tappable error message". - - // TODO TODO TODO - -// [self.messageSender sendMessage:message -// success:^{ -// OWSLogDebug(@"Successfully sent group update"); -// if (successCompletion) { -// successCompletion(); -// } -// } -// failure:^(NSError *error) { -// OWSLogError(@"Failed to send group update with error: %@", error); -// }]; - } - - self.thread = groupThread; + } - (void)popKeyBoard @@ -3814,7 +3751,7 @@ typedef enum : NSUInteger { [tsMessage saveWithTransaction:transaction]; }]; [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [SNMessageSender send:message withAttachments:[NSArray new] inThread:thread usingTransaction:transaction]; + [SNMessageSender send:message inThread:thread usingTransaction:transaction]; [thread setDraft:@"" transaction:transaction]; }]; [self messageWasSent:tsMessage]; diff --git a/Session/Signal/OWSConversationSettingsViewController.m b/Session/Signal/OWSConversationSettingsViewController.m index 3372ffa58..9cf4d70c3 100644 --- a/Session/Signal/OWSConversationSettingsViewController.m +++ b/Session/Signal/OWSConversationSettingsViewController.m @@ -876,7 +876,7 @@ static CGRect oldframe; SNExpirationTimerUpdate *expirationTimerUpdate = [SNExpirationTimerUpdate new]; expirationTimerUpdate.duration = self.disappearingMessagesConfiguration.durationSeconds; - [SNMessageSender send:expirationTimerUpdate withAttachments:@[] inThread:self.thread usingTransaction:transaction]; + [SNMessageSender send:expirationTimerUpdate inThread:self.thread usingTransaction:transaction]; }]; } } diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSOutgoingReceiptManager.m b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSOutgoingReceiptManager.m index 1dde261bb..c4209f073 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSOutgoingReceiptManager.m +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSOutgoingReceiptManager.m @@ -168,7 +168,7 @@ NSString *const kOutgoingReadReceiptManagerCollection = @"kOutgoingReadReceiptMa [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { AnyPromise *promise = [SNMessageSender sendNonDurably:readReceipt inThread:thread usingTransaction:transaction] .thenOn(self.serialQueue, ^(id object) { - [self dequeueReceiptsWithRecipientId:recipientId timestamps:timestampsAsSet receiptType:@"Read"]; + [self dequeueReceiptsWithRecipientId:recipientId timestamps:timestampsAsSet receiptType:OWSReceiptType_Read]; }); [sendPromises addObject:promise]; }]; diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m index cb7c6be47..8c66234a7 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m @@ -176,45 +176,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE - (void)process { - // TODO TODO TODO - /* - @synchronized(self) - { - OWSLogVerbose(@"Processing read receipts."); - - NSArray *readReceiptsForLinkedDevices = - [self.toLinkedDevicesReadReceiptMap allValues]; - [self.toLinkedDevicesReadReceiptMap removeAllObjects]; - if (readReceiptsForLinkedDevices.count > 0) { - OWSReadReceiptsForLinkedDevicesMessage *message = - [[OWSReadReceiptsForLinkedDevicesMessage alloc] initWithReadReceipts:readReceiptsForLinkedDevices]; - - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - [self.messageSenderJobQueue addMessage:message transaction:transaction]; - }]; - } - - BOOL didWork = readReceiptsForLinkedDevices.count > 0; - - if (didWork) { - // Wait N seconds before processing read receipts again. - // This allows time for a batch to accumulate. - // - // We want a value high enough to allow us to effectively de-duplicate, - // read receipts without being so high that we risk not sending read - // receipts due to app exit. - const CGFloat kProcessingFrequencySeconds = 3.f; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kProcessingFrequencySeconds * NSEC_PER_SEC)), - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^{ - [self process]; - }); - } else { - self.isProcessing = NO; - } - } - */ } #pragma mark - Mark as Read Locally diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift index bbad2c0f4..37d746b9f 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift @@ -3,35 +3,55 @@ import PromiseKit extension MessageSender : SharedSenderKeysDelegate { - @objc(send:withAttachments:inThread:usingTransaction:) - public static func send(_ message: Message, with attachments: [SignalAttachment] = [], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) { - if let message = message as? VisibleMessage { - guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { - #if DEBUG - preconditionFailure() - #endif - return - } - var streams: [TSAttachmentStream] = [] - attachments.forEach { - let stream = TSAttachmentStream(contentType: $0.mimeType, byteCount: UInt32($0.dataLength), sourceFilename: $0.sourceFilename, - caption: $0.captionText, albumMessageId: tsMessage.uniqueId!) - streams.append(stream) - stream.write($0.dataSource) - stream.save(with: transaction) - } - message.attachmentIDs = streams.map { $0.uniqueId! } + // MARK: - Sending Convenience + + private static func prep(_ attachments: [SignalAttachment], for message: Message, using transaction: YapDatabaseReadWriteTransaction) { + guard let message = message as? VisibleMessage else { return } + guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { + #if DEBUG + preconditionFailure() + #endif + return + } + var streams: [TSAttachmentStream] = [] + attachments.forEach { + let stream = TSAttachmentStream(contentType: $0.mimeType, byteCount: UInt32($0.dataLength), sourceFilename: $0.sourceFilename, + caption: $0.captionText, albumMessageId: tsMessage.uniqueId!) + streams.append(stream) + stream.write($0.dataSource) + stream.save(with: transaction) } + message.attachmentIDs = streams.map { $0.uniqueId! } + } + + @objc(send:withAttachments:inThread:usingTransaction:) + public static func send(_ message: Message, with attachments: [SignalAttachment], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) { + prep(attachments, for: message, using: transaction) + send(message, in: thread, using: transaction) + } + + @objc(send:inThread:usingTransaction:) + public static func send(_ message: Message, in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) { message.threadID = thread.uniqueId! let destination = Message.Destination.from(thread) let job = MessageSendJob(message: message, destination: destination) JobQueue.shared.add(job, using: transaction) } + @objc(sendNonDurably:withAttachments:inThread:usingTransaction:) + public static func objc_sendNonDurably(_ message: Message, with attachments: [SignalAttachment], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { + return AnyPromise.from(sendNonDurably(message, with: attachments, in: thread, using: transaction)) + } + @objc(sendNonDurably:inThread:usingTransaction:) public static func objc_sendNonDurably(_ message: Message, in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { return AnyPromise.from(sendNonDurably(message, in: thread, using: transaction)) } + + public static func sendNonDurably(_ message: Message, with attachments: [SignalAttachment], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise { + prep(attachments, for: message, using: transaction) + return sendNonDurably(message, in: thread, using: transaction) + } public static func sendNonDurably(_ message: Message, in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise { message.threadID = thread.uniqueId! @@ -39,6 +59,10 @@ extension MessageSender : SharedSenderKeysDelegate { return MessageSender.send(message, to: destination, using: transaction) } + + + // MARK: - Closed Groups + public static func createClosedGroup(name: String, members: Set, transaction: YapDatabaseReadWriteTransaction) -> Promise { // Prepare var members = members diff --git a/SignalUtilitiesKit/OWSRecordTranscriptJob.m b/SignalUtilitiesKit/OWSRecordTranscriptJob.m index e98fe2cd8..e505e89d3 100644 --- a/SignalUtilitiesKit/OWSRecordTranscriptJob.m +++ b/SignalUtilitiesKit/OWSRecordTranscriptJob.m @@ -46,138 +46,7 @@ NS_ASSUME_NONNULL_BEGIN NSArray *attachmentStreams))attachmentHandler transaction:(YapDatabaseReadWriteTransaction *)transaction { - // TODO TODO TODO - /* - OWSAssertDebug(transcript); - OWSAssertDebug(transaction); - - 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) { - OWSLogInfo(@"EndSession was sent to recipient: %@.", transcript.recipientId); - [self.primaryStorage deleteAllSessionsForContact:transcript.recipientId protocolContext:transaction]; - - // MJK TODO - we don't use this timestamp, safe to remove - [[[TSInfoMessage alloc] initWithTimestamp:transcript.timestamp - inThread:transcript.thread - messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction]; - - // Don't continue processing lest we print a bubble for the session reset. - return; - } - - TSOutgoingMessage *outgoingMessage = - [[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:transcript.timestamp - inThread:transcript.thread - messageBody:transcript.body - attachmentIds:[NSMutableArray new] - expiresInSeconds:transcript.expirationDuration - expireStartedAt:transcript.expirationStartedAt - isVoiceMessage:NO - groupMetaMessage:TSGroupMetaMessageUnspecified - quotedMessage:transcript.quotedMessage - contactShare:transcript.contact - linkPreview:transcript.linkPreview]; - - - if (transcript.thread.isGroupThread) { - TSGroupThread *thread = (TSGroupThread *)transcript.thread; - if (thread.isOpenGroup) { - [outgoingMessage setServerTimestampToReceivedTimestamp:serverTimestamp]; - } - } - - if (serverID != 0) { - outgoingMessage.openGroupServerMessageID = serverID; - } - - NSArray *attachmentPointers = - [TSAttachmentPointer attachmentPointersFromProtos:transcript.attachmentPointerProtos - albumMessage:outgoingMessage]; - for (TSAttachmentPointer *pointer in attachmentPointers) { - [pointer saveWithTransaction:transaction]; - [outgoingMessage.attachmentIds addObject:pointer.uniqueId]; - } - - TSQuotedMessage *_Nullable quotedMessage = transcript.quotedMessage; - if (quotedMessage && quotedMessage.thumbnailAttachmentPointerId) { - // We weren't able to derive a local thumbnail, so we'll fetch the referenced attachment. - TSAttachmentPointer *attachmentPointer = - [TSAttachmentPointer fetchObjectWithUniqueID:quotedMessage.thumbnailAttachmentPointerId - transaction:transaction]; - - if ([attachmentPointer isKindOfClass:[TSAttachmentPointer class]]) { - OWSLogDebug(@"downloading attachments for transcript: %lu", (unsigned long)transcript.timestamp); - - [self.attachmentDownloads downloadAttachmentPointer:attachmentPointer - success:^(NSArray *attachmentStreams) { - OWSAssertDebug(attachmentStreams.count == 1); - TSAttachmentStream *attachmentStream = attachmentStreams.firstObject; - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [outgoingMessage setQuotedMessageThumbnailAttachmentStream:attachmentStream]; - [outgoingMessage saveWithTransaction:transaction]; - if (serverID != 0) { - [OWSPrimaryStorage.sharedManager setIDForMessageWithServerID:serverID to:outgoingMessage.uniqueId in:transaction]; - } - }]; - } - failure:^(NSError *error) { - OWSLogWarn(@"failed to fetch thumbnail for transcript: %lu with error: %@", - (unsigned long)transcript.timestamp, - error); - }]; - } - } - - [[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:outgoingMessage.expiresInSeconds - thread:transcript.thread - createdByRemoteRecipientId:nil - createdInExistingGroup:NO - transaction:transaction]; - - if (transcript.isExpirationTimerUpdate) { - // early return to avoid saving an empty incoming message. - OWSAssertDebug(transcript.body.length == 0); - OWSAssertDebug(outgoingMessage.attachmentIds.count == 0); - - return; - } - - if (outgoingMessage.body.length < 1 && outgoingMessage.attachmentIds.count < 1 && !outgoingMessage.contactShare) { - OWSFailDebug(@"Ignoring message transcript for empty message."); - return; - } - - [outgoingMessage saveWithTransaction:transaction]; - [outgoingMessage updateWithWasSentFromLinkedDeviceWithUDRecipientIds:transcript.udRecipientIds - nonUdRecipientIds:transcript.nonUdRecipientIds - isSentUpdate:NO - transaction:transaction]; - [[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:outgoingMessage - expirationStartedAt:transcript.expirationStartedAt - transaction:transaction]; - [self.readReceiptManager applyEarlyReadReceiptsForOutgoingMessageFromLinkedDevice:outgoingMessage - transaction:transaction]; - - if (outgoingMessage.hasAttachments) { - [self.attachmentDownloads - downloadAttachmentsForMessage:outgoingMessage - transaction:transaction - success:attachmentHandler - failure:^(NSError *error) { - OWSLogError( - @"failed to fetch transcripts attachments for message: %@", outgoingMessage); - }]; - } - */ } #pragma mark - @@ -185,92 +54,7 @@ NS_ASSUME_NONNULL_BEGIN + (void)processRecipientUpdateWithTranscript:(OWSIncomingSentMessageTranscript *)transcript transaction:(YapDatabaseReadWriteTransaction *)transaction { - // TODO TODO TODO - /* - 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 *messages - = (NSArray *)[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 diff --git a/SignalUtilitiesKit/UI/BlockListUIUtils.m b/SignalUtilitiesKit/UI/BlockListUIUtils.m index c6c9ab310..9633eb1d0 100644 --- a/SignalUtilitiesKit/UI/BlockListUIUtils.m +++ b/SignalUtilitiesKit/UI/BlockListUIUtils.m @@ -231,9 +231,7 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action); // via params and instead have to create our own sneaky transaction here. [groupThread leaveGroupWithSneakyTransaction]; - // TODO TODO TODO - -// [ThreadUtil enqueueLeaveGroupMessageInThread:groupThread]; + // TODO: If we ever start using this again we should make sure to send a group leave message here NSString *groupName = groupThread.name.length > 0 ? groupThread.name : TSGroupThread.defaultGroupName; diff --git a/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m b/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m index 250ddc199..add5095c8 100644 --- a/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m +++ b/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m @@ -7,10 +7,11 @@ #import "UIColor+OWS.h" #import "UIFont+OWS.h" #import "UIView+OWS.h" +#import #import #import #import -#import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -215,35 +216,26 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); didApproveAttachments:(NSArray *_Nonnull)attachments messageText:(NSString *_Nullable)messageText { - [self - tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) { - OWSAssertIsOnMainThread(); - - __block TSOutgoingMessage *outgoingMessage = nil; - // DURABLE CLEANUP - SAE uses non-durable sending to make sure the app is running long enough to complete - // the sending operation. Alternatively, we could use a durable send, but do more to make sure the - // SAE runs as long as it needs. - // TODO ALBUMS - send album via SAE - - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { - - // TODO TODO TODO - -// outgoingMessage = [ThreadUtil sendMessageNonDurablyWithText:messageText -// mediaAttachments:attachments -// inThread:self.thread -// quotedReplyModel:nil -// transaction:transaction -// messageSender:self.messageSender -// completion:^(NSError *_Nullable error) { -// sendCompletion(error, outgoingMessage); -// }]; - }]; - - // This is necessary to show progress. - self.outgoingMessage = outgoingMessage; - } - fromViewController:attachmentApproval]; + [self tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) { + SNVisibleMessage *message = [SNVisibleMessage new]; + message.sentTimestamp = [NSDate millisecondTimestamp]; + message.text = messageText; + TSOutgoingMessage *tsMessage = [TSOutgoingMessage from:message associatedWith:self.thread]; + [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [tsMessage saveWithTransaction:transaction]; + }]; + [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [SNMessageSender sendNonDurably:message withAttachments:attachments inThread:self.thread usingTransaction:transaction] + .then(^(id object) { + sendCompletion(nil, tsMessage); + }).catch(^(NSError *error) { + sendCompletion(error, tsMessage); + }); + }]; + + // This is necessary to show progress + self.outgoingMessage = tsMessage; + } fromViewController:attachmentApproval]; } - (void)attachmentApprovalDidCancel:(AttachmentApprovalViewController *)attachmentApproval @@ -262,36 +254,26 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); - (void)messageApproval:(MessageApprovalViewController *)approvalViewController didApproveMessage:(NSString *)messageText { - OWSAssertDebug(messageText.length > 0); - [self tryToSendMessageWithBlock:^(SendCompletionBlock sendCompletion) { - OWSAssertIsOnMainThread(); - - __block TSOutgoingMessage *outgoingMessage = nil; - // DURABLE CLEANUP - SAE uses non-durable sending to make sure the app is running long enough to complete - // the sending operation. Alternatively, we could use a durable send, but do more to make sure the - // SAE runs as long as it needs. - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { - - // TODO TODO TODO -// -// outgoingMessage = [ThreadUtil sendMessageNonDurablyWithText:messageText -// inThread:self.thread -// quotedReplyModel:nil -// transaction:transaction -// messageSender:self.messageSender -// completion:^(NSError *_Nullable error) { -// if (error) { -// sendCompletion(error, outgoingMessage); -// } else { -// sendCompletion(nil, outgoingMessage); -// } -// }]; - // This is necessary to show progress. - self.outgoingMessage = outgoingMessage; + SNVisibleMessage *message = [SNVisibleMessage new]; + message.sentTimestamp = [NSDate millisecondTimestamp]; + message.text = messageText; + TSOutgoingMessage *tsMessage = [TSOutgoingMessage from:message associatedWith:self.thread]; + [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [tsMessage saveWithTransaction:transaction]; }]; - } - fromViewController:approvalViewController]; + [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [SNMessageSender sendNonDurably:message inThread:self.thread usingTransaction:transaction] + .then(^(id object) { + sendCompletion(nil, tsMessage); + }).catch(^(NSError *error) { + sendCompletion(error, tsMessage); + }); + }]; + + // This is necessary to show progress + self.outgoingMessage = tsMessage; + } fromViewController:approvalViewController]; } - (void)messageApprovalDidCancel:(MessageApprovalViewController *)approvalViewController