diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 23b9c3d8b..2f634819d 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -283,14 +283,6 @@ C32A026C25A801AF000ED5D4 /* NSData+messagePadding.h in Headers */ = {isa = PBXBuildFile; fileRef = C3A71D4E25589FF30043A11F /* NSData+messagePadding.h */; settings = {ATTRIBUTES = (Public, ); }; }; C32C598A256D0664003C73A2 /* SNProtoEnvelope+Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38EEF09255B49A8007E1867 /* SNProtoEnvelope+Conversion.swift */; }; C32C599E256DB02B003C73A2 /* TypingIndicators.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA87255A57FC00E217F9 /* TypingIndicators.swift */; }; - C32C59C0256DB41F003C73A2 /* TSThread.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAD3255A580300E217F9 /* TSThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C32C59C1256DB41F003C73A2 /* TSGroupThread.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDC01255A581C00E217F9 /* TSGroupThread.m */; }; - C32C59C2256DB41F003C73A2 /* TSContactThread.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAB3255A580000E217F9 /* TSContactThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C32C59C3256DB41F003C73A2 /* TSGroupModel.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB73255A581000E217F9 /* TSGroupModel.m */; }; - C32C59C4256DB41F003C73A2 /* TSContactThread.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAF9255A580600E217F9 /* TSContactThread.m */; }; - 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 */; }; C32C5A13256DB7A5003C73A2 /* PushNotificationAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBDE255A581900E217F9 /* PushNotificationAPI.swift */; }; C32C5A24256DB7DB003C73A2 /* SNUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* SNUserDefaults.swift */; }; C32C5A2D256DB849003C73A2 /* LKGroupUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBE1255A581A00E217F9 /* LKGroupUtilities.m */; }; @@ -353,7 +345,6 @@ C32C5FAA256DFED9003C73A2 /* NSArray+Functional.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB5C255A580E00E217F9 /* NSArray+Functional.h */; settings = {ATTRIBUTES = (Public, ); }; }; C32C5FBB256E0206003C73A2 /* OWSBackgroundTask.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDC1B255A581F00E217F9 /* OWSBackgroundTask.m */; }; C32C5FC4256E0209003C73A2 /* OWSBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB38255A580B00E217F9 /* OWSBackgroundTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C32C5FD6256E0346003C73A2 /* Notification+Thread.swift in Sources */ = {isa = PBXBuildFile; fileRef = C32C5FD5256E0346003C73A2 /* Notification+Thread.swift */; }; C32C600F256E07F5003C73A2 /* NSUserDefaults+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB77255A581000E217F9 /* NSUserDefaults+OWS.m */; }; C32C6018256E07F9003C73A2 /* NSUserDefaults+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB51255A580D00E217F9 /* NSUserDefaults+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; }; C33100082558FF6D00070591 /* NewConversationButtonSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83F2B85240C7B8F000A54AB /* NewConversationButtonSet.swift */; }; @@ -709,12 +700,12 @@ FD09C5EA282A1BB2000CE219 /* ThreadTypingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09C5E9282A1BB2000CE219 /* ThreadTypingIndicator.swift */; }; FD09C5EC282B8F18000CE219 /* AttachmentError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09C5EB282B8F17000CE219 /* AttachmentError.swift */; }; FD17D79927F40AB800122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */; }; - FD17D79C27F40B2E00122BE0 /* SMKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79B27F40B2E00122BE0 /* SMKLegacyModels.swift */; }; + FD17D79C27F40B2E00122BE0 /* SMKLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79B27F40B2E00122BE0 /* SMKLegacy.swift */; }; FD17D7A027F40CC800122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */; }; FD17D7A127F40D2500122BE0 /* GRDBStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F527EAD44C00FF65E7 /* GRDBStorage.swift */; }; FD17D7A227F40F0500122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79527F3E04600122BE0 /* _001_InitialSetupMigration.swift */; }; FD17D7A427F40F8100122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */; }; - FD17D7A727F41AF000122BE0 /* SSKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */; }; + FD17D7A727F41AF000122BE0 /* SSKLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A627F41AF000122BE0 /* SSKLegacy.swift */; }; FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A927F41BF500122BE0 /* SnodeSet.swift */; }; FD17D7AE27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */; }; FD17D7B027F4225C00122BE0 /* Set+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7AF27F4225C00122BE0 /* Set+Utilities.swift */; }; @@ -735,7 +726,7 @@ FD17D7E127F67BD400122BE0 /* SnodeReceivedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E027F67BD400122BE0 /* SnodeReceivedMessage.swift */; }; FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E427F6A09900122BE0 /* Identity.swift */; }; FD17D7E727F6A16700122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */; }; - FD17D7EA27F6A1C600122BE0 /* SUKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */; }; + FD17D7EA27F6A1C600122BE0 /* SUKLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */; }; FD1C98E4282E3C5B00B76F9E /* UINavigationBar+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1C98E3282E3C5B00B76F9E /* UINavigationBar+Utilities.swift */; }; FD28A4F227E990E800FF65E7 /* BlockingManagerRemovalMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F127E990E800FF65E7 /* BlockingManagerRemovalMigration.swift */; }; FD28A4F427EA79F800FF65E7 /* BlockListUIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */; }; @@ -1304,7 +1295,6 @@ C328255125CA64470062D0A7 /* ContextMenuVC+ActionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContextMenuVC+ActionView.swift"; sourceTree = ""; }; C32C5A87256DBCF9003C73A2 /* MessageReceiver+Handling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+Handling.swift"; sourceTree = ""; }; C32C5B3E256DC1DF003C73A2 /* TSQuotedMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSQuotedMessage+Conversion.swift"; sourceTree = ""; }; - C32C5FD5256E0346003C73A2 /* Notification+Thread.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+Thread.swift"; sourceTree = ""; }; C33100132558FFC200070591 /* UIImage+Tinting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Tinting.swift"; sourceTree = ""; }; C33100272559000A00070591 /* UIView+Rendering.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Rendering.swift"; sourceTree = ""; }; C3310032255900A400070591 /* Notification+AppMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+AppMode.swift"; sourceTree = ""; }; @@ -1319,7 +1309,6 @@ C33FDA6F255A57FA00E217F9 /* ReachabilityManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReachabilityManager.swift; sourceTree = ""; }; C33FDA70255A57FA00E217F9 /* TSMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMessage.h; sourceTree = ""; }; C33FDA73255A57FA00E217F9 /* ECKeyPair+Hexadecimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ECKeyPair+Hexadecimal.swift"; sourceTree = ""; }; - C33FDA79255A57FB00E217F9 /* TSGroupThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSGroupThread.h; sourceTree = ""; }; C33FDA7A255A57FB00E217F9 /* NSRegularExpression+SSK.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+SSK.swift"; sourceTree = ""; }; C33FDA86255A57FC00E217F9 /* OWSDisappearingMessagesFinder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDisappearingMessagesFinder.m; sourceTree = ""; }; C33FDA87255A57FC00E217F9 /* TypingIndicators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypingIndicators.swift; sourceTree = ""; }; @@ -1336,7 +1325,6 @@ C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildConfiguration.swift; sourceTree = ""; }; C33FDAAA255A580000E217F9 /* NSObject+Casting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Casting.m"; sourceTree = ""; }; C33FDAB1255A580000E217F9 /* OWSStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSStorage.m; sourceTree = ""; }; - C33FDAB3255A580000E217F9 /* TSContactThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContactThread.h; sourceTree = ""; }; C33FDAB8255A580100E217F9 /* NSArray+Functional.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Functional.m"; sourceTree = ""; }; C33FDAB9255A580100E217F9 /* OWSStorage+Subclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OWSStorage+Subclass.h"; sourceTree = ""; }; C33FDABE255A580100E217F9 /* TSConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSConstants.m; sourceTree = ""; }; @@ -1345,7 +1333,6 @@ C33FDAC2255A580200E217F9 /* TSAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachment.m; sourceTree = ""; }; C33FDAC3255A580200E217F9 /* OWSDispatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDispatch.m; sourceTree = ""; }; C33FDAC4255A580200E217F9 /* TSAttachmentStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentStream.m; sourceTree = ""; }; - C33FDAD3255A580300E217F9 /* TSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSThread.h; sourceTree = ""; }; C33FDAD5255A580300E217F9 /* TSQuotedMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSQuotedMessage.h; sourceTree = ""; }; C33FDADC255A580400E217F9 /* NSObject+Casting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Casting.h"; sourceTree = ""; }; C33FDADD255A580400E217F9 /* TSInfoMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInfoMessage.h; sourceTree = ""; }; @@ -1358,13 +1345,11 @@ C33FDAF1255A580500E217F9 /* OWSThumbnailService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSThumbnailService.swift; sourceTree = ""; }; C33FDAF2255A580500E217F9 /* ProxiedContentDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxiedContentDownloader.swift; sourceTree = ""; }; C33FDAF4255A580600E217F9 /* SSKEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKEnvironment.m; sourceTree = ""; }; - C33FDAF9255A580600E217F9 /* TSContactThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSContactThread.m; sourceTree = ""; }; C33FDAFC255A580600E217F9 /* MIMETypeUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIMETypeUtil.h; sourceTree = ""; }; C33FDAFD255A580600E217F9 /* LRUCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LRUCache.swift; sourceTree = ""; }; C33FDAFE255A580600E217F9 /* OWSStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSStorage.h; sourceTree = ""; }; C33FDB01255A580700E217F9 /* AppReadiness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppReadiness.h; sourceTree = ""; }; C33FDB07255A580700E217F9 /* OWSBackupFragment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupFragment.m; sourceTree = ""; }; - C33FDB0A255A580700E217F9 /* TSGroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSGroupModel.h; sourceTree = ""; }; C33FDB0D255A580800E217F9 /* NSArray+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+OWS.m"; sourceTree = ""; }; C33FDB12255A580800E217F9 /* NSString+SSK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SSK.h"; sourceTree = ""; }; C33FDB14255A580800E217F9 /* OWSMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMath.h; sourceTree = ""; }; @@ -1403,7 +1388,6 @@ C33FDB69255A580F00E217F9 /* FeatureFlags.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeatureFlags.swift; sourceTree = ""; }; C33FDB6B255A580F00E217F9 /* SNUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SNUserDefaults.swift; sourceTree = ""; }; C33FDB6C255A580F00E217F9 /* NSNotificationCenter+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+OWS.m"; sourceTree = ""; }; - C33FDB73255A581000E217F9 /* TSGroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSGroupModel.m; sourceTree = ""; }; C33FDB75255A581000E217F9 /* AppReadiness.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppReadiness.m; sourceTree = ""; }; C33FDB77255A581000E217F9 /* NSUserDefaults+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSUserDefaults+OWS.m"; sourceTree = ""; }; C33FDB78255A581000E217F9 /* OWSOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOperation.m; sourceTree = ""; }; @@ -1424,7 +1408,6 @@ C33FDBAB255A581500E217F9 /* OWSFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSFileSystem.h; sourceTree = ""; }; C33FDBB4255A581600E217F9 /* NSURLSessionDataTask+StatusCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLSessionDataTask+StatusCode.m"; sourceTree = ""; }; C33FDBB6255A581600E217F9 /* DataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataSource.m; sourceTree = ""; }; - C33FDBB8255A581600E217F9 /* TSThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSThread.m; sourceTree = ""; }; C33FDBBA255A581600E217F9 /* OWSPrimaryStorage+keyFromIntLong.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OWSPrimaryStorage+keyFromIntLong.h"; sourceTree = ""; }; C33FDBBC255A581600E217F9 /* SSKKeychainStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSKKeychainStorage.swift; sourceTree = ""; }; C33FDBC2255A581700E217F9 /* SSKAsserts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKAsserts.h; sourceTree = ""; }; @@ -1439,7 +1422,6 @@ C33FDBF8255A581C00E217F9 /* NSArray+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+OWS.h"; sourceTree = ""; }; C33FDBF9255A581C00E217F9 /* OWSError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSError.h; sourceTree = ""; }; C33FDBFE255A581C00E217F9 /* NSSet+Functional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSSet+Functional.h"; sourceTree = ""; }; - C33FDC01255A581C00E217F9 /* TSGroupThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSGroupThread.m; sourceTree = ""; }; C33FDC02255A581D00E217F9 /* OWSPrimaryStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSPrimaryStorage.m; sourceTree = ""; }; C33FDC03255A581D00E217F9 /* ByteParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteParser.h; sourceTree = ""; }; C33FDC05255A581D00E217F9 /* OWSDisappearingMessagesFinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDisappearingMessagesFinder.h; sourceTree = ""; }; @@ -1756,10 +1738,10 @@ FD09C5EB282B8F17000CE219 /* AttachmentError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentError.swift; sourceTree = ""; }; FD17D79527F3E04600122BE0 /* _001_InitialSetupMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_InitialSetupMigration.swift; sourceTree = ""; }; FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = ""; }; - FD17D79B27F40B2E00122BE0 /* SMKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMKLegacyModels.swift; sourceTree = ""; }; + FD17D79B27F40B2E00122BE0 /* SMKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMKLegacy.swift; sourceTree = ""; }; FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_InitialSetupMigration.swift; sourceTree = ""; }; FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = ""; }; - FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKLegacyModels.swift; sourceTree = ""; }; + FD17D7A627F41AF000122BE0 /* SSKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKLegacy.swift; sourceTree = ""; }; FD17D7A927F41BF500122BE0 /* SnodeSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeSet.swift; sourceTree = ""; }; FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessageInfo.swift; sourceTree = ""; }; FD17D7AF27F4225C00122BE0 /* Set+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Set+Utilities.swift"; sourceTree = ""; }; @@ -1780,7 +1762,7 @@ FD17D7E027F67BD400122BE0 /* SnodeReceivedMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessage.swift; sourceTree = ""; }; FD17D7E427F6A09900122BE0 /* Identity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identity.swift; sourceTree = ""; }; FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = ""; }; - FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUKLegacyModels.swift; sourceTree = ""; }; + FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUKLegacy.swift; sourceTree = ""; }; FD1C98E3282E3C5B00B76F9E /* UINavigationBar+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationBar+Utilities.swift"; sourceTree = ""; }; FD28A4F127E990E800FF65E7 /* BlockingManagerRemovalMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockingManagerRemovalMigration.swift; sourceTree = ""; }; FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListUIUtils.swift; sourceTree = ""; }; @@ -2573,22 +2555,6 @@ path = "Typing Indicators"; sourceTree = ""; }; - C32C59AF256DB31A003C73A2 /* Threads */ = { - isa = PBXGroup; - children = ( - C32C5FD5256E0346003C73A2 /* Notification+Thread.swift */, - C33FDAB3255A580000E217F9 /* TSContactThread.h */, - C33FDAF9255A580600E217F9 /* TSContactThread.m */, - C33FDB0A255A580700E217F9 /* TSGroupModel.h */, - C33FDB73255A581000E217F9 /* TSGroupModel.m */, - C33FDA79255A57FB00E217F9 /* TSGroupThread.h */, - C33FDC01255A581C00E217F9 /* TSGroupThread.m */, - C33FDAD3255A580300E217F9 /* TSThread.h */, - C33FDBB8255A581600E217F9 /* TSThread.m */, - ); - path = Threads; - sourceTree = ""; - }; C32C59F8256DB5A6003C73A2 /* Pollers */ = { isa = PBXGroup; children = ( @@ -3234,7 +3200,6 @@ C3BBE07F2554CDD70050F1E3 /* Storage.swift */, C32C5BCB256DC818003C73A2 /* Database */, C300A5BB2554AFFB00555489 /* Messages */, - C32C59AF256DB31A003C73A2 /* Threads */, C300A5F02554B08500555489 /* Sending & Receiving */, C352A2F325574B3300338F3E /* Jobs */, C3A7215C2558C0AC0043A11F /* File Server */, @@ -3564,7 +3529,7 @@ FD17D79A27F40ADA00122BE0 /* LegacyDatabase */ = { isa = PBXGroup; children = ( - FD17D79B27F40B2E00122BE0 /* SMKLegacyModels.swift */, + FD17D79B27F40B2E00122BE0 /* SMKLegacy.swift */, ); path = LegacyDatabase; sourceTree = ""; @@ -3593,7 +3558,7 @@ FD17D7A527F41ADE00122BE0 /* LegacyDatabase */ = { isa = PBXGroup; children = ( - FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */, + FD17D7A627F41AF000122BE0 /* SSKLegacy.swift */, ); path = LegacyDatabase; sourceTree = ""; @@ -3684,7 +3649,7 @@ FD17D7E827F6A1B800122BE0 /* LegacyDatabase */ = { isa = PBXGroup; children = ( - FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */, + FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */, ); path = LegacyDatabase; sourceTree = ""; @@ -3860,18 +3825,14 @@ C32C5EE5256DF506003C73A2 /* YapDatabaseConnection+OWS.h in Headers */, C32C5AAF256DBE8F003C73A2 /* TSMessage.h in Headers */, C32C5B8D256DC565003C73A2 /* SSKEnvironment.h in Headers */, - C32C59C6256DB41F003C73A2 /* TSGroupThread.h in Headers */, C3C2A6F425539DE700C340D1 /* SessionMessagingKit.h in Headers */, - C32C59C2256DB41F003C73A2 /* TSContactThread.h in Headers */, C32C5B2D256DC1A1003C73A2 /* TSQuotedMessage.h in Headers */, - C32C59C5256DB41F003C73A2 /* TSGroupModel.h in Headers */, C32C5C46256DCBB2003C73A2 /* AppReadiness.h in Headers */, C3D9E487256775D20040E4F3 /* TSAttachmentStream.h in Headers */, B8856CB1256F0F47001CE70E /* OWSBackupFragment.h in Headers */, C3A3A122256E1A97004D228D /* OWSDisappearingMessagesFinder.h in Headers */, C3A3A12B256E1AD5004D228D /* TSDatabaseSecondaryIndexes.h in Headers */, C32C5FC4256E0209003C73A2 /* OWSBackgroundTask.h in Headers */, - C32C59C0256DB41F003C73A2 /* TSThread.h in Headers */, C32C5AB3256DBE8F003C73A2 /* TSInteraction.h in Headers */, C3D9E486256775D20040E4F3 /* TSAttachmentPointer.h in Headers */, C32C5EF7256DF567003C73A2 /* TSDatabaseView.h in Headers */, @@ -4716,7 +4677,7 @@ C3C2A5DE2553860B00C340D1 /* String+Trimming.swift in Sources */, C3C2A5DB2553860B00C340D1 /* Promise+Hashing.swift in Sources */, C3C2A5E42553860B00C340D1 /* Data+Utilities.swift in Sources */, - FD17D7A727F41AF000122BE0 /* SSKLegacyModels.swift in Sources */, + FD17D7A727F41AF000122BE0 /* SSKLegacy.swift in Sources */, C3C2A5C2255385EE00C340D1 /* Configuration.swift in Sources */, FD17D7D827F658E200122BE0 /* SSKDestination.swift in Sources */, FD6A7A6D2818C61500035AC1 /* _002_SetupStandardJobs.swift in Sources */, @@ -4742,7 +4703,7 @@ C3D9E39B256763C20040E4F3 /* AppContext.m in Sources */, C3BBE0A82554D4DE0050F1E3 /* JSON.swift in Sources */, FD17D7C127F5200100122BE0 /* TypedTableDefinition.swift in Sources */, - FD17D7EA27F6A1C600122BE0 /* SUKLegacyModels.swift in Sources */, + FD17D7EA27F6A1C600122BE0 /* SUKLegacy.swift in Sources */, FDA8EB10280F8238002B68E5 /* Codable+Utilities.swift in Sources */, C352A36D2557858E00338F3E /* NSTimer+Proxying.m in Sources */, FD09797B27FBB25900936362 /* Updatable.swift in Sources */, @@ -4862,7 +4823,6 @@ FD09798927FD1C5A00936362 /* OpenGroup.swift in Sources */, C32C5CA4256DD1DC003C73A2 /* TSAccountManager.m in Sources */, C3BBE0B52554F0E10050F1E3 /* ProofOfWork.swift in Sources */, - C32C59C1256DB41F003C73A2 /* TSGroupThread.m in Sources */, C3A3A08F256E1728004D228D /* FullTextSearchFinder.swift in Sources */, FDF0B7472804F0CE004C14C5 /* DisappearingMessagesJob.swift in Sources */, B8856D1A256F114D001CE70E /* ProximityMonitoringManager.swift in Sources */, @@ -4883,7 +4843,6 @@ FD09798727FD1B7800936362 /* GroupMember.swift in Sources */, FD09799127FD499200936362 /* BoxKeyPair+Utilities.swift in Sources */, FDF0B7552807C4BB004C14C5 /* SSKEnvironment.swift in Sources */, - C32C59C3256DB41F003C73A2 /* TSGroupModel.m in Sources */, B8856ECE256F1E58001CE70E /* OWSPreferences.m in Sources */, FD09C5EC282B8F18000CE219 /* AttachmentError.swift in Sources */, FD17D79927F40AB800122BE0 /* _003_YDBToGRDBMigration.swift in Sources */, @@ -4966,17 +4925,14 @@ C352A35B2557824E00338F3E /* AttachmentUploadJob.swift in Sources */, FD09797027FA6FF300936362 /* Profile.swift in Sources */, C32C5AAE256DBE8F003C73A2 /* TSInteraction.m in Sources */, - C32C5FD6256E0346003C73A2 /* Notification+Thread.swift in Sources */, FD09798B27FD1CFE00936362 /* Capability.swift in Sources */, C3BBE0C72554F1570050F1E3 /* FixedWidthInteger+BigEndian.swift in Sources */, C32C5C88256DD0D2003C73A2 /* Storage+Messaging.swift in Sources */, - FD17D79C27F40B2E00122BE0 /* SMKLegacyModels.swift in Sources */, - C32C59C7256DB41F003C73A2 /* TSThread.m in Sources */, + FD17D79C27F40B2E00122BE0 /* SMKLegacy.swift in Sources */, C300A5B22554AF9800555489 /* VisibleMessage+Profile.swift in Sources */, FD09798127FCFEE800936362 /* SessionThread.swift in Sources */, C32C5A75256DBBCF003C73A2 /* TSAttachmentPointer+Conversion.swift in Sources */, C32C5EBA256DE130003C73A2 /* OWSQuotedReplyModel.m in Sources */, - C32C59C4256DB41F003C73A2 /* TSContactThread.m in Sources */, FD09C5EA282A1BB2000CE219 /* ThreadTypingIndicator.swift in Sources */, FDF0B75E280AAF35004C14C5 /* Preferences.swift in Sources */, C32C5AB0256DBE8F003C73A2 /* TSOutgoingMessage.m in Sources */, diff --git a/Session/Conversations/Settings/OWSConversationSettingsViewController.m b/Session/Conversations/Settings/OWSConversationSettingsViewController.m index f2bc3be9e..b4c818942 100644 --- a/Session/Conversations/Settings/OWSConversationSettingsViewController.m +++ b/Session/Conversations/Settings/OWSConversationSettingsViewController.m @@ -13,9 +13,7 @@ #import #import #import -#import #import -#import @import ContactsUI; @import PromiseKit; diff --git a/Session/Conversations/Settings/OWSConversationSettingsViewDelegate.h b/Session/Conversations/Settings/OWSConversationSettingsViewDelegate.h index 6e421cfa4..b3e432abc 100644 --- a/Session/Conversations/Settings/OWSConversationSettingsViewDelegate.h +++ b/Session/Conversations/Settings/OWSConversationSettingsViewDelegate.h @@ -9,7 +9,6 @@ NS_ASSUME_NONNULL_BEGIN @protocol OWSConversationSettingsViewDelegate -- (void)groupWasUpdated:(TSGroupModel *)groupModel; - (void)conversationSettingsDidRequestConversationSearch:(OWSConversationSettingsViewController *)conversationSettingsViewController; - (void)popAllConversationSettingsViewsWithCompletion:(void (^_Nullable)(void))completionBlock; diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index e38c479e8..47d2e3805 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -395,8 +395,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD PushNotificationAPI.unregister(data).retainUntilComplete() } - ThreadUtil.deleteAllContent() - Identity.clearAll() + GRDBStorage.shared.write { db in + _ = try SessionThread.deleteAll(db) + _ = try Identity.deleteAll(db) + } + SnodeAPI.clearSnodePool() stopPollers() diff --git a/Session/Meta/Signal-Bridging-Header.h b/Session/Meta/Signal-Bridging-Header.h index d77037259..28e533d98 100644 --- a/Session/Meta/Signal-Bridging-Header.h +++ b/Session/Meta/Signal-Bridging-Header.h @@ -62,12 +62,9 @@ #import #import #import -#import -#import #import #import #import -#import #import #import #import diff --git a/Session/Settings/PrivacySettingsTableViewController.m b/Session/Settings/PrivacySettingsTableViewController.m index fe7ea6cf2..b0bd17de9 100644 --- a/Session/Settings/PrivacySettingsTableViewController.m +++ b/Session/Settings/PrivacySettingsTableViewController.m @@ -212,7 +212,7 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s - (void)deleteThreadsAndMessages { - [ThreadUtil deleteAllContent]; + [SMKThread deleteAll]; } - (void)didToggleScreenSecuritySwitch:(UISwitch *)sender diff --git a/Session/Utilities/AvatarViewHelper.h b/Session/Utilities/AvatarViewHelper.h index dcd86c983..e6a0e8e06 100644 --- a/Session/Utilities/AvatarViewHelper.h +++ b/Session/Utilities/AvatarViewHelper.h @@ -8,7 +8,6 @@ NS_ASSUME_NONNULL_BEGIN @class AvatarViewHelper; @class OWSContactsManager; -@class TSThread; @protocol AvatarViewHelperDelegate diff --git a/Session/Utilities/AvatarViewHelper.m b/Session/Utilities/AvatarViewHelper.m index 178f0a05f..db7d36938 100644 --- a/Session/Utilities/AvatarViewHelper.m +++ b/Session/Utilities/AvatarViewHelper.m @@ -9,9 +9,6 @@ #import -#import -#import -#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/SessionMessagingKit/Database/LegacyDatabase/SMKLegacyModels.swift b/SessionMessagingKit/Database/LegacyDatabase/SMKLegacy.swift similarity index 89% rename from SessionMessagingKit/Database/LegacyDatabase/SMKLegacyModels.swift rename to SessionMessagingKit/Database/LegacyDatabase/SMKLegacy.swift index 1a72c9bfd..eb2a5970c 100644 --- a/SessionMessagingKit/Database/LegacyDatabase/SMKLegacyModels.swift +++ b/SessionMessagingKit/Database/LegacyDatabase/SMKLegacy.swift @@ -7,9 +7,7 @@ import YapDatabase import SignalCoreKit import SessionUtilitiesKit -public typealias SMKLegacy = Legacy - -public enum Legacy { +public enum SMKLegacy { // MARK: - Collections and Keys internal static let contactThreadPrefix = "c" @@ -18,7 +16,7 @@ public enum Legacy { internal static let closedGroupKeyPairPrefix = "SNClosedGroupEncryptionKeyPairCollection-" public static let contactCollection = "LokiContactCollection" - internal static let threadCollection = "TSThread" + public static let threadCollection = "TSThread" internal static let disappearingMessagesCollection = "OWSDisappearingMessagesConfiguration" internal static let closedGroupPublicKeyCollection = "SNClosedGroupPublicKeyCollection" @@ -32,6 +30,7 @@ public enum Legacy { internal static let openGroupLastDeletionServerIDCollection = "SNLastDeletionServerIDCollection" internal static let openGroupServerIdToUniqueIdLookupCollection = "SNOpenGroupServerIdToUniqueIdLookup" + public static let messageDatabaseViewExtensionName = "TSMessageDatabaseViewExtensionName_Monotonic" internal static let interactionCollection = "TSInteraction" internal static let attachmentsCollection = "TSAttachements" // Note: This is how it was previously spelt internal static let outgoingReadReceiptManagerCollection = "kOutgoingReadReceiptManagerCollection" @@ -54,6 +53,7 @@ public enum Legacy { internal static let preferencesKeyNotificationPreviewType = "preferencesKeyNotificationPreviewType" internal static let preferencesKeyNotificationSoundInForeground = "NotificationSoundInForeground" internal static let preferencesKeyHasSavedThreadKey = "hasSavedThread" + internal static let preferencesKeyHasSentAMessageKey = "User has sent a message" internal static let readReceiptManagerCollection = "OWSReadReceiptManagerCollection" internal static let readReceiptManagerAreReadReceiptsEnabled = "areReadReceiptsEnabled" @@ -74,18 +74,18 @@ public enum Legacy { @objc(SNContact) public class _Contact: NSObject, NSCoding { - @objc public let sessionID: String - @objc public var profilePictureURL: String? - @objc public var profilePictureFileName: String? - @objc public var profileEncryptionKey: OWSAES256Key? - @objc public var threadID: String? - @objc public var isTrusted = false - @objc public var isApproved = false - @objc public var isBlocked = false - @objc public var didApproveMe = false - @objc public var hasBeenBlocked = false - @objc public var name: String? - @objc public var nickname: String? + public let sessionID: String + public var profilePictureURL: String? + public var profilePictureFileName: String? + public var profileEncryptionKey: OWSAES256Key? + public var threadID: String? + public var isTrusted = false + public var isApproved = false + public var isBlocked = false + public var didApproveMe = false + public var hasBeenBlocked = false + public var name: String? + public var nickname: String? // MARK: Coding @@ -114,9 +114,9 @@ public enum Legacy { @objc(OWSDisappearingMessagesConfiguration) internal class _DisappearingMessagesConfiguration: MTLModel { - @objc public let uniqueId: String - @objc public var isEnabled: Bool - @objc public var durationSeconds: UInt32 + public let uniqueId: String + public var isEnabled: Bool + public var durationSeconds: UInt32 // MARK: - NSCoder @@ -829,27 +829,139 @@ public enum Legacy { ) } } + + // MARK: - Threads + + @objc(TSThread) + public class _Thread: NSObject, NSCoding { + public var uniqueId: String + public var creationDate: Date + public var shouldBeVisible: Bool + public var isPinned: Bool + public var mutedUntilDate: Date? + public var messageDraft: String? + + // MARK: - Convenience + + open var isClosedGroup: Bool { false } + open var isOpenGroup: Bool { false } + + // MARK: - NSCoder + + public required init(coder: NSCoder) { + self.uniqueId = coder.decodeObject(forKey: "uniqueId") as! String + self.creationDate = coder.decodeObject(forKey: "creationDate") as! Date + + // Legacy version of 'shouldBeVisible' + if let hasEverHadMessage: Bool = (coder.decodeObject(forKey: "hasEverHadMessage") as? NSNumber)?.boolValue { + self.shouldBeVisible = hasEverHadMessage + } + else { + self.shouldBeVisible = ((coder.decodeObject(forKey: "shouldBeVisible") as? NSNumber)? + .boolValue) + .defaulting(to: false) + } + + self.isPinned = ((coder.decodeObject(forKey: "isPinned") as? NSNumber)? + .boolValue) + .defaulting(to: false) + self.mutedUntilDate = coder.decodeObject(forKey: "mutedUntilDate") as? Date + self.messageDraft = coder.decodeObject(forKey: "messageDraft") as? String // TODO: Test this + } + + public func encode(with coder: NSCoder) { + fatalError("encode(with:) should never be called for legacy types") + } + } + + @objc(TSContactThread) + public class _ContactThread: _Thread { + // MARK: - NSCoder + + public required init(coder: NSCoder) { + super.init(coder: coder) + } + + // MARK: - Functions + + internal static func threadId(from sessionId: String) -> String { + return "\(SMKLegacy.contactThreadPrefix)\(sessionId)" + } + + public static func contactSessionId(fromThreadId threadId: String) -> String { + return String(threadId.substring(from: SMKLegacy.contactThreadPrefix.count)) + } + } + + @objc(TSGroupThread) + public class _GroupThread: _Thread { + public var groupModel: _GroupModel + public var isOnlyNotifyingForMentions: Bool + + // MARK: - Convenience + + public override var isClosedGroup: Bool { (groupModel.groupType == .closedGroup) } + public override var isOpenGroup: Bool { (groupModel.groupType == .openGroup) } + + // MARK: - NSCoder + + public required init(coder: NSCoder) { + self.groupModel = coder.decodeObject(forKey: "groupModel") as! _GroupModel + self.isOnlyNotifyingForMentions = ((coder.decodeObject(forKey: "isOnlyNotifyingForMentions") as? NSNumber)? + .boolValue) + .defaulting(to: false) + + super.init(coder: coder) + } + } + + @objc(TSGroupModel) + public class _GroupModel: NSObject, NSCoding { + public enum _GroupType: Int { + case closedGroup + case openGroup + } + + public var groupId: Data + public var groupType: _GroupType + public var groupName: String? + public var groupMemberIds: [String] + public var groupAdminIds: [String] + + // MARK: - NSCoder + + public required init(coder: NSCoder) { + self.groupId = coder.decodeObject(forKey: "groupId") as! Data + self.groupType = _GroupType(rawValue: coder.decodeObject(forKey: "groupType") as! Int)! + self.groupName = ((coder.decodeObject(forKey: "groupName") as? String) ?? "Group") + self.groupMemberIds = coder.decodeObject(forKey: "groupMemberIds") as! [String] + self.groupAdminIds = coder.decodeObject(forKey: "groupAdminIds") as! [String] + } + + public func encode(with coder: NSCoder) { + fatalError("encode(with:) should never be called for legacy types") + } + } // MARK: - Attachments @objc(TSAttachment) internal class _Attachment: NSObject, NSCoding { - @objc(TSAttachmentType) public enum _AttachmentType: Int { case `default` case voiceMessage } - @objc public var serverId: UInt64 - @objc public var encryptionKey: Data? - @objc public var contentType: String - @objc public var isDownloaded: Bool - @objc public var attachmentType: _AttachmentType - @objc public var downloadURL: String - @objc public var byteCount: UInt32 - @objc public var sourceFilename: String? - @objc public var caption: String? - @objc public var albumMessageId: String? + public var serverId: UInt64 + public var encryptionKey: Data? + public var contentType: String + public var isDownloaded: Bool + public var attachmentType: _AttachmentType + public var downloadURL: String + public var byteCount: UInt32 + public var sourceFilename: String? + public var caption: String? + public var albumMessageId: String? public var isImage: Bool { return MIMETypeUtil.isImage(contentType) } public var isVideo: Bool { return MIMETypeUtil.isVideo(contentType) } @@ -879,18 +991,17 @@ public enum Legacy { @objc(TSAttachmentPointer) internal class _AttachmentPointer: _Attachment { - @objc(TSAttachmentPointerState) public enum _State: Int { case enqueued case downloading case failed } - @objc public var state: _State - @objc public var mostRecentFailureLocalizedText: String? - @objc public var digest: Data? - @objc public var mediaSize: CGSize - @objc public var lazyRestoreFragmentId: String? + public var state: _State + public var mostRecentFailureLocalizedText: String? + public var digest: Data? + public var mediaSize: CGSize + public var lazyRestoreFragmentId: String? // MARK: - NSCoder @@ -913,15 +1024,15 @@ public enum Legacy { @objc(TSAttachmentStream) internal class _AttachmentStream: _Attachment { - @objc public var digest: Data? - @objc public var isUploaded: Bool - @objc public var creationTimestamp: Date - @objc public var localRelativeFilePath: String? - @objc public var cachedImageWidth: NSNumber? - @objc public var cachedImageHeight: NSNumber? - @objc public var cachedAudioDurationSeconds: NSNumber? - @objc public var isValidImageCached: NSNumber? - @objc public var isValidVideoCached: NSNumber? + public var digest: Data? + public var isUploaded: Bool + public var creationTimestamp: Date + public var localRelativeFilePath: String? + public var cachedImageWidth: NSNumber? + public var cachedImageHeight: NSNumber? + public var cachedAudioDurationSeconds: NSNumber? + public var isValidImageCached: NSNumber? + public var isValidVideoCached: NSNumber? public var isValidImage: Bool { return (isValidImageCached?.boolValue == true) } public var isValidVideo: Bool { return (isValidVideoCached?.boolValue == true) } diff --git a/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift b/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift index 601e6fb26..b8268d45d 100644 --- a/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift +++ b/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift @@ -16,18 +16,18 @@ enum _003_YDBToGRDBMigration: Migration { // MARK: - Process Contacts, Threads & Interactions print("RAWR [\(Date().timeIntervalSince1970)] - SessionMessagingKit migration - Start") var shouldFailMigration: Bool = false - var contacts: Set = [] + var contacts: Set = [] var validProfileIds: Set = [] var contactThreadIds: Set = [] var legacyThreadIdToIdMap: [String: String] = [:] - var threads: Set = [] - var disappearingMessagesConfiguration: [String: Legacy._DisappearingMessagesConfiguration] = [:] + var legacyThreads: Set = [] + var disappearingMessagesConfiguration: [String: SMKLegacy._DisappearingMessagesConfiguration] = [:] var closedGroupKeys: [String: [TimeInterval: SUKLegacy.KeyPair]] = [:] var closedGroupName: [String: String] = [:] var closedGroupFormation: [String: UInt64] = [:] - var closedGroupModel: [String: TSGroupModel] = [:] + var closedGroupModel: [String: SMKLegacy._GroupModel] = [:] var closedGroupZombieMemberIds: [String: Set] = [:] var openGroupInfo: [String: OpenGroupV2] = [:] @@ -38,37 +38,53 @@ enum _003_YDBToGRDBMigration: Migration { // var openGroupServerToUniqueIdLookup: [String: [String]] = [:] // TODO: Not needed???? var interactions: [String: [TSInteraction]] = [:] - var attachments: [String: Legacy._Attachment] = [:] + var attachments: [String: SMKLegacy._Attachment] = [:] var processedAttachmentIds: Set = [] var outgoingReadReceiptsTimestampsMs: [String: Set] = [:] var receivedMessageTimestamps: Set = [] // Map the Legacy types for the NSKeyedUnarchiver NSKeyedUnarchiver.setClass( - Legacy._Contact.self, + SMKLegacy._Thread.self, + forClassName: "TSThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._ContactThread.self, + forClassName: "TSContactThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._GroupThread.self, + forClassName: "TSGroupThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._GroupModel.self, + forClassName: "TSGroupModel" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._Contact.self, forClassName: "SNContact" ) NSKeyedUnarchiver.setClass( - Legacy._Attachment.self, + SMKLegacy._Attachment.self, forClassName: "TSAttachment" ) NSKeyedUnarchiver.setClass( - Legacy._AttachmentStream.self, + SMKLegacy._AttachmentStream.self, forClassName: "TSAttachmentStream" ) NSKeyedUnarchiver.setClass( - Legacy._AttachmentPointer.self, + SMKLegacy._AttachmentPointer.self, forClassName: "TSAttachmentPointer" ) NSKeyedUnarchiver.setClass( - Legacy._DisappearingConfigurationUpdateInfoMessage.self, + SMKLegacy._DisappearingConfigurationUpdateInfoMessage.self, forClassName: "OWSDisappearingConfigurationUpdateInfoMessage" ) Storage.read { transaction in // Process the Contacts - transaction.enumerateRows(inCollection: Legacy.contactCollection) { _, object, _, _ in - guard let contact = object as? Legacy._Contact else { return } + transaction.enumerateRows(inCollection: SMKLegacy.contactCollection) { _, object, _, _ in + guard let contact = object as? SMKLegacy._Contact else { return } contacts.insert(contact) validProfileIds.insert(contact.sessionID) } @@ -76,26 +92,27 @@ enum _003_YDBToGRDBMigration: Migration { print("RAWR [\(Date().timeIntervalSince1970)] - Process threads - Start") // Process the threads - transaction.enumerateKeysAndObjects(inCollection: Legacy.threadCollection) { key, object, _ in - guard let thread: TSThread = object as? TSThread else { return } - guard let threadId: String = thread.uniqueId else { return } + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.threadCollection) { key, object, _ in + guard let thread: SMKLegacy._Thread = object as? SMKLegacy._Thread else { return } - threads.insert(thread) + legacyThreads.insert(thread) // Want to exclude threads which aren't visible (ie. threads which we started // but the user never ended up sending a message) - if key.starts(with: Legacy.contactThreadPrefix) && thread.shouldBeVisible { + if key.starts(with: SMKLegacy.contactThreadPrefix) && thread.shouldBeVisible { contactThreadIds.insert(key) } // Get the disappearing messages config - disappearingMessagesConfiguration[threadId] = transaction - .object(forKey: threadId, inCollection: Legacy.disappearingMessagesCollection) - .asType(Legacy._DisappearingMessagesConfiguration.self) + disappearingMessagesConfiguration[thread.uniqueId] = transaction + .object(forKey: thread.uniqueId, inCollection: SMKLegacy.disappearingMessagesCollection) + .asType(SMKLegacy._DisappearingMessagesConfiguration.self) // Process group-specific info - guard let groupThread: TSGroupThread = thread as? TSGroupThread else { - legacyThreadIdToIdMap[threadId] = threadId.substring(from: Legacy.contactThreadPrefix.count) + guard let groupThread: SMKLegacy._GroupThread = thread as? SMKLegacy._GroupThread else { + legacyThreadIdToIdMap[thread.uniqueId] = thread.uniqueId.substring( + from: SMKLegacy.contactThreadPrefix.count + ) return } @@ -104,7 +121,7 @@ enum _003_YDBToGRDBMigration: Migration { // really need the unnecessary complexity so process the key and extract // the publicKey from it // `g{base64String(Data(__textsecure_group__!{publicKey}))} - let base64GroupId: String = String(threadId.suffix(from: threadId.index(after: threadId.startIndex))) + let base64GroupId: String = String(thread.uniqueId.suffix(from: thread.uniqueId.index(after: thread.uniqueId.startIndex))) guard let groupIdData: Data = Data(base64Encoded: base64GroupId), let groupId: String = String(data: groupIdData, encoding: .utf8), @@ -115,18 +132,18 @@ enum _003_YDBToGRDBMigration: Migration { return } - legacyThreadIdToIdMap[threadId] = publicKey - closedGroupName[threadId] = groupThread.name(with: transaction) - closedGroupModel[threadId] = groupThread.groupModel - closedGroupFormation[threadId] = ((transaction.object(forKey: publicKey, inCollection: Legacy.closedGroupFormationTimestampCollection) as? UInt64) ?? 0) - closedGroupZombieMemberIds[threadId] = transaction.object( + legacyThreadIdToIdMap[thread.uniqueId] = publicKey + closedGroupName[thread.uniqueId] = groupThread.groupModel.groupName + closedGroupModel[thread.uniqueId] = groupThread.groupModel + closedGroupFormation[thread.uniqueId] = ((transaction.object(forKey: publicKey, inCollection: SMKLegacy.closedGroupFormationTimestampCollection) as? UInt64) ?? 0) + closedGroupZombieMemberIds[thread.uniqueId] = transaction.object( forKey: publicKey, - inCollection: Legacy.closedGroupZombieMembersCollection + inCollection: SMKLegacy.closedGroupZombieMembersCollection ) as? Set // Note: If the user is no longer in a closed group then the group will still exist but the user // won't have the closed group public key anymore - let keyCollection: String = "\(Legacy.closedGroupKeyPairPrefix)\(publicKey)" + let keyCollection: String = "\(SMKLegacy.closedGroupKeyPairPrefix)\(publicKey)" transaction.enumerateKeysAndObjects(inCollection: keyCollection) { key, object, _ in guard @@ -134,33 +151,33 @@ enum _003_YDBToGRDBMigration: Migration { let keyPair: SUKLegacy.KeyPair = object as? SUKLegacy.KeyPair else { return } - closedGroupKeys[threadId] = (closedGroupKeys[threadId] ?? [:]) + closedGroupKeys[thread.uniqueId] = (closedGroupKeys[thread.uniqueId] ?? [:]) .setting(timestamp, keyPair) } } else if groupThread.isOpenGroup { - guard let openGroup: OpenGroupV2 = transaction.object(forKey: threadId, inCollection: Legacy.openGroupCollection) as? OpenGroupV2 else { + guard let openGroup: OpenGroupV2 = transaction.object(forKey: thread.uniqueId, inCollection: SMKLegacy.openGroupCollection) as? OpenGroupV2 else { SNLog("[Migration Error] Unable to find open group info") shouldFailMigration = true return } - legacyThreadIdToIdMap[threadId] = OpenGroup.idFor( + legacyThreadIdToIdMap[thread.uniqueId] = OpenGroup.idFor( room: openGroup.room, server: openGroup.server ) - openGroupInfo[threadId] = openGroup - openGroupUserCount[threadId] = ((transaction.object(forKey: openGroup.id, inCollection: Legacy.openGroupUserCountCollection) as? Int) ?? 0) - openGroupImage[threadId] = transaction.object(forKey: openGroup.id, inCollection: Legacy.openGroupImageCollection) as? Data - openGroupLastMessageServerId[threadId] = transaction.object(forKey: openGroup.id, inCollection: Legacy.openGroupLastMessageServerIDCollection) as? Int64 - openGroupLastDeletionServerId[threadId] = transaction.object(forKey: openGroup.id, inCollection: Legacy.openGroupLastDeletionServerIDCollection) as? Int64 + openGroupInfo[thread.uniqueId] = openGroup + openGroupUserCount[thread.uniqueId] = ((transaction.object(forKey: openGroup.id, inCollection: SMKLegacy.openGroupUserCountCollection) as? Int) ?? 0) + openGroupImage[thread.uniqueId] = transaction.object(forKey: openGroup.id, inCollection: SMKLegacy.openGroupImageCollection) as? Data + openGroupLastMessageServerId[thread.uniqueId] = transaction.object(forKey: openGroup.id, inCollection: SMKLegacy.openGroupLastMessageServerIDCollection) as? Int64 + openGroupLastDeletionServerId[thread.uniqueId] = transaction.object(forKey: openGroup.id, inCollection: SMKLegacy.openGroupLastDeletionServerIDCollection) as? Int64 } } print("RAWR [\(Date().timeIntervalSince1970)] - Process threads - End") // Process interactions print("RAWR [\(Date().timeIntervalSince1970)] - Process interactions - Start") - transaction.enumerateKeysAndObjects(inCollection: Legacy.interactionCollection) { _, object, _ in + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.interactionCollection) { _, object, _ in guard let interaction: TSInteraction = object as? TSInteraction else { SNLog("[Migration Error] Unable to process interaction") shouldFailMigration = true @@ -174,8 +191,8 @@ enum _003_YDBToGRDBMigration: Migration { // Process attachments print("RAWR [\(Date().timeIntervalSince1970)] - Process attachments - Start") - transaction.enumerateKeysAndObjects(inCollection: Legacy.attachmentsCollection) { key, object, _ in - guard let attachment: Legacy._Attachment = object as? Legacy._Attachment else { + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.attachmentsCollection) { key, object, _ in + guard let attachment: SMKLegacy._Attachment = object as? SMKLegacy._Attachment else { SNLog("[Migration Error] Unable to process attachment") shouldFailMigration = true return @@ -186,7 +203,7 @@ enum _003_YDBToGRDBMigration: Migration { print("RAWR [\(Date().timeIntervalSince1970)] - Process attachments - End") // Process read receipts - transaction.enumerateKeysAndObjects(inCollection: Legacy.outgoingReadReceiptManagerCollection) { key, object, _ in + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.outgoingReadReceiptManagerCollection) { key, object, _ in guard let timestampsMs: Set = object as? Set else { return } outgoingReadReceiptsTimestampsMs[key] = (outgoingReadReceiptsTimestampsMs[key] ?? Set()) @@ -196,8 +213,8 @@ enum _003_YDBToGRDBMigration: Migration { receivedMessageTimestamps = receivedMessageTimestamps.inserting( contentsOf: transaction .object( - forKey: Legacy.receivedMessageTimestampsKey, - inCollection: Legacy.receivedMessageTimestampsCollection + forKey: SMKLegacy.receivedMessageTimestampsKey, + inCollection: SMKLegacy.receivedMessageTimestampsCollection ) .asType([UInt64].self) .defaulting(to: []) @@ -217,19 +234,18 @@ enum _003_YDBToGRDBMigration: Migration { try autoreleasepool { let currentUserPublicKey: String = getUserHexEncodedPublicKey(db) - try contacts.forEach { contact in - let isCurrentUser: Bool = (contact.sessionID == currentUserPublicKey) - let contactThreadId: String = TSContactThread.threadID(fromContactSessionID: contact.sessionID) + try contacts.forEach { legacyContact in + let isCurrentUser: Bool = (legacyContact.sessionID == currentUserPublicKey) + let contactThreadId: String = SMKLegacy._ContactThread.threadId(from: legacyContact.sessionID) - // TODO: Contact 'hasOne' profile??? // Create the "Profile" for the legacy contact try Profile( - id: contact.sessionID, - name: (contact.name ?? contact.sessionID), - nickname: contact.nickname, - profilePictureUrl: contact.profilePictureURL, - profilePictureFileName: contact.profilePictureFileName, - profileEncryptionKey: contact.profileEncryptionKey + id: legacyContact.sessionID, + name: (legacyContact.name ?? legacyContact.sessionID), + nickname: legacyContact.nickname, + profilePictureUrl: legacyContact.profilePictureURL, + profilePictureFileName: legacyContact.profilePictureFileName, + profileEncryptionKey: legacyContact.profileEncryptionKey ).insert(db) // Determine if this contact is a "real" contact (don't want to create contacts for @@ -237,19 +253,19 @@ enum _003_YDBToGRDBMigration: Migration { if isCurrentUser || contactThreadIds.contains(contactThreadId) || - contact.isApproved || - contact.didApproveMe || - contact.isBlocked || - contact.hasBeenBlocked { + legacyContact.isApproved || + legacyContact.didApproveMe || + legacyContact.isBlocked || + legacyContact.hasBeenBlocked { // Create the contact // TODO: Closed group admins??? try Contact( - id: contact.sessionID, - isTrusted: (isCurrentUser || contact.isTrusted), - isApproved: (isCurrentUser || contact.isApproved), - isBlocked: (!isCurrentUser && contact.isBlocked), - didApproveMe: (isCurrentUser || contact.didApproveMe), - hasBeenBlocked: (!isCurrentUser && (contact.hasBeenBlocked || contact.isBlocked)) + id: legacyContact.sessionID, + isTrusted: (isCurrentUser || legacyContact.isTrusted), + isApproved: (isCurrentUser || legacyContact.isApproved), + isBlocked: (!isCurrentUser && legacyContact.isBlocked), + didApproveMe: (isCurrentUser || legacyContact.didApproveMe), + hasBeenBlocked: (!isCurrentUser && (legacyContact.hasBeenBlocked || legacyContact.isBlocked)) ).insert(db) } } @@ -296,11 +312,8 @@ enum _003_YDBToGRDBMigration: Migration { } // Sort by id just so we can make the migration process more determinstic - try threads.sorted(by: { lhs, rhs in (lhs.uniqueId ?? "") < (rhs.uniqueId ?? "") }).forEach { thread in - guard - let legacyThreadId: String = thread.uniqueId, - let threadId: String = legacyThreadIdToIdMap[legacyThreadId] - else { + try legacyThreads.sorted(by: { lhs, rhs in lhs.uniqueId < rhs.uniqueId }).forEach { legacyThread in + guard let threadId: String = legacyThreadIdToIdMap[legacyThread.uniqueId] else { SNLog("[Migration Error] Unable to migrate thread with no id mapping") throw GRDBStorageError.migrationFailed } @@ -308,8 +321,8 @@ enum _003_YDBToGRDBMigration: Migration { let threadVariant: SessionThread.Variant let onlyNotifyForMentions: Bool - switch thread { - case let groupThread as TSGroupThread: + switch legacyThread { + case let groupThread as SMKLegacy._GroupThread: threadVariant = (groupThread.isOpenGroup ? .openGroup : .closedGroup) onlyNotifyForMentions = groupThread.isOnlyNotifyingForMentions @@ -322,19 +335,19 @@ enum _003_YDBToGRDBMigration: Migration { try SessionThread( id: threadId, variant: threadVariant, - creationDateTimestamp: thread.creationDate.timeIntervalSince1970, - shouldBeVisible: thread.shouldBeVisible, - isPinned: thread.isPinned, - messageDraft: ((thread.messageDraft ?? "").isEmpty ? + creationDateTimestamp: legacyThread.creationDate.timeIntervalSince1970, + shouldBeVisible: legacyThread.shouldBeVisible, + isPinned: legacyThread.isPinned, + messageDraft: ((legacyThread.messageDraft ?? "").isEmpty ? nil : - thread.messageDraft + legacyThread.messageDraft ), - mutedUntilTimestamp: thread.mutedUntilDate?.timeIntervalSince1970, + mutedUntilTimestamp: legacyThread.mutedUntilDate?.timeIntervalSince1970, onlyNotifyForMentions: onlyNotifyForMentions ).insert(db) // Disappearing Messages Configuration - if let config: Legacy._DisappearingMessagesConfiguration = disappearingMessagesConfiguration[threadId] { + if let config: SMKLegacy._DisappearingMessagesConfiguration = disappearingMessagesConfiguration[threadId] { try DisappearingMessagesConfiguration( threadId: threadId, isEnabled: config.isEnabled, @@ -348,11 +361,11 @@ enum _003_YDBToGRDBMigration: Migration { } // Closed Groups - if (thread as? TSGroupThread)?.isClosedGroup == true { + if legacyThread.isClosedGroup { guard - let name: String = closedGroupName[legacyThreadId], - let groupModel: TSGroupModel = closedGroupModel[legacyThreadId], - let formationTimestamp: UInt64 = closedGroupFormation[legacyThreadId] + let name: String = closedGroupName[legacyThread.uniqueId], + let groupModel: SMKLegacy._GroupModel = closedGroupModel[legacyThread.uniqueId], + let formationTimestamp: UInt64 = closedGroupFormation[legacyThread.uniqueId] else { SNLog("[Migration Error] Closed group missing required data") throw GRDBStorageError.migrationFailed @@ -367,7 +380,7 @@ enum _003_YDBToGRDBMigration: Migration { // Note: If a user has left a closed group then they won't actually have any keys // but they should still be able to browse the old messages so we do want to allow // this case and migrate the rest of the info - try closedGroupKeys[legacyThreadId]?.forEach { timestamp, legacyKeys in + try closedGroupKeys[legacyThread.uniqueId]?.forEach { timestamp, legacyKeys in try ClosedGroupKeyPair( threadId: threadId, publicKey: legacyKeys.publicKey, @@ -396,7 +409,7 @@ enum _003_YDBToGRDBMigration: Migration { ).insert(db) } - try (closedGroupZombieMemberIds[legacyThreadId] ?? []).forEach { zombieId in + try (closedGroupZombieMemberIds[legacyThread.uniqueId] ?? []).forEach { zombieId in try GroupMember( groupId: threadId, profileId: zombieId, @@ -407,8 +420,8 @@ enum _003_YDBToGRDBMigration: Migration { } // Open Groups - if (thread as? TSGroupThread)?.isOpenGroup == true { - guard let openGroup: OpenGroupV2 = openGroupInfo[legacyThreadId] else { + if legacyThread.isOpenGroup { + guard let openGroup: OpenGroupV2 = openGroupInfo[legacyThread.uniqueId] else { SNLog("[Migration Error] Open group missing required data") throw GRDBStorageError.migrationFailed } @@ -420,15 +433,15 @@ enum _003_YDBToGRDBMigration: Migration { name: openGroup.name, groupDescription: nil, // TODO: Add with SOGS V4. imageId: nil, // TODO: Add with SOGS V4. - imageData: openGroupImage[legacyThreadId], - userCount: (openGroupUserCount[legacyThreadId] ?? 0), // Will be updated next poll + imageData: openGroupImage[legacyThread.uniqueId], + userCount: (openGroupUserCount[legacyThread.uniqueId] ?? 0), // Will be updated next poll infoUpdates: 0 // TODO: Add with SOGS V4. ).insert(db) } } try autoreleasepool { - try interactions[legacyThreadId]? + try interactions[legacyThread.uniqueId]? .sorted(by: { lhs, rhs in lhs.timestamp < rhs.timestamp }) // Maintain sort order .forEach { legacyInteraction in let serverHash: String? @@ -530,7 +543,7 @@ enum _003_YDBToGRDBMigration: Migration { // a string at display time so we want to continue that behaviour guard infoMessage.messageType == .disappearingMessagesUpdate, - let updateMessage: Legacy._DisappearingConfigurationUpdateInfoMessage = infoMessage as? Legacy._DisappearingConfigurationUpdateInfoMessage, + let updateMessage: SMKLegacy._DisappearingConfigurationUpdateInfoMessage = infoMessage as? SMKLegacy._DisappearingConfigurationUpdateInfoMessage, let infoMessageData: Data = try? JSONEncoder().encode( DisappearingMessagesConfiguration.MessageInfo( senderName: updateMessage.createdByRemoteName, @@ -713,7 +726,7 @@ enum _003_YDBToGRDBMigration: Migration { // original interaction and re-create the attachment link before // falling back to having no attachment in the quote if quoteAttachmentId == nil && !quotedMessage.quotedAttachments.isEmpty { - quoteAttachmentId = interactions[legacyThreadId]? + quoteAttachmentId = interactions[legacyThread.uniqueId]? .first(where: { $0.timestamp == quotedMessage.timestamp && ( @@ -827,7 +840,7 @@ enum _003_YDBToGRDBMigration: Migration { contacts = [] contactThreadIds = [] - threads = [] + legacyThreads = [] disappearingMessagesConfiguration = [:] closedGroupKeys = [:] @@ -850,137 +863,137 @@ enum _003_YDBToGRDBMigration: Migration { print("RAWR [\(Date().timeIntervalSince1970)] - Process jobs - Start") - var notifyPushServerJobs: Set = [] - var messageReceiveJobs: Set = [] - var messageSendJobs: Set = [] - var attachmentUploadJobs: Set = [] - var attachmentDownloadJobs: Set = [] + var notifyPushServerJobs: Set = [] + var messageReceiveJobs: Set = [] + var messageSendJobs: Set = [] + var attachmentUploadJobs: Set = [] + var attachmentDownloadJobs: Set = [] // Map the Legacy types for the NSKeyedUnarchiver NSKeyedUnarchiver.setClass( - Legacy._NotifyPNServerJob.self, + SMKLegacy._NotifyPNServerJob.self, forClassName: "SessionMessagingKit.NotifyPNServerJob" ) NSKeyedUnarchiver.setClass( - Legacy._NotifyPNServerJob._SnodeMessage.self, + SMKLegacy._NotifyPNServerJob._SnodeMessage.self, forClassName: "SessionSnodeKit.SnodeMessage" ) NSKeyedUnarchiver.setClass( - Legacy._MessageSendJob.self, + SMKLegacy._MessageSendJob.self, forClassName: "SessionMessagingKit.SNMessageSendJob" ) NSKeyedUnarchiver.setClass( - Legacy._MessageReceiveJob.self, + SMKLegacy._MessageReceiveJob.self, forClassName: "SessionMessagingKit.MessageReceiveJob" ) NSKeyedUnarchiver.setClass( - Legacy._AttachmentUploadJob.self, + SMKLegacy._AttachmentUploadJob.self, forClassName: "SessionMessagingKit.AttachmentUploadJob" ) NSKeyedUnarchiver.setClass( - Legacy._AttachmentDownloadJob.self, + SMKLegacy._AttachmentDownloadJob.self, forClassName: "SessionMessagingKit.AttachmentDownloadJob" ) NSKeyedUnarchiver.setClass( - Legacy._Message.self, + SMKLegacy._Message.self, forClassName: "SNMessage" ) NSKeyedUnarchiver.setClass( - Legacy._VisibleMessage.self, + SMKLegacy._VisibleMessage.self, forClassName: "SNVisibleMessage" ) NSKeyedUnarchiver.setClass( - Legacy._Quote.self, + SMKLegacy._Quote.self, forClassName: "SNQuote" ) NSKeyedUnarchiver.setClass( - Legacy._LinkPreview.self, + SMKLegacy._LinkPreview.self, forClassName: "SessionServiceKit.OWSLinkPreview" // Very old legacy name ) NSKeyedUnarchiver.setClass( - Legacy._LinkPreview.self, + SMKLegacy._LinkPreview.self, forClassName: "SNLinkPreview" ) NSKeyedUnarchiver.setClass( - Legacy._Profile.self, + SMKLegacy._Profile.self, forClassName: "SNProfile" ) NSKeyedUnarchiver.setClass( - Legacy._OpenGroupInvitation.self, + SMKLegacy._OpenGroupInvitation.self, forClassName: "SNOpenGroupInvitation" ) NSKeyedUnarchiver.setClass( - Legacy._ControlMessage.self, + SMKLegacy._ControlMessage.self, forClassName: "SNControlMessage" ) NSKeyedUnarchiver.setClass( - Legacy._ReadReceipt.self, + SMKLegacy._ReadReceipt.self, forClassName: "SNReadReceipt" ) NSKeyedUnarchiver.setClass( - Legacy._TypingIndicator.self, + SMKLegacy._TypingIndicator.self, forClassName: "SNTypingIndicator" ) NSKeyedUnarchiver.setClass( - Legacy._ClosedGroupControlMessage.self, + SMKLegacy._ClosedGroupControlMessage.self, forClassName: "SessionMessagingKit.ClosedGroupControlMessage" ) NSKeyedUnarchiver.setClass( - Legacy._ClosedGroupControlMessage._KeyPairWrapper.self, + SMKLegacy._ClosedGroupControlMessage._KeyPairWrapper.self, forClassName: "ClosedGroupControlMessage.SNKeyPairWrapper" ) NSKeyedUnarchiver.setClass( - Legacy._DataExtractionNotification.self, + SMKLegacy._DataExtractionNotification.self, forClassName: "SessionMessagingKit.DataExtractionNotification" ) NSKeyedUnarchiver.setClass( - Legacy._ExpirationTimerUpdate.self, + SMKLegacy._ExpirationTimerUpdate.self, forClassName: "SNExpirationTimerUpdate" ) NSKeyedUnarchiver.setClass( - Legacy._ConfigurationMessage.self, + SMKLegacy._ConfigurationMessage.self, forClassName: "SNConfigurationMessage" ) NSKeyedUnarchiver.setClass( - Legacy._CMClosedGroup.self, + SMKLegacy._CMClosedGroup.self, forClassName: "SNClosedGroup" ) NSKeyedUnarchiver.setClass( - Legacy._CMContact.self, + SMKLegacy._CMContact.self, forClassName: "SNConfigurationMessage.SNConfigurationMessageContact" ) NSKeyedUnarchiver.setClass( - Legacy._UnsendRequest.self, + SMKLegacy._UnsendRequest.self, forClassName: "SNUnsendRequest" ) NSKeyedUnarchiver.setClass( - Legacy._MessageRequestResponse.self, + SMKLegacy._MessageRequestResponse.self, forClassName: "SNMessageRequestResponse" ) Storage.read { transaction in - transaction.enumerateRows(inCollection: Legacy.notifyPushServerJobCollection) { _, object, _, _ in - guard let job = object as? Legacy._NotifyPNServerJob else { return } + transaction.enumerateRows(inCollection: SMKLegacy.notifyPushServerJobCollection) { _, object, _, _ in + guard let job = object as? SMKLegacy._NotifyPNServerJob else { return } notifyPushServerJobs.insert(job) } - transaction.enumerateRows(inCollection: Legacy.messageReceiveJobCollection) { _, object, _, _ in - guard let job = object as? Legacy._MessageReceiveJob else { return } + transaction.enumerateRows(inCollection: SMKLegacy.messageReceiveJobCollection) { _, object, _, _ in + guard let job = object as? SMKLegacy._MessageReceiveJob else { return } messageReceiveJobs.insert(job) } - transaction.enumerateRows(inCollection: Legacy.messageSendJobCollection) { _, object, _, _ in - guard let job = object as? Legacy._MessageSendJob else { return } + transaction.enumerateRows(inCollection: SMKLegacy.messageSendJobCollection) { _, object, _, _ in + guard let job = object as? SMKLegacy._MessageSendJob else { return } messageSendJobs.insert(job) } - transaction.enumerateRows(inCollection: Legacy.attachmentUploadJobCollection) { _, object, _, _ in - guard let job = object as? Legacy._AttachmentUploadJob else { return } + transaction.enumerateRows(inCollection: SMKLegacy.attachmentUploadJobCollection) { _, object, _, _ in + guard let job = object as? SMKLegacy._AttachmentUploadJob else { return } attachmentUploadJobs.insert(job) } - transaction.enumerateRows(inCollection: Legacy.attachmentDownloadJobCollection) { _, object, _, _ in - guard let job = object as? Legacy._AttachmentDownloadJob else { return } + transaction.enumerateRows(inCollection: SMKLegacy.attachmentDownloadJobCollection) { _, object, _, _ in + guard let job = object as? SMKLegacy._AttachmentDownloadJob else { return } attachmentDownloadJobs.insert(job) } } @@ -1110,7 +1123,7 @@ enum _003_YDBToGRDBMigration: Migration { destination: legacyJob.destination, variant: { switch legacyJob.message { - case is Legacy._ExpirationTimerUpdate: + case is SMKLegacy._ExpirationTimerUpdate: return .infoDisappearingMessagesUpdate default: return nil } @@ -1229,73 +1242,74 @@ enum _003_YDBToGRDBMigration: Migration { var legacyPreferences: [String: Any] = [:] Storage.read { transaction in - transaction.enumerateKeysAndObjects(inCollection: Legacy.preferencesCollection) { key, object, _ in + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.preferencesCollection) { key, object, _ in legacyPreferences[key] = object } // Note: The 'int(forKey:inCollection:)' defaults to `0` which is an incorrect value // for the notification sound so catch it and default let globalNotificationSoundValue: Int32 = transaction.int( - forKey: Legacy.soundsGlobalNotificationKey, - inCollection: Legacy.soundsStorageNotificationCollection + forKey: SMKLegacy.soundsGlobalNotificationKey, + inCollection: SMKLegacy.soundsStorageNotificationCollection ) - legacyPreferences[Legacy.soundsGlobalNotificationKey] = (globalNotificationSoundValue > 0 ? + legacyPreferences[SMKLegacy.soundsGlobalNotificationKey] = (globalNotificationSoundValue > 0 ? Int(globalNotificationSoundValue) : Preferences.Sound.defaultNotificationSound.rawValue ) - legacyPreferences[Legacy.readReceiptManagerAreReadReceiptsEnabled] = transaction.bool( - forKey: Legacy.readReceiptManagerAreReadReceiptsEnabled, - inCollection: Legacy.readReceiptManagerCollection, + legacyPreferences[SMKLegacy.readReceiptManagerAreReadReceiptsEnabled] = transaction.bool( + forKey: SMKLegacy.readReceiptManagerAreReadReceiptsEnabled, + inCollection: SMKLegacy.readReceiptManagerCollection, defaultValue: false ) - legacyPreferences[Legacy.typingIndicatorsEnabledKey] = transaction.bool( - forKey: Legacy.typingIndicatorsEnabledKey, - inCollection: Legacy.typingIndicatorsCollection, + legacyPreferences[SMKLegacy.typingIndicatorsEnabledKey] = transaction.bool( + forKey: SMKLegacy.typingIndicatorsEnabledKey, + inCollection: SMKLegacy.typingIndicatorsCollection, defaultValue: false ) - legacyPreferences[Legacy.screenLockIsScreenLockEnabledKey] = transaction.bool( - forKey: Legacy.screenLockIsScreenLockEnabledKey, - inCollection: Legacy.screenLockCollection, + legacyPreferences[SMKLegacy.screenLockIsScreenLockEnabledKey] = transaction.bool( + forKey: SMKLegacy.screenLockIsScreenLockEnabledKey, + inCollection: SMKLegacy.screenLockCollection, defaultValue: false ) - legacyPreferences[Legacy.screenLockScreenLockTimeoutSecondsKey] = transaction.double( - forKey: Legacy.screenLockScreenLockTimeoutSecondsKey, - inCollection: Legacy.screenLockCollection, + legacyPreferences[SMKLegacy.screenLockScreenLockTimeoutSecondsKey] = transaction.double( + forKey: SMKLegacy.screenLockScreenLockTimeoutSecondsKey, + inCollection: SMKLegacy.screenLockCollection, defaultValue: (15 * 60) ) } - db[.defaultNotificationSound] = Preferences.Sound(rawValue: legacyPreferences[Legacy.soundsGlobalNotificationKey] as? Int ?? -1) + db[.defaultNotificationSound] = Preferences.Sound(rawValue: legacyPreferences[SMKLegacy.soundsGlobalNotificationKey] as? Int ?? -1) .defaulting(to: Preferences.Sound.defaultNotificationSound) - db[.playNotificationSoundInForeground] = (legacyPreferences[Legacy.preferencesKeyNotificationSoundInForeground] as? Bool == true) - db[.preferencesNotificationPreviewType] = Preferences.NotificationPreviewType(rawValue: legacyPreferences[Legacy.preferencesKeyNotificationPreviewType] as? Int ?? -1) + db[.playNotificationSoundInForeground] = (legacyPreferences[SMKLegacy.preferencesKeyNotificationSoundInForeground] as? Bool == true) + db[.preferencesNotificationPreviewType] = Preferences.NotificationPreviewType(rawValue: legacyPreferences[SMKLegacy.preferencesKeyNotificationPreviewType] as? Int ?? -1) .defaulting(to: .nameAndPreview) - if let lastPushToken: String = legacyPreferences[Legacy.preferencesKeyLastRecordedPushToken] as? String { + if let lastPushToken: String = legacyPreferences[SMKLegacy.preferencesKeyLastRecordedPushToken] as? String { db[.lastRecordedPushToken] = lastPushToken } - if let lastVoipToken: String = legacyPreferences[Legacy.preferencesKeyLastRecordedVoipToken] as? String { + if let lastVoipToken: String = legacyPreferences[SMKLegacy.preferencesKeyLastRecordedVoipToken] as? String { db[.lastRecordedVoipToken] = lastVoipToken } // Note: The 'preferencesKeyScreenSecurityDisabled' value previously controlled whether the // setting was disabled, this has been inverted to 'appSwitcherPreviewEnabled' so it can default // to 'false' (as most Bool values do) - db[.areReadReceiptsEnabled] = (legacyPreferences[Legacy.readReceiptManagerAreReadReceiptsEnabled] as? Bool == true) - db[.typingIndicatorsEnabled] = (legacyPreferences[Legacy.typingIndicatorsEnabledKey] as? Bool == true) - db[.isScreenLockEnabled] = (legacyPreferences[Legacy.screenLockIsScreenLockEnabledKey] as? Bool == true) - db[.screenLockTimeoutSeconds] = (legacyPreferences[Legacy.screenLockScreenLockTimeoutSecondsKey] as? Double) + db[.areReadReceiptsEnabled] = (legacyPreferences[SMKLegacy.readReceiptManagerAreReadReceiptsEnabled] as? Bool == true) + db[.typingIndicatorsEnabled] = (legacyPreferences[SMKLegacy.typingIndicatorsEnabledKey] as? Bool == true) + db[.isScreenLockEnabled] = (legacyPreferences[SMKLegacy.screenLockIsScreenLockEnabledKey] as? Bool == true) + db[.screenLockTimeoutSeconds] = (legacyPreferences[SMKLegacy.screenLockScreenLockTimeoutSecondsKey] as? Double) .defaulting(to: (15 * 60)) - db[.appSwitcherPreviewEnabled] = (legacyPreferences[Legacy.preferencesKeyScreenSecurityDisabled] as? Bool == false) - db[.areLinkPreviewsEnabled] = (legacyPreferences[Legacy.preferencesKeyAreLinkPreviewsEnabled] as? Bool == true) + db[.appSwitcherPreviewEnabled] = (legacyPreferences[SMKLegacy.preferencesKeyScreenSecurityDisabled] as? Bool == false) + db[.areLinkPreviewsEnabled] = (legacyPreferences[SMKLegacy.preferencesKeyAreLinkPreviewsEnabled] as? Bool == true) db[.hasHiddenMessageRequests] = CurrentAppContext().appUserDefaults() - .bool(forKey: Legacy.userDefaultsHasHiddenMessageRequests) - db[.hasSavedThreadKey] = (legacyPreferences[Legacy.preferencesKeyHasSavedThreadKey] as? Bool == true) + .bool(forKey: SMKLegacy.userDefaultsHasHiddenMessageRequests) + db[.hasSavedThread] = (legacyPreferences[SMKLegacy.preferencesKeyHasSavedThreadKey] as? Bool == true) + db[.hasSentAMessage] = (legacyPreferences[SMKLegacy.preferencesKeyHasSentAMessageKey] as? Bool == true) print("RAWR [\(Date().timeIntervalSince1970)] - Process preferences inserts - End") @@ -1309,7 +1323,7 @@ enum _003_YDBToGRDBMigration: Migration { for legacyAttachmentId: String?, interactionVariant: Interaction.Variant? = nil, isQuotedMessage: Bool = false, - attachments: [String: Legacy._Attachment], + attachments: [String: SMKLegacy._Attachment], processedAttachmentIds: inout Set ) throws -> String? { guard let legacyAttachmentId: String = legacyAttachmentId else { return nil } @@ -1322,12 +1336,12 @@ enum _003_YDBToGRDBMigration: Migration { return legacyAttachmentId } - guard let legacyAttachment: Legacy._Attachment = attachments[legacyAttachmentId] else { + guard let legacyAttachment: SMKLegacy._Attachment = attachments[legacyAttachmentId] else { SNLog("[Migration Warning] Missing attachment - interaction will appear as blank") return nil } - let processedLocalRelativeFilePath: String? = (legacyAttachment as? Legacy._AttachmentStream)? + let processedLocalRelativeFilePath: String? = (legacyAttachment as? SMKLegacy._AttachmentStream)? .localRelativeFilePath .map { filePath -> String in // The old 'localRelativeFilePath' seemed to have a leading forward slash (want @@ -1338,7 +1352,7 @@ enum _003_YDBToGRDBMigration: Migration { } let state: Attachment.State = { switch legacyAttachment { - case let stream as Legacy._AttachmentStream: // Outgoing or already downloaded + case let stream as SMKLegacy._AttachmentStream: // Outgoing or already downloaded switch interactionVariant { case .standardOutgoing: return (stream.isUploaded ? .uploaded : .pending) default: return .downloaded @@ -1350,7 +1364,7 @@ enum _003_YDBToGRDBMigration: Migration { }() let size: CGSize = { switch legacyAttachment { - case let stream as Legacy._AttachmentStream: + case let stream as SMKLegacy._AttachmentStream: // First try to get an image size using the 'localRelativeFilePath' value if let localRelativeFilePath: String = processedLocalRelativeFilePath, @@ -1377,13 +1391,13 @@ enum _003_YDBToGRDBMigration: Migration { ) .defaulting(to: .zero) - case let pointer as Legacy._AttachmentPointer: return pointer.mediaSize + case let pointer as SMKLegacy._AttachmentPointer: return pointer.mediaSize default: return CGSize.zero } }() let (isValid, duration): (Bool, TimeInterval?) = { guard - let stream: Legacy._AttachmentStream = legacyAttachment as? Legacy._AttachmentStream, + let stream: SMKLegacy._AttachmentStream = legacyAttachment as? SMKLegacy._AttachmentStream, let originalFilePath: String = Attachment.originalFilePath( id: legacyAttachmentId, mimeType: stream.contentType, @@ -1435,7 +1449,7 @@ enum _003_YDBToGRDBMigration: Migration { state: state, contentType: legacyAttachment.contentType, byteCount: UInt(legacyAttachment.byteCount), - creationTimestamp: (legacyAttachment as? Legacy._AttachmentStream)? + creationTimestamp: (legacyAttachment as? SMKLegacy._AttachmentStream)? .creationTimestamp.timeIntervalSince1970, sourceFilename: legacyAttachment.sourceFilename, downloadUrl: legacyAttachment.downloadURL, @@ -1445,7 +1459,7 @@ enum _003_YDBToGRDBMigration: Migration { duration: duration, isValid: isValid, encryptionKey: legacyAttachment.encryptionKey, - digest: (legacyAttachment as? Legacy._AttachmentStream)?.digest, + digest: (legacyAttachment as? SMKLegacy._AttachmentStream)?.digest, caption: legacyAttachment.caption ).inserted(db) diff --git a/SessionMessagingKit/Database/Models/SessionThread.swift b/SessionMessagingKit/Database/Models/SessionThread.swift index d0605cb5a..2fd51a151 100644 --- a/SessionMessagingKit/Database/Models/SessionThread.swift +++ b/SessionMessagingKit/Database/Models/SessionThread.swift @@ -127,7 +127,7 @@ public struct SessionThread: Codable, Identifiable, Equatable, FetchableRecord, public func insert(_ db: Database) throws { try performInsert(db) - db[.hasSavedThreadKey] = true + db[.hasSavedThread] = true } public func delete(_ db: Database) throws -> Bool { @@ -311,6 +311,13 @@ public extension SessionThread { @objc(SMKThread) public class SMKThread: NSObject { + @objc(deleteAll) + public static func deleteAll() { + GRDBStorage.shared.writeAsync { db in + _ = try SessionThread.deleteAll(db) + } + } + @objc(isThreadMuted:) public static func isThreadMuted(_ threadId: String) -> Bool { return GRDBStorage.shared.read { db in diff --git a/SessionMessagingKit/Database/OWSPrimaryStorage.m b/SessionMessagingKit/Database/OWSPrimaryStorage.m index c44b6dd7e..df54ae71e 100644 --- a/SessionMessagingKit/Database/OWSPrimaryStorage.m +++ b/SessionMessagingKit/Database/OWSPrimaryStorage.m @@ -4,7 +4,6 @@ #import "OWSPrimaryStorage.h" #import "AppContext.h" -#import "OWSDisappearingMessagesFinder.h" #import "OWSFileSystem.h" #import "OWSIncomingMessageFinder.h" #import diff --git a/SessionMessagingKit/Database/TSDatabaseView.m b/SessionMessagingKit/Database/TSDatabaseView.m index f2beee9c9..6e733cbc9 100644 --- a/SessionMessagingKit/Database/TSDatabaseView.m +++ b/SessionMessagingKit/Database/TSDatabaseView.m @@ -7,7 +7,6 @@ #import "TSAttachmentPointer.h" #import "TSIncomingMessage.h" #import "TSOutgoingMessage.h" -#import "TSThread.h" #import #import #import diff --git a/SessionMessagingKit/Messages/Message.swift b/SessionMessagingKit/Messages/Message.swift index b76c4e05c..aeb747893 100644 --- a/SessionMessagingKit/Messages/Message.swift +++ b/SessionMessagingKit/Messages/Message.swift @@ -67,7 +67,7 @@ public class Message: Codable { guard let threadId: String = threadId, (try? ClosedGroup.exists(db, id: threadId)) == true, - let legacyGroupId: Data = "\(Legacy.closedGroupIdPrefix)\(threadId)".data(using: .utf8) + let legacyGroupId: Data = "\(SMKLegacy.closedGroupIdPrefix)\(threadId)".data(using: .utf8) else { return } // Android needs a group context or it'll interpret the message as a one-to-one message diff --git a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m index 8dfbc6ce3..7731e86c2 100644 --- a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m @@ -5,9 +5,7 @@ #import "TSIncomingMessage.h" #import "NSNotificationCenter+OWS.h" #import "TSAttachmentPointer.h" -#import "TSContactThread.h" #import "TSDatabaseSecondaryIndexes.h" -#import "TSGroupThread.h" #import #import #import diff --git a/SessionMessagingKit/Messages/Signal/TSInteraction.m b/SessionMessagingKit/Messages/Signal/TSInteraction.m index b7100e0a5..7eb2eca62 100644 --- a/SessionMessagingKit/Messages/Signal/TSInteraction.m +++ b/SessionMessagingKit/Messages/Signal/TSInteraction.m @@ -4,8 +4,6 @@ #import "TSInteraction.h" #import "TSDatabaseSecondaryIndexes.h" -#import "TSThread.h" -#import "TSGroupThread.h" #import #import diff --git a/SessionMessagingKit/Messages/Signal/TSMessage.m b/SessionMessagingKit/Messages/Signal/TSMessage.m index 575a3ffdb..bd22479e1 100644 --- a/SessionMessagingKit/Messages/Signal/TSMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSMessage.m @@ -8,12 +8,10 @@ #import "TSAttachment.h" #import "TSAttachmentStream.h" #import "TSQuotedMessage.h" -#import "TSThread.h" #import #import #import #import -#import "TSContactThread.h" #import NS_ASSUME_NONNULL_BEGIN diff --git a/SessionMessagingKit/Messages/Signal/TSOutgoingMessage.m b/SessionMessagingKit/Messages/Signal/TSOutgoingMessage.m index 3470fb821..a8f6cc1cb 100644 --- a/SessionMessagingKit/Messages/Signal/TSOutgoingMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSOutgoingMessage.m @@ -10,8 +10,6 @@ #import "SSKEnvironment.h" #import "TSAccountManager.h" #import "TSAttachmentStream.h" -#import "TSContactThread.h" -#import "TSGroupThread.h" #import "TSQuotedMessage.h" #import #import diff --git a/SessionMessagingKit/Meta/SessionMessagingKit.h b/SessionMessagingKit/Meta/SessionMessagingKit.h index 8a69caee9..9d306116d 100644 --- a/SessionMessagingKit/Meta/SessionMessagingKit.h +++ b/SessionMessagingKit/Meta/SessionMessagingKit.h @@ -9,7 +9,6 @@ FOUNDATION_EXPORT const unsigned char SessionMessagingKitVersionString[]; #import #import #import -#import #import #import #import @@ -24,16 +23,12 @@ FOUNDATION_EXPORT const unsigned char SessionMessagingKitVersionString[]; #import #import #import -#import #import #import -#import -#import #import #import #import #import #import -#import #import #import diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift index 07d594dae..56ba23f92 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift @@ -217,7 +217,7 @@ public final class ClosedGroupPoller: NSObject { ) } - SNLog("Received \(messageCount) message(s) in closed group with public key: \(groupPublicKey).") + SNLog("Received \(messageCount) new message\(messageCount == 1 ? "" : "s") in closed group with public key: \(groupPublicKey) (\(messages.count - messageCount) duplicates)") } } .map { _ in } diff --git a/SessionMessagingKit/Sending & Receiving/Quotes/OWSQuotedReplyModel.m b/SessionMessagingKit/Sending & Receiving/Quotes/OWSQuotedReplyModel.m index 59dada4d7..705caf663 100644 --- a/SessionMessagingKit/Sending & Receiving/Quotes/OWSQuotedReplyModel.m +++ b/SessionMessagingKit/Sending & Receiving/Quotes/OWSQuotedReplyModel.m @@ -12,7 +12,6 @@ #import #import #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/SessionMessagingKit/Sending & Receiving/Quotes/TSQuotedMessage.m b/SessionMessagingKit/Sending & Receiving/Quotes/TSQuotedMessage.m index d69b971e0..576ccda30 100644 --- a/SessionMessagingKit/Sending & Receiving/Quotes/TSQuotedMessage.m +++ b/SessionMessagingKit/Sending & Receiving/Quotes/TSQuotedMessage.m @@ -10,7 +10,6 @@ #import "TSIncomingMessage.h" #import "TSInteraction.h" #import "TSOutgoingMessage.h" -#import "TSThread.h" #import #import diff --git a/SessionMessagingKit/Threads/Notification+Thread.swift b/SessionMessagingKit/Threads/Notification+Thread.swift deleted file mode 100644 index 77b74d0ef..000000000 --- a/SessionMessagingKit/Threads/Notification+Thread.swift +++ /dev/null @@ -1,12 +0,0 @@ - -public extension Notification.Name { - - static let groupThreadUpdated = Notification.Name("groupThreadUpdated") - static let muteSettingUpdated = Notification.Name("muteSettingUpdated") -} - -@objc public extension NSNotification { - - @objc static let groupThreadUpdated = Notification.Name.groupThreadUpdated.rawValue as NSString - @objc static let muteSettingUpdated = Notification.Name.muteSettingUpdated.rawValue as NSString -} diff --git a/SessionMessagingKit/Threads/TSContactThread.h b/SessionMessagingKit/Threads/TSContactThread.h deleted file mode 100644 index f40a7b98c..000000000 --- a/SessionMessagingKit/Threads/TSContactThread.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -extern NSString *const TSContactThreadPrefix; - -@interface TSContactThread : TSThread - -- (instancetype)initWithContactSessionID:(NSString *)contactSessionID; - -+ (instancetype)getOrCreateThreadWithContactSessionID:(NSString *)contactSessionID NS_SWIFT_NAME(getOrCreateThread(contactSessionID:)); - -+ (instancetype)getOrCreateThreadWithContactSessionID:(NSString *)contactSessionID - transaction:(YapDatabaseReadWriteTransaction *)transaction; - -// Unlike getOrCreateThreadWithContactSessionID, this will _NOT_ create a thread if one does not already exist. -+ (nullable instancetype)getThreadWithContactSessionID:(NSString *)contactSessionID transaction:(YapDatabaseReadTransaction *)transaction; - -- (NSString *)contactSessionID; - -+ (NSString *)contactSessionIDFromThreadID:(NSString *)threadId; - -+ (NSString *)threadIDFromContactSessionID:(NSString *)contactSessionID; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSContactThread.m b/SessionMessagingKit/Threads/TSContactThread.m deleted file mode 100644 index 4eb4ead40..000000000 --- a/SessionMessagingKit/Threads/TSContactThread.m +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "TSContactThread.h" -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -NSString *const TSContactThreadPrefix = @"c"; - -@implementation TSContactThread - -- (instancetype)initWithContactSessionID:(NSString *)contactSessionID { - NSString *uniqueIdentifier = [[self class] threadIDFromContactSessionID:contactSessionID]; - - self = [super initWithUniqueId:uniqueIdentifier]; - - return self; -} - -+ (instancetype)getOrCreateThreadWithContactSessionID:(NSString *)contactSessionID - transaction:(YapDatabaseReadWriteTransaction *)transaction { - TSContactThread *thread = - [self fetchObjectWithUniqueID:[self threadIDFromContactSessionID:contactSessionID] transaction:transaction]; - - if (!thread) { - thread = [[TSContactThread alloc] initWithContactSessionID:contactSessionID]; - [thread saveWithTransaction:transaction]; - } - - return thread; -} - -+ (instancetype)getOrCreateThreadWithContactSessionID:(NSString *)contactSessionID -{ - __block TSContactThread *thread; - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [self getOrCreateThreadWithContactSessionID:contactSessionID transaction:transaction]; - }]; - - return thread; -} - -+ (nullable instancetype)getThreadWithContactSessionID:(NSString *)contactSessionID transaction:(YapDatabaseReadTransaction *)transaction; -{ - return [TSContactThread fetchObjectWithUniqueID:[self threadIDFromContactSessionID:contactSessionID] transaction:transaction]; -} - -- (NSString *)contactSessionID { - return [[self class] contactSessionIDFromThreadID:self.uniqueId]; -} - -- (NSArray *)recipientIdentifiers -{ - return @[ self.contactSessionID ]; -} - -- (BOOL)isMessageRequest { - NSString *sessionID = self.contactSessionID; - SMKContact *contact = [SMKContact fetchOrCreateWithId: sessionID]; - - return ( - self.shouldBeVisible && - !self.isNoteToSelf && ( - contact == nil || - !contact.isApproved - ) - ); -} - -- (BOOL)isMessageRequestUsingTransaction:(YapDatabaseReadTransaction *)transaction { - NSString *sessionID = self.contactSessionID; - SMKContact *contact = [SMKContact fetchOrCreateWithId: sessionID]; - - return ( - self.shouldBeVisible && - !self.isNoteToSelf && ( - contact == nil || - !contact.isApproved - ) - ); -} - -- (BOOL)isBlocked { - NSString *sessionID = self.contactSessionID; - SMKContact *contact = [SMKContact fetchOrCreateWithId: sessionID]; - - return (contact.isBlocked == YES); -} - -- (BOOL)isBlockedUsingTransaction:(YapDatabaseReadTransaction *)transaction { - NSString *sessionID = self.contactSessionID; - SMKContact *contact = [SMKContact fetchOrCreateWithId: sessionID]; - - return (contact.isBlocked == YES); -} - -- (BOOL)isGroupThread -{ - return NO; -} - -- (NSString *)name -{ - NSString *sessionID = self.contactSessionID; - return [SMKProfile displayNameWithId:sessionID]; -} - -- (NSString *)nameWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - NSString *sessionID = self.contactSessionID; - return [SMKProfile displayNameWithId:sessionID]; -} - -+ (NSString *)threadIDFromContactSessionID:(NSString *)contactSessionID { - return [TSContactThreadPrefix stringByAppendingString:contactSessionID]; -} - -+ (NSString *)contactSessionIDFromThreadID:(NSString *)threadId { - return [threadId substringWithRange:NSMakeRange(1, threadId.length - 1)]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSGroupModel.h b/SessionMessagingKit/Threads/TSGroupModel.h deleted file mode 100644 index f05879470..000000000 --- a/SessionMessagingKit/Threads/TSGroupModel.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSInteger, GroupType) { - closedGroup = 0, - openGroup = 1, -}; - -extern const int32_t kGroupIdLength; - -@interface TSGroupModel : TSYapDatabaseObject - -@property (nonatomic) NSArray *groupMemberIds; -@property (nonatomic) NSArray *groupAdminIds; -@property (nullable, readonly, nonatomic) NSString *groupName; -@property (readonly, nonatomic) NSData *groupId; -@property (nonatomic) GroupType groupType; - -#if TARGET_OS_IOS -@property (nullable, nonatomic, strong) UIImage *groupImage; - -- (instancetype)initWithTitle:(nullable NSString *)title - memberIds:(NSArray *)memberIds - image:(nullable UIImage *)image - groupId:(NSData *)groupId - groupType:(GroupType)groupType - adminIds:(NSArray *)adminIds; - -- (BOOL)isEqual:(id)other; -- (BOOL)isEqualToGroupModel:(TSGroupModel *)model; -- (NSString *)getInfoStringAboutUpdateTo:(TSGroupModel *)model; - -#endif - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSGroupModel.m b/SessionMessagingKit/Threads/TSGroupModel.m deleted file mode 100644 index 8af3d8b52..000000000 --- a/SessionMessagingKit/Threads/TSGroupModel.m +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "TSGroupModel.h" -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -const int32_t kGroupIdLength = 16; - -@interface TSGroupModel () - -@property (nullable, nonatomic) NSString *groupName; - -@end - -#pragma mark - - -@implementation TSGroupModel - -- (nullable NSString *)groupName -{ - return _groupName.filterStringForDisplay; -} - -#if TARGET_OS_IOS -- (instancetype)initWithTitle:(nullable NSString *)title - memberIds:(NSArray *)memberIds - image:(nullable UIImage *)image - groupId:(NSData *)groupId - groupType:(GroupType)groupType - adminIds:(NSArray *)adminIds -{ - _groupName = title; - _groupMemberIds = [memberIds copy]; - _groupImage = image; - _groupType = groupType; - _groupId = groupId; - _groupAdminIds = [adminIds copy]; - - return self; -} - -- (nullable instancetype)initWithCoder:(NSCoder *)coder -{ - self = [super initWithCoder:coder]; - if (!self) { - return self; - } - - // Occasionally seeing this as nil in legacy data, - // which causes crashes. - if (_groupMemberIds == nil) { - _groupMemberIds = [NSArray new]; - } - - if (_groupAdminIds == nil) { - _groupAdminIds = [NSArray new]; - } - - return self; -} - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } - if (!other || ![other isKindOfClass:[self class]]) { - return NO; - } - return [self isEqualToGroupModel:other]; -} - -- (BOOL)isEqualToGroupModel:(TSGroupModel *)other { - if (self == other) - return YES; - if (![_groupId isEqualToData:other.groupId]) { - return NO; - } - if (![_groupName isEqual:other.groupName]) { - return NO; - } - if (!(_groupImage != nil && other.groupImage != nil && - [UIImagePNGRepresentation(_groupImage) isEqualToData:UIImagePNGRepresentation(other.groupImage)])) { - return NO; - } - if (_groupType != other.groupType) { - return NO; - } - NSMutableArray *compareMyGroupMemberIds = [NSMutableArray arrayWithArray:_groupMemberIds]; - [compareMyGroupMemberIds removeObjectsInArray:other.groupMemberIds]; - if ([compareMyGroupMemberIds count] > 0) { - return NO; - } - return YES; -} - -- (NSString *)getInfoStringAboutUpdateTo:(TSGroupModel *)newModel { - // This is only invoked for group * changes *, i.e. not when a group is created. - NSString *userPublicKey = [SNGeneralUtilities getUserPublicKey]; - NSString *updatedGroupInfoString = @""; - if (self == newModel) { - return NSLocalizedString(@"GROUP_UPDATED", @""); - } - // Name change - if (![_groupName isEqual:newModel.groupName]) { - updatedGroupInfoString = [updatedGroupInfoString stringByAppendingString:[NSString stringWithFormat:NSLocalizedString(@"GROUP_TITLE_CHANGED", @""), newModel.groupName]]; - } - // Added & removed members - NSSet *oldMembers = [NSSet setWithArray:_groupMemberIds]; - NSSet *newMembers = [NSSet setWithArray:newModel.groupMemberIds]; - - NSMutableSet *addedMembers = newMembers.mutableCopy; - [addedMembers minusSet:oldMembers]; - - NSMutableSet *removedMembers = oldMembers.mutableCopy; - [removedMembers minusSet:newMembers]; - - NSMutableSet *removedMembersMinusSelf = removedMembers.mutableCopy; - [removedMembersMinusSelf minusSet:[NSSet setWithObject:userPublicKey]]; - - if (removedMembersMinusSelf.count > 0) { - NSArray *removedMemberNames = [removedMembers.allObjects map:^NSString *(NSString *publicKey) { - return [SMKProfile displayNameWithId:publicKey]; - }]; - NSString *format = removedMembers.count > 1 ? NSLocalizedString(@"GROUP_MEMBERS_REMOVED", @"") : NSLocalizedString(@"GROUP_MEMBER_REMOVED", @""); - updatedGroupInfoString = [updatedGroupInfoString - stringByAppendingString:[NSString - stringWithFormat: format, - [removedMemberNames componentsJoinedByString:@", "]]]; - } - - if (addedMembers.count > 0) { - NSArray *addedMemberNames = [[addedMembers allObjects] map:^NSString*(NSString* publicKey) { - return [SMKProfile displayNameWithId:publicKey]; - }]; - updatedGroupInfoString = [updatedGroupInfoString - stringByAppendingString:[NSString - stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_JOINED", @""), - [addedMemberNames componentsJoinedByString:@", "]]]; - } - - if ([removedMembers containsObject:userPublicKey]) { - updatedGroupInfoString = [updatedGroupInfoString stringByAppendingString:NSLocalizedString(@"YOU_WERE_REMOVED", @"")]; - } - // Return - if ([updatedGroupInfoString length] == 0) { - updatedGroupInfoString = NSLocalizedString(@"GROUP_UPDATED", @""); - } - return updatedGroupInfoString; -} - -#endif - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSGroupThread.h b/SessionMessagingKit/Threads/TSGroupThread.h deleted file mode 100644 index 1ed89a978..000000000 --- a/SessionMessagingKit/Threads/TSGroupThread.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class TSAttachmentStream; -@class YapDatabaseReadWriteTransaction; - -extern NSString *const TSGroupThreadAvatarChangedNotification; -extern NSString *const TSGroupThread_NotificationKey_UniqueId; - -@interface TSGroupThread : TSThread - -@property (nonatomic, strong) TSGroupModel *groupModel; -@property (nonatomic, readonly) BOOL isOpenGroup; -@property (nonatomic, readonly) BOOL isClosedGroup; -@property (nonatomic) BOOL isOnlyNotifyingForMentions; - -+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel; -+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel - transaction:(YapDatabaseReadWriteTransaction *)transaction; - -+ (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId - groupType:(GroupType) groupType; -+ (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId - groupType:(GroupType) groupType - transaction:(YapDatabaseReadWriteTransaction *)transaction; - -+ (nullable instancetype)threadWithGroupId:(NSData *)groupId transaction:(YapDatabaseReadTransaction *)transaction - NS_SWIFT_NAME(fetch(groupId:transaction:)); - -+ (NSString *)threadIdFromGroupId:(NSData *)groupId; - -+ (NSString *)defaultGroupName; - -- (BOOL)isCurrentUserMemberInGroup; -- (BOOL)isUserMemberInGroup:(NSString *)publicKey; -- (BOOL)isUserAdminInGroup:(NSString *)publicKey; - -// all group threads containing recipient as a member -+ (NSArray *)groupThreadsWithRecipientId:(NSString *)recipientId - transaction:(YapDatabaseReadWriteTransaction *)transaction; - -- (void)setGroupModel:(TSGroupModel *)newGroupModel withTransaction:(YapDatabaseReadWriteTransaction *)transaction; -- (void)setIsOnlyNotifyingForMentions:(BOOL)isOnlyNotifyingForMentions withTransaction:(YapDatabaseReadWriteTransaction *)transaction; -- (void)leaveGroupWithSneakyTransaction; -- (void)leaveGroupWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - -#pragma mark - Avatar - -- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream; -- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream - transaction:(YapDatabaseReadWriteTransaction *)transaction; - -- (void)fireAvatarChangedNotification; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSGroupThread.m b/SessionMessagingKit/Threads/TSGroupThread.m deleted file mode 100644 index 61b2e706e..000000000 --- a/SessionMessagingKit/Threads/TSGroupThread.m +++ /dev/null @@ -1,283 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "TSGroupThread.h" -#import "TSAttachmentStream.h" -#import -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -NSString *const TSGroupThreadAvatarChangedNotification = @"TSGroupThreadAvatarChangedNotification"; -NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_NotificationKey_UniqueId"; - -@implementation TSGroupThread - -#define TSGroupThreadPrefix @"g" - -- (instancetype)initWithGroupModel:(TSGroupModel *)groupModel -{ - NSString *uniqueIdentifier = [[self class] threadIdFromGroupId:groupModel.groupId]; - self = [super initWithUniqueId:uniqueIdentifier]; - - if (!self) { - return self; - } - - _groupModel = groupModel; - - return self; -} - -- (instancetype)initWithGroupId:(NSData *)groupId groupType:(GroupType)groupType -{ - NSString *localNumber = [TSAccountManager localNumber]; - - TSGroupModel *groupModel = [[TSGroupModel alloc] initWithTitle:nil - memberIds:@[ localNumber ] - image:nil - groupId:groupId - groupType:groupType - adminIds:@[ localNumber ]]; - - self = [self initWithGroupModel:groupModel]; - - if (!self) { - return self; - } - - return self; -} - -+ (nullable instancetype)threadWithGroupId:(NSData *)groupId transaction:(YapDatabaseReadTransaction *)transaction -{ - return [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupId] transaction:transaction]; -} - -+ (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId - groupType:(GroupType)groupType - transaction:(YapDatabaseReadWriteTransaction *)transaction -{ - TSGroupThread *thread = [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupId] transaction:transaction]; - - if (!thread) { - thread = [[self alloc] initWithGroupId:groupId groupType:groupType]; - [thread saveWithTransaction:transaction]; - } - - return thread; -} - -+ (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId groupType:(GroupType)groupType -{ - __block TSGroupThread *thread; - - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [self getOrCreateThreadWithGroupId:groupId groupType:groupType transaction:transaction]; - }]; - - return thread; -} - -+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel - transaction:(YapDatabaseReadWriteTransaction *)transaction { - TSGroupThread *thread = - [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupModel.groupId] transaction:transaction]; - - if (!thread) { - thread = [[TSGroupThread alloc] initWithGroupModel:groupModel]; - [thread saveWithTransaction:transaction]; - } - - return thread; -} - -+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel -{ - __block TSGroupThread *thread; - - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [self getOrCreateThreadWithGroupModel:groupModel transaction:transaction]; - }]; - - return thread; -} - -+ (NSString *)threadIdFromGroupId:(NSData *)groupId -{ - return [TSGroupThreadPrefix stringByAppendingString:[[LKGroupUtilities getDecodedGroupIDAsData:groupId] base64EncodedString]]; -} - -+ (NSData *)groupIdFromThreadId:(NSString *)threadId -{ - return [NSData dataFromBase64String:[threadId substringWithRange:NSMakeRange(1, threadId.length - 1)]]; -} - -- (NSArray *)recipientIdentifiers -{ - if (self.isClosedGroup) { - NSMutableArray *groupMemberIds = [self.groupModel.groupMemberIds mutableCopy]; - if (groupMemberIds == nil) { return @[]; } - [groupMemberIds removeObject:TSAccountManager.localNumber]; - return [groupMemberIds copy]; - } else { - return @[ [LKGroupUtilities getDecodedGroupID:self.groupModel.groupId] ]; - } -} - -// @returns all threads to which the recipient is a member. -// -// @note If this becomes a hotspot we can extract into a YapDB View. -// As is, the number of groups should be small (dozens, *maybe* hundreds), and we only enumerate them upon SN changes. -+ (NSArray *)groupThreadsWithRecipientId:(NSString *)recipientId - transaction:(YapDatabaseReadWriteTransaction *)transaction -{ - NSMutableArray *groupThreads = [NSMutableArray new]; - - [self enumerateCollectionObjectsWithTransaction:transaction usingBlock:^(id obj, BOOL *stop) { - if ([obj isKindOfClass:[TSGroupThread class]]) { - TSGroupThread *groupThread = (TSGroupThread *)obj; - if ([groupThread.groupModel.groupMemberIds containsObject:recipientId]) { - [groupThreads addObject:groupThread]; - } - } - }]; - - return [groupThreads copy]; -} - -- (BOOL)isGroupThread -{ - return true; -} - -- (BOOL)isClosedGroup -{ - return (self.groupModel.groupType == closedGroup); -} - -- (BOOL)isOpenGroup -{ - return (self.groupModel.groupType == openGroup); -} - -- (BOOL)isCurrentUserMemberInGroup -{ - NSString *userPublicKey = [SNGeneralUtilities getUserPublicKey]; - return [self isUserMemberInGroup:userPublicKey]; -} - -- (BOOL)isUserMemberInGroup:(NSString *)publicKey -{ - if (publicKey == nil) { return NO; } - return [self.groupModel.groupMemberIds containsObject:publicKey]; -} - -- (BOOL)isUserAdminInGroup:(NSString *)publicKey -{ - if (publicKey == nil) { return NO; } - return [self.groupModel.groupAdminIds containsObject:publicKey]; -} - -- (NSString *)name -{ - // TODO sometimes groupName is set to the empty string. I'm hesitent to change - // the semantics here until we have time to thouroughly test the fallout. - // Instead, see the `groupNameOrDefault` which is appropriate for use when displaying - // text corresponding to a group. - return self.groupModel.groupName ?: self.class.defaultGroupName; -} - -- (NSString *)nameWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - return [self name]; -} - -+ (NSString *)defaultGroupName -{ - return @"Group"; -} - -- (void)setGroupModel:(TSGroupModel *)newGroupModel withTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - self.groupModel = newGroupModel; - - [self saveWithTransaction:transaction]; - - [transaction addCompletionQueue:dispatch_get_main_queue() completionBlock:^{ - [NSNotificationCenter.defaultCenter postNotificationName:NSNotification.groupThreadUpdated object:self.uniqueId]; - }]; -} - -- (void)setIsOnlyNotifyingForMentions:(BOOL)isOnlyNotifyingForMentions withTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - self.isOnlyNotifyingForMentions = isOnlyNotifyingForMentions; - - [self saveWithTransaction:transaction]; - - [transaction addCompletionQueue:dispatch_get_main_queue() completionBlock:^{ - [NSNotificationCenter.defaultCenter postNotificationName:NSNotification.groupThreadUpdated object:self.uniqueId]; - }]; -} - -- (void)leaveGroupWithSneakyTransaction -{ - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - [self leaveGroupWithTransaction:transaction]; - }]; -} - -- (void)leaveGroupWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - NSMutableSet *newGroupMemberIDs = [NSMutableSet setWithArray:self.groupModel.groupMemberIds]; - NSString *userPublicKey = TSAccountManager.localNumber; - if (userPublicKey == nil) { return; } - [newGroupMemberIDs removeObject:userPublicKey]; - self.groupModel.groupMemberIds = newGroupMemberIDs.allObjects; - [self saveWithTransaction:transaction]; - [transaction addCompletionQueue:dispatch_get_main_queue() completionBlock:^{ - [NSNotificationCenter.defaultCenter postNotificationName:NSNotification.groupThreadUpdated object:self.uniqueId]; - }]; -} - -#pragma mark - Avatar - -- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream -{ - [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [self updateAvatarWithAttachmentStream:attachmentStream transaction:transaction]; - }]; -} - -- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream - transaction:(YapDatabaseReadWriteTransaction *)transaction -{ - self.groupModel.groupImage = [attachmentStream thumbnailImageSmallSync]; - [self saveWithTransaction:transaction]; - - [transaction addCompletionQueue:nil - completionBlock:^{ - [self fireAvatarChangedNotification]; - }]; - - // Avatars are stored directly in the database, so there's no need - // to keep the attachment around after assigning the image. - [attachmentStream removeWithTransaction:transaction]; -} - -- (void)fireAvatarChangedNotification -{ - NSDictionary *userInfo = @{ TSGroupThread_NotificationKey_UniqueId : self.uniqueId }; - - [[NSNotificationCenter defaultCenter] postNotificationName:TSGroupThreadAvatarChangedNotification - object:self.uniqueId - userInfo:userInfo]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSThread.h b/SessionMessagingKit/Threads/TSThread.h deleted file mode 100644 index f1c660a22..000000000 --- a/SessionMessagingKit/Threads/TSThread.h +++ /dev/null @@ -1,137 +0,0 @@ -// -// Copyright (c) 2019 Open Whisper Systems. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -BOOL IsNoteToSelfEnabled(void); - -@class TSInteraction; - -/** - * TSThread is the superclass of TSContactThread and TSGroupThread - */ -@interface TSThread : TSYapDatabaseObject - -@property (nonatomic) BOOL isPinned; -@property (nonatomic) BOOL shouldBeVisible; -@property (nonatomic, readonly) NSDate *creationDate; -@property (nonatomic, readonly, nullable) NSDate *lastInteractionDate; -@property (nonatomic, readonly) TSInteraction *lastInteraction; -@property (atomic, readonly) BOOL isMuted; -@property (nonatomic, copy, nullable) NSString *messageDraft; -@property (atomic, readonly, nullable) NSDate *mutedUntilDate; - -/** - * Whether the object is a group thread or not. - * - * @return YES if is a group thread, NO otherwise. - */ -- (BOOL)isGroupThread; - -/** - * Returns the name of the thread. - * - * @return The name of the thread. - */ -- (NSString *)name; - -- (NSString *)nameWithTransaction:(YapDatabaseReadTransaction *)transaction; - -/** - * @returns recipientId for each recipient in the thread - */ -@property (nonatomic, readonly) NSArray *recipientIdentifiers; - -- (BOOL)isNoteToSelf; - -/** - * Whether the thread is a message request. - * - * @return YES if the combination of thread and contact approval means this thread should appear in the message requests section, NO otherwise. - */ -- (BOOL)isMessageRequest; -- (BOOL)isMessageRequestUsingTransaction:(YapDatabaseReadTransaction *)transaction; - -- (BOOL)isBlocked; -- (BOOL)isBlockedUsingTransaction:(YapDatabaseReadTransaction *)transaction; - -#pragma mark Interactions - -- (void)enumerateInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction usingBlock:(void (^)(TSInteraction *interaction, BOOL *stop))block; - -- (void)enumerateInteractionsUsingBlock:(void (^)(TSInteraction *interaction))block; - -/** - * @return The number of interactions in this thread. - */ -- (NSUInteger)numberOfInteractions; - -- (NSUInteger)numberOfInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction; - -/** - * @return If there is any message mentioning current user in this thread. - */ -- (NSUInteger)unreadMentionMessageCount; - -- (NSUInteger)unreadMentionMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction; - -/** - * Returns the string that will be displayed typically in a conversations view as a preview of the last message - * received in this thread. - * - * @return Thread preview string. - */ -- (NSString *)lastMessageTextWithTransaction:(YapDatabaseReadTransaction *)transaction - NS_SWIFT_NAME(lastMessageText(transaction:)); - -- (nullable TSInteraction *)lastInteractionForInboxWithTransaction:(YapDatabaseReadTransaction *)transaction - NS_SWIFT_NAME(lastInteractionForInbox(transaction:)); - -/** - * Updates the thread's caches of the latest interaction. - * - * @param lastMessage Latest Interaction to take into consideration. - * @param transaction Database transaction. - */ -- (void)updateWithLastMessage:(TSInteraction *)lastMessage transaction:(YapDatabaseReadWriteTransaction *)transaction; - -- (void)removeAllThreadInteractionsWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - -- (TSInteraction *)getLastInteractionWithTransaction:(YapDatabaseReadTransaction *)transaction; - -#pragma mark Disappearing Messages - -- (OWSDisappearingMessagesConfiguration *)disappearingMessagesConfigurationWithTransaction: - (YapDatabaseReadTransaction *)transaction; - -- (uint32_t)disappearingMessagesDurationWithTransaction:(YapDatabaseReadTransaction *)transaction; - -#pragma mark Drafts - -/** - * Returns the last known draft for that thread. Always returns a string. Empty string if nil. - * - * @param transaction Database transaction. - * - * @return Last known draft for that thread. - */ -- (NSString *)currentDraftWithTransaction:(YapDatabaseReadTransaction *)transaction; - -/** - * Sets the draft of a thread. Typically called when leaving a conversation view. - * - * @param draftString Draft string to be saved. - * @param transaction Database transaction. - */ -- (void)setDraft:(NSString *)draftString transaction:(YapDatabaseReadWriteTransaction *)transaction; - -#pragma mark Muting - -- (void)updateWithMutedUntilDate:(NSDate * _Nullable)mutedUntilDate transaction:(YapDatabaseReadWriteTransaction *)transaction; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Threads/TSThread.m b/SessionMessagingKit/Threads/TSThread.m deleted file mode 100644 index d9f4f9000..000000000 --- a/SessionMessagingKit/Threads/TSThread.m +++ /dev/null @@ -1,375 +0,0 @@ -// -// Copyright (c) 2019 Open Whisper Systems. All rights reserved. -// - -#import "TSThread.h" -#import -#import -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -BOOL IsNoteToSelfEnabled(void) -{ - return YES; -} - -@interface TSThread () - -@property (nonatomic) NSDate *creationDate; -@property (nonatomic, nullable) NSDate *lastInteractionDate; -@property (nonatomic, nullable) NSNumber *archivedAsOfMessageSortId; -@property (atomic, nullable) NSDate *mutedUntilDate; - -@end - -@implementation TSThread - -#pragma mark Initialization - -+ (NSString *)collection { - return @"TSThread"; -} - -- (instancetype)initWithUniqueId:(NSString *_Nullable)uniqueId -{ - self = [super initWithUniqueId:uniqueId]; - - if (self) { - _creationDate = [NSDate date]; - _messageDraft = nil; - } - - return self; -} - -- (nullable instancetype)initWithCoder:(NSCoder *)coder -{ - self = [super initWithCoder:coder]; - if (!self) { - return self; - } - - // renamed `hasEverHadMessage` -> `shouldBeVisible` - if (!_shouldBeVisible) { - NSNumber *_Nullable legacy_hasEverHadMessage = [coder decodeObjectForKey:@"hasEverHadMessage"]; - - if (legacy_hasEverHadMessage != nil) { - _shouldBeVisible = legacy_hasEverHadMessage.boolValue; - } - } - - NSDate *_Nullable lastMessageDate = [coder decodeObjectOfClass:NSDate.class forKey:@"lastMessageDate"]; - NSDate *_Nullable archivalDate = [coder decodeObjectOfClass:NSDate.class forKey:@"archivalDate"]; - - return self; -} - -- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - [super saveWithTransaction:transaction]; - - [SSKPreferences setHasSavedThreadWithValue:YES transaction:transaction]; -} - -- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - [self removeAllThreadInteractionsWithTransaction:transaction]; - - [super removeWithTransaction:transaction]; -} - -- (void)removeAllThreadInteractionsWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - // We can't safely delete interactions while enumerating them, so - // we collect and delete separately. - // - // We don't want to instantiate the interactions when collecting them - // or when deleting them. - NSMutableArray *interactionIds = [NSMutableArray new]; - YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName]; - __block BOOL didDetectCorruption = NO; - [interactionsByThread enumerateKeysInGroup:self.uniqueId - usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop) { - if (![key isKindOfClass:[NSString class]] || key.length < 1) { - didDetectCorruption = YES; - return; - } - [interactionIds addObject:key]; - }]; - - if (didDetectCorruption) { - [OWSPrimaryStorage incrementVersionOfDatabaseExtension:TSMessageDatabaseViewExtensionName]; - } - - for (NSString *interactionId in interactionIds) { - // We need to fetch each interaction, since [TSInteraction removeWithTransaction:] does important work. - TSInteraction *_Nullable interaction = - [TSInteraction fetchObjectWithUniqueID:interactionId transaction:transaction]; - if (!interaction) { - continue; - } - [interaction removeWithTransaction:transaction]; - } -} - -- (BOOL)isNoteToSelf -{ - if (!IsNoteToSelfEnabled()) { return NO; } - if (![self isKindOfClass:TSContactThread.class]) { return NO; } - return [self.contactSessionID isEqual:[SNGeneralUtilities getUserPublicKey]]; -} - -// Override in ContactThread -- (BOOL)isMessageRequest { - return NO; -} - -// Override in ContactThread -- (BOOL)isMessageRequestUsingTransaction:(YapDatabaseReadTransaction *)transaction { - return NO; -} - -// Override in ContactThread -- (BOOL)isBlocked { - return NO; -} - -// Override in ContactThread -- (BOOL)isBlockedUsingTransaction:(YapDatabaseReadTransaction *)transaction { - return NO; -} - -#pragma mark To be subclassed. - -- (BOOL)isGroupThread { - return NO; -} - -// Override in ContactThread -- (nullable NSString *)contactSessionID -{ - return nil; -} - -- (NSString *)name { - return nil; -} - -- (NSString *)nameWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - return nil; -} - -- (NSArray *)recipientIdentifiers -{ - return @[]; -} - -#pragma mark Interactions - -/** - * Iterate over this thread's interactions - */ -- (void)enumerateInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction - usingBlock:(void (^)(TSInteraction *interaction, BOOL *stop))block -{ - YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName]; - [interactionsByThread - enumerateKeysAndObjectsInGroup:self.uniqueId - usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { - TSInteraction *interaction = object; - block(interaction, stop); - }]; -} - -/** - * Enumerates all the threads interactions. Note this will explode if you try to create a transaction in the block. - * If you need a transaction, use the sister method: `enumerateInteractionsWithTransaction:usingBlock` - */ -- (void)enumerateInteractionsUsingBlock:(void (^)(TSInteraction *interaction))block -{ - [self.dbReadWriteConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [self enumerateInteractionsWithTransaction:transaction - usingBlock:^( - TSInteraction *interaction, BOOL *stop) { - - block(interaction); - }]; - }]; -} - -- (TSInteraction *)lastInteraction -{ - __block TSInteraction *interaction; - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - interaction = [self getLastInteractionWithTransaction:transaction]; - }]; - return interaction; -} - -- (TSInteraction *)getLastInteractionWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - YapDatabaseViewTransaction *interactions = [transaction ext:TSMessageDatabaseViewExtensionName]; - return [interactions lastObjectInGroup:self.uniqueId]; -} - -/** - * Useful for tests and debugging. In production use an enumeration method. - */ -- (NSArray *)allInteractions -{ - NSMutableArray *interactions = [NSMutableArray new]; - [self enumerateInteractionsUsingBlock:^(TSInteraction *interaction) { - [interactions addObject:interaction]; - }]; - - return [interactions copy]; -} - -- (NSUInteger)numberOfInteractions -{ - __block NSUInteger count; - [[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) { - count = [self numberOfInteractionsWithTransaction:transaction]; - }]; - return count; -} - -- (NSUInteger)numberOfInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName]; - return [interactionsByThread numberOfItemsInGroup:self.uniqueId]; -} - -- (NSUInteger)unreadMentionMessageCount -{ - __block NSUInteger unreadMentionMessageCount; - [[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) { - unreadMentionMessageCount = [self unreadMentionMessageCountWithTransaction:transaction]; - }]; - return unreadMentionMessageCount; -} - -- (NSUInteger)unreadMentionMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - YapDatabaseViewTransaction *unreadMentions = [transaction ext:TSUnreadMentionDatabaseViewExtensionName]; - return [unreadMentions numberOfItemsInGroup:self.uniqueId]; -} - -- (nullable TSInteraction *)lastInteractionForInboxWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - __block NSUInteger missedCount = 0; - __block TSInteraction *last = nil; - [[transaction ext:TSMessageDatabaseViewExtensionName] - enumerateKeysAndObjectsInGroup:self.uniqueId - withOptions:NSEnumerationReverse - usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { - missedCount++; - TSInteraction *interaction = (TSInteraction *)object; - - if ([TSThread shouldInteractionAppearInInbox:interaction]) { - last = interaction; - - // For long ignored threads, with lots of SN changes this can get really slow. - // I see this in development because I have a lot of long forgotten threads with - // members who's test devices are constantly reinstalled. We could add a - // purpose-built DB view, but I think in the real world this is rare to be a - // hotspot. - - *stop = YES; - } - }]; - return last; -} - -- (NSString *)lastMessageTextWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - TSInteraction *interaction = [self lastInteractionForInboxWithTransaction:transaction]; - if ([interaction conformsToProtocol:@protocol(OWSPreviewText)]) { - id previewable = (id)interaction; - return [previewable previewTextWithTransaction:transaction].filterStringForDisplay; - } else { - return @""; - } -} - -// Returns YES IFF the interaction should show up in the inbox as the last message. -+ (BOOL)shouldInteractionAppearInInbox:(TSInteraction *)interaction -{ - if (interaction.isDynamicInteraction) { - return NO; - } - - if ([interaction isKindOfClass:[TSMessage class]]) { - TSMessage *message = (TSMessage *)interaction; - if (message.isDeleted) { - return NO; - } - } - - return YES; -} - -- (void)updateWithLastMessage:(TSInteraction *)lastMessage transaction:(YapDatabaseReadWriteTransaction *)transaction { - if (![self.class shouldInteractionAppearInInbox:lastMessage]) { - return; - } - - if ([_lastInteractionDate compare: lastMessage.receivedAtDate] == NSOrderedAscending) { - _lastInteractionDate = lastMessage.receivedAtDate; - [super saveWithTransaction:transaction]; - } - - if (!self.shouldBeVisible) { - self.shouldBeVisible = YES; - [self saveWithTransaction:transaction]; - } else { - [self touchWithTransaction:transaction]; - } -} - -#pragma mark Drafts - -- (NSString *)currentDraftWithTransaction:(YapDatabaseReadTransaction *)transaction { - TSThread *thread = [TSThread fetchObjectWithUniqueID:self.uniqueId transaction:transaction]; - if (thread.messageDraft) { - return thread.messageDraft; - } else { - return @""; - } -} - -- (void)setDraft:(NSString *)draftString transaction:(YapDatabaseReadWriteTransaction *)transaction { - TSThread *thread = [TSThread fetchObjectWithUniqueID:self.uniqueId transaction:transaction]; - thread.messageDraft = draftString; - [thread saveWithTransaction:transaction]; -} - -#pragma mark Muting - -- (BOOL)isMuted -{ - NSDate *mutedUntilDate = self.mutedUntilDate; - NSDate *now = [NSDate date]; - return (mutedUntilDate != nil && [mutedUntilDate timeIntervalSinceDate:now] > 0); -} - -- (void)updateWithMutedUntilDate:(NSDate * _Nullable)mutedUntilDate transaction:(YapDatabaseReadWriteTransaction *)transaction -{ - [self applyChangeToSelfAndLatestCopy:transaction - changeBlock:^(TSThread *thread) { - [thread setMutedUntilDate:mutedUntilDate]; - }]; - - [transaction addCompletionQueue:dispatch_get_main_queue() completionBlock:^{ - [NSNotificationCenter.defaultCenter postNotificationName:NSNotification.muteSettingUpdated object:self.uniqueId]; - }]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Utilities/Preferences.swift b/SessionMessagingKit/Utilities/Preferences.swift index f37f048ae..022c1e4c6 100644 --- a/SessionMessagingKit/Utilities/Preferences.swift +++ b/SessionMessagingKit/Utilities/Preferences.swift @@ -45,7 +45,10 @@ public extension Setting.BoolKey { static let playNotificationSoundInForeground: Setting.BoolKey = "playNotificationSoundInForeground" /// A flag indicating whether the user has ever saved a thread - static let hasSavedThreadKey: Setting.BoolKey = "hasSavedThread" + static let hasSavedThread: Setting.BoolKey = "hasSavedThread" + + /// A flag indicating whether the user has ever send a message + static let hasSentAMessage: Setting.BoolKey = "hasSentAMessageKey" } public extension Setting.StringKey { diff --git a/SessionSnodeKit/Database/LegacyDatabase/SSKLegacyModels.swift b/SessionSnodeKit/Database/LegacyDatabase/SSKLegacy.swift similarity index 99% rename from SessionSnodeKit/Database/LegacyDatabase/SSKLegacyModels.swift rename to SessionSnodeKit/Database/LegacyDatabase/SSKLegacy.swift index cb271285b..375634444 100644 --- a/SessionSnodeKit/Database/LegacyDatabase/SSKLegacyModels.swift +++ b/SessionSnodeKit/Database/LegacyDatabase/SSKLegacy.swift @@ -2,7 +2,7 @@ import Foundation -public enum Legacy { +public enum SSKLegacy { // MARK: - Collections and Keys internal static let swarmCollectionPrefix = "LokiSwarmCollection-" diff --git a/SessionSnodeKit/Database/Migrations/_003_YDBToGRDBMigration.swift b/SessionSnodeKit/Database/Migrations/_003_YDBToGRDBMigration.swift index 09cf59825..a29fde245 100644 --- a/SessionSnodeKit/Database/Migrations/_003_YDBToGRDBMigration.swift +++ b/SessionSnodeKit/Database/Migrations/_003_YDBToGRDBMigration.swift @@ -11,28 +11,28 @@ enum _003_YDBToGRDBMigration: Migration { // MARK: - OnionRequestPath, Snode Pool & Swarm // Note: Want to exclude the Snode's we already added from the 'onionRequestPathResult' - var snodeResult: Set = [] - var snodeSetResult: [String: Set] = [:] + var snodeResult: Set = [] + var snodeSetResult: [String: Set] = [:] var lastSnodePoolRefreshDate: Date? = nil // Map the Legacy types for the NSKeyedUnarchiver NSKeyedUnarchiver.setClass( - Legacy.Snode.self, + SSKLegacy.Snode.self, forClassName: "SessionSnodeKit.Snode" ) Storage.read { transaction in // Process the lastSnodePoolRefreshDate lastSnodePoolRefreshDate = transaction.object( - forKey: Legacy.lastSnodePoolRefreshDateKey, - inCollection: Legacy.lastSnodePoolRefreshDateCollection + forKey: SSKLegacy.lastSnodePoolRefreshDateKey, + inCollection: SSKLegacy.lastSnodePoolRefreshDateCollection ) as? Date // Process the OnionRequestPaths if - let path0Snode0 = transaction.object(forKey: "0-0", inCollection: Legacy.onionRequestPathCollection) as? Legacy.Snode, - let path0Snode1 = transaction.object(forKey: "0-1", inCollection: Legacy.onionRequestPathCollection) as? Legacy.Snode, - let path0Snode2 = transaction.object(forKey: "0-2", inCollection: Legacy.onionRequestPathCollection) as? Legacy.Snode + let path0Snode0 = transaction.object(forKey: "0-0", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode, + let path0Snode1 = transaction.object(forKey: "0-1", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode, + let path0Snode2 = transaction.object(forKey: "0-2", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode { snodeResult.insert(path0Snode0) snodeResult.insert(path0Snode1) @@ -40,9 +40,9 @@ enum _003_YDBToGRDBMigration: Migration { snodeSetResult["\(SnodeSet.onionRequestPathPrefix)0"] = [ path0Snode0, path0Snode1, path0Snode2 ] if - let path1Snode0 = transaction.object(forKey: "1-0", inCollection: Legacy.onionRequestPathCollection) as? Legacy.Snode, - let path1Snode1 = transaction.object(forKey: "1-1", inCollection: Legacy.onionRequestPathCollection) as? Legacy.Snode, - let path1Snode2 = transaction.object(forKey: "1-2", inCollection: Legacy.onionRequestPathCollection) as? Legacy.Snode + let path1Snode0 = transaction.object(forKey: "1-0", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode, + let path1Snode1 = transaction.object(forKey: "1-1", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode, + let path1Snode2 = transaction.object(forKey: "1-2", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode { snodeResult.insert(path1Snode0) snodeResult.insert(path1Snode1) @@ -52,8 +52,8 @@ enum _003_YDBToGRDBMigration: Migration { } // Process the SnodePool - transaction.enumerateKeysAndObjects(inCollection: Legacy.snodePoolCollection) { _, object, _ in - guard let snode = object as? Legacy.Snode else { return } + transaction.enumerateKeysAndObjects(inCollection: SSKLegacy.snodePoolCollection) { _, object, _ in + guard let snode = object as? SSKLegacy.Snode else { return } snodeResult.insert(snode) } @@ -61,16 +61,16 @@ enum _003_YDBToGRDBMigration: Migration { var swarmCollections: Set = [] transaction.enumerateCollections { collectionName, _ in - if collectionName.starts(with: Legacy.swarmCollectionPrefix) { - swarmCollections.insert(collectionName.substring(from: Legacy.swarmCollectionPrefix.count)) + if collectionName.starts(with: SSKLegacy.swarmCollectionPrefix) { + swarmCollections.insert(collectionName.substring(from: SSKLegacy.swarmCollectionPrefix.count)) } } for swarmCollection in swarmCollections { - let collection: String = "\(Legacy.swarmCollectionPrefix)\(swarmCollection)" + let collection: String = "\(SSKLegacy.swarmCollectionPrefix)\(swarmCollection)" transaction.enumerateKeysAndObjects(inCollection: collection) { _, object, _ in - guard let snode = object as? Legacy.Snode else { return } + guard let snode = object as? SSKLegacy.Snode else { return } snodeResult.insert(snode) snodeSetResult[swarmCollection] = (snodeSetResult[swarmCollection] ?? Set()).inserting(snode) } @@ -112,13 +112,13 @@ enum _003_YDBToGRDBMigration: Migration { // TODO: Move into the top read block??? Storage.read { transaction in // Extract the received message hashes - transaction.enumerateKeysAndObjects(inCollection: Legacy.receivedMessagesCollection) { key, object, _ in + transaction.enumerateKeysAndObjects(inCollection: SSKLegacy.receivedMessagesCollection) { key, object, _ in guard let hashSet = object as? Set else { return } receivedMessageResults[key] = hashSet } // Retrieve the last message info - transaction.enumerateKeysAndObjects(inCollection: Legacy.lastMessageHashCollection) { key, object, _ in + transaction.enumerateKeysAndObjects(inCollection: SSKLegacy.lastMessageHashCollection) { key, object, _ in guard let lastMessageJson = object as? JSON else { return } guard let lastMessageHash: String = lastMessageJson["hash"] as? String else { return } diff --git a/SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacyModels.swift b/SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacy.swift similarity index 97% rename from SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacyModels.swift rename to SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacy.swift index 28fd3aaeb..1bd4f7da4 100644 --- a/SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacyModels.swift +++ b/SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacy.swift @@ -2,9 +2,7 @@ import Foundation -public typealias SUKLegacy = Legacy - -public enum Legacy { +public enum SUKLegacy { // MARK: - Collections and Keys internal static let userAccountRegisteredNumberKey = "TSStorageRegisteredNumberKey" diff --git a/SessionUtilitiesKit/Database/Migrations/_003_YDBToGRDBMigration.swift b/SessionUtilitiesKit/Database/Migrations/_003_YDBToGRDBMigration.swift index 436ad7f85..3f8cc5b32 100644 --- a/SessionUtilitiesKit/Database/Migrations/_003_YDBToGRDBMigration.swift +++ b/SessionUtilitiesKit/Database/Migrations/_003_YDBToGRDBMigration.swift @@ -14,42 +14,42 @@ enum _003_YDBToGRDBMigration: Migration { var seedHexString: String? var userEd25519SecretKeyHexString: String? var userEd25519PublicKeyHexString: String? - var userX25519KeyPair: Legacy.KeyPair? + var userX25519KeyPair: SUKLegacy.KeyPair? // Map the Legacy types for the NSKeyedUnarchiver NSKeyedUnarchiver.setClass( - Legacy.KeyPair.self, + SUKLegacy.KeyPair.self, forClassName: "ECKeyPair" ) Storage.read { transaction in registeredNumber = transaction.object( - forKey: Legacy.userAccountRegisteredNumberKey, - inCollection: Legacy.userAccountCollection + forKey: SUKLegacy.userAccountRegisteredNumberKey, + inCollection: SUKLegacy.userAccountCollection ) as? String // Note: The 'seed', 'ed25519SecretKey' and 'ed25519PublicKey' were // all previously stored as hex strings, so we need to convert them // to data before we store them in the new database seedHexString = transaction.object( - forKey: Legacy.identityKeyStoreSeedKey, - inCollection: Legacy.identityKeyStoreCollection + forKey: SUKLegacy.identityKeyStoreSeedKey, + inCollection: SUKLegacy.identityKeyStoreCollection ) as? String userEd25519SecretKeyHexString = transaction.object( - forKey: Legacy.identityKeyStoreEd25519SecretKey, - inCollection: Legacy.identityKeyStoreCollection + forKey: SUKLegacy.identityKeyStoreEd25519SecretKey, + inCollection: SUKLegacy.identityKeyStoreCollection ) as? String userEd25519PublicKeyHexString = transaction.object( - forKey: Legacy.identityKeyStoreEd25519PublicKey, - inCollection: Legacy.identityKeyStoreCollection + forKey: SUKLegacy.identityKeyStoreEd25519PublicKey, + inCollection: SUKLegacy.identityKeyStoreCollection ) as? String userX25519KeyPair = transaction.object( - forKey: Legacy.identityKeyStoreIdentityKey, - inCollection: Legacy.identityKeyStoreCollection - ) as? Legacy.KeyPair + forKey: SUKLegacy.identityKeyStoreIdentityKey, + inCollection: SUKLegacy.identityKeyStoreCollection + ) as? SUKLegacy.KeyPair } // No need to continue if the user isn't registered @@ -60,7 +60,7 @@ enum _003_YDBToGRDBMigration: Migration { let seedHexString: String = seedHexString, let userEd25519SecretKeyHexString: String = userEd25519SecretKeyHexString, let userEd25519PublicKeyHexString: String = userEd25519PublicKeyHexString, - let userX25519KeyPair: Legacy.KeyPair = userX25519KeyPair + let userX25519KeyPair: SUKLegacy.KeyPair = userX25519KeyPair else { // If this is a fresh install then we would have created all of the Identity // values directly within the 'Identity' table so this is actually a valid diff --git a/SessionUtilitiesKit/Database/Models/Identity.swift b/SessionUtilitiesKit/Database/Models/Identity.swift index 3ebf1d214..577f55bfc 100644 --- a/SessionUtilitiesKit/Database/Models/Identity.swift +++ b/SessionUtilitiesKit/Database/Models/Identity.swift @@ -127,18 +127,4 @@ public extension Identity { return data.toHexString() } } - - static func clearAll() { - GRDBStorage.shared.write { db in - try Identity.deleteAll(db) - } - } -} - -@objc(SUKIdentity) -public class objc_Identity: NSObject { - @objc(clearAll) - public static func objc_clearAll() { - Identity.clearAll() - } } diff --git a/SignalUtilitiesKit/Database/Migrations/BlockingManagerRemovalMigration.swift b/SignalUtilitiesKit/Database/Migrations/BlockingManagerRemovalMigration.swift index 676eb1252..1e2ead55e 100644 --- a/SignalUtilitiesKit/Database/Migrations/BlockingManagerRemovalMigration.swift +++ b/SignalUtilitiesKit/Database/Migrations/BlockingManagerRemovalMigration.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import Foundation +import YapDatabase import SessionMessagingKit @objc(SNBlockingManagerRemovalMigration) @@ -19,6 +20,12 @@ public class BlockingManagerRemovalMigration: OWSDatabaseMigration { let kOWSBlockingManager_BlockListCollection: String = "kOWSBlockingManager_BlockedPhoneNumbersCollection" let kOWSBlockingManager_BlockedPhoneNumbersKey: String = "kOWSBlockingManager_BlockedPhoneNumbersKey" + // Note: These will be done in the YDB to GRDB migration but have added it here to be safe + NSKeyedUnarchiver.setClass( + SMKLegacy._Contact.self, + forClassName: "SNContact" + ) + let dbConnection: YapDatabaseConnection = primaryStorage.newDatabaseConnection() let blockedSessionIds: Set = Set(dbConnection.object( @@ -28,10 +35,10 @@ public class BlockingManagerRemovalMigration: OWSDatabaseMigration { Storage.write( with: { transaction in - var result: Set = [] + var result: Set = [] - transaction.enumerateRows(inCollection: Legacy.contactCollection) { _, object, _, _ in - guard let contact = object as? SessionMessagingKit.Legacy._Contact else { return } + transaction.enumerateRows(inCollection: SMKLegacy.contactCollection) { _, object, _, _ in + guard let contact = object as? SMKLegacy._Contact else { return } result.insert(contact) } @@ -39,7 +46,7 @@ public class BlockingManagerRemovalMigration: OWSDatabaseMigration { .filter { contact -> Bool in blockedSessionIds.contains(contact.sessionID) } .forEach { contact in contact.isBlocked = true - transaction.setObject(contact, forKey: contact.sessionID, inCollection: Legacy.contactCollection) + transaction.setObject(contact, forKey: contact.sessionID, inCollection: SMKLegacy.contactCollection) } // Now that the values have been migrated we can clear out the old collection diff --git a/SignalUtilitiesKit/Database/Migrations/ContactsMigration.swift b/SignalUtilitiesKit/Database/Migrations/ContactsMigration.swift index f0cbead75..b2290d10b 100644 --- a/SignalUtilitiesKit/Database/Migrations/ContactsMigration.swift +++ b/SignalUtilitiesKit/Database/Migrations/ContactsMigration.swift @@ -1,10 +1,11 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import Foundation +import YapDatabase import SessionMessagingKit @objc(SNContactsMigration) -public class ContactsMigration : OWSDatabaseMigration { +public class ContactsMigration: OWSDatabaseMigration { @objc class func migrationId() -> String { @@ -17,20 +18,33 @@ public class ContactsMigration : OWSDatabaseMigration { private func doMigrationAsync(completion: @escaping OWSDatabaseMigrationCompletion) { var contacts: [SMKLegacy._Contact] = [] - TSContactThread.enumerateCollectionObjects { object, _ in - guard let thread = object as? TSContactThread else { return } - let sessionID = thread.contactSessionID() - var contact: SMKLegacy._Contact? - - Storage.read { transaction in - contact = transaction.object(forKey: sessionID, inCollection: SMKLegacy.contactCollection) as? SMKLegacy._Contact - } - - if let contact: SMKLegacy._Contact = contact { - contact.isTrusted = true - contacts.append(contact) + + // Note: These will be done in the YDB to GRDB migration but have added it here to be safe + NSKeyedUnarchiver.setClass( + SMKLegacy._Thread.self, + forClassName: "TSThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._ContactThread.self, + forClassName: "TSContactThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._Contact.self, + forClassName: "SNContact" + ) + + Storage.read { transaction in + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.threadCollection) { _, object, _ in + guard let thread = object as? SMKLegacy._ContactThread else { return } + + let sessionId: String = SMKLegacy._ContactThread.contactSessionId(fromThreadId: thread.uniqueId) + let contact: SMKLegacy._Contact? = transaction.object(forKey: sessionId, inCollection: SMKLegacy.contactCollection) as? SMKLegacy._Contact + + contact?.isTrusted = true + contacts = contacts.appending(contact) } } + Storage.write(with: { transaction in contacts.forEach { contact in transaction.setObject(contact, forKey: contact.sessionID, inCollection: SMKLegacy.contactCollection) diff --git a/SignalUtilitiesKit/Database/Migrations/MessageRequestsMigration.swift b/SignalUtilitiesKit/Database/Migrations/MessageRequestsMigration.swift index 6593880a3..92223ee70 100644 --- a/SignalUtilitiesKit/Database/Migrations/MessageRequestsMigration.swift +++ b/SignalUtilitiesKit/Database/Migrations/MessageRequestsMigration.swift @@ -1,10 +1,11 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import Foundation +import YapDatabase import SessionMessagingKit @objc(SNMessageRequestsMigration) -public class MessageRequestsMigration : OWSDatabaseMigration { +public class MessageRequestsMigration: OWSDatabaseMigration { @objc class func migrationId() -> String { @@ -16,42 +17,61 @@ public class MessageRequestsMigration : OWSDatabaseMigration { } private func doMigrationAsync(completion: @escaping OWSDatabaseMigrationCompletion) { + let userPublicKey: String = getUserHexEncodedPublicKey() var contacts: Set = Set() - var threads: [TSThread] = [] + var threads: [SMKLegacy._Thread] = [] + + // Note: These will be done in the YDB to GRDB migration but have added it here to be safe + NSKeyedUnarchiver.setClass( + SMKLegacy._Thread.self, + forClassName: "TSThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._ContactThread.self, + forClassName: "TSContactThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._GroupThread.self, + forClassName: "TSGroupThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._GroupModel.self, + forClassName: "TSGroupModel" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._Contact.self, + forClassName: "SNContact" + ) - TSThread.enumerateCollectionObjects { object, _ in - guard let thread: TSThread = object as? TSThread else { return } + Storage.read { transaction in + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.threadCollection) { _, object, _ in + guard let thread: SMKLegacy._Thread = object as? SMKLegacy._Thread else { return } - Storage.read { transaction in - if let contactThread: TSContactThread = thread as? TSContactThread { - let sessionId: String = contactThread.contactSessionID() + if thread is SMKLegacy._ContactThread { + let sessionId: String = SMKLegacy._ContactThread.contactSessionId(fromThreadId: thread.uniqueId) - if let contact: SMKLegacy._Contact = transaction.object(forKey: sessionId, inCollection: Legacy.contactCollection) as? SMKLegacy._Contact { + if let contact: SMKLegacy._Contact = transaction.object(forKey: sessionId, inCollection: SMKLegacy.contactCollection) as? SMKLegacy._Contact { contact.isApproved = true contact.didApproveMe = true contacts.insert(contact) } } - else if let groupThread: TSGroupThread = thread as? TSGroupThread, groupThread.isClosedGroup { + else if let groupThread: SMKLegacy._GroupThread = thread as? SMKLegacy._GroupThread, groupThread.isClosedGroup { let groupAdmins: [String] = groupThread.groupModel.groupAdminIds groupAdmins.forEach { sessionId in - if let contact: SMKLegacy._Contact = transaction.object(forKey: sessionId, inCollection: Legacy.contactCollection) as? SMKLegacy._Contact { + if let contact: SMKLegacy._Contact = transaction.object(forKey: sessionId, inCollection: SMKLegacy.contactCollection) as? SMKLegacy._Contact { contact.isApproved = true contact.didApproveMe = true contacts.insert(contact) } } } + + threads.append(thread) } - threads.append(thread) - } - - let userPublicKey: String = getUserHexEncodedPublicKey() - - Storage.read { transaction in - if let user = transaction.object(forKey: userPublicKey, inCollection: Legacy.contactCollection) as? SMKLegacy._Contact { + if let user = transaction.object(forKey: userPublicKey, inCollection: SMKLegacy.contactCollection) as? SMKLegacy._Contact { user.isApproved = true user.didApproveMe = true contacts.insert(user) @@ -60,10 +80,10 @@ public class MessageRequestsMigration : OWSDatabaseMigration { Storage.write(with: { transaction in contacts.forEach { contact in - transaction.setObject(contact, forKey: contact.sessionID, inCollection: Legacy.contactCollection) + transaction.setObject(contact, forKey: contact.sessionID, inCollection: SMKLegacy.contactCollection) } threads.forEach { thread in - thread.save(with: transaction) + transaction.setObject(thread, forKey: thread.uniqueId, inCollection: SMKLegacy.threadCollection) } self.save(with: transaction) // Intentionally capture self }, completion: { diff --git a/SignalUtilitiesKit/Database/Migrations/OpenGroupServerIdLookupMigration.swift b/SignalUtilitiesKit/Database/Migrations/OpenGroupServerIdLookupMigration.swift index 1765e463c..54f7f0e83 100644 --- a/SignalUtilitiesKit/Database/Migrations/OpenGroupServerIdLookupMigration.swift +++ b/SignalUtilitiesKit/Database/Migrations/OpenGroupServerIdLookupMigration.swift @@ -1,6 +1,8 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import Foundation +import YapDatabase +import SessionMessagingKit @objc(SNOpenGroupServerIdLookupMigration) public class OpenGroupServerIdLookupMigration: OWSDatabaseMigration { @@ -16,14 +18,35 @@ public class OpenGroupServerIdLookupMigration: OWSDatabaseMigration { private func doMigrationAsync(completion: @escaping OWSDatabaseMigrationCompletion) { var lookups: [OpenGroupServerIdLookup] = [] + // Note: These will be done in the YDB to GRDB migration but have added it here to be safe + NSKeyedUnarchiver.setClass( + SMKLegacy._Thread.self, + forClassName: "TSThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._ContactThread.self, + forClassName: "TSContactThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._GroupThread.self, + forClassName: "TSGroupThread" + ) + NSKeyedUnarchiver.setClass( + SMKLegacy._GroupModel.self, + forClassName: "TSGroupModel" + ) + // TODO: Add, SMKLegacy._OpenGroup, SMKLegacy._TSMessage (and related) + Storage.write(with: { transaction in - TSGroupThread.enumerateCollectionObjects(with: transaction) { object, _ in - guard let thread: TSGroupThread = object as? TSGroupThread else { return } - guard let threadId: String = thread.uniqueId else { return } - guard let openGroup: OpenGroupV2 = Storage.shared.getV2OpenGroup(for: threadId) else { return } + transaction.enumerateKeysAndObjects(inCollection: SMKLegacy.threadCollection) { _, object, _ in + guard let thread = object as? SMKLegacy._GroupThread else { return } + guard let openGroup: OpenGroupV2 = Storage.shared.getV2OpenGroup(for: thread.uniqueId) else { return } + guard let interactionsByThread: YapDatabaseViewTransaction = transaction.ext(SMKLegacy.messageDatabaseViewExtensionName) as? YapDatabaseViewTransaction else { + return + } - thread.enumerateInteractions(with: transaction) { interaction, _ in - guard let tsMessage: TSMessage = interaction as? TSMessage else { return } + interactionsByThread.enumerateKeysAndObjects(inGroup: thread.uniqueId) { _, _, object, _, _ in + guard let tsMessage: TSMessage = object as? TSMessage else { return } guard let tsMessageId: String = tsMessage.uniqueId else { return } lookups.append( diff --git a/SignalUtilitiesKit/Utilities/ThreadUtil.m b/SignalUtilitiesKit/Utilities/ThreadUtil.m index 34ddf9398..702d16870 100644 --- a/SignalUtilitiesKit/Utilities/ThreadUtil.m +++ b/SignalUtilitiesKit/Utilities/ThreadUtil.m @@ -8,11 +8,9 @@ #import #import #import -#import #import #import #import -#import #import diff --git a/SignalUtilitiesKit/Utilities/VersionMigrations.m b/SignalUtilitiesKit/Utilities/VersionMigrations.m index e0d0787b5..6aca6986b 100644 --- a/SignalUtilitiesKit/Utilities/VersionMigrations.m +++ b/SignalUtilitiesKit/Utilities/VersionMigrations.m @@ -8,8 +8,6 @@ #import #import #import -#import -#import #import #import