From f0cbdb8cda72d368f6646d52228602601f393812 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Thu, 3 Dec 2020 10:12:29 +1100 Subject: [PATCH] Fix share extension --- .../MessageReceiver+Handling.swift | 10 +++-- .../Sending & Receiving/MessageSender.swift | 45 +++++++++---------- .../NotificationServiceExtension.swift | 6 +-- .../MessageSender+Convenience.swift | 19 +++++++- .../UI/SharingThreadPickerViewController.m | 15 +------ 5 files changed, 49 insertions(+), 46 deletions(-) diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index 2ef304d0e..31e093258 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -139,6 +139,10 @@ extension MessageReceiver { public static func handleVisibleMessage(_ message: VisibleMessage, associatedWithProto proto: SNProtoContent, openGroupID: String?, using transaction: Any) throws -> String { let storage = SNMessagingKitConfiguration.shared.storage let transaction = transaction as! YapDatabaseReadWriteTransaction + var isMainAppAndActive = false + if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") { + isMainAppAndActive = sharedUserDefaults.bool(forKey: "isMainAppActive") + } // Parse & persist attachments let attachments: [VisibleMessage.Attachment] = proto.dataMessage!.attachments.compactMap { proto in guard let attachment = VisibleMessage.Attachment.fromProto(proto) else { return nil } @@ -191,18 +195,18 @@ extension MessageReceiver { // Start attachment downloads if needed attachmentsToDownload.forEach { attachmentID in let downloadJob = AttachmentDownloadJob(attachmentID: attachmentID, tsIncomingMessageID: tsIncomingMessageID) - if CurrentAppContext().isMainAppAndActive { + if isMainAppAndActive { JobQueue.shared.add(downloadJob, using: transaction) } else { JobQueue.shared.addWithoutExecuting(downloadJob, using: transaction) } } // Cancel any typing indicators if needed - if CurrentAppContext().isMainAppAndActive { + if isMainAppAndActive { cancelTypingIndicatorsIfNeeded(for: message.sender!) } // Notify the user if needed - guard CurrentAppContext().isMainAppAndActive, let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction), + guard isMainAppAndActive, let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction), let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return tsIncomingMessageID } SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction) return tsIncomingMessageID diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index a2e95f574..b1d2b18d4 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -114,8 +114,9 @@ public final class MessageSender : NSObject { guard !isSelfSend else { storage.withAsync({ transaction in MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction) - }, completion: { }) - seal.fulfill(()) + }, completion: { + seal.fulfill(()) + }) return promise } // Attach the user's profile if needed @@ -211,7 +212,18 @@ public final class MessageSender : NSObject { let _ = $0.done(on: DispatchQueue.global(qos: .userInitiated)) { _ in guard !isSuccess else { return } // Succeed as soon as the first promise succeeds isSuccess = true - seal.fulfill(()) + if case .contact(_) = destination, message is VisibleMessage, !isSelfSend { + NotificationCenter.default.post(name: .messageSent, object: NSNumber(value: message.sentTimestamp!)) + } + storage.withAsync({ transaction in + MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction) + if message is VisibleMessage { + let notifyPNServerJob = NotifyPNServerJob(message: snodeMessage) + JobQueue.shared.add(notifyPNServerJob, using: transaction) + } + }, completion: { + seal.fulfill(()) + }) } $0.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in errorCount += 1 @@ -223,21 +235,6 @@ public final class MessageSender : NSObject { SNLog("Couldn't send message due to error: \(error).") seal.reject(error) } - // Handle completion - let _ = promise.done(on: DispatchQueue.main) { - storage.withAsync({ transaction in - MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction) - }, completion: { }) - if case .contact(_) = destination, message is VisibleMessage, !isSelfSend { - NotificationCenter.default.post(name: .messageSent, object: NSNumber(value: message.sentTimestamp!)) - } - if message is VisibleMessage { - let notifyPNServerJob = NotifyPNServerJob(message: snodeMessage) - storage.withAsync({ transaction in - JobQueue.shared.add(notifyPNServerJob, using: transaction) - }, completion: { }) - } - } // Return return promise } @@ -282,15 +279,13 @@ public final class MessageSender : NSObject { // Send the result OpenGroupAPI.sendMessage(openGroupMessage, to: channel, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { openGroupMessage in message.openGroupServerMessageID = openGroupMessage.serverID - seal.fulfill(()) - }.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in - seal.reject(error) - } - // Handle completion - let _ = promise.done(on: DispatchQueue.global(qos: .userInitiated)) { storage.withAsync({ transaction in MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction) - }, completion: { }) + }, completion: { + seal.fulfill(()) + }) + }.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in + seal.reject(error) } // Return return promise diff --git a/SessionPushNotificationExtension/NotificationServiceExtension.swift b/SessionPushNotificationExtension/NotificationServiceExtension.swift index eed427f2b..335df69e1 100644 --- a/SessionPushNotificationExtension/NotificationServiceExtension.swift +++ b/SessionPushNotificationExtension/NotificationServiceExtension.swift @@ -18,11 +18,11 @@ final class NotificationServiceExtension : UNNotificationServiceExtension { self.notificationContent = request.content.mutableCopy() as? UNMutableNotificationContent // Abort if the main app is running - var isMainAppActive = false + var isMainAppAndActive = false if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") { - isMainAppActive = sharedUserDefaults.bool(forKey: "isMainAppActive") + isMainAppAndActive = sharedUserDefaults.bool(forKey: "isMainAppActive") } - guard !isMainAppActive else { return self.handleFailure(for: notificationContent!) } + guard !isMainAppAndActive else { return self.handleFailure(for: notificationContent!) } // Perform main setup DispatchQueue.main.sync { self.setUpIfNecessary() { } } diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift index ec516191d..fb79c5f34 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift @@ -29,7 +29,24 @@ extension MessageSender { public static func sendNonDurably(_ message: VisibleMessage, with attachments: [SignalAttachment], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise { prep(attachments, for: message, using: transaction) - return sendNonDurably(message, in: thread, using: transaction) + let attachments = message.attachmentIDs.compactMap { TSAttachmentStream.fetch(uniqueId: $0, transaction: transaction) } + let attachmentsToUpload = attachments.filter { !$0.isUploaded } + let attachmentUploadPromises: [Promise] = attachmentsToUpload.map { stream in + let openGroup = SNMessagingKitConfiguration.shared.storage.getOpenGroup(for: thread.uniqueId!) + let server = openGroup?.server ?? FileServerAPI.server + // FIXME: This is largely a duplication of the code in AttachmentUploadJob + let maxRetryCount: UInt = (openGroup != nil) ? 24 : 8 + return attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global(qos: .userInitiated)) { + FileServerAPI.uploadAttachment(stream, with: stream.uniqueId!, to: server) + } + } + return when(resolved: attachmentUploadPromises).then(on: DispatchQueue.global(qos: .userInitiated)) { results -> Promise in + let errors = results.compactMap { result -> Swift.Error? in + if case .rejected(let error) = result { return error } else { return nil } + } + if let error = errors.first { return Promise(error: error) } + return sendNonDurably(message, in: thread, using: transaction) + } } public static func sendNonDurably(_ message: Message, in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise { diff --git a/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m b/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m index 0789020a7..a30c44d9c 100644 --- a/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m +++ b/SignalUtilitiesKit/UI/SharingThreadPickerViewController.m @@ -26,7 +26,6 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); @property (nonatomic, readonly) OWSMessageSender *messageSender; @property (nonatomic) TSThread *thread; @property (nonatomic, readonly, weak) id shareViewDelegate; -@property (nonatomic, readonly) UIProgressView *progressView; @property (atomic, nullable) TSOutgoingMessage *outgoingMessage; @end @@ -66,7 +65,6 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); { [super loadView]; - _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; self.title = NSLocalizedString(@"SHARE_EXTENSION_VIEW_TITLE", @"Title for the 'share extension' view."); } @@ -286,8 +284,6 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); - (void)tryToSendMessageWithBlock:(SendMessageBlock)sendMessageBlock fromViewController:(UIViewController *)fromViewController { - // Reset progress in case we're retrying - self.progressView.progress = 0; NSString *progressTitle = NSLocalizedString(@"SHARE_EXTENSION_SENDING_IN_PROGRESS_TITLE", @"Alert title"); UIAlertController *progressAlert = [UIAlertController alertControllerWithTitle:progressTitle @@ -301,14 +297,6 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); }]; [progressAlert addAction:progressCancelAction]; - - // We add a progress subview to an AlertController, which is a total hack. - // ...but it looks good, and given how short a progress view is and how - // little the alert controller changes, I'm not super worried about it. - [progressAlert.view addSubview:self.progressView]; - [self.progressView autoPinWidthToSuperviewWithMargin:24]; - [self.progressView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:progressAlert.view withOffset:4]; - SendCompletionBlock sendCompletion = ^(NSError *_Nullable error, TSOutgoingMessage *message) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -476,7 +464,6 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); { OWSLogDebug(@"upload progress."); OWSAssertIsOnMainThread(); - OWSAssertDebug(self.progressView); if (!self.outgoingMessage) { OWSLogDebug(@"Ignoring upload progress until there is an outgoing message."); @@ -496,7 +483,7 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); if ([attachmentRecordId isEqual:attachmentID]) { if (!isnan(progress)) { - [self.progressView setProgress:progress animated:YES]; + // This is where we'd set progress if we could } else { OWSFailDebug(@"Invalid attachment progress."); }