diff --git a/Session/Components/ConversationCell.swift b/Session/Components/ConversationCell.swift index e4230a88d..2fcc524bd 100644 --- a/Session/Components/ConversationCell.swift +++ b/Session/Components/ConversationCell.swift @@ -132,8 +132,7 @@ final class ConversationCell : UITableViewCell { // MARK: Updating private func update() { AssertIsOnMainThread() - let thread = threadViewModel.threadRecord - guard let threadID = thread.uniqueId else { return } + guard let thread = threadViewModel?.threadRecord, let threadID = thread.uniqueId else { return } MentionsManager.populateUserPublicKeyCacheIfNeeded(for: threadID) // FIXME: This is a terrible place to do this let isBlocked: Bool if let thread = thread as? TSContactThread { diff --git a/Session/Signal/ConversationView/ConversationViewController.m b/Session/Signal/ConversationView/ConversationViewController.m index ff1bc290e..d4259f70c 100644 --- a/Session/Signal/ConversationView/ConversationViewController.m +++ b/Session/Signal/ConversationView/ConversationViewController.m @@ -3797,7 +3797,6 @@ typedef enum : NSUInteger { - (void)tryToSendTextMessage:(NSString *)text updateKeyboardState:(BOOL)updateKeyboardState { OWSAssertIsOnMainThread(); - __weak ConversationViewController *weakSelf = self; if ([self isBlockedConversation]) { [self showUnblockConversationUI:^(BOOL isBlocked) { @@ -3807,38 +3806,26 @@ typedef enum : NSUInteger { }]; return; } - text = [text ows_stripped]; - if (text.length < 1) { return; } - SNVisibleMessage *message = [SNVisibleMessage new]; - [message setSentTimestamp:[NSDate millisecondTimestamp]]; + message.sentTimestamp = [NSDate millisecondTimestamp]; message.text = text; message.quote = [SNQuote from:self.inputToolbar.quotedReply]; + TSThread *thread = self.thread; + TSOutgoingMessage *tsMessage = [TSOutgoingMessage from:message associatedWith:thread]; + [self.conversationViewModel appendUnsavedOutgoingTextMessage:tsMessage]; [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [SNMessageSender send:message inThread:self.thread usingTransaction:transaction]; + [tsMessage saveWithTransaction:transaction]; + [SNMessageSender send:message inThread:thread usingTransaction:transaction]; + [thread setDraft:@"" transaction:transaction]; }]; - - TSOutgoingMessage *tsMessage = [TSOutgoingMessage from:message associatedWith:self.thread]; - - [tsMessage save]; - - [self.conversationViewModel appendUnsavedOutgoingTextMessage:tsMessage]; - [self messageWasSent:tsMessage]; - [self.inputToolbar clearTextMessageAnimated:YES]; - [self resetMentions]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self.inputToolbar toggleDefaultKeyboard]; + [[weakSelf inputToolbar] toggleDefaultKeyboard]; }); - - [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [self.thread setDraft:@"" transaction:transaction]; - }]; } - (void)voiceMemoGestureDidStart @@ -4562,7 +4549,10 @@ typedef enum : NSUInteger { - (void)handleMessageSendingFailedNotification:(NSNotification *)notification { NSNumber *timestamp = (NSNumber *)notification.object; - [self hideProgressIndicatorViewForMessageWithTimestamp:timestamp]; + self.progressIndicatorView.progressTintColor = LKColors.destructive; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void) { + [self hideProgressIndicatorViewForMessageWithTimestamp:timestamp]; + }); } - (void)setProgressIfNeededTo:(float)progress forMessageWithTimestamp:(NSNumber *)timestamp @@ -4600,6 +4590,7 @@ typedef enum : NSUInteger { self.progressIndicatorView.alpha = 0; } completion:^(BOOL finished) { [self.progressIndicatorView setProgress:0.0f]; + self.progressIndicatorView.progressTintColor = LKColors.accent; }]; }); } diff --git a/Session/Signal/ConversationView/ConversationViewModel.m b/Session/Signal/ConversationView/ConversationViewModel.m index c791e5474..c7884aa4b 100644 --- a/Session/Signal/ConversationView/ConversationViewModel.m +++ b/Session/Signal/ConversationView/ConversationViewModel.m @@ -1068,17 +1068,6 @@ static const int kYapDatabaseRangeMaxLength = 25000; OWSAssertDebug(!viewItemCache[interaction.uniqueId]); viewItemCache[interaction.uniqueId] = viewItem; [viewItems addObject:viewItem]; - TSMessage *message = (TSMessage *)viewItem.interaction; - if (message.hasUnfetchedAttachmentsFromPN) { - [SSKEnvironment.shared.attachmentDownloads downloadAttachmentsForMessage:message - transaction:transaction - success:^(NSArray *attachmentStreams) { - OWSLogInfo(@"Successfully redownloaded attachment in thread: %@", message.thread); - } - failure:^(NSError *error) { - OWSLogWarn(@"Failed to redownload message with error: %@", error); - }]; - } return viewItem; }; diff --git a/SessionMessagingKit/Jobs/AttachmentUploadJob.swift b/SessionMessagingKit/Jobs/AttachmentUploadJob.swift index 6caf85c4b..7b49adc7a 100644 --- a/SessionMessagingKit/Jobs/AttachmentUploadJob.swift +++ b/SessionMessagingKit/Jobs/AttachmentUploadJob.swift @@ -3,7 +3,7 @@ import SessionUtilitiesKit public final class AttachmentUploadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility public var delegate: JobDelegate? public let attachmentID: String - private let threadID: String + public let threadID: String public var id: String? public var failureCount: UInt = 0 diff --git a/SessionMessagingKit/Jobs/MessageSendJob.swift b/SessionMessagingKit/Jobs/MessageSendJob.swift index 1c9a9b2ea..d91e1c46d 100644 --- a/SessionMessagingKit/Jobs/MessageSendJob.swift +++ b/SessionMessagingKit/Jobs/MessageSendJob.swift @@ -3,7 +3,7 @@ import SessionUtilitiesKit @objc(SNMessageSendJob) public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility public var delegate: JobDelegate? - private let message: Message + public let message: Message private let destination: Message.Destination public var id: String? public var failureCount: UInt = 0 diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 04c3c36f1..cc8bac427 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -149,9 +149,9 @@ public final class MessageSender : NSObject { JobQueue.shared.add(notifyPNServerJob, using: transaction) }, completion: { }) } - let _ = promise.catch(on: DispatchQueue.main) { _ in + let _ = promise.catch(on: DispatchQueue.main) { error in storage.withAsync({ transaction in - Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, using: transaction) + Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, with: error, using: transaction) }, completion: { }) if case .contact(_) = destination { NotificationCenter.default.post(name: .messageSendingFailed, object: NSNumber(value: message.sentTimestamp!)) @@ -184,9 +184,9 @@ public final class MessageSender : NSObject { Configuration.shared.messageSenderDelegate.handleSuccessfulMessageSend(message, using: transaction) }, completion: { }) } - promise.catch(on: DispatchQueue.global(qos: .userInitiated)) { _ in + promise.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in storage.withAsync({ transaction in - Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, using: transaction) + Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, with: error, using: transaction) }, completion: { }) } return promise.map { _ in } diff --git a/SessionMessagingKit/Sending & Receiving/MessageSenderDelegate.swift b/SessionMessagingKit/Sending & Receiving/MessageSenderDelegate.swift index dac0ecc66..1f1cc0969 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSenderDelegate.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSenderDelegate.swift @@ -2,5 +2,5 @@ public protocol MessageSenderDelegate { func handleSuccessfulMessageSend(_ message: Message, using transaction: Any) - func handleFailedMessageSend(_ message: Message, using transaction: Any) + func handleFailedMessageSend(_ message: Message, with error: Error, using transaction: Any) } diff --git a/SignalUtilitiesKit/Database/Storage/Storage+Jobs.swift b/SignalUtilitiesKit/Database/Storage/Storage+Jobs.swift index 60c18412f..ac91708a7 100644 --- a/SignalUtilitiesKit/Database/Storage/Storage+Jobs.swift +++ b/SignalUtilitiesKit/Database/Storage/Storage+Jobs.swift @@ -23,6 +23,25 @@ extension Storage { } return result } + + public func cancelAllPendingJobs(of type: Job.Type, using transaction: YapDatabaseReadWriteTransaction) { + transaction.removeAllObjects(inCollection: type.collection) + } + + public func cancelPendingMessageSendJobs(for threadID: String, using transaction: YapDatabaseReadWriteTransaction) { + var attachmentUploadJobKeys: [String] = [] + transaction.enumerateRows(inCollection: AttachmentUploadJob.collection) { key, object, _, _ in + guard let job = object as? AttachmentUploadJob, job.threadID == threadID else { return } + attachmentUploadJobKeys.append(key) + } + var messageSendJobKeys: [String] = [] + transaction.enumerateRows(inCollection: MessageSendJob.collection) { key, object, _, _ in + guard let job = object as? MessageSendJob, job.message.threadID == threadID else { return } + messageSendJobKeys.append(key) + } + transaction.removeObjects(forKeys: attachmentUploadJobKeys, inCollection: AttachmentUploadJob.collection) + transaction.removeObjects(forKeys: messageSendJobKeys, inCollection: MessageSendJob.collection) + } public func getAttachmentUploadJob(for attachmentID: String) -> AttachmentUploadJob? { var result: [AttachmentUploadJob] = [] diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h index 906bbf1fe..e8010e70e 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h @@ -40,8 +40,7 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value); @property (nonatomic, readonly) uint64_t sortId; @property (nonatomic, readonly) uint64_t receivedAtTimestamp; @property (nonatomic, readonly) BOOL shouldUseServerTime; -// Push notifications -@property (nonatomic) BOOL hasUnfetchedAttachmentsFromPN; +@property (nonatomic, readonly) BOOL isOpenGroupMessage; - (void)setServerTimestampToReceivedTimestamp:(uint64_t)receivedAtTimestamp; diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.m b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.m index 6bc729a9e..004d923f5 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.m +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.m @@ -205,19 +205,18 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value) { OWSAssertDebug(other); - // Sort the messages by the sender's timestamp (Signal uses sortId) - uint64_t sortId1 = self.timestamp; - uint64_t sortId2 = other.timestamp; + uint64_t sortId1; + uint64_t sortId2; - // In open groups messages should be sorted by their server timestamp. `sortId` represents the order in which messages + // In open groups messages should be sorted by server timestamp. `sortId` represents the order in which messages // were processed. Since in the open group poller we sort messages by their server timestamp, sorting by `sortId` is // effectively the same as sorting by server timestamp. - if (self.thread.isGroupThread) { - TSGroupThread *thread = (TSGroupThread *)self.thread; - if (thread.isOpenGroup) { - sortId1 = self.sortId; - sortId2 = other.sortId; - } + if (self.isOpenGroupMessage) { + sortId1 = self.sortId; + sortId2 = other.sortId; + } else { + sortId1 = self.timestamp; + sortId2 = other.timestamp; } if (sortId1 > sortId2) { diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift index 92fc37e3c..e720bcfa1 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift @@ -32,8 +32,9 @@ public final class MessageSenderDelegate : NSObject, SessionMessagingKit.Message tsMessage.update(withSentRecipient: message.recipient!, wasSentByUD: true, transaction: transaction as! YapDatabaseReadWriteTransaction) } - public func handleFailedMessageSend(_ message: Message, using transaction: Any) { - // TODO: Implement + public func handleFailedMessageSend(_ message: Message, with error: Swift.Error, using transaction: Any) { + guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return } + tsMessage.update(sendingError: error, transaction: transaction as! YapDatabaseReadWriteTransaction) } // MARK: Closed Groups diff --git a/SignalUtilitiesKit/OWSAttachmentDownloads.m b/SignalUtilitiesKit/OWSAttachmentDownloads.m index a1d02969a..5501818f8 100644 --- a/SignalUtilitiesKit/OWSAttachmentDownloads.m +++ b/SignalUtilitiesKit/OWSAttachmentDownloads.m @@ -282,8 +282,6 @@ typedef void (^AttachmentDownloadFailure)(NSError *error); [job.attachmentPointer saveWithTransaction:transaction]; if (job.message) { - job.message.hasUnfetchedAttachmentsFromPN = !CurrentAppContext().isMainApp; - [job.message saveWithTransaction:transaction]; [job.message touchWithTransaction:transaction]; } diff --git a/SignalUtilitiesKit/TSPreKeyManager.m b/SignalUtilitiesKit/TSPreKeyManager.m index 612265b73..91ea8857d 100644 --- a/SignalUtilitiesKit/TSPreKeyManager.m +++ b/SignalUtilitiesKit/TSPreKeyManager.m @@ -216,7 +216,6 @@ static const NSUInteger kMaxPrekeyUpdateFailureCount = 5; if (!keyId) { // currentSignedPreKeyId should only be nil before we've completed registration. // We have this guard here for robustness, but we should never get here. - OWSFailDebug(@"Ignoring request to clear signed preKeys since no keyId was specified"); return; }