diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index 155154500..1647ff4c7 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -202,9 +202,7 @@ extension MessageReceiver { cancelTypingIndicatorsIfNeeded(for: message.sender!) // Notify the user if needed guard let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction), let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return } - Storage.read { transaction in - SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction) - } + SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction) } private static func handleClosedGroupUpdate(_ message: ClosedGroupUpdate, using transaction: Any) { diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift similarity index 72% rename from SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift rename to SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift index 670a924a4..4ef0698fb 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift @@ -1,103 +1,7 @@ -import SessionProtocolKit import PromiseKit extension MessageSender : SharedSenderKeysDelegate { - // MARK: - Sending Convenience - - private static func prep(_ attachments: [SignalAttachment], for message: VisibleMessage, using transaction: YapDatabaseReadWriteTransaction) { - guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { - #if DEBUG - preconditionFailure() - #endif - return - } - // Anything added to message.attachmentIDs will be uploaded by an UploadAttachmentJob. Any attachment IDs added to tsMessage will - // make it render as an attachment (not what we want in the case of a link preview or quoted attachment). - 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) - } - tsMessage.quotedMessage?.createThumbnailAttachmentsIfNecessary(with: transaction) - var linkPreviewAttachmentID: String? - if let id = tsMessage.linkPreview?.imageAttachmentId, - let stream = TSAttachment.fetch(uniqueId: id, transaction: transaction) as? TSAttachmentStream { - linkPreviewAttachmentID = id - streams.append(stream) - } - message.attachmentIDs = streams.map { $0.uniqueId! } - tsMessage.attachmentIds.addObjects(from: message.attachmentIDs) - if let id = linkPreviewAttachmentID { tsMessage.attachmentIds.remove(id) } - tsMessage.save(with: transaction) - } - - @objc(send:withAttachments:inThread:usingTransaction:) - public static func send(_ message: VisibleMessage, 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: VisibleMessage, 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: VisibleMessage, 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! - let destination = Message.Destination.from(thread) - return MessageSender.send(message, to: destination, using: transaction) - } - - - - // MARK: - Success & Failure Handling - - public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, using transaction: Any) { - guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return } - tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0 - tsMessage.isOpenGroupMessage = tsMessage.openGroupServerMessageID != 0 - var recipients = [ message.recipient! ] - if case .closedGroup(_) = destination, let threadID = message.threadID, // threadID should always be set at this point - let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction as! YapDatabaseReadTransaction), thread.usesSharedSenderKeys { - recipients = thread.groupModel.groupMemberIds - } - recipients.forEach { recipient in - tsMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction as! YapDatabaseReadWriteTransaction) - } - OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction as! YapDatabaseReadWriteTransaction) - } - - public static 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 - public static func createClosedGroup(name: String, members: Set, transaction: YapDatabaseReadWriteTransaction) -> Promise { // Prepare var members = members @@ -289,7 +193,7 @@ extension MessageSender : SharedSenderKeysDelegate { newMembers.remove(userPublicKey) return update(groupPublicKey, with: newMembers, name: group.groupName!, transaction: transaction) } - + public func requestSenderKey(for groupPublicKey: String, senderPublicKey: String, using transaction: Any) { // FIXME: This should be static SNLog("Requesting sender key for group public key: \(groupPublicKey), sender public key: \(senderPublicKey).") let transaction = transaction as! YapDatabaseReadWriteTransaction diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index bd5635132..f1952c505 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -42,6 +42,37 @@ public final class MessageSender : NSObject { public static let shared = MessageSender() // FIXME: Remove once requestSenderKey is static + // MARK: Preparation + private static func prep(_ attachments: [SignalAttachment], for message: VisibleMessage, using transaction: YapDatabaseReadWriteTransaction) { + guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { + #if DEBUG + preconditionFailure() + #endif + return + } + // Anything added to message.attachmentIDs will be uploaded by an UploadAttachmentJob. Any attachment IDs added to tsMessage will + // make it render as an attachment (not what we want in the case of a link preview or quoted attachment). + 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) + } + tsMessage.quotedMessage?.createThumbnailAttachmentsIfNecessary(with: transaction) + var linkPreviewAttachmentID: String? + if let id = tsMessage.linkPreview?.imageAttachmentId, + let stream = TSAttachment.fetch(uniqueId: id, transaction: transaction) as? TSAttachmentStream { + linkPreviewAttachmentID = id + streams.append(stream) + } + message.attachmentIDs = streams.map { $0.uniqueId! } + tsMessage.attachmentIds.addObjects(from: message.attachmentIDs) + if let id = linkPreviewAttachmentID { tsMessage.attachmentIds.remove(id) } + tsMessage.save(with: transaction) + } + // MARK: Convenience public static func send(_ message: Message, to destination: Message.Destination, using transaction: Any) -> Promise { switch destination { @@ -258,4 +289,25 @@ public final class MessageSender : NSObject { // Return return promise } + + // MARK: Success & Failure Handling + public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, using transaction: Any) { + guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return } + tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0 + tsMessage.isOpenGroupMessage = tsMessage.openGroupServerMessageID != 0 + var recipients = [ message.recipient! ] + if case .closedGroup(_) = destination, let threadID = message.threadID, // threadID should always be set at this point + let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction as! YapDatabaseReadTransaction), thread.usesSharedSenderKeys { + recipients = thread.groupModel.groupMemberIds + } + recipients.forEach { recipient in + tsMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction as! YapDatabaseReadWriteTransaction) + } + OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction as! YapDatabaseReadWriteTransaction) + } + + public static 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) + } } diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index dcec96784..41dd955a6 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -317,7 +317,7 @@ C32C59C5256DB41F003C73A2 /* TSGroupModel.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB0A255A580700E217F9 /* TSGroupModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; C32C59C6256DB41F003C73A2 /* TSGroupThread.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA79255A57FB00E217F9 /* TSGroupThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; C32C59C7256DB41F003C73A2 /* TSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBB8255A581600E217F9 /* TSThread.m */; }; - C32C5A02256DB658003C73A2 /* MessageSender+Handling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D8F1EF256621180092EF10 /* MessageSender+Handling.swift */; }; + C32C5A02256DB658003C73A2 /* MessageSender+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D8F1EF256621180092EF10 /* MessageSender+Convenience.swift */; }; C32C5A13256DB7A5003C73A2 /* PushNotificationAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBDE255A581900E217F9 /* PushNotificationAPI.swift */; }; C32C5A24256DB7DB003C73A2 /* LKUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* LKUserDefaults.swift */; }; C32C5A2D256DB849003C73A2 /* LKGroupUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBE1255A581A00E217F9 /* LKGroupUtilities.m */; }; @@ -579,6 +579,7 @@ C37F54BA255BB2D8002AEA92 /* SessionProtocolKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A8622553B41A00C340D1 /* SessionProtocolKit.framework */; }; C37F54CB255BB53F002AEA92 /* SessionProtocolKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A8622553B41A00C340D1 /* SessionProtocolKit.framework */; }; C37F54DC255BB84A002AEA92 /* SessionSnodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A59F255385C100C340D1 /* SessionSnodeKit.framework */; }; + C38D5E8D2575011E00B6A65C /* MessageSender+ClosedGroups.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38D5E8C2575011E00B6A65C /* MessageSender+ClosedGroups.swift */; }; C38EF00C255B61CC007E1867 /* SignalUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C33FD9AB255A548A00E217F9 /* SignalUtilitiesKit.framework */; }; C38EF00E255B61DC007E1867 /* SignalUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C33FD9AB255A548A00E217F9 /* SignalUtilitiesKit.framework */; }; C38EF216255B6D3B007E1867 /* Theme.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF212255B6D3A007E1867 /* Theme.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1388,7 +1389,7 @@ B8D8F18825661BA50092EF10 /* Storage+OpenGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+OpenGroups.swift"; sourceTree = ""; }; B8D8F19225661BF80092EF10 /* Storage+Messaging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+Messaging.swift"; sourceTree = ""; }; B8D8F1BC25661C6F0092EF10 /* Storage+OnionRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+OnionRequests.swift"; sourceTree = ""; }; - B8D8F1EF256621180092EF10 /* MessageSender+Handling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "MessageSender+Handling.swift"; path = "../../SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Handling.swift"; sourceTree = ""; }; + B8D8F1EF256621180092EF10 /* MessageSender+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "MessageSender+Convenience.swift"; path = "../../SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift"; sourceTree = ""; }; B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = ""; }; B90418E5183E9DD40038554A /* DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DateUtil.m; sourceTree = ""; }; B9EB5ABC1884C002007CBB57 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; @@ -1684,6 +1685,7 @@ C379DCFD25673DBC0002D4EB /* TSAttachmentPointer+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSAttachmentPointer+Conversion.swift"; sourceTree = ""; }; C37F53E8255BA9BB002AEA92 /* Environment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Environment.h; sourceTree = ""; }; C37F5402255BA9ED002AEA92 /* Environment.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Environment.m; sourceTree = ""; }; + C38D5E8C2575011E00B6A65C /* MessageSender+ClosedGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageSender+ClosedGroups.swift"; sourceTree = ""; }; C38EEF09255B49A8007E1867 /* SNProtoEnvelope+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SNProtoEnvelope+Conversion.swift"; sourceTree = ""; }; C38EF212255B6D3A007E1867 /* Theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Theme.h; path = SignalUtilitiesKit/UI/Theme.h; sourceTree = SOURCE_ROOT; }; C38EF214255B6D3A007E1867 /* Theme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Theme.m; path = SignalUtilitiesKit/UI/Theme.m; sourceTree = SOURCE_ROOT; }; @@ -2671,8 +2673,9 @@ C32C5995256DAF85003C73A2 /* Typing Indicators */, C3471FA32555439E00297E91 /* Notification+MessageSender.swift */, C300A5F12554B09800555489 /* MessageSender.swift */, + C38D5E8C2575011E00B6A65C /* MessageSender+ClosedGroups.swift */, + B8D8F1EF256621180092EF10 /* MessageSender+Convenience.swift */, C3471ECA2555356A00297E91 /* MessageSender+Encryption.swift */, - B8D8F1EF256621180092EF10 /* MessageSender+Handling.swift */, C300A5FB2554B0A000555489 /* MessageReceiver.swift */, C3471F4B25553AB000297E91 /* MessageReceiver+Decryption.swift */, C32C5A87256DBCF9003C73A2 /* MessageReceiver+Handling.swift */, @@ -5223,7 +5226,7 @@ C32C5AAB256DBE8F003C73A2 /* TSIncomingMessage+Conversion.swift in Sources */, C32C5A88256DBCF9003C73A2 /* MessageReceiver+Handling.swift in Sources */, C32C5C1B256DC9E0003C73A2 /* GeneralUtilities.swift in Sources */, - C32C5A02256DB658003C73A2 /* MessageSender+Handling.swift in Sources */, + C32C5A02256DB658003C73A2 /* MessageSender+Convenience.swift in Sources */, B8566C6C256F60F50045A0B9 /* OWSUserProfile.m in Sources */, C32C5D2E256DD4EA003C73A2 /* TSUnreadIndicatorInteraction.m in Sources */, C32C599E256DB02B003C73A2 /* TypingIndicators.swift in Sources */, @@ -5239,6 +5242,7 @@ C3A3A0EC256E1949004D228D /* OWSRecipientIdentity.m in Sources */, C32C5AB2256DBE8F003C73A2 /* TSMessage.m in Sources */, C3A3A0FE256E1A3C004D228D /* TSDatabaseSecondaryIndexes.m in Sources */, + C38D5E8D2575011E00B6A65C /* MessageSender+ClosedGroups.swift in Sources */, C32C5B1C256DC19D003C73A2 /* TSQuotedMessage.m in Sources */, C352A349255781F400338F3E /* AttachmentDownloadJob.swift in Sources */, C352A30925574D8500338F3E /* Message+Destination.swift in Sources */, diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift new file mode 100644 index 000000000..ec516191d --- /dev/null +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift @@ -0,0 +1,40 @@ +import SessionProtocolKit +import PromiseKit + +extension MessageSender { + + @objc(send:withAttachments:inThread:usingTransaction:) + public static func send(_ message: VisibleMessage, 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: VisibleMessage, 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: VisibleMessage, 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! + let destination = Message.Destination.from(thread) + return MessageSender.send(message, to: destination, using: transaction) + } +}