diff --git a/Session/Configuration.swift b/Session/Configuration.swift index 68f2373cc..c100c7d96 100644 --- a/Session/Configuration.swift +++ b/Session/Configuration.swift @@ -2,6 +2,8 @@ import SessionMessagingKit import SessionProtocolKit import SessionSnodeKit +extension OWSPrimaryStorage : OWSPrimaryStorageProtocol { } + @objc(SNConfiguration) final class Configuration : NSObject { @@ -20,5 +22,6 @@ final class Configuration : NSObject { ) SessionProtocolKit.configure(storage: Storage.shared, sharedSenderKeysDelegate: MessageSenderDelegate.shared) SessionSnodeKit.configure(storage: Storage.shared) + SessionUtilitiesKit.configure(owsPrimaryStorage: OWSPrimaryStorage.shared(), maxFileSize: UInt(Double(FileServerAPI.maxFileSize) / FileServerAPI.fileSizeORMultiplier)) } } diff --git a/Session/Meta/Signal-Bridging-Header.h b/Session/Meta/Signal-Bridging-Header.h index a22e34763..578c0f2e7 100644 --- a/Session/Meta/Signal-Bridging-Header.h +++ b/Session/Meta/Signal-Bridging-Header.h @@ -63,9 +63,9 @@ #import #import #import -#import +#import #import -#import +#import #import #import #import @@ -80,9 +80,9 @@ #import #import #import -#import -#import -#import +#import +#import +#import #import #import #import @@ -92,7 +92,7 @@ #import #import #import -#import +#import #import #import #import diff --git a/Session/Signal/ConversationView/Cells/AttachmentUploadView.m b/Session/Signal/ConversationView/Cells/AttachmentUploadView.m index 4b74b21ef..6672ffa8e 100644 --- a/Session/Signal/ConversationView/Cells/AttachmentUploadView.m +++ b/Session/Signal/ConversationView/Cells/AttachmentUploadView.m @@ -9,7 +9,7 @@ #import #import #import -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/Session/Signal/ConversationView/Cells/OWSGenericAttachmentView.m b/Session/Signal/ConversationView/Cells/OWSGenericAttachmentView.m index b80503e03..55ea4cd7d 100644 --- a/Session/Signal/ConversationView/Cells/OWSGenericAttachmentView.m +++ b/Session/Signal/ConversationView/Cells/OWSGenericAttachmentView.m @@ -12,7 +12,7 @@ #import #import #import -#import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/Session/Signal/ConversationView/Cells/OWSQuotedMessageView.m b/Session/Signal/ConversationView/Cells/OWSQuotedMessageView.m index 6ef78ab2c..9ae9cdd14 100644 --- a/Session/Signal/ConversationView/Cells/OWSQuotedMessageView.m +++ b/Session/Signal/ConversationView/Cells/OWSQuotedMessageView.m @@ -12,7 +12,7 @@ #import #import #import -#import +#import #import #import diff --git a/Session/Signal/ConversationView/ConversationViewItem.m b/Session/Signal/ConversationView/ConversationViewItem.m index 687094150..0d9b25ee6 100644 --- a/Session/Signal/ConversationView/ConversationViewItem.m +++ b/Session/Signal/ConversationView/ConversationViewItem.m @@ -11,7 +11,7 @@ #import "Session-Swift.h" #import "AnyPromise.h" #import -#import +#import #import #import diff --git a/Session/Signal/MediaDetailViewController.m b/Session/Signal/MediaDetailViewController.m index 1d7845a62..825660050 100644 --- a/Session/Signal/MediaDetailViewController.m +++ b/Session/Signal/MediaDetailViewController.m @@ -17,7 +17,7 @@ #import #import #import -#import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/Session/Signal/OWSBackupExportJob.m b/Session/Signal/OWSBackupExportJob.m index fdcba1c38..0d0593483 100644 --- a/Session/Signal/OWSBackupExportJob.m +++ b/Session/Signal/OWSBackupExportJob.m @@ -13,8 +13,8 @@ #import #import #import -#import -#import +#import +#import #import #import diff --git a/Session/Signal/OWSBackupImportJob.m b/Session/Signal/OWSBackupImportJob.m index 6c58e9d07..024f47e56 100644 --- a/Session/Signal/OWSBackupImportJob.m +++ b/Session/Signal/OWSBackupImportJob.m @@ -11,7 +11,7 @@ #import #import #import -#import +#import #import #import diff --git a/Session/Signal/OWSOrphanDataCleaner.m b/Session/Signal/OWSOrphanDataCleaner.m index 0ed5cc8b0..5da139091 100644 --- a/Session/Signal/OWSOrphanDataCleaner.m +++ b/Session/Signal/OWSOrphanDataCleaner.m @@ -9,10 +9,10 @@ #import #import #import - +#import #import #import -#import +#import #import #import #import diff --git a/Session/Signal/SessionResetJob.swift b/Session/Signal/SessionResetJob.swift index 163926c1d..a35f8418c 100644 --- a/Session/Signal/SessionResetJob.swift +++ b/Session/Signal/SessionResetJob.swift @@ -7,7 +7,7 @@ import PromiseKit import SignalUtilitiesKit @objc(OWSSessionResetJobQueue) -public class SessionResetJobQueue: NSObject, JobQueue { +public class SessionResetJobQueue: NSObject, SignalUtilitiesKit.JobQueue { @objc(addContactThread:transaction:) public func add(contactThread: TSContactThread, transaction: YapDatabaseReadWriteTransaction) { diff --git a/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift b/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift index f7c6e4dad..1ebb22422 100644 --- a/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift +++ b/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift @@ -5,6 +5,7 @@ import SignalCoreKit public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility public var delegate: JobDelegate? private let attachmentID: String + private let tsIncomingMessageID: String public var id: String? public var failureCount: UInt = 0 @@ -23,18 +24,22 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject public static let maxFailureCount: UInt = 20 // MARK: Initialization - public init(attachmentID: String) { + public init(attachmentID: String, tsIncomingMessageID: String) { self.attachmentID = attachmentID + self.tsIncomingMessageID = tsIncomingMessageID } // MARK: Coding public init?(coder: NSCoder) { - guard let attachmentID = coder.decodeObject(forKey: "attachmentID") as! String? else { return nil } + guard let attachmentID = coder.decodeObject(forKey: "attachmentID") as! String?, + let tsIncomingMessageID = coder.decodeObject(forKey: "tsIncomingMessageID") as! String? else { return nil } self.attachmentID = attachmentID + self.tsIncomingMessageID = tsIncomingMessageID } public func encode(with coder: NSCoder) { coder.encode(attachmentID, forKey: "attachmentID") + coder.encode(tsIncomingMessageID, forKey: "tsIncomingMessageID") } // MARK: Running @@ -42,19 +47,30 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject guard let pointer = TSAttachmentPointer.fetch(uniqueId: attachmentID) else { return handleFailure(error: Error.noAttachment) } + let storage = Configuration.shared.storage + storage.withAsync({ transaction in + storage.setAttachmentState(to: .downloading, for: pointer, associatedWith: self.tsIncomingMessageID, using: transaction) + }, completion: { }) let temporaryFilePath = URL(fileURLWithPath: OWSTemporaryDirectoryAccessibleAfterFirstAuth() + UUID().uuidString) - FileServerAPI.downloadAttachment(from: pointer.downloadURL).done(on: DispatchQueue.global(qos: .userInitiated)) { data in // Intentionally capture self + let handleFailure: (Swift.Error) -> Void = { error in // Intentionally capture self + OWSFileSystem.deleteFile(temporaryFilePath.absoluteString) + storage.withAsync({ transaction in + storage.setAttachmentState(to: .failed, for: pointer, associatedWith: self.tsIncomingMessageID, using: transaction) + }, completion: { }) + self.handleFailure(error: error) + } + FileServerAPI.downloadAttachment(from: pointer.downloadURL).done(on: DispatchQueue.global(qos: .userInitiated)) { data in do { try data.write(to: temporaryFilePath, options: .atomic) } catch { - return self.handleFailure(error: error) + return handleFailure(error) } let plaintext: Data if let key = pointer.encryptionKey, let digest = pointer.digest { do { plaintext = try Cryptography.decryptAttachment(data, withKey: key, digest: digest, unpaddedSize: pointer.byteCount) } catch { - return self.handleFailure(error: error) + return handleFailure(error) } } else { plaintext = data // Open group attachments are unencrypted @@ -63,15 +79,14 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject do { try stream.write(plaintext) } catch { - return self.handleFailure(error: error) + return handleFailure(error) } OWSFileSystem.deleteFile(temporaryFilePath.absoluteString) - Configuration.shared.storage.withAsync({ transaction in - stream.save(with: transaction as! YapDatabaseReadWriteTransaction) - // TODO: Update the message + storage.withAsync({ transaction in + storage.persist(stream, associatedWith: self.tsIncomingMessageID, using: transaction) }, completion: { }) }.catch(on: DispatchQueue.global()) { error in - self.handleFailure(error: error) + handleFailure(error) } } diff --git a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.h b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.h index 3e67f5f08..121a19be9 100644 --- a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.h +++ b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.h @@ -41,11 +41,6 @@ typedef NS_ENUM(NSUInteger, TSAttachmentType) { @property (nonatomic, readonly, nullable) NSString *caption; @property (nonatomic, nullable) NSString *albumMessageId; -// `migrateAlbumMessageId` is only used in the migration to the new multi-attachment message scheme, -// and shouldn't be used as a general purpose setter. Instead, `albumMessageId` should be passed as -// an initializer param. -- (void)migrateAlbumMessageId:(NSString *)albumMesssageId; - #pragma mark - // This constructor is used for new instances of TSAttachmentPointer, diff --git a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.m b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.m index 43c7139b5..2a36909ee 100644 --- a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.m +++ b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachment.m @@ -244,13 +244,6 @@ NSUInteger const TSAttachmentSchemaVersion = 4; return _contentType.filterFilename; } -#pragma mark - Relationships - -- (void)migrateAlbumMessageId:(NSString *)albumMesssageId -{ - _albumMessageId = albumMesssageId; -} - @end NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.h b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.h index f8f8e6276..66ae2d8d8 100644 --- a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.h +++ b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.h @@ -35,6 +35,9 @@ typedef NS_ENUM(NSUInteger, TSAttachmentPointerState) { @property (nonatomic, readonly) CGSize mediaSize; +// Optional property. Only set for attachments which need "lazy backup restore." +@property (nonatomic, nullable) NSString *lazyRestoreFragmentId; + - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; - (instancetype)initWithServerId:(UInt64)serverId diff --git a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.m b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.m index c7bad6658..666904683 100644 --- a/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.m +++ b/SessionMessagingKit/Messages/Visible Messages/Attachments/TSAttachmentPointer.m @@ -15,16 +15,6 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - - -@interface TSAttachmentPointer () - -// Optional property. Only set for attachments which need "lazy backup restore." -@property (nonatomic, nullable) NSString *lazyRestoreFragmentId; - -@end - -#pragma mark - - @implementation TSAttachmentPointer - (nullable instancetype)initWithCoder:(NSCoder *)coder diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index 8f6caf6f2..885298ba2 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -139,16 +139,24 @@ internal enum MessageReceiver { private static func handleVisibleMessage(_ message: VisibleMessage, associatedWithProto proto: SNProtoContent, using transaction: Any) throws { let delegate = Configuration.shared.messageReceiverDelegate let storage = Configuration.shared.storage - // Handle attachments + // Parse & persist attachments let attachments: [VisibleMessage.Attachment] = proto.dataMessage!.attachments.compactMap { proto in guard let attachment = VisibleMessage.Attachment.fromProto(proto) else { return nil } return attachment.isValid ? attachment : nil } - let attachmentIDs = storage.save(attachments, using: transaction) + let attachmentIDs = storage.persist(attachments, using: transaction) message.attachmentIDs = attachmentIDs + // Update profile if needed + if let profile = message.profile { + delegate.updateProfile(for: message.sender!, from: profile, using: transaction) + } + // Persist the message + guard let (threadID, tsIncomingMessageID) = storage.persist(message, groupPublicKey: message.groupPublicKey, using: transaction) else { throw Error.noThread } + message.threadID = threadID + // Start attachment downloads if needed storage.withAsync({ transaction in attachmentIDs.forEach { attachmentID in - let downloadJob = AttachmentDownloadJob(attachmentID: attachmentID) + let downloadJob = AttachmentDownloadJob(attachmentID: attachmentID, tsIncomingMessageID: tsIncomingMessageID) if CurrentAppContext().isMainAppAndActive { JobQueue.shared.add(downloadJob, using: transaction) } else { @@ -156,16 +164,9 @@ internal enum MessageReceiver { } } }, completion: { }) - // Update profile if needed - if let profile = message.profile { - delegate.updateProfile(for: message.sender!, from: profile, using: transaction) - } - // Persist the message - guard let (threadID, tsIncomingMessage) = storage.persist(message, groupPublicKey: message.groupPublicKey, using: transaction) else { throw Error.noThread } - message.threadID = threadID // Cancel any typing indicators delegate.cancelTypingIndicatorsIfNeeded(for: message.sender!) // Notify the user if needed - delegate.notifyUserIfNeeded(for: tsIncomingMessage, threadID: threadID) + delegate.notifyUserIfNeeded(forMessageWithID: tsIncomingMessageID, threadID: threadID) } } diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiverDelegate.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiverDelegate.swift index cba87224d..4ac94717d 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiverDelegate.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiverDelegate.swift @@ -6,7 +6,7 @@ public protocol MessageReceiverDelegate { func showTypingIndicatorIfNeeded(for senderPublicKey: String) func hideTypingIndicatorIfNeeded(for senderPublicKey: String) func cancelTypingIndicatorsIfNeeded(for senderPublicKey: String) - func notifyUserIfNeeded(for message: Any, threadID: String) + func notifyUserIfNeeded(forMessageWithID messageID: String, threadID: String) func markMessagesAsRead(_ timestamps: [UInt64], from senderPublicKey: String, at timestamp: UInt64) func setExpirationTimer(to duration: UInt32, for senderPublicKey: String, groupPublicKey: String?, using transaction: Any) func disableExpirationTimer(for senderPublicKey: String, groupPublicKey: String?, using transaction: Any) diff --git a/SessionMessagingKit/Storage.swift b/SessionMessagingKit/Storage.swift index 71b0d3fab..62978ad4b 100644 --- a/SessionMessagingKit/Storage.swift +++ b/SessionMessagingKit/Storage.swift @@ -61,8 +61,12 @@ public protocol SessionMessagingKitStorageProtocol { // MARK: - Message Handling - /// Returns the ID of the thread the message was stored under along with the `TSIncomingMessage` that was constructed. - func persist(_ message: VisibleMessage, groupPublicKey: String?, using transaction: Any) -> (String, Any)? + /// Returns the ID of the thread the message was stored under along with the ID of the `TSIncomingMessage` that was constructed. + func persist(_ message: VisibleMessage, groupPublicKey: String?, using transaction: Any) -> (String, String)? /// Returns the IDs of the saved attachments. - func save(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String] + func persist(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String] + /// Also touches the associated message. + func setAttachmentState(to state: TSAttachmentPointerState, for pointer: TSAttachmentPointer, associatedWith tsIncomingMessageID: String, using transaction: Any) + /// Also touches the associated message. + func persist(_ stream: TSAttachmentStream, associatedWith tsIncomingMessageID: String, using transaction: Any) } diff --git a/SessionUtilitiesKit/Configuration.swift b/SessionUtilitiesKit/Configuration.swift index 2e3699ab3..22c85f3a3 100644 --- a/SessionUtilitiesKit/Configuration.swift +++ b/SessionUtilitiesKit/Configuration.swift @@ -1,5 +1,5 @@ -@objc(SNConfiguration) +@objc(SNUtilitiesKitConfiguration) public final class Configuration : NSObject { @objc public let owsPrimaryStorage: OWSPrimaryStorageProtocol public let maxFileSize: UInt diff --git a/SessionUtilitiesKit/TSYapDatabaseObject.m b/SessionUtilitiesKit/TSYapDatabaseObject.m index ce9aa7f73..1c3c84b0a 100644 --- a/SessionUtilitiesKit/TSYapDatabaseObject.m +++ b/SessionUtilitiesKit/TSYapDatabaseObject.m @@ -113,7 +113,7 @@ NS_ASSUME_NONNULL_BEGIN + (YapDatabaseConnection *)dbReadWriteConnection { - return SNConfiguration.shared.owsPrimaryStorage.dbReadWriteConnection; + return SNUtilitiesKitConfiguration.shared.owsPrimaryStorage.dbReadWriteConnection; } + (NSString *)collection diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 05c2cdedf..66780ac69 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -263,6 +263,10 @@ B8CCF63723961D6D0091D419 /* NewPrivateChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */; }; B8CCF63F23975CFB0091D419 /* JoinPublicChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */; }; B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF6422397711F0091D419 /* SettingsVC.swift */; }; + B8D797B2256B25A1007C59DF /* TSAttachmentPointer+Backups.m in Sources */ = {isa = PBXBuildFile; fileRef = B8D797B1256B25A1007C59DF /* TSAttachmentPointer+Backups.m */; }; + B8D797C3256B25A8007C59DF /* TSAttachmentPointer+Backups.h in Headers */ = {isa = PBXBuildFile; fileRef = B8D797B0256B2590007C59DF /* TSAttachmentPointer+Backups.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8D797D5256B2715007C59DF /* TSAttachment+Albums.m in Sources */ = {isa = PBXBuildFile; fileRef = B8D797D4256B2715007C59DF /* TSAttachment+Albums.m */; }; + B8D797DF256B2737007C59DF /* TSAttachment+Albums.h in Headers */ = {isa = PBXBuildFile; fileRef = B8D797DE256B2732007C59DF /* TSAttachment+Albums.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8D8F0F32565F98E0092EF10 /* LKUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* LKUserDefaults.swift */; }; B8D8F0F42565F98E0092EF10 /* PushNotificationAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBDE255A581900E217F9 /* PushNotificationAPI.swift */; }; B8D8F1382566120F0092EF10 /* Storage+ClosedGroups.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D8F1372566120F0092EF10 /* Storage+ClosedGroups.swift */; }; @@ -1385,6 +1389,10 @@ B8CCF638239721E20091D419 /* TabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBar.swift; sourceTree = ""; }; B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinPublicChatVC.swift; sourceTree = ""; }; B8CCF6422397711F0091D419 /* SettingsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsVC.swift; sourceTree = ""; }; + B8D797B0256B2590007C59DF /* TSAttachmentPointer+Backups.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TSAttachmentPointer+Backups.h"; sourceTree = ""; }; + B8D797B1256B25A1007C59DF /* TSAttachmentPointer+Backups.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "TSAttachmentPointer+Backups.m"; sourceTree = ""; }; + B8D797D4256B2715007C59DF /* TSAttachment+Albums.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "TSAttachment+Albums.m"; sourceTree = ""; }; + B8D797DE256B2732007C59DF /* TSAttachment+Albums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TSAttachment+Albums.h"; sourceTree = ""; }; B8D8F1372566120F0092EF10 /* Storage+ClosedGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+ClosedGroups.swift"; sourceTree = ""; }; B8D8F17625661AFA0092EF10 /* Storage+Jobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+Jobs.swift"; sourceTree = ""; }; B8D8F18825661BA50092EF10 /* Storage+OpenGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+OpenGroups.swift"; sourceTree = ""; }; @@ -3289,6 +3297,10 @@ children = ( C379DCFD25673DBC0002D4EB /* Attachment+Conversion.swift */, C38EF224255B6D5D007E1867 /* SignalAttachment.swift */, + B8D797B0256B2590007C59DF /* TSAttachmentPointer+Backups.h */, + B8D797B1256B25A1007C59DF /* TSAttachmentPointer+Backups.m */, + B8D797DE256B2732007C59DF /* TSAttachment+Albums.h */, + B8D797D4256B2715007C59DF /* TSAttachment+Albums.m */, ); path = Attachments; sourceTree = ""; @@ -3970,6 +3982,7 @@ C33FDC97255A582000E217F9 /* TSInfoMessage.h in Headers */, C33FDC6D255A582000E217F9 /* TSContactThread.h in Headers */, C33FDC3A255A581F00E217F9 /* OWSDisappearingMessagesJob.h in Headers */, + B8D797C3256B25A8007C59DF /* TSAttachmentPointer+Backups.h in Headers */, C33FDD6A255A582000E217F9 /* TSErrorMessage.h in Headers */, C33FDDA9255A582000E217F9 /* TSStorageKeys.h in Headers */, C33FDC7A255A582000E217F9 /* OWSIncomingMessageFinder.h in Headers */, @@ -4029,6 +4042,7 @@ C33FDCC8255A582000E217F9 /* NSError+MessageSending.h in Headers */, C38EF403255B6DF7007E1867 /* ContactCellView.h in Headers */, C33FDCA0255A582000E217F9 /* TSInteraction.h in Headers */, + B8D797DF256B2737007C59DF /* TSAttachment+Albums.h in Headers */, C33FDD68255A582000E217F9 /* SignalAccount.h in Headers */, C38EF35E255B6DCC007E1867 /* OWSViewController.h in Headers */, C33FDC4F255A582000E217F9 /* OWSChunkedOutputStream.h in Headers */, @@ -5155,6 +5169,7 @@ C33FDCEE255A582000E217F9 /* ClosedGroupPoller.swift in Sources */, C38EF3BD255B6DE7007E1867 /* ImageEditorTransform.swift in Sources */, C38EF24F255B6D67007E1867 /* UIColor+OWS.m in Sources */, + B8D797D5256B2715007C59DF /* TSAttachment+Albums.m in Sources */, C33FDC9A255A582000E217F9 /* ByteParser.m in Sources */, C38EF293255B6D86007E1867 /* AppSetup.m in Sources */, C33FDDC0255A582000E217F9 /* SignalAccount.m in Sources */, @@ -5202,6 +5217,7 @@ C38EF38D255B6DD2007E1867 /* AttachmentCaptionViewController.swift in Sources */, C33FDC2D255A581F00E217F9 /* ECKeyPair+Hexadecimal.swift in Sources */, C33FDDC6255A582000E217F9 /* TSInfoMessage.m in Sources */, + B8D797B2256B25A1007C59DF /* TSAttachmentPointer+Backups.m in Sources */, C38EF319255B6DBF007E1867 /* Weak.swift in Sources */, C38EF31C255B6DBF007E1867 /* Searcher.swift in Sources */, C38EF2B3255B6D9C007E1867 /* UIViewController+Utilities.swift in Sources */, diff --git a/SignalUtilitiesKit/Database/Migration/OWSDatabaseMigration.h b/SignalUtilitiesKit/Database/Migration/OWSDatabaseMigration.h index ec59a44cd..3f1bd715e 100644 --- a/SignalUtilitiesKit/Database/Migration/OWSDatabaseMigration.h +++ b/SignalUtilitiesKit/Database/Migration/OWSDatabaseMigration.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/Database/Storage/Storage+Messaging.swift b/SignalUtilitiesKit/Database/Storage/Storage+Messaging.swift index ca05b565c..fca7c17b5 100644 --- a/SignalUtilitiesKit/Database/Storage/Storage+Messaging.swift +++ b/SignalUtilitiesKit/Database/Storage/Storage+Messaging.swift @@ -16,8 +16,8 @@ extension Storage { return try! promise.wait() } - /// Returns the ID of the thread the message was stored under along with the `TSIncomingMessage` that was constructed. - public func persist(_ message: VisibleMessage, groupPublicKey: String?, using transaction: Any) -> (String, Any)? { + /// Returns the ID of the thread the message was stored under along with the ID of the `TSIncomingMessage` that was constructed. + public func persist(_ message: VisibleMessage, groupPublicKey: String?, using transaction: Any) -> (String, String)? { let transaction = transaction as! YapDatabaseReadWriteTransaction var threadOrNil: TSThread? if let groupPublicKey = groupPublicKey { @@ -30,14 +30,32 @@ extension Storage { guard let thread = threadOrNil else { return nil } let message = TSIncomingMessage.from(message, associatedWith: thread) message.save(with: transaction) - return (thread.uniqueId!, message) + return (thread.uniqueId!, message.uniqueId!) } - public func save(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String] { + /// Returns the IDs of the saved attachments. + public func persist(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String] { return attachments.map { attachment in let tsAttachment = TSAttachmentPointer.from(attachment) tsAttachment.save(with: transaction as! YapDatabaseReadWriteTransaction) return tsAttachment.uniqueId! } } + + /// Also touches the associated message. + public func setAttachmentState(to state: TSAttachmentPointerState, for pointer: TSAttachmentPointer, associatedWith tsIncomingMessageID: String, using transaction: Any) { + let transaction = transaction as! YapDatabaseReadWriteTransaction + pointer.state = state + pointer.save(with: transaction) + guard let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction) else { return } + tsIncomingMessage.touch(with: transaction) + } + + /// Also touches the associated message. + public func persist(_ stream: TSAttachmentStream, associatedWith tsIncomingMessageID: String, using transaction: Any) { + let transaction = transaction as! YapDatabaseReadWriteTransaction + stream.save(with: transaction) + guard let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction) else { return } + tsIncomingMessage.touch(with: transaction) + } } diff --git a/SignalUtilitiesKit/Database/Utilities/TSDatabaseView.m b/SignalUtilitiesKit/Database/Utilities/TSDatabaseView.m index 86b1658ec..fdb13e221 100644 --- a/SignalUtilitiesKit/Database/Utilities/TSDatabaseView.m +++ b/SignalUtilitiesKit/Database/Utilities/TSDatabaseView.m @@ -3,7 +3,7 @@ // #import "TSDatabaseView.h" - +#import "TSAttachmentPointer+Backups.h" #import "OWSReadTracking.h" #import "TSAttachment.h" #import "TSAttachmentPointer.h" diff --git a/SignalUtilitiesKit/Messaging/Attachments/TSAttachment+Albums.h b/SignalUtilitiesKit/Messaging/Attachments/TSAttachment+Albums.h new file mode 100644 index 000000000..946791856 --- /dev/null +++ b/SignalUtilitiesKit/Messaging/Attachments/TSAttachment+Albums.h @@ -0,0 +1,18 @@ +#import +#import "TSMessage.h" + +#ifndef TSAttachment_Albums_h +#define TSAttachment_Albums_h + +@interface TSAttachment (Albums) + +- (nullable TSMessage *)fetchAlbumMessageWithTransaction:(YapDatabaseReadTransaction *)transaction; + +// `migrateAlbumMessageId` is only used in the migration to the new multi-attachment message scheme, +// and shouldn't be used as a general purpose setter. Instead, `albumMessageId` should be passed as +// an initializer param. +- (void)migrateAlbumMessageId:(NSString *)albumMesssageId; + +@end + +#endif diff --git a/SignalUtilitiesKit/Messaging/Attachments/TSAttachment+Albums.m b/SignalUtilitiesKit/Messaging/Attachments/TSAttachment+Albums.m new file mode 100644 index 000000000..83999453c --- /dev/null +++ b/SignalUtilitiesKit/Messaging/Attachments/TSAttachment+Albums.m @@ -0,0 +1,18 @@ +#import "TSAttachment+Albums.h" + +@implementation TSAttachment (Albums) + +- (nullable TSMessage *)fetchAlbumMessageWithTransaction:(YapDatabaseReadTransaction *)transaction +{ + if (self.albumMessageId == nil) { + return nil; + } + return [TSMessage fetchObjectWithUniqueID:self.albumMessageId transaction:transaction]; +} + +- (void)migrateAlbumMessageId:(NSString *)albumMesssageId +{ + self.albumMessageId = albumMesssageId; +} + +@end diff --git a/SignalUtilitiesKit/Messaging/Attachments/TSAttachmentPointer+Backups.h b/SignalUtilitiesKit/Messaging/Attachments/TSAttachmentPointer+Backups.h new file mode 100644 index 000000000..7fab5a7d9 --- /dev/null +++ b/SignalUtilitiesKit/Messaging/Attachments/TSAttachmentPointer+Backups.h @@ -0,0 +1,19 @@ +#import +#import +#import "OWSBackupFragment.h" + +#ifndef TSAttachmentPointer_Backups_h +#define TSAttachmentPointer_Backups_h + +@interface TSAttachmentPointer (Backups) + +// Non-nil for attachments which need "lazy backup restore." +- (nullable OWSBackupFragment *)lazyRestoreFragment; + +// Marks attachment as needing "lazy backup restore." +- (void)markForLazyRestoreWithFragment:(OWSBackupFragment *)lazyRestoreFragment + transaction:(YapDatabaseReadWriteTransaction *)transaction; + +@end + +#endif diff --git a/SignalUtilitiesKit/Messaging/Attachments/TSAttachmentPointer+Backups.m b/SignalUtilitiesKit/Messaging/Attachments/TSAttachmentPointer+Backups.m new file mode 100644 index 000000000..2e21f84df --- /dev/null +++ b/SignalUtilitiesKit/Messaging/Attachments/TSAttachmentPointer+Backups.m @@ -0,0 +1,34 @@ +#import "TSAttachmentPointer+Backups.h" + +@implementation TSAttachmentPointer (Backups) + +- (nullable OWSBackupFragment *)lazyRestoreFragment +{ + if (!self.lazyRestoreFragmentId) { + return nil; + } + OWSBackupFragment *_Nullable backupFragment = + [OWSBackupFragment fetchObjectWithUniqueID:self.lazyRestoreFragmentId]; + OWSAssertDebug(backupFragment); + return backupFragment; +} + +- (void)markForLazyRestoreWithFragment:(OWSBackupFragment *)lazyRestoreFragment + transaction:(YapDatabaseReadWriteTransaction *)transaction +{ + OWSAssertDebug(lazyRestoreFragment); + OWSAssertDebug(transaction); + + if (!lazyRestoreFragment.uniqueId) { + // If metadata hasn't been saved yet, save now. + [lazyRestoreFragment saveWithTransaction:transaction]; + + OWSAssertDebug(lazyRestoreFragment.uniqueId); + } + [self applyChangeToSelfAndLatestCopy:transaction + changeBlock:^(TSAttachmentPointer *attachment) { + [attachment setLazyRestoreFragmentId:lazyRestoreFragment.uniqueId]; + }]; +} + +@end diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h index 477a59a7f..906bbf1fe 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/Messaging/Disappearing Messages/OWSDisappearingMessagesConfiguration.h b/SignalUtilitiesKit/Messaging/Disappearing Messages/OWSDisappearingMessagesConfiguration.h index c84747523..3b1c12e19 100644 --- a/SignalUtilitiesKit/Messaging/Disappearing Messages/OWSDisappearingMessagesConfiguration.h +++ b/SignalUtilitiesKit/Messaging/Disappearing Messages/OWSDisappearingMessagesConfiguration.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/Messaging/Quotes/OWSQuotedReplyModel.m b/SignalUtilitiesKit/Messaging/Quotes/OWSQuotedReplyModel.m index 29d9f5e32..3ea9a8420 100644 --- a/SignalUtilitiesKit/Messaging/Quotes/OWSQuotedReplyModel.m +++ b/SignalUtilitiesKit/Messaging/Quotes/OWSQuotedReplyModel.m @@ -6,10 +6,9 @@ #import "ConversationViewItem.h" #import #import - #import -#import -#import +#import +#import #import #import #import diff --git a/SignalUtilitiesKit/Messaging/Quotes/TSQuotedMessage.h b/SignalUtilitiesKit/Messaging/Quotes/TSQuotedMessage.h index ecfb822ce..bf18aaddb 100644 --- a/SignalUtilitiesKit/Messaging/Quotes/TSQuotedMessage.h +++ b/SignalUtilitiesKit/Messaging/Quotes/TSQuotedMessage.h @@ -3,7 +3,7 @@ // #import -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageReceiverDelegate.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageReceiverDelegate.swift index 84eb02a3f..bea7e37c4 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageReceiverDelegate.swift +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageReceiverDelegate.swift @@ -89,10 +89,10 @@ public final class MessageReceiverDelegate : SessionMessagingKit.MessageReceiver // MARK: - Notifications - public func notifyUserIfNeeded(for message: Any, threadID: String) { - guard let thread = TSThread.fetch(uniqueId: threadID) else { return } + public func notifyUserIfNeeded(forMessageWithID messageID: String, threadID: String) { + guard let message = TSIncomingMessage.fetch(uniqueId: messageID), let thread = TSThread.fetch(uniqueId: threadID) else { return } Storage.read { transaction in - SSKEnvironment.shared.notificationsManager!.notifyUser(for: (message as! TSIncomingMessage), in: thread, transaction: transaction) + SSKEnvironment.shared.notificationsManager!.notifyUser(for: message, in: thread, transaction: transaction) } } diff --git a/SignalUtilitiesKit/Meta/SignalUtilitiesKit.h b/SignalUtilitiesKit/Meta/SignalUtilitiesKit.h index ec10aed87..2a123cb5f 100644 --- a/SignalUtilitiesKit/Meta/SignalUtilitiesKit.h +++ b/SignalUtilitiesKit/Meta/SignalUtilitiesKit.h @@ -12,14 +12,12 @@ FOUNDATION_EXPORT const unsigned char SignalUtilitiesKitVersionString[]; #import #import #import -#import #import #import #import #import #import #import -#import #import #import #import @@ -72,8 +70,8 @@ FOUNDATION_EXPORT const unsigned char SignalUtilitiesKitVersionString[]; #import #import #import -#import -#import +#import +#import #import #import #import @@ -88,7 +86,6 @@ FOUNDATION_EXPORT const unsigned char SignalUtilitiesKitVersionString[]; #import #import #import -#import #import #import #import diff --git a/SignalUtilitiesKit/OWSBackupFragment.h b/SignalUtilitiesKit/OWSBackupFragment.h index 571d1af3e..392a7e73a 100644 --- a/SignalUtilitiesKit/OWSBackupFragment.h +++ b/SignalUtilitiesKit/OWSBackupFragment.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/OWSMediaGalleryFinder.m b/SignalUtilitiesKit/OWSMediaGalleryFinder.m index 04b39fb94..55bd348cb 100644 --- a/SignalUtilitiesKit/OWSMediaGalleryFinder.m +++ b/SignalUtilitiesKit/OWSMediaGalleryFinder.m @@ -12,6 +12,7 @@ #import #import #import +#import "TSAttachment+Albums.h" NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/OWSRecipientIdentity.h b/SignalUtilitiesKit/OWSRecipientIdentity.h index f1486c656..fec840379 100644 --- a/SignalUtilitiesKit/OWSRecipientIdentity.h +++ b/SignalUtilitiesKit/OWSRecipientIdentity.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/SSKJobRecord.h b/SignalUtilitiesKit/SSKJobRecord.h index 4ee258d5c..30c4adf2b 100644 --- a/SignalUtilitiesKit/SSKJobRecord.h +++ b/SignalUtilitiesKit/SSKJobRecord.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/SignalAccount.h b/SignalUtilitiesKit/SignalAccount.h index e8b54290e..bbf29282d 100644 --- a/SignalUtilitiesKit/SignalAccount.h +++ b/SignalUtilitiesKit/SignalAccount.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/SignalRecipient.h b/SignalUtilitiesKit/SignalRecipient.h index b1638cd4a..430698ae3 100644 --- a/SignalUtilitiesKit/SignalRecipient.h +++ b/SignalUtilitiesKit/SignalRecipient.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/Threads/TSGroupModel.h b/SignalUtilitiesKit/Threads/TSGroupModel.h index 9a3de614f..0855a2880 100644 --- a/SignalUtilitiesKit/Threads/TSGroupModel.h +++ b/SignalUtilitiesKit/Threads/TSGroupModel.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import #import diff --git a/SignalUtilitiesKit/Threads/TSThread.h b/SignalUtilitiesKit/Threads/TSThread.h index 08e8f8ecb..1c1858e58 100644 --- a/SignalUtilitiesKit/Threads/TSThread.h +++ b/SignalUtilitiesKit/Threads/TSThread.h @@ -2,7 +2,7 @@ // Copyright (c) 2019 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/To Do/OWSProfileManager.m b/SignalUtilitiesKit/To Do/OWSProfileManager.m index 8e99e6925..07bf55f90 100644 --- a/SignalUtilitiesKit/To Do/OWSProfileManager.m +++ b/SignalUtilitiesKit/To Do/OWSProfileManager.m @@ -11,7 +11,7 @@ #import #import #import -#import +#import #import #import #import @@ -21,8 +21,8 @@ #import #import #import -#import -#import +#import +#import #import diff --git a/SignalUtilitiesKit/To Do/OWSUserProfile.h b/SignalUtilitiesKit/To Do/OWSUserProfile.h index 1c79e4531..5e8d2a283 100644 --- a/SignalUtilitiesKit/To Do/OWSUserProfile.h +++ b/SignalUtilitiesKit/To Do/OWSUserProfile.h @@ -2,7 +2,7 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SignalUtilitiesKit/UI/UIUtil.h b/SignalUtilitiesKit/UI/UIUtil.h index 96983e675..c10563a72 100644 --- a/SignalUtilitiesKit/UI/UIUtil.h +++ b/SignalUtilitiesKit/UI/UIUtil.h @@ -5,7 +5,7 @@ #import #import #import -#import +#import #define ACCESSIBILITY_IDENTIFIER_WITH_NAME(_root_view, _variable_name) \ ([NSString stringWithFormat:@"%@.%@", _root_view.class, _variable_name]) diff --git a/SignalUtilitiesKit/Utilities/AttachmentSharing.m b/SignalUtilitiesKit/Utilities/AttachmentSharing.m index aada8799c..cb4f18bd1 100644 --- a/SignalUtilitiesKit/Utilities/AttachmentSharing.m +++ b/SignalUtilitiesKit/Utilities/AttachmentSharing.m @@ -5,7 +5,7 @@ #import "AttachmentSharing.h" #import "UIUtil.h" #import -#import +#import NS_ASSUME_NONNULL_BEGIN