Remove YapDatabase.
Apply asset from design. Fix rebase breakage.
This commit is contained in:
parent
7927bc1afe
commit
86b8eb08b8
4
Podfile
4
Podfile
@ -47,10 +47,6 @@ pod 'SQLCipher', ">= 4.0.1"
|
||||
pod 'Mantle', git: 'https://github.com/signalapp/Mantle', branch: 'signal-master'
|
||||
# pod 'Mantle', path: '../Mantle'
|
||||
|
||||
# Forked for compatibily with the ShareExtension, changes have an open PR, but have not been merged.
|
||||
pod 'YapDatabase/SQLCipher', :git => 'https://github.com/signalapp/YapDatabase.git', branch: 'signal-release'
|
||||
# pod 'YapDatabase/SQLCipher', path: '../YapDatabase'
|
||||
|
||||
# Forked to incorporate our self-built binary artifact.
|
||||
pod 'GRKOpenSSLFramework', git: 'https://github.com/signalapp/GRKOpenSSLFramework', branch: 'mkirk/1.0.2t'
|
||||
#pod 'GRKOpenSSLFramework', path: '../GRKOpenSSLFramework'
|
||||
|
||||
76
Podfile.lock
76
Podfile.lock
@ -113,7 +113,6 @@ PODS:
|
||||
- SignalMetadataKit
|
||||
- Starscream
|
||||
- SwiftProtobuf
|
||||
- YapDatabase/SQLCipher
|
||||
- YYImage/WebP
|
||||
- SignalServiceKit/Tests (0.9.0):
|
||||
- AFNetworking/NSURLSession
|
||||
@ -134,7 +133,6 @@ PODS:
|
||||
- SignalMetadataKit
|
||||
- Starscream
|
||||
- SwiftProtobuf
|
||||
- YapDatabase/SQLCipher
|
||||
- YYImage/WebP
|
||||
- SQLCipher (4.3.0):
|
||||
- SQLCipher/standard (= 4.3.0)
|
||||
@ -144,68 +142,6 @@ PODS:
|
||||
- SSZipArchive (2.1.4)
|
||||
- Starscream (3.0.6)
|
||||
- SwiftProtobuf (1.7.0)
|
||||
- YapDatabase/SQLCipher (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Core (3.1.1):
|
||||
- CocoaLumberjack
|
||||
- SQLCipher (>= 3.4.0)
|
||||
- YapDatabase/SQLCipher/Extensions (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/ActionManager (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/AutoView (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/CloudCore (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/CloudKit (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionPool (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/FilteredView (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/Hooks (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/ManualView (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/Relationships (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/RTreeIndex (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/SearchResultsView (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/View (= 3.1.1)
|
||||
- YapDatabase/SQLCipher/Extensions/ActionManager (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/AutoView
|
||||
- YapDatabase/SQLCipher/Extensions/AutoView (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/View
|
||||
- YapDatabase/SQLCipher/Extensions/CloudCore (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/CloudKit (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionPool (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/FilteredView (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/View
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Hooks (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/ManualView (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/View
|
||||
- YapDatabase/SQLCipher/Extensions/Relationships (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/RTreeIndex (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/SearchResultsView (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/AutoView
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch
|
||||
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/View (3.1.1):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YYImage (1.0.4):
|
||||
- YYImage/Core (= 1.0.4)
|
||||
- YYImage/Core (1.0.4)
|
||||
@ -246,7 +182,6 @@ DEPENDENCIES:
|
||||
- SSZipArchive
|
||||
- Starscream (from `https://github.com/signalapp/Starscream.git`, branch `signal-release`)
|
||||
- SwiftProtobuf (= 1.7.0)
|
||||
- YapDatabase/SQLCipher (from `https://github.com/signalapp/YapDatabase.git`, branch `signal-release`)
|
||||
- YYImage (from `https://github.com/signalapp/YYImage`)
|
||||
- ZKGroup (from `https://github.com/signalapp/signal-zkgroup-swift`)
|
||||
- ZKGroup/Tests (from `https://github.com/signalapp/signal-zkgroup-swift`)
|
||||
@ -301,9 +236,6 @@ EXTERNAL SOURCES:
|
||||
Starscream:
|
||||
:branch: signal-release
|
||||
:git: https://github.com/signalapp/Starscream.git
|
||||
YapDatabase:
|
||||
:branch: signal-release
|
||||
:git: https://github.com/signalapp/YapDatabase.git
|
||||
YYImage:
|
||||
:git: https://github.com/signalapp/YYImage
|
||||
ZKGroup:
|
||||
@ -343,9 +275,6 @@ CHECKOUT OPTIONS:
|
||||
Starscream:
|
||||
:commit: b09ea163c3cb305152c65b299cb024610f52e735
|
||||
:git: https://github.com/signalapp/Starscream.git
|
||||
YapDatabase:
|
||||
:commit: e43ab163b2dcb4c817339c819b07dac545f05fea
|
||||
:git: https://github.com/signalapp/YapDatabase.git
|
||||
YYImage:
|
||||
:commit: d91910e6f313a255febbf69795198e74259bd51c
|
||||
:git: https://github.com/signalapp/YYImage
|
||||
@ -377,16 +306,15 @@ SPEC CHECKSUMS:
|
||||
SignalCoreKit: 43daa8f15d6125d54705f35628ac35051bb205c6
|
||||
SignalMetadataKit: eb928ec98376ab5a6ef2108a7fcd3b2d792b8c65
|
||||
SignalRingRTC: 1769d40e1a155a2d6ddd95c404e7822bedd97076
|
||||
SignalServiceKit: b3337d511fc32129c8b8819a9ac2700490ecdd6f
|
||||
SignalServiceKit: 998e9bce294e9e4eb88b13ccd58f7016bb0c8021
|
||||
SQLCipher: d305a7bd9af4b64f095c79bdc1a1fa50f2a15116
|
||||
SSZipArchive: 41455d4b8d2b6ab93990820b50dc697c2554a322
|
||||
Starscream: 8aaf1a7feb805c816d0e7d3190ef23856f6665b9
|
||||
SwiftProtobuf: 4fd9645e69b72cbae6ec8da5be0cdd20ca6565dd
|
||||
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
|
||||
YYImage: 6db68da66f20d9f169ceb94dfb9947c3867b9665
|
||||
ZKGroup: 15a08eed5870a44b9dd14af0824ac95f6eed7380
|
||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||
|
||||
PODFILE CHECKSUM: 8470f6214af1e5e4c437a903764cb001011d8167
|
||||
PODFILE CHECKSUM: 6fcda6d7001d5be6e25668298eb82fe1325dba06
|
||||
|
||||
COCOAPODS: 1.9.2
|
||||
|
||||
@ -1622,14 +1622,12 @@ public extension %(class_name)s {
|
||||
|
||||
swift_body += '''
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return %(class_name)s.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(%(record_name)s.databaseTableName) WHERE \(%(record_identifier)sColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
}
|
||||
}
|
||||
''' % { "class_name": str(clazz.name), "record_name": record_name, "record_identifier": record_identifier(clazz.name) }
|
||||
''' % { "record_name": record_name, "record_identifier": record_identifier(clazz.name) }
|
||||
|
||||
swift_body += '''
|
||||
// Traverses all records.
|
||||
@ -1656,14 +1654,6 @@ public extension %(class_name)s {
|
||||
batchSize: UInt,
|
||||
block: @escaping (%s, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
%s.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? %s else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = %s.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -1680,7 +1670,7 @@ public extension %(class_name)s {
|
||||
}
|
||||
}
|
||||
}
|
||||
''' % ( ( str(clazz.name), ) * 6 )
|
||||
''' % ( ( str(clazz.name), ) * 4 )
|
||||
|
||||
swift_body += '''
|
||||
// Traverses all records' unique ids.
|
||||
@ -1707,10 +1697,6 @@ public extension %(class_name)s {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: %s.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -1721,7 +1707,7 @@ public extension %(class_name)s {
|
||||
block: block)
|
||||
}
|
||||
}
|
||||
''' % ( str(clazz.name), record_identifier(clazz.name), record_name, )
|
||||
''' % ( record_identifier(clazz.name), record_name, )
|
||||
|
||||
swift_body += '''
|
||||
// Does not order the results.
|
||||
@ -1748,13 +1734,11 @@ public extension %(class_name)s {
|
||||
swift_body += '''
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: %s.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return %s.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
}
|
||||
''' % ( str(clazz.name), record_name, )
|
||||
''' % ( record_name, )
|
||||
|
||||
# ---- Remove All ----
|
||||
|
||||
@ -1763,8 +1747,6 @@ public extension %(class_name)s {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: %s.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try %s.deleteAll(grdbTransaction.database)
|
||||
@ -1813,8 +1795,6 @@ public extension %(class_name)s {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: %s.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(%s.databaseTableName) WHERE \(%sColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
@ -1822,7 +1802,7 @@ public extension %(class_name)s {
|
||||
}
|
||||
}
|
||||
}
|
||||
''' % ( str(clazz.name), record_name, str(clazz.name), record_name, record_identifier(clazz.name), )
|
||||
''' % ( record_name, record_name, record_identifier(clazz.name), )
|
||||
|
||||
# ---- Fetch ----
|
||||
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
3405C06E25435048008B24EF /* ConversationViewController+Banners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3405C06D25435048008B24EF /* ConversationViewController+Banners.swift */; };
|
||||
34074F61203D0CBE004596AE /* OWSSounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F5F203D0CBD004596AE /* OWSSounds.m */; };
|
||||
34074F62203D0CBE004596AE /* OWSSounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 34074F60203D0CBE004596AE /* OWSSounds.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34080E4022E9F50200B4D9DA /* YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080E3F22E9F50200B4D9DA /* YDBToGRDBMigration.swift */; };
|
||||
34080EFE2225F96D0087E99F /* ImageEditorPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080EFD2225F96D0087E99F /* ImageEditorPaletteView.swift */; };
|
||||
34080F02222853E30087E99F /* ImageEditorBrushViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080F01222853E30087E99F /* ImageEditorBrushViewController.swift */; };
|
||||
34080F04222858DC0087E99F /* OWSViewController+ImageEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080F03222858DC0087E99F /* OWSViewController+ImageEditor.swift */; };
|
||||
@ -55,9 +54,6 @@
|
||||
340872DA22397FEB00CB25B0 /* AttachmentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340872D922397FEB00CB25B0 /* AttachmentTextView.swift */; };
|
||||
340B06C723C8DA2600929588 /* StorageService+GroupsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340B06C623C8DA2600929588 /* StorageService+GroupsV2.swift */; };
|
||||
340B870E23DF3E3A00BE0AFC /* GroupV2UpdatesImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340B870D23DF3E3A00BE0AFC /* GroupV2UpdatesImpl.swift */; };
|
||||
340CCB6A23032762005243B3 /* YDBLegacyMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 340CCB6823032762005243B3 /* YDBLegacyMigration.m */; };
|
||||
340CCB712305962B005243B3 /* YDBToGRDBMigrationKeyValueTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340CCB6F2305962A005243B3 /* YDBToGRDBMigrationKeyValueTest.swift */; };
|
||||
340CCB722305962B005243B3 /* YDBToGRDBMigrationModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340CCB702305962B005243B3 /* YDBToGRDBMigrationModelTest.swift */; };
|
||||
340D900024FEE6A9007B5504 /* GroupInviteLinksUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340D8FFF24FEE6A9007B5504 /* GroupInviteLinksUI.swift */; };
|
||||
340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */; };
|
||||
340FC8AF204DAC8D007AEB0F /* OWSLinkDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC885204DAC8C007AEB0F /* OWSLinkDeviceViewController.m */; };
|
||||
@ -139,8 +135,6 @@
|
||||
3461293A1FD1B47300532771 /* OWSPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129381FD1B47200532771 /* OWSPreferences.m */; };
|
||||
3461295A1FD1D74C00532771 /* Environment.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129401FD1D74B00532771 /* Environment.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3461295B1FD1D74C00532771 /* Environment.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129411FD1D74B00532771 /* Environment.m */; };
|
||||
346129951FD1E30000532771 /* OWSDatabaseMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129931FD1E30000532771 /* OWSDatabaseMigration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129961FD1E30000532771 /* OWSDatabaseMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129941FD1E30000532771 /* OWSDatabaseMigration.m */; };
|
||||
346129991FD1E4DA00532771 /* SignalApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129971FD1E4D900532771 /* SignalApp.m */; };
|
||||
346129A51FD1F09100532771 /* OWSContactsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129A21FD1F09100532771 /* OWSContactsManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129A31FD1F09100532771 /* OWSContactsManager.m */; };
|
||||
@ -152,21 +146,6 @@
|
||||
346129D61FD20ADC00532771 /* UIViewController+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129D41FD20ADC00532771 /* UIViewController+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129E21FD5C0BE00532771 /* VersionMigrations.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129E01FD5C0BE00532771 /* VersionMigrations.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129E31FD5C0BE00532771 /* VersionMigrations.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129E11FD5C0BE00532771 /* VersionMigrations.m */; };
|
||||
346129E61FD5C0C600532771 /* OWSDatabaseMigrationRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129E41FD5C0C600532771 /* OWSDatabaseMigrationRunner.m */; };
|
||||
346129E71FD5C0C600532771 /* OWSDatabaseMigrationRunner.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129E51FD5C0C600532771 /* OWSDatabaseMigrationRunner.h */; };
|
||||
346129F51FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129E81FD5F31200532771 /* OWS102MoveLoggingPreferenceToUserDefaults.m */; };
|
||||
346129F61FD5F31400532771 /* OWS103EnableVideoCalling.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129E91FD5F31300532771 /* OWS103EnableVideoCalling.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129F71FD5F31400532771 /* OWS105AttachmentFilePaths.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129EA1FD5F31300532771 /* OWS105AttachmentFilePaths.m */; };
|
||||
346129F81FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129EB1FD5F31300532771 /* OWS100RemoveTSRecipientsMigration.m */; };
|
||||
346129F91FD5F31400532771 /* OWS104CreateRecipientIdentities.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129EC1FD5F31300532771 /* OWS104CreateRecipientIdentities.m */; };
|
||||
346129FA1FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129ED1FD5F31300532771 /* OWS100RemoveTSRecipientsMigration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129FB1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129EE1FD5F31300532771 /* OWS101ExistingUsersBlockOnIdentityChange.m */; };
|
||||
346129FC1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129EF1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129FD1FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129F01FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346129FE1FD5F31400532771 /* OWS106EnsureProfileComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346129F11FD5F31400532771 /* OWS106EnsureProfileComplete.swift */; };
|
||||
346129FF1FD5F31400532771 /* OWS103EnableVideoCalling.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129F21FD5F31400532771 /* OWS103EnableVideoCalling.m */; };
|
||||
34612A001FD5F31400532771 /* OWS105AttachmentFilePaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129F31FD5F31400532771 /* OWS105AttachmentFilePaths.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34612A011FD5F31400532771 /* OWS104CreateRecipientIdentities.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129F41FD5F31400532771 /* OWS104CreateRecipientIdentities.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34612A061FD7238600532771 /* OWSSyncManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 34612A041FD7238500532771 /* OWSSyncManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34612A071FD7238600532771 /* OWSSyncManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 34612A051FD7238500532771 /* OWSSyncManager.m */; };
|
||||
34635330256EA52A003C5428 /* ConversationViewTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3463532E256EA525003C5428 /* ConversationViewTest.swift */; };
|
||||
@ -193,7 +172,6 @@
|
||||
346941A3215D2EE400B5BFAD /* Theme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3469419F215D2EE400B5BFAD /* Theme.m */; };
|
||||
346941A4215D2EE400B5BFAD /* OWSConversationColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 346941A0215D2EE400B5BFAD /* OWSConversationColor.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
346B4A772369BFC600B56007 /* PermissiveGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B4A762369BFC600B56007 /* PermissiveGestureRecognizer.swift */; };
|
||||
346B4A79236A138C00B56007 /* OWS116UpdatePrekeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B4A78236A138C00B56007 /* OWS116UpdatePrekeys.swift */; };
|
||||
346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */; };
|
||||
346C19DF25ACDF0B00061D3A /* DataSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346C19DE25ACDF0B00061D3A /* DataSettingsTableViewController.swift */; };
|
||||
346C19E125ACE9AE00061D3A /* MediaDownloadSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346C19E025ACE9AE00061D3A /* MediaDownloadSettingsViewController.swift */; };
|
||||
@ -277,6 +255,7 @@
|
||||
3491D9A121022DB7001EF5A1 /* RemoteAttestationSigningCertificateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3491D9A021022DB7001EF5A1 /* RemoteAttestationSigningCertificateTest.m */; };
|
||||
349439D624360C30001045F7 /* AddGroupMembersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349439D524360C30001045F7 /* AddGroupMembersViewController.swift */; };
|
||||
349439D824360D63001045F7 /* BaseGroupMemberViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349439D724360D63001045F7 /* BaseGroupMemberViewController.swift */; };
|
||||
34955A73260A366600F3789A /* OnboardingDroppedYdbViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34955A72260A366600F3789A /* OnboardingDroppedYdbViewController.swift */; };
|
||||
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496744E2076ACCE00080B5F /* LongTextViewController.swift */; };
|
||||
3496955C219B605E00DCFE74 /* ImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34969559219B605E00DCFE74 /* ImagePickerController.swift */; };
|
||||
3496955D219B605E00DCFE74 /* PhotoCollectionPickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496955A219B605E00DCFE74 /* PhotoCollectionPickerController.swift */; };
|
||||
@ -294,7 +273,6 @@
|
||||
349A5C5425CD7A6C00B30EE8 /* DebugContactsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349A5C5325CD7A6C00B30EE8 /* DebugContactsUtils.swift */; };
|
||||
349BC861253A2651003C949A /* GroupsV2MigrationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349BC860253A2651003C949A /* GroupsV2MigrationTest.swift */; };
|
||||
349C3637233D198300D52012 /* LaunchJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349C3636233D198300D52012 /* LaunchJobs.swift */; };
|
||||
349EA07C2162AEA800F7B17F /* OWS111UDAttributesMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */; };
|
||||
349ED990221B0194008045B0 /* Onboarding2FAViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */; };
|
||||
349ED992221EE80D008045B0 /* AppPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349ED991221EE80D008045B0 /* AppPreferences.swift */; };
|
||||
34A17D81253F7237009F8C02 /* ConversationSettingsViewController+LegacyGroups.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A17D80253F7236009F8C02 /* ConversationSettingsViewController+LegacyGroups.swift */; };
|
||||
@ -302,8 +280,6 @@
|
||||
34A4D56F24E4D342002F8044 /* UnfairLockPerformanceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4D56E24E4D341002F8044 /* UnfairLockPerformanceTest.swift */; };
|
||||
34A6C28021E503E700B5B12E /* OWSImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */; };
|
||||
34A8B3512190A40E00218A25 /* CVMediaAlbumView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A8B3502190A40E00218A25 /* CVMediaAlbumView.swift */; };
|
||||
34ABB2C42090C59700C727A6 /* OWSResaveCollectionDBMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 34ABB2C22090C59600C727A6 /* OWSResaveCollectionDBMigration.m */; };
|
||||
34ABB2C52090C59700C727A6 /* OWSResaveCollectionDBMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 34ABB2C32090C59700C727A6 /* OWSResaveCollectionDBMigration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34AC09DD211B39B100997B47 /* ViewControllerUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 34AC09BF211B39AE00997B47 /* ViewControllerUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34AC09DE211B39B100997B47 /* OWSNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 34AC09C0211B39AE00997B47 /* OWSNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34AC09DF211B39B100997B47 /* OWSNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34AC09C1211B39AF00997B47 /* OWSNavigationController.m */; };
|
||||
@ -353,7 +329,6 @@
|
||||
34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */; };
|
||||
34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B6A902218B3F62007C4606 /* TypingIndicatorView.swift */; };
|
||||
34B6A905218B4C91007C4606 /* TypingIndicatorInteraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B6A904218B4C90007C4606 /* TypingIndicatorInteraction.swift */; };
|
||||
34B6A909218B8824007C4606 /* OWS112TypingIndicatorsMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B6A908218B8824007C4606 /* OWS112TypingIndicatorsMigration.swift */; };
|
||||
34BB3C5D23C6644B001651FC /* GroupsV2Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BB3C5823C6644B001651FC /* GroupsV2Utils.swift */; };
|
||||
34BB3C5E23C6644B001651FC /* GroupsV2OutgoingChangesImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BB3C5923C6644B001651FC /* GroupsV2OutgoingChangesImpl.swift */; };
|
||||
34BB3C5F23C6644B001651FC /* GroupV2SnapshotImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BB3C5A23C6644B001651FC /* GroupV2SnapshotImpl.swift */; };
|
||||
@ -373,7 +348,6 @@
|
||||
34BECE2B1F74C12700D7438D /* DebugUIStress.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2A1F74C12700D7438D /* DebugUIStress.m */; };
|
||||
34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2D1F7ABCE000D7438D /* GifPickerViewController.swift */; };
|
||||
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2F1F7ABCF800D7438D /* GifPickerLayout.swift */; };
|
||||
34BEDB0B21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB0A21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift */; };
|
||||
34BEDB0E21C405B0007B0EAE /* ImageEditorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB0D21C405B0007B0EAE /* ImageEditorModel.swift */; };
|
||||
34BEDB1321C43F6A007B0EAE /* ImageEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB1221C43F69007B0EAE /* ImageEditorView.swift */; };
|
||||
34BEDB1621C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 34BEDB1421C80BC9007B0EAE /* OWSAnyTouchGestureRecognizer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -405,15 +379,12 @@
|
||||
34D2CCE0206939B400CB1A14 /* DebugUIMessagesAssetLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D2CCDC206939B200CB1A14 /* DebugUIMessagesAssetLoader.m */; };
|
||||
34D3E57B245A189D00F5E4A1 /* DebugUIScreenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D3E579245A189D00F5E4A1 /* DebugUIScreenshots.swift */; };
|
||||
34D3E57C245A189D00F5E4A1 /* DebugUIScreenshots.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D3E57A245A189D00F5E4A1 /* DebugUIScreenshots.m */; };
|
||||
34D5872F208E2C4200D2255A /* OWS109OutgoingMessageState.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5872D208E2C4100D2255A /* OWS109OutgoingMessageState.m */; };
|
||||
34D58730208E2C4200D2255A /* OWS109OutgoingMessageState.h in Headers */ = {isa = PBXBuildFile; fileRef = 34D5872E208E2C4100D2255A /* OWS109OutgoingMessageState.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34D5CCA91EAE3D30005515DB /* AvatarViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCA81EAE3D30005515DB /* AvatarViewHelper.m */; };
|
||||
34D8C0271ED3673300188D7C /* DebugUIMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D8C0241ED3673300188D7C /* DebugUIMessages.m */; };
|
||||
34D8C0281ED3673300188D7C /* DebugUITableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D8C0261ED3673300188D7C /* DebugUITableViewController.m */; };
|
||||
34D8C02B1ED3685800188D7C /* DebugUIContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D8C02A1ED3685800188D7C /* DebugUIContacts.m */; };
|
||||
34D99C931F2937CC00D284D6 /* OWSAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */; };
|
||||
34D99CE4217509C2000AFB39 /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D99CE3217509C1000AFB39 /* AppEnvironment.swift */; };
|
||||
34DB0BED2011548B007B313F /* OWSDatabaseConverterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */; };
|
||||
34DC9BD921543E0C00FDDCEC /* DebugContactsUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 34DC9BD721543E0A00FDDCEC /* DebugContactsUtils.m */; };
|
||||
34DE9C02256575300080E4AF /* CVMessageMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34DE9C012565752F0080E4AF /* CVMessageMapping.swift */; };
|
||||
34E0127423FDA960002D0D13 /* DebugUIGroupsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0127323FDA960002D0D13 /* DebugUIGroupsV2.swift */; };
|
||||
@ -432,8 +403,6 @@
|
||||
34FDB29221FF986600A01202 /* UIView+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34FDB29121FF986600A01202 /* UIView+OWS.swift */; };
|
||||
4503F1BE20470A5B00CEE724 /* classic-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 4503F1BB20470A5B00CEE724 /* classic-quiet.aifc */; };
|
||||
4503F1BF20470A5B00CEE724 /* classic.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 4503F1BC20470A5B00CEE724 /* classic.aifc */; };
|
||||
4503F1C3204711D300CEE724 /* OWS107LegacySounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 4503F1C1204711D200CEE724 /* OWS107LegacySounds.m */; };
|
||||
4503F1C4204711D300CEE724 /* OWS107LegacySounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 4503F1C2204711D200CEE724 /* OWS107LegacySounds.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
450998651FD8A34D00D89EB3 /* DeviceSleepManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 348F2EAD1F0D21BC00D4ECE0 /* DeviceSleepManager.swift */; };
|
||||
450998681FD8C0FF00D89EB3 /* AttachmentSharing.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83A1E8DF1700035BE1A /* AttachmentSharing.m */; };
|
||||
450998691FD8C10200D89EB3 /* AttachmentSharing.h in Headers */ = {isa = PBXBuildFile; fileRef = 34B3F8391E8DF1700035BE1A /* AttachmentSharing.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -492,8 +461,6 @@
|
||||
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */; };
|
||||
458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */; };
|
||||
459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 459311FB1D75C948008DD4F0 /* OWSDeviceTableViewCell.m */; };
|
||||
4598198E204E2F28009414F2 /* OWS108CallLoggingPreference.h in Headers */ = {isa = PBXBuildFile; fileRef = 4598198C204E2F28009414F2 /* OWS108CallLoggingPreference.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4598198F204E2F28009414F2 /* OWS108CallLoggingPreference.m in Sources */ = {isa = PBXBuildFile; fileRef = 4598198D204E2F28009414F2 /* OWS108CallLoggingPreference.m */; };
|
||||
459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */; };
|
||||
459B775D207BA4810071D0AB /* OWSQuotedReplyModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
45A2F005204473A3002E978A /* NewMessage.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45A2F004204473A3002E978A /* NewMessage.aifc */; };
|
||||
@ -590,7 +557,6 @@
|
||||
4C38E500230374D700E464B9 /* UIViewController+Permissions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C38E4FE230374D700E464B9 /* UIViewController+Permissions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4C38E501230374D700E464B9 /* UIViewController+Permissions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C38E4FF230374D700E464B9 /* UIViewController+Permissions.m */; };
|
||||
4C3A2BC72356620E004B3986 /* ProvisioningController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3A2BC62356620E004B3986 /* ProvisioningController.swift */; };
|
||||
4C3A556F228C7937000E4935 /* PrivateMethodsForMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C3A556E228C7937000E4935 /* PrivateMethodsForMigration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4C3E245C21F29FCE000AE092 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA5F792211E1F06008C2708 /* Toast.swift */; };
|
||||
4C3E245D21F2B395000AE092 /* DirectionalPanGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4523149F1F7E9E18003A428C /* DirectionalPanGestureRecognizer.swift */; };
|
||||
4C3EF7FD2107DDEE0007EBF7 /* ParamParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EF7FC2107DDEE0007EBF7 /* ParamParserTest.swift */; };
|
||||
@ -612,14 +578,12 @@
|
||||
4C6E6C6924241C00009DE948 /* ConversationViewControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E6C6824241C00009DE948 /* ConversationViewControllerTest.swift */; };
|
||||
4C6F527C20FFE8400097DEEE /* SignalUBSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */; };
|
||||
4C751BE523FA0284002A8AF1 /* ContactSupportAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C751BE423FA0284002A8AF1 /* ContactSupportAlert.swift */; };
|
||||
4C7537892193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7537882193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift */; };
|
||||
4C81DAD5242051C100F4C4D1 /* MessageSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C81DAD4242051C100F4C4D1 /* MessageSelectionView.swift */; };
|
||||
4C83AC4223C55D9C00D4F2E6 /* SignalBaseTest+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C83AC4123C55D9C00D4F2E6 /* SignalBaseTest+Swift.swift */; };
|
||||
4C858A52212DC5E1001B45D3 /* UIImage+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */; };
|
||||
4C8A6DFC22E5499300469AE7 /* MediaZoomAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8A6DFB22E5499300469AE7 /* MediaZoomAnimationController.swift */; };
|
||||
4C8A6DFE22E54AFA00469AE7 /* MediaInteractiveDismiss.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8A6DFD22E54AFA00469AE7 /* MediaInteractiveDismiss.swift */; };
|
||||
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C948FF62146EB4800349F0D /* BlockListCache.swift */; };
|
||||
4C9B4F23225025F100DD5B9A /* OWS1XXGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9B4F22225025F100DD5B9A /* OWS1XXGRDBMigration.swift */; };
|
||||
4C9C50FE22F36FA50054A33F /* OutboundMessage+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9C50FD22F36FA40054A33F /* OutboundMessage+OWS.swift */; };
|
||||
4C9D347B23679C25006A4307 /* GroupAndContactStreamTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9D347923679C13006A4307 /* GroupAndContactStreamTest.swift */; };
|
||||
4C9D347F23689E06006A4307 /* IncomingContactSyncJobQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9D347E23689E06006A4307 /* IncomingContactSyncJobQueue.swift */; };
|
||||
@ -633,9 +597,7 @@
|
||||
4CB5F26720F6E1E2004D1B42 /* MessageActionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF4C0920F55BBA005DA313 /* MessageActionsViewController.swift */; };
|
||||
4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5F26820F7D060004D1B42 /* MessageActions.swift */; };
|
||||
4CB93DC22180FF07004B9764 /* ProximityMonitoringManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB93DC12180FF07004B9764 /* ProximityMonitoringManager.swift */; };
|
||||
4CBBCA6321714B4500EEB37D /* OWS110SortIdMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBBCA6221714B4500EEB37D /* OWS110SortIdMigration.swift */; };
|
||||
4CBBFE4A2306F5D300B37450 /* LogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBBFE492306F5D300B37450 /* LogViewController.swift */; };
|
||||
4CBF6F7B230B03C000549FFC /* OWS115CleanupProfileAvatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBF6F7A230B03C000549FFC /* OWS115CleanupProfileAvatars.swift */; };
|
||||
4CC0B59C20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0B59B20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift */; };
|
||||
4CC1ECF9211A47CE00CC13BE /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC1ECF8211A47CD00CC13BE /* StoreKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC1ECFA211A553000CC13BE /* AppUpdateNag.swift */; };
|
||||
@ -1011,7 +973,6 @@
|
||||
3405C06D25435048008B24EF /* ConversationViewController+Banners.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ConversationViewController+Banners.swift"; sourceTree = "<group>"; };
|
||||
34074F5F203D0CBD004596AE /* OWSSounds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSounds.m; sourceTree = "<group>"; };
|
||||
34074F60203D0CBE004596AE /* OWSSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSounds.h; sourceTree = "<group>"; };
|
||||
34080E3F22E9F50200B4D9DA /* YDBToGRDBMigration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
||||
34080EFD2225F96D0087E99F /* ImageEditorPaletteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorPaletteView.swift; sourceTree = "<group>"; };
|
||||
34080F01222853E30087E99F /* ImageEditorBrushViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorBrushViewController.swift; sourceTree = "<group>"; };
|
||||
34080F03222858DC0087E99F /* OWSViewController+ImageEditor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSViewController+ImageEditor.swift"; sourceTree = "<group>"; };
|
||||
@ -1029,10 +990,6 @@
|
||||
340B02B61F9FD31800F9CFEC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = translations/he.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
340B06C623C8DA2600929588 /* StorageService+GroupsV2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StorageService+GroupsV2.swift"; sourceTree = "<group>"; };
|
||||
340B870D23DF3E3A00BE0AFC /* GroupV2UpdatesImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupV2UpdatesImpl.swift; sourceTree = "<group>"; };
|
||||
340CCB6823032762005243B3 /* YDBLegacyMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YDBLegacyMigration.m; sourceTree = "<group>"; };
|
||||
340CCB6923032762005243B3 /* YDBLegacyMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YDBLegacyMigration.h; sourceTree = "<group>"; };
|
||||
340CCB6F2305962A005243B3 /* YDBToGRDBMigrationKeyValueTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YDBToGRDBMigrationKeyValueTest.swift; sourceTree = "<group>"; };
|
||||
340CCB702305962B005243B3 /* YDBToGRDBMigrationModelTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YDBToGRDBMigrationModelTest.swift; sourceTree = "<group>"; };
|
||||
340D8FFF24FEE6A9007B5504 /* GroupInviteLinksUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupInviteLinksUI.swift; sourceTree = "<group>"; };
|
||||
340E9ABF235F876800FA362C /* ForwardMessageNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForwardMessageNavigationController.swift; sourceTree = "<group>"; };
|
||||
340E9AC3236095CC00FA362C /* AttachmentMultisend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentMultisend.swift; sourceTree = "<group>"; };
|
||||
@ -1140,8 +1097,6 @@
|
||||
346129381FD1B47200532771 /* OWSPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSPreferences.m; sourceTree = "<group>"; };
|
||||
346129401FD1D74B00532771 /* Environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Environment.h; sourceTree = "<group>"; };
|
||||
346129411FD1D74B00532771 /* Environment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Environment.m; sourceTree = "<group>"; };
|
||||
346129931FD1E30000532771 /* OWSDatabaseMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDatabaseMigration.h; sourceTree = "<group>"; };
|
||||
346129941FD1E30000532771 /* OWSDatabaseMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseMigration.m; sourceTree = "<group>"; };
|
||||
346129971FD1E4D900532771 /* SignalApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalApp.m; sourceTree = "<group>"; };
|
||||
346129981FD1E4DA00532771 /* SignalApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalApp.h; sourceTree = "<group>"; };
|
||||
346129A21FD1F09100532771 /* OWSContactsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsManager.h; sourceTree = "<group>"; };
|
||||
@ -1156,21 +1111,6 @@
|
||||
346129D41FD20ADC00532771 /* UIViewController+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+OWS.h"; sourceTree = "<group>"; };
|
||||
346129E01FD5C0BE00532771 /* VersionMigrations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionMigrations.h; sourceTree = "<group>"; };
|
||||
346129E11FD5C0BE00532771 /* VersionMigrations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionMigrations.m; sourceTree = "<group>"; };
|
||||
346129E41FD5C0C600532771 /* OWSDatabaseMigrationRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseMigrationRunner.m; sourceTree = "<group>"; };
|
||||
346129E51FD5C0C600532771 /* OWSDatabaseMigrationRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDatabaseMigrationRunner.h; sourceTree = "<group>"; };
|
||||
346129E81FD5F31200532771 /* OWS102MoveLoggingPreferenceToUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS102MoveLoggingPreferenceToUserDefaults.m; sourceTree = "<group>"; };
|
||||
346129E91FD5F31300532771 /* OWS103EnableVideoCalling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS103EnableVideoCalling.h; sourceTree = "<group>"; };
|
||||
346129EA1FD5F31300532771 /* OWS105AttachmentFilePaths.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS105AttachmentFilePaths.m; sourceTree = "<group>"; };
|
||||
346129EB1FD5F31300532771 /* OWS100RemoveTSRecipientsMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS100RemoveTSRecipientsMigration.m; sourceTree = "<group>"; };
|
||||
346129EC1FD5F31300532771 /* OWS104CreateRecipientIdentities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS104CreateRecipientIdentities.m; sourceTree = "<group>"; };
|
||||
346129ED1FD5F31300532771 /* OWS100RemoveTSRecipientsMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS100RemoveTSRecipientsMigration.h; sourceTree = "<group>"; };
|
||||
346129EE1FD5F31300532771 /* OWS101ExistingUsersBlockOnIdentityChange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS101ExistingUsersBlockOnIdentityChange.m; sourceTree = "<group>"; };
|
||||
346129EF1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS101ExistingUsersBlockOnIdentityChange.h; sourceTree = "<group>"; };
|
||||
346129F01FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS102MoveLoggingPreferenceToUserDefaults.h; sourceTree = "<group>"; };
|
||||
346129F11FD5F31400532771 /* OWS106EnsureProfileComplete.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS106EnsureProfileComplete.swift; sourceTree = "<group>"; };
|
||||
346129F21FD5F31400532771 /* OWS103EnableVideoCalling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS103EnableVideoCalling.m; sourceTree = "<group>"; };
|
||||
346129F31FD5F31400532771 /* OWS105AttachmentFilePaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS105AttachmentFilePaths.h; sourceTree = "<group>"; };
|
||||
346129F41FD5F31400532771 /* OWS104CreateRecipientIdentities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS104CreateRecipientIdentities.h; sourceTree = "<group>"; };
|
||||
34612A041FD7238500532771 /* OWSSyncManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSyncManager.h; sourceTree = "<group>"; };
|
||||
34612A051FD7238500532771 /* OWSSyncManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSyncManager.m; sourceTree = "<group>"; };
|
||||
3463532E256EA525003C5428 /* ConversationViewTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConversationViewTest.swift; sourceTree = "<group>"; };
|
||||
@ -1200,7 +1140,6 @@
|
||||
3469419F215D2EE400B5BFAD /* Theme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Theme.m; sourceTree = "<group>"; };
|
||||
346941A0215D2EE400B5BFAD /* OWSConversationColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationColor.h; sourceTree = "<group>"; };
|
||||
346B4A762369BFC600B56007 /* PermissiveGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PermissiveGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||
346B4A78236A138C00B56007 /* OWS116UpdatePrekeys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS116UpdatePrekeys.swift; sourceTree = "<group>"; };
|
||||
346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropScaleImageViewController.swift; sourceTree = "<group>"; };
|
||||
346C19DE25ACDF0B00061D3A /* DataSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataSettingsTableViewController.swift; sourceTree = "<group>"; };
|
||||
346C19E025ACE9AE00061D3A /* MediaDownloadSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaDownloadSettingsViewController.swift; sourceTree = "<group>"; };
|
||||
@ -1286,6 +1225,7 @@
|
||||
3491D9A021022DB7001EF5A1 /* RemoteAttestationSigningCertificateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteAttestationSigningCertificateTest.m; sourceTree = "<group>"; };
|
||||
349439D524360C30001045F7 /* AddGroupMembersViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddGroupMembersViewController.swift; sourceTree = "<group>"; };
|
||||
349439D724360D63001045F7 /* BaseGroupMemberViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseGroupMemberViewController.swift; sourceTree = "<group>"; };
|
||||
34955A72260A366600F3789A /* OnboardingDroppedYdbViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingDroppedYdbViewController.swift; sourceTree = "<group>"; };
|
||||
3495BC911F1426B800B478F5 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = translations/ar.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
3495FF1325F9A0C900959D6E /* ug */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ug; path = translations/ug.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
3495FF1425F9A0C900959D6E /* ug */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ug; path = translations/ug.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@ -1306,7 +1246,6 @@
|
||||
349A5C5325CD7A6C00B30EE8 /* DebugContactsUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugContactsUtils.swift; sourceTree = "<group>"; };
|
||||
349BC860253A2651003C949A /* GroupsV2MigrationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupsV2MigrationTest.swift; sourceTree = "<group>"; };
|
||||
349C3636233D198300D52012 /* LaunchJobs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LaunchJobs.swift; sourceTree = "<group>"; };
|
||||
349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS111UDAttributesMigration.swift; sourceTree = "<group>"; };
|
||||
349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Onboarding2FAViewController.swift; sourceTree = "<group>"; };
|
||||
349ED991221EE80D008045B0 /* AppPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppPreferences.swift; sourceTree = "<group>"; };
|
||||
34A17D80253F7236009F8C02 /* ConversationSettingsViewController+LegacyGroups.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ConversationSettingsViewController+LegacyGroups.swift"; sourceTree = "<group>"; };
|
||||
@ -1314,8 +1253,6 @@
|
||||
34A4D56E24E4D341002F8044 /* UnfairLockPerformanceTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnfairLockPerformanceTest.swift; sourceTree = "<group>"; };
|
||||
34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSImagePickerController.swift; sourceTree = "<group>"; };
|
||||
34A8B3502190A40E00218A25 /* CVMediaAlbumView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CVMediaAlbumView.swift; sourceTree = "<group>"; };
|
||||
34ABB2C22090C59600C727A6 /* OWSResaveCollectionDBMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSResaveCollectionDBMigration.m; sourceTree = "<group>"; };
|
||||
34ABB2C32090C59700C727A6 /* OWSResaveCollectionDBMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSResaveCollectionDBMigration.h; sourceTree = "<group>"; };
|
||||
34AC09BF211B39AE00997B47 /* ViewControllerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewControllerUtils.h; sourceTree = "<group>"; };
|
||||
34AC09C0211B39AE00997B47 /* OWSNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSNavigationController.h; sourceTree = "<group>"; };
|
||||
34AC09C1211B39AF00997B47 /* OWSNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSNavigationController.m; sourceTree = "<group>"; };
|
||||
@ -1369,7 +1306,6 @@
|
||||
34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InviteFlow.swift; sourceTree = "<group>"; };
|
||||
34B6A902218B3F62007C4606 /* TypingIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = "<group>"; };
|
||||
34B6A904218B4C90007C4606 /* TypingIndicatorInteraction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypingIndicatorInteraction.swift; sourceTree = "<group>"; };
|
||||
34B6A908218B8824007C4606 /* OWS112TypingIndicatorsMigration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS112TypingIndicatorsMigration.swift; sourceTree = "<group>"; };
|
||||
34BB3C5823C6644B001651FC /* GroupsV2Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupsV2Utils.swift; sourceTree = "<group>"; };
|
||||
34BB3C5923C6644B001651FC /* GroupsV2OutgoingChangesImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupsV2OutgoingChangesImpl.swift; sourceTree = "<group>"; };
|
||||
34BB3C5A23C6644B001651FC /* GroupV2SnapshotImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupV2SnapshotImpl.swift; sourceTree = "<group>"; };
|
||||
@ -1390,7 +1326,6 @@
|
||||
34BECE2A1F74C12700D7438D /* DebugUIStress.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIStress.m; sourceTree = "<group>"; };
|
||||
34BECE2D1F7ABCE000D7438D /* GifPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GifPickerViewController.swift; sourceTree = "<group>"; };
|
||||
34BECE2F1F7ABCF800D7438D /* GifPickerLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GifPickerLayout.swift; sourceTree = "<group>"; };
|
||||
34BEDB0A21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS114RemoveDynamicInteractions.swift; sourceTree = "<group>"; };
|
||||
34BEDB0D21C405B0007B0EAE /* ImageEditorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorModel.swift; sourceTree = "<group>"; };
|
||||
34BEDB1221C43F69007B0EAE /* ImageEditorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorView.swift; sourceTree = "<group>"; };
|
||||
34BEDB1421C80BC9007B0EAE /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAnyTouchGestureRecognizer.h; sourceTree = "<group>"; };
|
||||
@ -1431,8 +1366,6 @@
|
||||
34D3E578245A189D00F5E4A1 /* DebugUIScreenshots.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIScreenshots.h; sourceTree = "<group>"; };
|
||||
34D3E579245A189D00F5E4A1 /* DebugUIScreenshots.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugUIScreenshots.swift; sourceTree = "<group>"; };
|
||||
34D3E57A245A189D00F5E4A1 /* DebugUIScreenshots.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIScreenshots.m; sourceTree = "<group>"; };
|
||||
34D5872D208E2C4100D2255A /* OWS109OutgoingMessageState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS109OutgoingMessageState.m; sourceTree = "<group>"; };
|
||||
34D5872E208E2C4100D2255A /* OWS109OutgoingMessageState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS109OutgoingMessageState.h; sourceTree = "<group>"; };
|
||||
34D5CCA71EAE3D30005515DB /* AvatarViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvatarViewHelper.h; sourceTree = "<group>"; };
|
||||
34D5CCA81EAE3D30005515DB /* AvatarViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AvatarViewHelper.m; sourceTree = "<group>"; };
|
||||
34D8C0231ED3673300188D7C /* DebugUIMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIMessages.h; sourceTree = "<group>"; };
|
||||
@ -1444,7 +1377,6 @@
|
||||
34D913491F62D4A500722898 /* SignalAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalAttachment.swift; sourceTree = "<group>"; };
|
||||
34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAnalytics.swift; sourceTree = "<group>"; };
|
||||
34D99CE3217509C1000AFB39 /* AppEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = "<group>"; };
|
||||
34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseConverterTest.m; sourceTree = "<group>"; };
|
||||
34DBF001206BD5A500025978 /* OWSBubbleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBubbleView.m; sourceTree = "<group>"; };
|
||||
34DBF002206BD5A500025978 /* OWSBubbleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBubbleView.h; sourceTree = "<group>"; };
|
||||
34DBF005206C3CB100025978 /* OWSBubbleShapeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBubbleShapeView.h; sourceTree = "<group>"; };
|
||||
@ -1477,8 +1409,6 @@
|
||||
435EAC2E5E22D3F087EB3192 /* Pods-SignalShareExtension.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.app store release.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.app store release.xcconfig"; sourceTree = "<group>"; };
|
||||
4503F1BB20470A5B00CEE724 /* classic-quiet.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; path = "classic-quiet.aifc"; sourceTree = "<group>"; };
|
||||
4503F1BC20470A5B00CEE724 /* classic.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; path = classic.aifc; sourceTree = "<group>"; };
|
||||
4503F1C1204711D200CEE724 /* OWS107LegacySounds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS107LegacySounds.m; sourceTree = "<group>"; };
|
||||
4503F1C2204711D200CEE724 /* OWS107LegacySounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS107LegacySounds.h; sourceTree = "<group>"; };
|
||||
4509E7991DD653700025A59F /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = ThirdParty/WebRTC/Build/WebRTC.framework; sourceTree = "<group>"; };
|
||||
450D19111F85236600970622 /* RemoteVideoView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteVideoView.h; sourceTree = "<group>"; };
|
||||
450D19121F85236600970622 /* RemoteVideoView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RemoteVideoView.m; sourceTree = "<group>"; };
|
||||
@ -1537,8 +1467,6 @@
|
||||
459311FB1D75C948008DD4F0 /* OWSDeviceTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDeviceTableViewCell.m; sourceTree = "<group>"; };
|
||||
4597E94E1D8313C100040CDE /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = translations/sq.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
4597E94F1D8313CB00040CDE /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = translations/bg.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
4598198C204E2F28009414F2 /* OWS108CallLoggingPreference.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OWS108CallLoggingPreference.h; sourceTree = "<group>"; };
|
||||
4598198D204E2F28009414F2 /* OWS108CallLoggingPreference.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OWS108CallLoggingPreference.m; sourceTree = "<group>"; };
|
||||
459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OWSQuotedReplyModel.h; sourceTree = "<group>"; };
|
||||
459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OWSQuotedReplyModel.m; sourceTree = "<group>"; };
|
||||
45A2F004204473A3002E978A /* NewMessage.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; name = NewMessage.aifc; path = Signal/AudioFiles/NewMessage.aifc; sourceTree = SOURCE_ROOT; };
|
||||
@ -1625,7 +1553,6 @@
|
||||
4C38E4FE230374D700E464B9 /* UIViewController+Permissions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Permissions.h"; sourceTree = "<group>"; };
|
||||
4C38E4FF230374D700E464B9 /* UIViewController+Permissions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Permissions.m"; sourceTree = "<group>"; };
|
||||
4C3A2BC62356620E004B3986 /* ProvisioningController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProvisioningController.swift; sourceTree = "<group>"; };
|
||||
4C3A556E228C7937000E4935 /* PrivateMethodsForMigration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrivateMethodsForMigration.h; sourceTree = "<group>"; };
|
||||
4C3EF7FC2107DDEE0007EBF7 /* ParamParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParamParserTest.swift; sourceTree = "<group>"; };
|
||||
4C3EF801210918740007EBF7 /* SSKProtoEnvelopeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKProtoEnvelopeTest.swift; sourceTree = "<group>"; };
|
||||
4C42960D2318E5EB00D9D240 /* MessageProcessingPerformanceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageProcessingPerformanceTest.swift; sourceTree = "<group>"; };
|
||||
@ -1649,14 +1576,12 @@
|
||||
4C6E6C6824241C00009DE948 /* ConversationViewControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationViewControllerTest.swift; sourceTree = "<group>"; };
|
||||
4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalUBSan.supp; sourceTree = "<group>"; };
|
||||
4C751BE423FA0284002A8AF1 /* ContactSupportAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactSupportAlert.swift; sourceTree = "<group>"; };
|
||||
4C7537882193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWS113MultiAttachmentMediaMessages.swift; sourceTree = "<group>"; };
|
||||
4C81DAD4242051C100F4C4D1 /* MessageSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSelectionView.swift; sourceTree = "<group>"; };
|
||||
4C83AC4123C55D9C00D4F2E6 /* SignalBaseTest+Swift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SignalBaseTest+Swift.swift"; sourceTree = "<group>"; };
|
||||
4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+OWS.swift"; sourceTree = "<group>"; };
|
||||
4C8A6DFB22E5499300469AE7 /* MediaZoomAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaZoomAnimationController.swift; sourceTree = "<group>"; };
|
||||
4C8A6DFD22E54AFA00469AE7 /* MediaInteractiveDismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaInteractiveDismiss.swift; sourceTree = "<group>"; };
|
||||
4C948FF62146EB4800349F0D /* BlockListCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListCache.swift; sourceTree = "<group>"; };
|
||||
4C9B4F22225025F100DD5B9A /* OWS1XXGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWS1XXGRDBMigration.swift; sourceTree = "<group>"; };
|
||||
4C9C50FD22F36FA40054A33F /* OutboundMessage+OWS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OutboundMessage+OWS.swift"; sourceTree = "<group>"; };
|
||||
4C9C50FF22F495F60054A33F /* BroadcastMediaMessageJob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BroadcastMediaMessageJob.swift; sourceTree = "<group>"; };
|
||||
4C9CA25C217E676900607C63 /* ZXingObjC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ZXingObjC.framework; path = ThirdParty/Carthage/Build/iOS/ZXingObjC.framework; sourceTree = "<group>"; };
|
||||
@ -1672,9 +1597,7 @@
|
||||
4CA5F792211E1F06008C2708 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = "<group>"; };
|
||||
4CB5F26820F7D060004D1B42 /* MessageActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActions.swift; sourceTree = "<group>"; };
|
||||
4CB93DC12180FF07004B9764 /* ProximityMonitoringManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProximityMonitoringManager.swift; sourceTree = "<group>"; };
|
||||
4CBBCA6221714B4500EEB37D /* OWS110SortIdMigration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS110SortIdMigration.swift; sourceTree = "<group>"; };
|
||||
4CBBFE492306F5D300B37450 /* LogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewController.swift; sourceTree = "<group>"; };
|
||||
4CBF6F7A230B03C000549FFC /* OWS115CleanupProfileAvatars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWS115CleanupProfileAvatars.swift; sourceTree = "<group>"; };
|
||||
4CC0B59B20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationConfigurationSyncOperation.swift; sourceTree = "<group>"; };
|
||||
4CC1ECF8211A47CD00CC13BE /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||
4CC1ECFA211A553000CC13BE /* AppUpdateNag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdateNag.swift; sourceTree = "<group>"; };
|
||||
@ -2238,6 +2161,7 @@
|
||||
3448E1612213585C004B052E /* OnboardingBaseViewController.swift */,
|
||||
3448E1652215B313004B052E /* OnboardingCaptchaViewController.swift */,
|
||||
3448E15D221333F5004B052E /* OnboardingController.swift */,
|
||||
34955A72260A366600F3789A /* OnboardingDroppedYdbViewController.swift */,
|
||||
88EAD79123764F09004B797E /* OnboardingModeSwitchConfirmationViewController.swift */,
|
||||
3448E15B22133274004B052E /* OnboardingPermissionsViewController.swift */,
|
||||
88D1BCBD24F75226009A1738 /* OnboardingPhoneNumberDiscoverabilityViewController.swift */,
|
||||
@ -2468,7 +2392,6 @@
|
||||
346129411FD1D74B00532771 /* Environment.m */,
|
||||
349C3636233D198300D52012 /* LaunchJobs.swift */,
|
||||
4C35B08823F8A9A1003EB937 /* MessageRequestReadReceipts.swift */,
|
||||
346129921FD1E30000532771 /* migrations */,
|
||||
347850671FD9B78A007B8332 /* NoopCallMessageHandler.swift */,
|
||||
45F170AB1E2F0351003FC1F2 /* OWSAudioSession.swift */,
|
||||
34074F60203D0CBE004596AE /* OWSSounds.h */,
|
||||
@ -2479,48 +2402,6 @@
|
||||
path = environment;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
346129921FD1E30000532771 /* migrations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4C9B4F22225025F100DD5B9A /* OWS1XXGRDBMigration.swift */,
|
||||
346129ED1FD5F31300532771 /* OWS100RemoveTSRecipientsMigration.h */,
|
||||
346129EB1FD5F31300532771 /* OWS100RemoveTSRecipientsMigration.m */,
|
||||
346129EF1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.h */,
|
||||
346129EE1FD5F31300532771 /* OWS101ExistingUsersBlockOnIdentityChange.m */,
|
||||
346129F01FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.h */,
|
||||
346129E81FD5F31200532771 /* OWS102MoveLoggingPreferenceToUserDefaults.m */,
|
||||
346129E91FD5F31300532771 /* OWS103EnableVideoCalling.h */,
|
||||
346129F21FD5F31400532771 /* OWS103EnableVideoCalling.m */,
|
||||
346129F41FD5F31400532771 /* OWS104CreateRecipientIdentities.h */,
|
||||
346129EC1FD5F31300532771 /* OWS104CreateRecipientIdentities.m */,
|
||||
346129F31FD5F31400532771 /* OWS105AttachmentFilePaths.h */,
|
||||
346129EA1FD5F31300532771 /* OWS105AttachmentFilePaths.m */,
|
||||
346129F11FD5F31400532771 /* OWS106EnsureProfileComplete.swift */,
|
||||
4503F1C2204711D200CEE724 /* OWS107LegacySounds.h */,
|
||||
4503F1C1204711D200CEE724 /* OWS107LegacySounds.m */,
|
||||
4598198C204E2F28009414F2 /* OWS108CallLoggingPreference.h */,
|
||||
4598198D204E2F28009414F2 /* OWS108CallLoggingPreference.m */,
|
||||
34D5872E208E2C4100D2255A /* OWS109OutgoingMessageState.h */,
|
||||
34D5872D208E2C4100D2255A /* OWS109OutgoingMessageState.m */,
|
||||
4CBBCA6221714B4500EEB37D /* OWS110SortIdMigration.swift */,
|
||||
349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */,
|
||||
34B6A908218B8824007C4606 /* OWS112TypingIndicatorsMigration.swift */,
|
||||
4C7537882193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift */,
|
||||
34BEDB0A21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift */,
|
||||
4CBF6F7A230B03C000549FFC /* OWS115CleanupProfileAvatars.swift */,
|
||||
346B4A78236A138C00B56007 /* OWS116UpdatePrekeys.swift */,
|
||||
346129931FD1E30000532771 /* OWSDatabaseMigration.h */,
|
||||
346129941FD1E30000532771 /* OWSDatabaseMigration.m */,
|
||||
346129E51FD5C0C600532771 /* OWSDatabaseMigrationRunner.h */,
|
||||
346129E41FD5C0C600532771 /* OWSDatabaseMigrationRunner.m */,
|
||||
34ABB2C32090C59700C727A6 /* OWSResaveCollectionDBMigration.h */,
|
||||
34ABB2C22090C59600C727A6 /* OWSResaveCollectionDBMigration.m */,
|
||||
4C3A556E228C7937000E4935 /* PrivateMethodsForMigration.h */,
|
||||
34080E3F22E9F50200B4D9DA /* YDBToGRDBMigration.swift */,
|
||||
);
|
||||
path = migrations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
346129A11FD1F09100532771 /* contacts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3296,8 +3177,6 @@
|
||||
4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */,
|
||||
FCFA64B11A24F29E0007FB87 /* UI Categories */,
|
||||
8811CF832295D8DA00FF6549 /* VolumeButtons.swift */,
|
||||
340CCB6923032762005243B3 /* YDBLegacyMigration.h */,
|
||||
340CCB6823032762005243B3 /* YDBLegacyMigration.m */,
|
||||
);
|
||||
path = util;
|
||||
sourceTree = "<group>";
|
||||
@ -3832,7 +3711,6 @@
|
||||
345AE2B52317048200DB6225 /* GRDBFinderTest.swift */,
|
||||
4C9D347923679C13006A4307 /* GroupAndContactStreamTest.swift */,
|
||||
455AC69D1F4F8B0300134004 /* ImageCacheTest.swift */,
|
||||
34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */,
|
||||
34843B25214327C9004DED45 /* OWSOrphanDataCleanerTest.m */,
|
||||
45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */,
|
||||
34E8A8D02085238900B272B1 /* ProtoParsingTest.m */,
|
||||
@ -3840,8 +3718,6 @@
|
||||
452D1AF02081059C00A67F7F /* StringAdditionsTest.swift */,
|
||||
B660F6B31C29868000687D6E /* UtilTest.h */,
|
||||
B660F6B41C29868000687D6E /* UtilTest.m */,
|
||||
340CCB6F2305962A005243B3 /* YDBToGRDBMigrationKeyValueTest.swift */,
|
||||
340CCB702305962B005243B3 /* YDBToGRDBMigrationModelTest.swift */,
|
||||
);
|
||||
path = util;
|
||||
sourceTree = "<group>";
|
||||
@ -3980,21 +3856,14 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
346129E71FD5C0C600532771 /* OWSDatabaseMigrationRunner.h in Headers */,
|
||||
3464451222B7F97100A957B1 /* DateUtil.h in Headers */,
|
||||
3464450E22B7F93600A957B1 /* OWSOrphanDataCleaner.h in Headers */,
|
||||
34AC09F9211B39B100997B47 /* CountryCodeViewController.h in Headers */,
|
||||
34ABB2C52090C59700C727A6 /* OWSResaveCollectionDBMigration.h in Headers */,
|
||||
8860CC1C25084BD400A4D18E /* OWSBubbleView.h in Headers */,
|
||||
459B775D207BA4810071D0AB /* OWSQuotedReplyModel.h in Headers */,
|
||||
34612A001FD5F31400532771 /* OWS105AttachmentFilePaths.h in Headers */,
|
||||
346129F61FD5F31400532771 /* OWS103EnableVideoCalling.h in Headers */,
|
||||
4C3A556F228C7937000E4935 /* PrivateMethodsForMigration.h in Headers */,
|
||||
34480B551FD0A7A400BC14EF /* DebugLogger.h in Headers */,
|
||||
4503F1C4204711D300CEE724 /* OWS107LegacySounds.h in Headers */,
|
||||
34AC0A20211B39EA00997B47 /* ThreadViewHelper.h in Headers */,
|
||||
34AC09DE211B39B100997B47 /* OWSNavigationController.h in Headers */,
|
||||
34612A011FD5F31400532771 /* OWS104CreateRecipientIdentities.h in Headers */,
|
||||
450998691FD8C10200D89EB3 /* AttachmentSharing.h in Headers */,
|
||||
34BEDB1621C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.h in Headers */,
|
||||
34AC09EC211B39B100997B47 /* OWSTableViewController.h in Headers */,
|
||||
@ -4003,24 +3872,19 @@
|
||||
3426A36E255EB9F50036407F /* CVItemViewModel.h in Headers */,
|
||||
34612A061FD7238600532771 /* OWSSyncManager.h in Headers */,
|
||||
34480B571FD0A7A400BC14EF /* OWSScrubbingLogFormatter.h in Headers */,
|
||||
346129FC1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.h in Headers */,
|
||||
34AC09F2211B39B100997B47 /* OWSViewController.h in Headers */,
|
||||
4C38E500230374D700E464B9 /* UIViewController+Permissions.h in Headers */,
|
||||
451F8A491FD715CF005CB9DA /* OWSAvatarBuilder.h in Headers */,
|
||||
346129951FD1E30000532771 /* OWSDatabaseMigration.h in Headers */,
|
||||
34AC09E4211B39B100997B47 /* ScreenLockViewController.h in Headers */,
|
||||
346129B41FD1F7E800532771 /* OWSProfileManager.h in Headers */,
|
||||
342950892124CB0A0000B063 /* OWSSearchBar.h in Headers */,
|
||||
346941A1215D2EE400B5BFAD /* Theme.h in Headers */,
|
||||
346129FA1FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.h in Headers */,
|
||||
346129E21FD5C0BE00532771 /* VersionMigrations.h in Headers */,
|
||||
453518961FC63DBF00210559 /* SignalMessaging.h in Headers */,
|
||||
346941A4215D2EE400B5BFAD /* OWSConversationColor.h in Headers */,
|
||||
3461295A1FD1D74C00532771 /* Environment.h in Headers */,
|
||||
450C801020AD1AE400F3A091 /* OWSWindowManager.h in Headers */,
|
||||
34D58730208E2C4200D2255A /* OWS109OutgoingMessageState.h in Headers */,
|
||||
8860CC1D25084BE700A4D18E /* OWSBubbleShapeView.h in Headers */,
|
||||
4598198E204E2F28009414F2 /* OWS108CallLoggingPreference.h in Headers */,
|
||||
34AC0A0F211B39EA00997B47 /* ContactTableViewCell.h in Headers */,
|
||||
34480B631FD0A98800BC14EF /* UIView+OWS.h in Headers */,
|
||||
451F8A4B1FD715E1005CB9DA /* OWSGroupAvatarBuilder.h in Headers */,
|
||||
@ -4039,7 +3903,6 @@
|
||||
34480B681FD0AA9400BC14EF /* UIFont+OWS.h in Headers */,
|
||||
342950852124C9750000B063 /* OWSTextField.h in Headers */,
|
||||
45194F901FD7200000333B2C /* ThreadUtil.h in Headers */,
|
||||
346129FD1FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.h in Headers */,
|
||||
34074F62203D0CBE004596AE /* OWSSounds.h in Headers */,
|
||||
34AC0A1D211B39EA00997B47 /* ContactCellView.h in Headers */,
|
||||
);
|
||||
@ -4610,7 +4473,6 @@
|
||||
"${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/ZKGroup/ZKGroup.framework",
|
||||
"${PODS_ROOT}/ZXingObjC/ZXingObjC.framework",
|
||||
"${PODS_ROOT}/ZXingObjC/ZXingObjC.framework.dSYM",
|
||||
@ -4644,7 +4506,6 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZKGroup.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZXingObjC.framework",
|
||||
"${DWARF_DSYM_FOLDER_PATH}/ZXingObjC.framework.dSYM",
|
||||
@ -4706,7 +4567,6 @@
|
||||
"${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/ZKGroup/ZKGroup.framework",
|
||||
"${PODS_ROOT}/ZXingObjC/ZXingObjC.framework",
|
||||
"${PODS_ROOT}/ZXingObjC/ZXingObjC.framework.dSYM",
|
||||
@ -4737,7 +4597,6 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZKGroup.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZXingObjC.framework",
|
||||
"${DWARF_DSYM_FOLDER_PATH}/ZXingObjC.framework.dSYM",
|
||||
@ -4796,7 +4655,6 @@
|
||||
"${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/ZKGroup/ZKGroup.framework",
|
||||
"${PODS_ROOT}/ZXingObjC/ZXingObjC.framework",
|
||||
"${PODS_ROOT}/ZXingObjC/ZXingObjC.framework.dSYM",
|
||||
@ -4827,7 +4685,6 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZKGroup.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZXingObjC.framework",
|
||||
"${DWARF_DSYM_FOLDER_PATH}/ZXingObjC.framework.dSYM",
|
||||
@ -4920,11 +4777,8 @@
|
||||
4C9D347F23689E06006A4307 /* IncomingContactSyncJobQueue.swift in Sources */,
|
||||
4C35B08A23F8A9D2003EB937 /* MessageRequestReadReceipts.swift in Sources */,
|
||||
34BEDB1321C43F6A007B0EAE /* ImageEditorView.swift in Sources */,
|
||||
346B4A79236A138C00B56007 /* OWS116UpdatePrekeys.swift in Sources */,
|
||||
34AC09EE211B39B100997B47 /* EditContactShareNameViewController.swift in Sources */,
|
||||
346129F71FD5F31400532771 /* OWS105AttachmentFilePaths.m in Sources */,
|
||||
450998681FD8C0FF00D89EB3 /* AttachmentSharing.m in Sources */,
|
||||
346129F81FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.m in Sources */,
|
||||
34AC09DF211B39B100997B47 /* OWSNavigationController.m in Sources */,
|
||||
34074F61203D0CBE004596AE /* OWSSounds.m in Sources */,
|
||||
34C2EEB02270B8E200BCA1D0 /* StickerKeyboard.swift in Sources */,
|
||||
@ -4933,14 +4787,12 @@
|
||||
34BEDB1721C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.m in Sources */,
|
||||
340872C92239563500CB25B0 /* AttachmentItemCollection.swift in Sources */,
|
||||
34080EFE2225F96D0087E99F /* ImageEditorPaletteView.swift in Sources */,
|
||||
34B6A909218B8824007C4606 /* OWS112TypingIndicatorsMigration.swift in Sources */,
|
||||
4C6E446922AEDDEE007982E6 /* NewAccountDiscovery.swift in Sources */,
|
||||
4C3E245D21F2B395000AE092 /* DirectionalPanGestureRecognizer.swift in Sources */,
|
||||
3426A375256321190036407F /* OWSMessageTextView.m in Sources */,
|
||||
8835DE08230E092F00DC6B66 /* FindByPhoneNumberViewController.swift in Sources */,
|
||||
346129B51FD1F7E800532771 /* OWSProfileManager.m in Sources */,
|
||||
8851DB4124CCE9E5001EACD2 /* Mention.swift in Sources */,
|
||||
4CBBCA6321714B4500EEB37D /* OWS110SortIdMigration.swift in Sources */,
|
||||
342950832124C9750000B063 /* OWSTextView.m in Sources */,
|
||||
34BBC85D220D19D600857249 /* ImageEditorPanGestureRecognizer.swift in Sources */,
|
||||
348C686D246B0B110039705A /* ThreadUtil.swift in Sources */,
|
||||
@ -4967,7 +4819,6 @@
|
||||
4C858A52212DC5E1001B45D3 /* UIImage+OWS.swift in Sources */,
|
||||
34480B671FD0AA9400BC14EF /* UIFont+OWS.m in Sources */,
|
||||
4C0387532339B3220062D293 /* UIColor+OWS.swift in Sources */,
|
||||
346129E61FD5C0C600532771 /* OWSDatabaseMigrationRunner.m in Sources */,
|
||||
88D5887824846A7F00DC9AB6 /* InputAccessoryViewPlaceholder.swift in Sources */,
|
||||
88D23D0B23CEBF4400B0E74B /* UserNotificationsAdaptee.swift in Sources */,
|
||||
886BB3D825BA871B00079781 /* Wallpaper+SolidColor.swift in Sources */,
|
||||
@ -4979,14 +4830,11 @@
|
||||
34AC09E2211B39B100997B47 /* ReturnToCallViewController.swift in Sources */,
|
||||
345DE96023ED9AA500A8E6E3 /* GroupsV2ProfileKeyUpdater.swift in Sources */,
|
||||
885091C02525650100428A37 /* PHPhotoLibrary+Xcode11.swift in Sources */,
|
||||
34080E4022E9F50200B4D9DA /* YDBToGRDBMigration.swift in Sources */,
|
||||
34123C60239AA93B00782788 /* ViewOnceTooltip.swift in Sources */,
|
||||
34AC0A12211B39EA00997B47 /* ContactTableViewCell.m in Sources */,
|
||||
451F8A461FD715BA005CB9DA /* OWSGroupAvatarBuilder.m in Sources */,
|
||||
34C2EEB42270D1CE00BCA1D0 /* StickerView.swift in Sources */,
|
||||
346129961FD1E30000532771 /* OWSDatabaseMigration.m in Sources */,
|
||||
341CBFC42405B7C000F15C13 /* GroupsV2Impl+RestoreGroups.swift in Sources */,
|
||||
346129FB1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.m in Sources */,
|
||||
34AC09EA211B39B100997B47 /* ModalActivityIndicatorViewController.swift in Sources */,
|
||||
88BAE55F24875A24001F00F9 /* ImageEditorBlurRegionsItem.swift in Sources */,
|
||||
344F248D2007CCD600CFB4F4 /* DisplayableText.swift in Sources */,
|
||||
@ -4995,12 +4843,10 @@
|
||||
34AC0A1F211B39EA00997B47 /* AvatarImageView.swift in Sources */,
|
||||
3466087220E550F400AFFE73 /* ConversationStyle.swift in Sources */,
|
||||
3478506B1FD9B78A007B8332 /* NoopCallMessageHandler.swift in Sources */,
|
||||
4C9B4F23225025F100DD5B9A /* OWS1XXGRDBMigration.swift in Sources */,
|
||||
340872CA2239563500CB25B0 /* AttachmentApprovalViewController.swift in Sources */,
|
||||
346129AD1FD1F34E00532771 /* ImageCache.swift in Sources */,
|
||||
3465948424352FE900E5C510 /* OWSTableViewController.swift in Sources */,
|
||||
88EFF4F525AD1ACB000FAFBA /* ConversationItem.swift in Sources */,
|
||||
34D5872F208E2C4200D2255A /* OWS109OutgoingMessageState.m in Sources */,
|
||||
340B870E23DF3E3A00BE0AFC /* GroupV2UpdatesImpl.swift in Sources */,
|
||||
340872D02239787F00CB25B0 /* AttachmentTextToolbar.swift in Sources */,
|
||||
3470249C238367EA0078D72C /* TextApprovalViewController.swift in Sources */,
|
||||
@ -5009,14 +4855,11 @@
|
||||
34AC09F8211B39B100997B47 /* CountryCodeViewController.m in Sources */,
|
||||
451F8A341FD710C3005CB9DA /* FullTextSearcher.swift in Sources */,
|
||||
34080F04222858DC0087E99F /* OWSViewController+ImageEditor.swift in Sources */,
|
||||
346129FE1FD5F31400532771 /* OWS106EnsureProfileComplete.swift in Sources */,
|
||||
34AC0A10211B39EA00997B47 /* TappableView.swift in Sources */,
|
||||
3426A372256320420036407F /* CVText.swift in Sources */,
|
||||
346129F91FD5F31400532771 /* OWS104CreateRecipientIdentities.m in Sources */,
|
||||
34C2EEAC2270A69400BCA1D0 /* CircleView.swift in Sources */,
|
||||
34AC09E9211B39B100997B47 /* OWSTableViewController.m in Sources */,
|
||||
340872CE2239596100CB25B0 /* AttachmentApprovalToolbar.swift in Sources */,
|
||||
346129F51FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.m in Sources */,
|
||||
45194F8F1FD71FF500333B2C /* ThreadUtil.m in Sources */,
|
||||
340B06C723C8DA2600929588 /* StorageService+GroupsV2.swift in Sources */,
|
||||
34BEDB0E21C405B0007B0EAE /* ImageEditorModel.swift in Sources */,
|
||||
@ -5028,7 +4871,6 @@
|
||||
45BC829D1FD9C4B400011CF3 /* ShareViewDelegate.swift in Sources */,
|
||||
3461295B1FD1D74C00532771 /* Environment.m in Sources */,
|
||||
3426A378256321C50036407F /* CVUtils.swift in Sources */,
|
||||
4CBF6F7B230B03C000549FFC /* OWS115CleanupProfileAvatars.swift in Sources */,
|
||||
346129D51FD20ADC00532771 /* UIViewController+OWS.m in Sources */,
|
||||
34BB3C5D23C6644B001651FC /* GroupsV2Utils.swift in Sources */,
|
||||
8860CC212508507F00A4D18E /* GroupLinkPreview.swift in Sources */,
|
||||
@ -5049,14 +4891,11 @@
|
||||
34080F02222853E30087E99F /* ImageEditorBrushViewController.swift in Sources */,
|
||||
34AC0A14211B39EA00997B47 /* ContactCellView.m in Sources */,
|
||||
34AC0A15211B39EA00997B47 /* ContactsViewHelper.m in Sources */,
|
||||
346129FF1FD5F31400532771 /* OWS103EnableVideoCalling.m in Sources */,
|
||||
346129E31FD5C0BE00532771 /* VersionMigrations.m in Sources */,
|
||||
4C7537892193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift in Sources */,
|
||||
340872CB2239563500CB25B0 /* AttachmentPrepViewController.swift in Sources */,
|
||||
88E34F2922F26CC100966CC2 /* StorageServiceProto+Sync.swift in Sources */,
|
||||
3476236224081F8900D4FB6F /* GroupManager+SignalMessaging.swift in Sources */,
|
||||
34AC0A16211B39EA00997B47 /* OWSNavigationBar.swift in Sources */,
|
||||
34BEDB0B21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift in Sources */,
|
||||
34AC0A1A211B39EA00997B47 /* CommonStrings.swift in Sources */,
|
||||
34AC0A19211B39EA00997B47 /* OWSActionSheets.swift in Sources */,
|
||||
340872DA22397FEB00CB25B0 /* AttachmentTextView.swift in Sources */,
|
||||
@ -5066,7 +4905,6 @@
|
||||
34BBC859220C7ADA00857249 /* ImageEditorStrokeItem.swift in Sources */,
|
||||
451F8A351FD710DE005CB9DA /* Searcher.swift in Sources */,
|
||||
451F8A481FD715BA005CB9DA /* OWSContactAvatarBuilder.m in Sources */,
|
||||
4503F1C3204711D300CEE724 /* OWS107LegacySounds.m in Sources */,
|
||||
3464450D22B7F93600A957B1 /* OWSOrphanDataCleaner.m in Sources */,
|
||||
34FB6A5725D4127A00E599B1 /* OWSTableViewController2.swift in Sources */,
|
||||
34AC0A18211B39EA00997B47 /* TappableStackView.swift in Sources */,
|
||||
@ -5077,7 +4915,6 @@
|
||||
8809CE8122F534B200D38867 /* CustomKeyboard.swift in Sources */,
|
||||
4541B71D209D3B7A0008608F /* ContactShareViewModel.swift in Sources */,
|
||||
4C618199219DF03A009BD6B5 /* OWSButton.swift in Sources */,
|
||||
4598198F204E2F28009414F2 /* OWS108CallLoggingPreference.m in Sources */,
|
||||
4C3E245C21F29FCE000AE092 /* Toast.swift in Sources */,
|
||||
3456A73223D63EBE00947219 /* GroupsV2Protos.swift in Sources */,
|
||||
34BBC84B220B2CB200857249 /* ImageEditorTextViewController.swift in Sources */,
|
||||
@ -5102,7 +4939,6 @@
|
||||
88F67A0C24E5126D00435A71 /* HapticFeedback.swift in Sources */,
|
||||
347191F923F457BD003A3106 /* GroupsV2AvatarDownloadOperation.swift in Sources */,
|
||||
34641E182088D7E900E2EDE5 /* OWSScreenLock.swift in Sources */,
|
||||
349EA07C2162AEA800F7B17F /* OWS111UDAttributesMigration.swift in Sources */,
|
||||
34BB3C5E23C6644B001651FC /* GroupsV2OutgoingChangesImpl.swift in Sources */,
|
||||
8821334E2304E72700353626 /* NonContactTableViewCell.swift in Sources */,
|
||||
34480B561FD0A7A400BC14EF /* DebugLogger.m in Sources */,
|
||||
@ -5110,7 +4946,6 @@
|
||||
459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */,
|
||||
340872D622397E6800CB25B0 /* AttachmentCaptionToolbar.swift in Sources */,
|
||||
3464451122B7F97100A957B1 /* DateUtil.m in Sources */,
|
||||
34ABB2C42090C59700C727A6 /* OWSResaveCollectionDBMigration.m in Sources */,
|
||||
4C38E501230374D700E464B9 /* UIViewController+Permissions.m in Sources */,
|
||||
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */,
|
||||
34BBC84F220B8A0100857249 /* ImageEditorCropViewController.swift in Sources */,
|
||||
@ -5262,10 +5097,10 @@
|
||||
347342F72548587900D440CD /* ConversationViewController+BottomBar.swift in Sources */,
|
||||
45B27B862037FFB400A539DF /* DebugUIFileBrowser.swift in Sources */,
|
||||
3498AC892513896400B1F315 /* Dependencies+MainApp.swift in Sources */,
|
||||
340CCB6A23032762005243B3 /* YDBLegacyMigration.m in Sources */,
|
||||
347C3834252CE69400F3D941 /* CVItemModel.swift in Sources */,
|
||||
88A4CC09246CB0960082211F /* OnboardingTransferChoiceViewController.swift in Sources */,
|
||||
3496955D219B605E00DCFE74 /* PhotoCollectionPickerController.swift in Sources */,
|
||||
34955A73260A366600F3789A /* OnboardingDroppedYdbViewController.swift in Sources */,
|
||||
880D9027247F90CC003D2B14 /* Emoji+Available.swift in Sources */,
|
||||
8835DDFD230CEE8900DC6B66 /* RecipientPickerDelegate.swift in Sources */,
|
||||
3465947E2434CCC100E5C510 /* NewGroupConfirmViewController.swift in Sources */,
|
||||
@ -5554,15 +5389,12 @@
|
||||
349BC861253A2651003C949A /* GroupsV2MigrationTest.swift in Sources */,
|
||||
3421981C21061D2E00C57195 /* ByteParserTest.swift in Sources */,
|
||||
34843B26214327C9004DED45 /* OWSOrphanDataCleanerTest.m in Sources */,
|
||||
340CCB722305962B005243B3 /* YDBToGRDBMigrationModelTest.swift in Sources */,
|
||||
34BBC862220E883300857249 /* ImageEditorTest.swift in Sources */,
|
||||
34DB0BED2011548B007B313F /* OWSDatabaseConverterTest.m in Sources */,
|
||||
3499998122EF1E2100654932 /* SearcherTest.swift in Sources */,
|
||||
345AE2B62317048300DB6225 /* GRDBFinderTest.swift in Sources */,
|
||||
34843B2C214FE296004DED45 /* MockEnvironment.m in Sources */,
|
||||
45360B911F952AA900FA666C /* MarqueeLabel.swift in Sources */,
|
||||
454EBAB41F2BE14C00ACE0BB /* OWSAnalytics.swift in Sources */,
|
||||
340CCB712305962B005243B3 /* YDBToGRDBMigrationKeyValueTest.swift in Sources */,
|
||||
954AEE6A1DF33E01002E5410 /* ContactsPickerTest.swift in Sources */,
|
||||
45666F581D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m in Sources */,
|
||||
B660F6E01C29868000687D6E /* UtilTest.m in Sources */,
|
||||
|
||||
21
Signal/Images.xcassets/logo_blue.imageset/Contents.json
vendored
Normal file
21
Signal/Images.xcassets/logo_blue.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "logo_blue.pdf",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
267
Signal/Images.xcassets/logo_blue.imageset/logo_blue.pdf
vendored
Normal file
267
Signal/Images.xcassets/logo_blue.imageset/logo_blue.pdf
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 106.000000 106.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000031 -0.405746 cm
|
||||
0.227451 0.462745 0.941176 scn
|
||||
40.279968 104.857155 m
|
||||
41.472469 100.037468 l
|
||||
36.781410 98.883797 32.291866 97.027115 28.156218 94.530434 c
|
||||
25.605595 98.786995 l
|
||||
30.163071 101.538589 35.110466 103.585114 40.279968 104.857155 c
|
||||
40.279968 104.857155 l
|
||||
h
|
||||
65.719971 104.857155 m
|
||||
64.527466 100.037468 l
|
||||
69.218529 98.883797 73.708069 97.027115 77.843719 94.530434 c
|
||||
80.410904 98.786995 l
|
||||
75.848297 101.540123 70.895203 103.586693 65.719971 104.857155 c
|
||||
65.719971 104.857155 l
|
||||
h
|
||||
7.618719 80.800117 m
|
||||
4.867129 76.242645 2.820604 71.295242 1.548563 66.125748 c
|
||||
6.368250 64.933243 l
|
||||
7.521918 69.624298 9.378601 74.113846 11.875282 78.249496 c
|
||||
7.618719 80.800117 l
|
||||
h
|
||||
4.968719 53.405743 m
|
||||
4.967119 55.814663 5.147055 58.220276 5.507000 60.602150 c
|
||||
0.596219 61.347462 l
|
||||
-0.198740 56.082825 -0.198740 50.728668 0.596219 45.464027 c
|
||||
5.507000 46.209335 l
|
||||
5.147055 48.591209 4.967119 50.996826 4.968719 53.405743 c
|
||||
4.968719 53.405743 l
|
||||
h
|
||||
80.394348 8.024490 m
|
||||
77.843719 12.281052 l
|
||||
73.713211 9.785904 69.229362 7.929268 64.544029 6.774025 c
|
||||
65.736526 1.954338 l
|
||||
70.900299 3.227951 75.842003 5.274429 80.394348 8.024490 c
|
||||
80.394348 8.024490 l
|
||||
h
|
||||
101.031219 53.405743 m
|
||||
101.032822 50.996826 100.852882 48.591209 100.492935 46.209335 c
|
||||
105.403717 45.464027 l
|
||||
106.198677 50.728668 106.198677 56.082825 105.403717 61.347462 c
|
||||
100.492935 60.602150 l
|
||||
100.852882 58.220276 101.032822 55.814663 101.031219 53.405743 c
|
||||
101.031219 53.405743 l
|
||||
h
|
||||
104.451370 40.685745 m
|
||||
99.631683 41.878242 l
|
||||
98.478020 37.187187 96.621338 32.697639 94.124657 28.561989 c
|
||||
98.381218 25.994804 l
|
||||
101.134346 30.557419 103.180908 35.510506 104.451370 40.685745 c
|
||||
104.451370 40.685745 l
|
||||
h
|
||||
60.196377 5.904488 m
|
||||
55.425617 5.186729 50.574322 5.186729 45.803562 5.904488 c
|
||||
45.058250 0.993706 l
|
||||
50.322887 0.198746 55.677044 0.198746 60.941685 0.993706 c
|
||||
60.196377 5.904488 l
|
||||
h
|
||||
91.665123 24.909958 m
|
||||
88.800392 21.030121 85.369637 17.602158 81.487473 14.740585 c
|
||||
84.435593 10.740746 l
|
||||
88.718185 13.889534 92.503540 17.663719 95.664963 21.936989 c
|
||||
91.665123 24.909958 l
|
||||
h
|
||||
81.487473 92.070900 m
|
||||
85.370239 89.206802 88.801033 85.776016 91.665123 81.893242 c
|
||||
95.664963 84.874496 l
|
||||
92.513618 89.145340 88.739563 92.919395 84.468719 96.070747 c
|
||||
81.487473 92.070900 l
|
||||
h
|
||||
14.334813 81.893242 m
|
||||
17.198910 85.776016 20.629698 89.206802 24.512470 92.070900 c
|
||||
21.531219 96.070747 l
|
||||
17.260380 92.919395 13.486319 89.145340 10.334969 84.874496 c
|
||||
14.334813 81.893242 l
|
||||
h
|
||||
98.381218 80.800117 m
|
||||
94.124657 78.249496 l
|
||||
96.619804 74.118988 98.476440 69.635132 99.631683 64.949806 c
|
||||
104.451370 66.142303 l
|
||||
103.177757 71.306076 101.131279 76.247780 98.381218 80.800117 c
|
||||
98.381218 80.800117 l
|
||||
h
|
||||
45.803562 100.898712 m
|
||||
50.574322 101.616478 55.425617 101.616478 60.196377 100.898712 c
|
||||
60.941685 105.809494 l
|
||||
55.677044 106.604454 50.322887 106.604454 45.058250 105.809494 c
|
||||
45.803562 100.898712 l
|
||||
h
|
||||
16.885439 9.424019 m
|
||||
6.624969 7.030739 l
|
||||
9.018250 17.291206 l
|
||||
4.182001 18.425743 l
|
||||
1.788719 8.165276 l
|
||||
1.595951 7.342094 1.616416 6.483345 1.848178 5.670288 c
|
||||
2.079939 4.857224 2.515332 4.116745 3.113153 3.518921 c
|
||||
3.710974 2.921104 4.451451 2.485710 5.264512 2.253944 c
|
||||
6.077572 2.022186 6.936323 2.001724 7.759501 2.194496 c
|
||||
18.011688 4.546364 l
|
||||
16.885439 9.424019 l
|
||||
h
|
||||
5.217157 22.856209 m
|
||||
10.053407 21.729958 l
|
||||
11.709657 28.843552 l
|
||||
9.295546 32.900970 7.495555 37.293510 6.368250 41.878242 c
|
||||
1.548563 40.685745 l
|
||||
2.629022 36.294586 4.271208 32.061081 6.434500 28.089958 c
|
||||
5.217157 22.856209 l
|
||||
h
|
||||
28.404655 12.090584 m
|
||||
21.291063 10.434334 l
|
||||
22.417313 5.598083 l
|
||||
27.651062 6.815430 l
|
||||
31.622185 4.652138 35.855686 3.009949 40.246841 1.929489 c
|
||||
41.439342 6.749184 l
|
||||
36.864239 7.889954 32.482990 9.701057 28.437780 12.123711 c
|
||||
28.404655 12.090584 l
|
||||
h
|
||||
52.999969 96.468246 m
|
||||
45.305874 96.464264 37.753365 94.398903 31.127958 90.486984 c
|
||||
24.502552 86.575066 19.046249 80.959473 15.326546 74.224274 c
|
||||
11.606842 67.489075 9.759604 59.880276 9.976958 52.189251 c
|
||||
10.194313 44.498226 12.468323 37.005898 16.562469 30.491524 c
|
||||
12.421844 12.827614 l
|
||||
30.085751 16.968239 l
|
||||
35.735271 13.409973 42.134800 11.214119 48.778805 10.554146 c
|
||||
55.422806 9.894173 62.129265 10.788162 68.368385 13.165497 c
|
||||
74.607506 15.542824 80.208374 19.338371 84.728523 24.252289 c
|
||||
89.248680 29.166206 92.564285 35.063873 94.413429 41.479401 c
|
||||
96.262573 47.894932 96.594589 54.652561 95.383255 61.218460 c
|
||||
94.171921 67.784363 91.450417 73.978653 87.433739 79.311996 c
|
||||
83.417061 84.645355 78.215240 88.971649 72.239220 91.949142 c
|
||||
66.263191 94.926636 59.676666 96.473740 52.999969 96.468246 c
|
||||
52.999969 96.468246 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
4584
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 106.000000 106.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 106.000000 m
|
||||
106.000000 106.000000 l
|
||||
106.000000 0.000000 l
|
||||
0.000000 0.000000 l
|
||||
0.000000 106.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
237
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /XObject << /X1 1 0 R >>
|
||||
/ExtGState << /E1 << /SMask << /Type /Mask
|
||||
/G 3 0 R
|
||||
/S /Alpha
|
||||
>>
|
||||
/Type /ExtGState
|
||||
>> >>
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Length 7 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
/E1 gs
|
||||
/X1 Do
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 106.000000 106.000000 ]
|
||||
/Resources 5 0 R
|
||||
/Contents 6 0 R
|
||||
/Parent 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<< /Kids [ 8 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000004844 00000 n
|
||||
0000004867 00000 n
|
||||
0000005354 00000 n
|
||||
0000005376 00000 n
|
||||
0000005674 00000 n
|
||||
0000005776 00000 n
|
||||
0000005797 00000 n
|
||||
0000005972 00000 n
|
||||
0000006046 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
6106
|
||||
%%EOF
|
||||
@ -1763,26 +1763,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, yap.TV Inc. All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Neither the name of yap.TV nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of yap.TV Inc.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</string>
|
||||
<key>License</key>
|
||||
<string>MIT</string>
|
||||
<key>Title</key>
|
||||
<string>YapDatabase</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>This software is provided under:
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#import "Signal-Swift.h"
|
||||
#import "SignalApp.h"
|
||||
#import "ViewControllerUtils.h"
|
||||
#import "YDBLegacyMigration.h"
|
||||
#import <Intents/Intents.h>
|
||||
#import <PromiseKit/AnyPromise.h>
|
||||
#import <SignalCoreKit/iOSVersions.h>
|
||||
@ -174,22 +173,20 @@ void uncaughtExceptionHandler(NSException *exception)
|
||||
deviceTransferRestoreFailed = ![DeviceTransferService.shared launchCleanup];
|
||||
}];
|
||||
|
||||
// XXX - careful when moving this. It must happen before we load YDB and/or GRDB.
|
||||
// XXX - careful when moving this. It must happen before we load GRDB.
|
||||
[self verifyDBKeysAvailableBeforeBackgroundLaunch];
|
||||
|
||||
// We need to do this _after_ we set up logging, when the keychain is unlocked,
|
||||
// but before we access YapDatabase, files on disk, or NSUserDefaults
|
||||
// but before we access the database, files on disk, or NSUserDefaults.
|
||||
NSError *_Nullable launchError = nil;
|
||||
LaunchFailure launchFailure = LaunchFailure_None;
|
||||
|
||||
BOOL isYdbNotReady = ![YDBLegacyMigration ensureIsYDBReadyForAppExtensions:&launchError];
|
||||
if (deviceTransferRestoreFailed) {
|
||||
launchFailure = LaunchFailure_CouldNotRestoreTransferredData;
|
||||
} else if (isYdbNotReady || launchError != nil) {
|
||||
} else if (launchError != nil) {
|
||||
launchFailure = LaunchFailure_CouldNotLoadDatabase;
|
||||
} else if (StorageCoordinator.hasInvalidDatabaseVersion) {
|
||||
// Prevent:
|
||||
// * Users who have used GRDB revert to using YDB.
|
||||
// * Users with an unknown GRDB schema revert to using an earlier GRDB schema.
|
||||
launchFailure = LaunchFailure_UnknownDatabaseVersion;
|
||||
}
|
||||
@ -287,20 +284,7 @@ void uncaughtExceptionHandler(NSException *exception)
|
||||
return;
|
||||
}
|
||||
|
||||
// someone currently using yap
|
||||
if (StorageCoordinator.hasYdbFile && !SSKPreferences.isYdbMigrated
|
||||
&& OWSPrimaryStorage.isDatabasePasswordAccessible) {
|
||||
return;
|
||||
}
|
||||
|
||||
// someone who migrated from yap to grdb needs the GRDB spec
|
||||
if (SSKPreferences.isYdbMigrated && GRDBDatabaseStorageAdapter.isKeyAccessible) {
|
||||
return;
|
||||
}
|
||||
|
||||
// someone who never used yap needs the GRDB spec
|
||||
if (!StorageCoordinator.hasYdbFile && StorageCoordinator.hasGrdbFile
|
||||
&& GRDBDatabaseStorageAdapter.isKeyAccessible) {
|
||||
if (StorageCoordinator.hasGrdbFile && GRDBDatabaseStorageAdapter.isKeyAccessible) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -635,54 +635,6 @@ class ThreadMapping: NSObject {
|
||||
|
||||
return ThreadMappingDiff(sectionChanges: [], rowChanges: rowChanges)
|
||||
}
|
||||
|
||||
// For performance reasons, the database modification notifications are used
|
||||
// to determine which items were modified. If YapDatabase ever changes the
|
||||
// structure or semantics of these notifications, we'll need to update this
|
||||
// code to reflect that.
|
||||
@objc
|
||||
public func updatedYapItemIds(forNotifications notifications: [NSNotification]) -> Set<String> {
|
||||
// We'll move this into the Yap adapter when addressing updates/observation
|
||||
let viewName: String = TSThreadDatabaseViewExtensionName
|
||||
|
||||
var updatedItemIds = Set<String>()
|
||||
for notification in notifications {
|
||||
// Unpack the YDB notification, looking for row changes.
|
||||
guard let userInfo =
|
||||
notification.userInfo else {
|
||||
owsFailDebug("Missing userInfo.")
|
||||
continue
|
||||
}
|
||||
guard let viewChangesets =
|
||||
userInfo[YapDatabaseExtensionsKey] as? NSDictionary else {
|
||||
// No changes for any views, skip.
|
||||
continue
|
||||
}
|
||||
guard let changeset =
|
||||
viewChangesets[viewName] as? NSDictionary else {
|
||||
// No changes for this view, skip.
|
||||
continue
|
||||
}
|
||||
// This constant matches a private constant in YDB.
|
||||
let changeset_key_changes: String = "changes"
|
||||
guard let changesetChanges = changeset[changeset_key_changes] as? [Any] else {
|
||||
owsFailDebug("Missing changeset changes.")
|
||||
continue
|
||||
}
|
||||
for change in changesetChanges {
|
||||
if change as? YapDatabaseViewSectionChange != nil {
|
||||
// Ignore.
|
||||
} else if let rowChange = change as? YapDatabaseViewRowChange {
|
||||
updatedItemIds.insert(rowChange.collectionKey.key)
|
||||
} else {
|
||||
owsFailDebug("Invalid change: \(type(of: change)).")
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updatedItemIds
|
||||
}
|
||||
}
|
||||
|
||||
extension Collection where Element: Equatable {
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#import "OWSBezierPathView.h"
|
||||
#import "OWSBubbleShapeView.h"
|
||||
#import "OWSBubbleView.h"
|
||||
#import "OWSDatabaseMigration.h"
|
||||
#import "OWSDeviceTableViewCell.h"
|
||||
#import "OWSLinkDeviceViewController.h"
|
||||
#import "OWSMessageTextView.h"
|
||||
|
||||
@ -113,9 +113,7 @@ class InternalSettingsViewController: OWSTableViewController2 {
|
||||
|
||||
infoSection.add(.label(withText: "dataStoreForUI: \(NSStringForDataStore(StorageCoordinator.dataStoreForUI))"))
|
||||
|
||||
infoSection.add(.label(withText: "hasYdbFile: \(StorageCoordinator.hasYdbFile)"))
|
||||
infoSection.add(.label(withText: "hasGrdbFile: \(StorageCoordinator.hasGrdbFile)"))
|
||||
infoSection.add(.label(withText: "hasUnmigratedYdbFile: \(StorageCoordinator.hasUnmigratedYdbFile)"))
|
||||
infoSection.add(.label(withText: "didEverUseYdb: \(SSKPreferences.didEverUseYdb())"))
|
||||
|
||||
infoSection.add(.actionItem(
|
||||
|
||||
@ -3010,9 +3010,7 @@ typedef enum : NSUInteger {
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
|
||||
// We always want to scroll to the bottom of the conversation after the local user
|
||||
// sends a message. Normally, this is taken care of in yapDatabaseModified:, but
|
||||
// we don't listen to db modifications when this view isn't visible, i.e. when the
|
||||
// attachment approval view is presented.
|
||||
// sends a message.
|
||||
[self scrollToBottomOfConversationAnimated:NO];
|
||||
}
|
||||
|
||||
|
||||
@ -23,14 +23,6 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSStorage (DebugUI)
|
||||
|
||||
- (NSData *)databasePassword;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation DebugUIMisc
|
||||
|
||||
#pragma mark - Factory Methods
|
||||
@ -106,17 +98,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}]];
|
||||
|
||||
|
||||
if (thread) {
|
||||
[items addObject:[OWSTableItem itemWithTitle:@"Send Encrypted Database"
|
||||
actionBlock:^{
|
||||
[DebugUIMisc sendEncryptedDatabase:thread];
|
||||
}]];
|
||||
[items addObject:[OWSTableItem itemWithTitle:@"Send Unencrypted Database"
|
||||
actionBlock:^{
|
||||
[DebugUIMisc sendUnencryptedDatabase:thread];
|
||||
}]];
|
||||
}
|
||||
|
||||
[items addObject:[OWSTableItem itemWithTitle:@"Show 2FA Reminder"
|
||||
actionBlock:^() {
|
||||
UIViewController *reminderVC =
|
||||
@ -154,21 +135,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
actionBlock:^(UIViewController *viewController) {
|
||||
[DebugUIMisc sharePDFs:2];
|
||||
}]];
|
||||
|
||||
[items addObject:[OWSTableItem
|
||||
itemWithTitle:@"Increment Database Extension Versions"
|
||||
actionBlock:^() {
|
||||
if (StorageCoordinator.dataStoreForUI == DataStoreYdb) {
|
||||
for (NSString *extensionName in OWSPrimaryStorage.shared.registeredExtensionNames) {
|
||||
[OWSStorage incrementVersionOfDatabaseExtension:extensionName];
|
||||
}
|
||||
}
|
||||
}]];
|
||||
|
||||
[items addObject:[OWSTableItem
|
||||
itemWithTitle:@"Fetch system contacts"
|
||||
actionBlock:^() { [Environment.shared.contactsManagerImpl requestSystemContactsOnce]; }]];
|
||||
|
||||
[items addObject:[OWSTableItem itemWithTitle:@"Cycle websockets"
|
||||
actionBlock:^() {
|
||||
[SSKEnvironment.shared.socketManager cycleSocket];
|
||||
@ -316,40 +285,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
});
|
||||
}
|
||||
|
||||
+ (void)sendEncryptedDatabase:(TSThread *)thread
|
||||
{
|
||||
NSString *filePath = [OWSFileSystem temporaryFilePathWithFileExtension:@"sqlite"];
|
||||
NSString *fileName = filePath.lastPathComponent;
|
||||
|
||||
__block BOOL success;
|
||||
DatabaseStorageWrite(self.databaseStorage, ^(SDSAnyWriteTransaction *transaction) {
|
||||
NSError *error;
|
||||
success = [[NSFileManager defaultManager] copyItemAtPath:OWSPrimaryStorage.databaseFilePath
|
||||
toPath:filePath
|
||||
error:&error];
|
||||
if (!success || error) {
|
||||
OWSFailDebug(@"Could not copy database file: %@.", error);
|
||||
success = NO;
|
||||
}
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:fileName.pathExtension];
|
||||
NSError *error;
|
||||
_Nullable id<DataSource> dataSource = [DataSourcePath dataSourceWithFilePath:filePath
|
||||
shouldDeleteOnDeallocation:YES
|
||||
error:&error];
|
||||
OWSAssertDebug(dataSource != nil);
|
||||
[dataSource setSourceFilename:fileName];
|
||||
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType];
|
||||
NSData *databasePassword = [OWSPrimaryStorage.shared databasePassword];
|
||||
attachment.captionText = [databasePassword hexadecimalString];
|
||||
[self sendAttachment:attachment thread:thread];
|
||||
}
|
||||
|
||||
+ (void)sendAttachment:(SignalAttachment *)attachment thread:(TSThread *)thread
|
||||
{
|
||||
if (!attachment || [attachment hasError]) {
|
||||
@ -366,31 +301,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)sendUnencryptedDatabase:(TSThread *)thread
|
||||
{
|
||||
NSString *filePath = [OWSFileSystem temporaryFilePathWithFileExtension:@"sqlite"];
|
||||
NSString *fileName = filePath.lastPathComponent;
|
||||
|
||||
NSError *error = [OWSPrimaryStorage.shared.newDatabaseConnection backupToPath:filePath];
|
||||
if (error != nil) {
|
||||
OWSFailDebug(@"Could not copy database file: %@.", error);
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *utiType = [MIMETypeUtil utiTypeForFileExtension:fileName.pathExtension];
|
||||
_Nullable id<DataSource> dataSource = [DataSourcePath dataSourceWithFilePath:filePath
|
||||
shouldDeleteOnDeallocation:YES
|
||||
error:&error];
|
||||
if (dataSource == nil) {
|
||||
OWSFailDebug(@"Could not create dataSource: %@.", error);
|
||||
return;
|
||||
}
|
||||
|
||||
[dataSource setSourceFilename:fileName];
|
||||
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType];
|
||||
[self sendAttachment:attachment thread:thread];
|
||||
}
|
||||
|
||||
+ (void)shareAssets:(NSUInteger)count
|
||||
fromAssetLoaders:(NSArray<DebugUIMessagesAssetLoader *> *)assetLoaders
|
||||
{
|
||||
@ -526,14 +436,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// KnownStickerPack
|
||||
[[[KnownStickerPack alloc] initWithInfo:stickerPackInfo] anyInsertWithTransaction:transaction];
|
||||
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// TODO: Generate real envelope data.
|
||||
if (StorageCoordinator.dataStoreForUI == DataStoreYdb) {
|
||||
[[[OWSMessageDecryptJob alloc] initWithEnvelopeData:[Randomness generateRandomBytes:16]
|
||||
serverDeliveryTimestamp:0] anyInsertWithTransaction:transaction];
|
||||
}
|
||||
|
||||
// OWSMessageContentJob
|
||||
//
|
||||
// TODO: Generate real envelope data.
|
||||
|
||||
@ -37,12 +37,12 @@ typedef NS_ENUM(NSInteger, ConversationListMode) {
|
||||
ConversationListMode_Inbox,
|
||||
};
|
||||
|
||||
// The bulk of the content in this view is driven by a YapDB view/mapping.
|
||||
// The bulk of the content in this view is driven by ThreadMapping.
|
||||
// However, we also want to optionally include ReminderView's at the top
|
||||
// and an "Archived Conversations" button at the bottom. Rather than introduce
|
||||
// index-offsets into the Mapping calculation, we introduce two pseudo groups
|
||||
// to add a top and bottom section to the content, and create cells for those
|
||||
// sections without consulting the YapMapping.
|
||||
// sections without consulting the ThreadMapping.
|
||||
// This is a bit of a hack, but it consolidates the hacks into the Reminder/Archive section
|
||||
// and allows us to leaves the bulk of the content logic on the happy path.
|
||||
NSString *const kReminderViewPseudoGroup = @"kReminderViewPseudoGroup";
|
||||
@ -1920,16 +1920,6 @@ NSString *const kArchiveButtonPseudoGroup = @"kArchiveButtonPseudoGroup";
|
||||
return (ConversationListViewController *)topViewController;
|
||||
}
|
||||
|
||||
- (NSString *)currentGrouping
|
||||
{
|
||||
switch (self.conversationListMode) {
|
||||
case ConversationListMode_Inbox:
|
||||
return TSInboxGroup;
|
||||
case ConversationListMode_Archive:
|
||||
return TSArchiveGroup;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Previewing
|
||||
|
||||
#pragma mark Old Style
|
||||
|
||||
@ -228,7 +228,11 @@ public class OnboardingController: NSObject {
|
||||
Logger.info("milestone: \(milestone)")
|
||||
switch milestone {
|
||||
case .verifiedPhoneNumber, .verifiedLinkedDevice:
|
||||
return OnboardingSplashViewController(onboardingController: self)
|
||||
if SSKPreferences.didDropYdb() {
|
||||
return OnboardingDroppedYdbViewController(onboardingController: self)
|
||||
} else {
|
||||
return OnboardingSplashViewController(onboardingController: self)
|
||||
}
|
||||
case .setupProfile:
|
||||
return OnboardingProfileCreationViewController(onboardingController: self)
|
||||
case .restorePin:
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import PromiseKit
|
||||
|
||||
@objc
|
||||
public class OnboardingDroppedYdbViewController: OnboardingBaseViewController {
|
||||
|
||||
override public func loadView() {
|
||||
view = UIView()
|
||||
view.addSubview(primaryView)
|
||||
primaryView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
view.backgroundColor = Theme.backgroundColor
|
||||
|
||||
let heroImageView = UIImageView.withTemplateImageName("logo_blue",
|
||||
tintColor: .ows_accentBlue)
|
||||
heroImageView.autoSetDimensions(to: .square(100))
|
||||
heroImageView.setContentHuggingHigh()
|
||||
|
||||
let titleLabel = self.createTitleLabel(text: NSLocalizedString("ONBOARDING_DROPPED_YDB_TITLE",
|
||||
comment: "Title of the 'onboarding after dropped YDB' view."))
|
||||
primaryView.addSubview(titleLabel)
|
||||
titleLabel.accessibilityIdentifier = "onboarding.droppedYdb." + "titleLabel"
|
||||
|
||||
let explanationLabel = UILabel()
|
||||
explanationLabel.text = NSLocalizedString("ONBOARDING_DROPPED_YDB_EXPLANATION",
|
||||
comment: "Explanation on the 'onboarding after dropped YDB' view.")
|
||||
explanationLabel.textColor = Theme.secondaryTextAndIconColor
|
||||
explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped
|
||||
explanationLabel.numberOfLines = 0
|
||||
explanationLabel.textAlignment = .center
|
||||
explanationLabel.lineBreakMode = .byWordWrapping
|
||||
explanationLabel.accessibilityIdentifier = "onboarding.droppedYdb." + "explanationLabel"
|
||||
|
||||
let nextButton = self.primaryButton(title: CommonStrings.nextButton,
|
||||
selector: #selector(nextPressed))
|
||||
nextButton.accessibilityIdentifier = "onboarding.droppedYdb." + "nextButton"
|
||||
let primaryButtonView = OnboardingBaseViewController.horizontallyWrap(primaryButton: nextButton)
|
||||
|
||||
let topStack = UIStackView(arrangedSubviews: [
|
||||
heroImageView,
|
||||
UIView.spacer(withHeight: 28),
|
||||
titleLabel,
|
||||
UIView.spacer(withHeight: 12),
|
||||
explanationLabel
|
||||
])
|
||||
topStack.axis = .vertical
|
||||
topStack.alignment = .center
|
||||
|
||||
let topVSpacer = UIView.vStretchingSpacer()
|
||||
let bottomVSpacer = UIView.vStretchingSpacer()
|
||||
|
||||
let stackView = UIStackView(arrangedSubviews: [
|
||||
topVSpacer,
|
||||
topStack,
|
||||
bottomVSpacer,
|
||||
primaryButtonView
|
||||
])
|
||||
stackView.axis = .vertical
|
||||
stackView.alignment = .fill
|
||||
|
||||
primaryView.addSubview(stackView)
|
||||
stackView.autoPinEdgesToSuperviewMargins()
|
||||
|
||||
topVSpacer.autoMatch(.height, to: .height, of: bottomVSpacer)
|
||||
}
|
||||
|
||||
// MARK: - Events
|
||||
|
||||
@objc func nextPressed() {
|
||||
Logger.info("")
|
||||
|
||||
SSKPreferences.setDidDropYdb(false)
|
||||
|
||||
let splash = OnboardingSplashViewController(onboardingController: onboardingController)
|
||||
navigationController?.setViewControllers([splash], animated: true)
|
||||
}
|
||||
}
|
||||
@ -69,8 +69,6 @@ public class AppEnvironment: NSObject {
|
||||
super.init()
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
|
||||
YDBToGRDBMigration.add(keyStore: AppUpdateNag.shared.keyValueStore, label: "AppUpdateNag")
|
||||
}
|
||||
|
||||
@objc
|
||||
|
||||
@ -115,7 +115,9 @@ class AppUpdateNag: NSObject {
|
||||
}
|
||||
|
||||
switch frontmostViewController {
|
||||
case is ConversationSplitViewController, is OnboardingSplashViewController:
|
||||
case is ConversationSplitViewController,
|
||||
is OnboardingSplashViewController,
|
||||
is OnboardingDroppedYdbViewController:
|
||||
self.setLastNagDate(Date())
|
||||
self.clearFirstHeardOfNewVersionDate()
|
||||
presentUpgradeNag(appStoreRecord: appStoreRecord)
|
||||
|
||||
@ -53,7 +53,7 @@ extension DeviceTransferService {
|
||||
return false
|
||||
}
|
||||
|
||||
guard database.key.count == kSQLCipherKeySpecLength else {
|
||||
guard database.key.count == GRDBDatabaseStorageAdapter.kSQLCipherKeySpecLength else {
|
||||
owsFailDebug("incorrect database key length")
|
||||
return false
|
||||
}
|
||||
|
||||
@ -18,9 +18,6 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
|
||||
|
||||
@property (nonatomic, nullable) NSMutableArray<AppActiveBlock> *appActiveBlocks;
|
||||
|
||||
// POST GRDB TODO: Remove this
|
||||
@property (nonatomic) NSUUID *disposableDatabaseUUID;
|
||||
|
||||
@property (nonatomic, readonly) UIApplicationState mainApplicationStateOnLaunch;
|
||||
|
||||
@end
|
||||
@ -45,7 +42,6 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
|
||||
self.reportedApplicationState = UIApplicationStateInactive;
|
||||
|
||||
_appLaunchTime = [NSDate new];
|
||||
_disposableDatabaseUUID = [NSUUID UUID];
|
||||
_mainApplicationStateOnLaunch = [UIApplication sharedApplication].applicationState;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
@ -392,11 +388,7 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
|
||||
|
||||
- (NSString *)appDatabaseBaseDirectoryPath
|
||||
{
|
||||
if (SDSDatabaseStorage.shouldUseDisposableGrdb) {
|
||||
return [self.appSharedDataDirectoryPath stringByAppendingPathComponent:self.disposableDatabaseUUID.UUIDString];
|
||||
} else {
|
||||
return self.appSharedDataDirectoryPath;
|
||||
}
|
||||
return self.appSharedDataDirectoryPath;
|
||||
}
|
||||
|
||||
- (NSUserDefaults *)appUserDefaults
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface YDBLegacyMigration : NSObject
|
||||
|
||||
+ (BOOL)ensureIsYDBReadyForAppExtensions:(NSError **)error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,129 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "YDBLegacyMigration.h"
|
||||
#import <SignalCoreKit/NSData+OWS.h>
|
||||
#import <SignalMessaging/OWSPreferences.h>
|
||||
#import <SignalServiceKit/AppReadiness.h>
|
||||
#import <SignalServiceKit/NSUserDefaults+OWS.h>
|
||||
#import <SignalServiceKit/OWSBackgroundTask.h>
|
||||
#import <SignalServiceKit/OWSError.h>
|
||||
#import <SignalServiceKit/OWSFileSystem.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/OWSUserProfile.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/StorageCoordinator.h>
|
||||
#import <SignalServiceKit/TSAttachmentStream.h>
|
||||
#import <YapDatabase/YapDatabaseCryptoUtils.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation YDBLegacyMigration
|
||||
|
||||
+ (void)appDidBecomeReady
|
||||
{
|
||||
if (CurrentAppContext().isMainApp) {
|
||||
// Disable the SAE until the main app has:
|
||||
//
|
||||
// * Successfully completed launch process at least once in the post-SAE world.
|
||||
// * Successfully completed launch process at least once in the post-GRDB world.
|
||||
[OWSPreferences setIsYdbReadyForAppExtensions];
|
||||
|
||||
if (StorageCoordinator.dataStoreForUI == DataStoreGrdb) {
|
||||
[OWSPreferences setIsGrdbReadyForAppExtensions];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)ensureIsYDBReadyForAppExtensions:(NSError **)errorHandle
|
||||
{
|
||||
OWSAssertDebug(errorHandle != nil);
|
||||
|
||||
AppReadinessRunNowOrWhenAppDidBecomeReadySync(^{ [self appDidBecomeReady]; });
|
||||
|
||||
if ([OWSPreferences isReadyForAppExtensions]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
|
||||
SUPPRESS_DEADSTORE_WARNING(backgroundTask);
|
||||
|
||||
NSError *_Nullable error = [self convertDatabaseIfNecessary];
|
||||
|
||||
if (!error) {
|
||||
[NSUserDefaults migrateToSharedUserDefaults];
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
error = [OWSPrimaryStorage migrateToSharedData];
|
||||
}
|
||||
if (!error) {
|
||||
error = [OWSUserProfile migrateToSharedData];
|
||||
}
|
||||
if (!error) {
|
||||
error = [TSAttachmentStream migrateToSharedData];
|
||||
}
|
||||
|
||||
if (error) {
|
||||
OWSFailDebug(@"database conversion failed: %@", error);
|
||||
*errorHandle = error;
|
||||
return NO;
|
||||
}
|
||||
|
||||
OWSAssertDebug(backgroundTask);
|
||||
backgroundTask = nil;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (nullable NSError *)convertDatabaseIfNecessary
|
||||
{
|
||||
OWSLogInfo(@"");
|
||||
|
||||
NSString *databaseFilePath = [OWSPrimaryStorage legacyDatabaseFilePath];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:databaseFilePath]) {
|
||||
OWSLogVerbose(@"no legacy database file found");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *_Nullable error;
|
||||
NSData *_Nullable databasePassword = [OWSStorage tryToLoadDatabaseLegacyPassphrase:&error];
|
||||
if (!databasePassword || error) {
|
||||
return (error
|
||||
?: OWSErrorWithCodeDescription(
|
||||
OWSErrorCodeDatabaseConversionFatalError, @"Failed to load database password"));
|
||||
}
|
||||
|
||||
YapRecordDatabaseSaltBlock recordSaltBlock = ^(NSData *saltData) {
|
||||
OWSLogVerbose(@"saltData: %@", saltData.hexadecimalString);
|
||||
|
||||
// Derive and store the raw cipher key spec, to avoid the ongoing tax of future KDF
|
||||
NSData *_Nullable keySpecData =
|
||||
[YapDatabaseCryptoUtils deriveDatabaseKeySpecForPassword:databasePassword saltData:saltData];
|
||||
|
||||
if (!keySpecData) {
|
||||
OWSLogError(@"Failed to derive key spec.");
|
||||
return NO;
|
||||
}
|
||||
|
||||
[OWSStorage storeDatabaseCipherKeySpec:keySpecData];
|
||||
|
||||
return YES;
|
||||
};
|
||||
|
||||
YapDatabaseOptions *dbOptions = [OWSStorage defaultDatabaseOptions];
|
||||
error = [YapDatabaseCryptoUtils convertDatabaseIfNecessary:databaseFilePath
|
||||
databasePassword:databasePassword
|
||||
options:dbOptions
|
||||
recordSaltBlock:recordSaltBlock];
|
||||
if (!error) {
|
||||
[OWSStorage removeLegacyPassphrase];
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -27,7 +27,6 @@ class MessageProcessingPerformanceTest: PerformanceBaseTest {
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
storageCoordinator.useGRDBForTests()
|
||||
try! databaseStorage.grdbStorage.setupUIDatabase()
|
||||
|
||||
let dbObserver = BlockObserver(block: { [weak self] in self?.dbObserverBlock?() })
|
||||
|
||||
@ -53,7 +53,6 @@ class MessageSendingPerformanceTest: PerformanceBaseTest {
|
||||
|
||||
func testGRDBPerf_messageSending_contactThread() {
|
||||
// This is an example of a performance test case.
|
||||
storageCoordinator.useGRDBForTests()
|
||||
try! databaseStorage.grdbStorage.setupUIDatabase()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
sendMessages_contactThread()
|
||||
@ -63,7 +62,6 @@ class MessageSendingPerformanceTest: PerformanceBaseTest {
|
||||
|
||||
func testGRDBPerf_messageSending_groupThread() {
|
||||
// This is an example of a performance test case.
|
||||
storageCoordinator.useGRDBForTests()
|
||||
try! databaseStorage.grdbStorage.setupUIDatabase()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
sendMessages_groupThread()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -11,14 +11,12 @@ class SDSPerformanceTest: PerformanceBaseTest {
|
||||
// MARK: - Insert Messages
|
||||
|
||||
func testYDBPerf_insertMessages() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
insertMessages()
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_insertMessages() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
insertMessages()
|
||||
}
|
||||
@ -62,14 +60,12 @@ class SDSPerformanceTest: PerformanceBaseTest {
|
||||
// MARK: - Fetch Messages
|
||||
|
||||
func testYDBPerf_fetchMessages() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
fetchMessages()
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_fetchMessages() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
fetchMessages()
|
||||
}
|
||||
@ -108,28 +104,24 @@ class SDSPerformanceTest: PerformanceBaseTest {
|
||||
// MARK: - Enumerate Messages
|
||||
|
||||
func testYDBPerf_enumerateMessagesUnbatched() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
enumerateMessages(batched: false)
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_enumerateMessagesUnbatched() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
enumerateMessages(batched: false)
|
||||
}
|
||||
}
|
||||
|
||||
func testYDBPerf_enumerateMessagesBatched() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
enumerateMessages(batched: true)
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_enumerateMessagesBatched() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
enumerateMessages(batched: true)
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -9,14 +9,12 @@ import SignalServiceKit
|
||||
class ThreadFinderPerformanceTest: PerformanceBaseTest {
|
||||
|
||||
func testGRDBPerf_enumerateVisibleThreads() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
enumerateVisibleThreads(isArchived: false)
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_enumerateVisibleThreads_isArchived() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
enumerateVisibleThreads(isArchived: true)
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -14,14 +14,12 @@ class ThreadPerformanceTest: PerformanceBaseTest {
|
||||
// MARK: - writeThreadAndInteractions
|
||||
|
||||
func testYDBPerf_writeThreadAndInteractions() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
writeThreadAndInteractions()
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_writeThreadAndInteractions() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
writeThreadAndInteractions()
|
||||
}
|
||||
@ -50,14 +48,12 @@ class ThreadPerformanceTest: PerformanceBaseTest {
|
||||
// MARK: - writeAndDeleteThreadAndInteractions
|
||||
|
||||
func testYDBPerf_writeAndDeleteThreadAndInteractions() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
writeAndDeleteThreadAndInteractions()
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_writeAndDeleteThreadAndInteractions() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
writeAndDeleteThreadAndInteractions()
|
||||
}
|
||||
@ -83,14 +79,12 @@ class ThreadPerformanceTest: PerformanceBaseTest {
|
||||
// MARK: - writeAndUpdateAndDeleteThreadAndInteractions
|
||||
|
||||
func testYDBPerf_writeAndUpdateAndDeleteThreadAndInteractions() {
|
||||
storageCoordinator.useYDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
writeAndUpdateAndDeleteThreadAndInteractions()
|
||||
}
|
||||
}
|
||||
|
||||
func testGRDBPerf_writeAndUpdateAndDeleteThreadAndInteractions() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
|
||||
writeAndUpdateAndDeleteThreadAndInteractions()
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MockEnvironment.h"
|
||||
#import <SignalServiceKit/MockSSKEnvironment.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <YapDatabase/YapDatabaseConnection.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -14,14 +13,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface SignalBaseTest : XCTestCase
|
||||
|
||||
@property (nonatomic, readonly, nullable) OWSPrimaryStorage *primaryStorage;
|
||||
|
||||
- (void)readWithBlock:(void (^)(SDSAnyReadTransaction *transaction))block;
|
||||
- (void)writeWithBlock:(void (^)(SDSAnyWriteTransaction *transaction))block;
|
||||
|
||||
- (void)yapReadWithBlock:(void (^)(YapDatabaseReadTransaction *transaction))block;
|
||||
- (void)yapWriteWithBlock:(void (^)(YapDatabaseReadWriteTransaction *transaction))block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -5,22 +5,12 @@
|
||||
#import "SignalBaseTest.h"
|
||||
#import "Environment.h"
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/SDSDatabaseStorage+Objc.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TestAppContext.h>
|
||||
#import <YapDatabase/YapDatabaseConnection.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface SignalBaseTest ()
|
||||
|
||||
@property (nonatomic) YapDatabaseConnection *ydbConnection;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation SignalBaseTest
|
||||
|
||||
- (void)setUp
|
||||
@ -38,8 +28,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[MockEnvironment activate];
|
||||
|
||||
((MockSSKEnvironment *)SSKEnvironment.shared).groupsV2Ref = [GroupsV2Impl new];
|
||||
|
||||
self.ydbConnection = [SSKEnvironment.shared.primaryStorage newDatabaseConnection];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
@ -59,22 +47,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
DatabaseStorageWrite(SDSDatabaseStorage.shared, block);
|
||||
}
|
||||
|
||||
- (void)yapReadWithBlock:(void (^)(YapDatabaseReadTransaction *transaction))block
|
||||
{
|
||||
OWSAssert(block);
|
||||
OWSAssert(self.ydbConnection);
|
||||
|
||||
[self.ydbConnection readWithBlock:block];
|
||||
}
|
||||
|
||||
- (void)yapWriteWithBlock:(void (^)(YapDatabaseReadWriteTransaction *transaction))block
|
||||
{
|
||||
OWSAssert(block);
|
||||
OWSAssert(self.ydbConnection);
|
||||
|
||||
[self.ydbConnection readWriteWithBlock:block];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -12,8 +12,6 @@ class GRDBFinderTest: SignalBaseTest {
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
// ensure local client has necessary "registered" state
|
||||
let localE164Identifier = "+13235551234"
|
||||
let localUUID = UUID()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,556 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import SignalServiceKit
|
||||
@testable import SignalMessaging
|
||||
|
||||
class YDBToGRDBMigrationKeyValueTest: SignalBaseTest {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testKeyValueInt() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
let randomValue = {
|
||||
return Int(arc4random())
|
||||
}
|
||||
let value0 = randomValue()
|
||||
let value1 = randomValue()
|
||||
let value2 = randomValue()
|
||||
let value3 = randomValue()
|
||||
let value4 = randomValue()
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setInt(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setInt(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setInt(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setInt(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setInt(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getInt("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store2.getInt("key0", transaction: transaction))
|
||||
XCTAssertEqual(value2, store3.getInt("key0", transaction: transaction))
|
||||
XCTAssertEqual(value3, store1.getInt("key1", transaction: transaction))
|
||||
XCTAssertEqual(value4, store2.getInt("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getInt("key1", transaction: transaction))
|
||||
|
||||
// NSNumber variations
|
||||
XCTAssertEqual(NSNumber(value: value0), store1.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value1), store2.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value2), store3.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value3), store1.getNSNumber("key1", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value4), store2.getNSNumber("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getNSNumber("key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyValueUInt() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
let randomValue = {
|
||||
return UInt(arc4random())
|
||||
}
|
||||
let value0 = randomValue()
|
||||
let value1 = randomValue()
|
||||
let value2 = randomValue()
|
||||
let value3 = randomValue()
|
||||
let value4 = randomValue()
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setUInt(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setUInt(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setUInt(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setUInt(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setUInt(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getUInt("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store2.getUInt("key0", transaction: transaction))
|
||||
XCTAssertEqual(value2, store3.getUInt("key0", transaction: transaction))
|
||||
XCTAssertEqual(value3, store1.getUInt("key1", transaction: transaction))
|
||||
XCTAssertEqual(value4, store2.getUInt("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getUInt("key1", transaction: transaction))
|
||||
|
||||
// NSNumber variations
|
||||
XCTAssertEqual(NSNumber(value: value0), store1.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value1), store2.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value2), store3.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value3), store1.getNSNumber("key1", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value4), store2.getNSNumber("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getNSNumber("key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyValueDouble() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
let randomValue = {
|
||||
return Double(arc4random()) / Double(arc4random())
|
||||
}
|
||||
let value0 = randomValue()
|
||||
let value1 = randomValue()
|
||||
let value2 = randomValue()
|
||||
let value3 = randomValue()
|
||||
let value4 = randomValue()
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setDouble(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setDouble(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setDouble(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setDouble(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setDouble(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getDouble("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store2.getDouble("key0", transaction: transaction))
|
||||
XCTAssertEqual(value2, store3.getDouble("key0", transaction: transaction))
|
||||
XCTAssertEqual(value3, store1.getDouble("key1", transaction: transaction))
|
||||
XCTAssertEqual(value4, store2.getDouble("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getDouble("key1", transaction: transaction))
|
||||
|
||||
// NSNumber variations
|
||||
XCTAssertEqual(NSNumber(value: value0), store1.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value1), store2.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value2), store3.getNSNumber("key0", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value3), store1.getNSNumber("key1", transaction: transaction))
|
||||
XCTAssertEqual(NSNumber(value: value4), store2.getNSNumber("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getNSNumber("key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyValueData() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
let randomValue = {
|
||||
return UUID().uuidString.data(using: .utf8)!
|
||||
}
|
||||
let value0 = randomValue()
|
||||
let value1 = randomValue()
|
||||
let value2 = randomValue()
|
||||
let value3 = randomValue()
|
||||
let value4 = randomValue()
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setData(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setData(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setData(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setData(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setData(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getData("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store2.getData("key0", transaction: transaction))
|
||||
XCTAssertEqual(value2, store3.getData("key0", transaction: transaction))
|
||||
XCTAssertEqual(value3, store1.getData("key1", transaction: transaction))
|
||||
XCTAssertEqual(value4, store2.getData("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getData("key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyValueString() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
let randomValue = {
|
||||
return UUID().uuidString
|
||||
}
|
||||
let value0 = randomValue()
|
||||
let value1 = randomValue()
|
||||
let value2 = randomValue()
|
||||
let value3 = randomValue()
|
||||
let value4 = randomValue()
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setString(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setString(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setString(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setString(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setString(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getString("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store2.getString("key0", transaction: transaction))
|
||||
XCTAssertEqual(value2, store3.getString("key0", transaction: transaction))
|
||||
XCTAssertEqual(value3, store1.getString("key1", transaction: transaction))
|
||||
XCTAssertEqual(value4, store2.getString("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getString("key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyValueDate() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
// A special store we use for date edge cases.
|
||||
let store4 = SDSKeyValueStore(collection: "store4")
|
||||
|
||||
let randomValue = {
|
||||
return NSDate.ows_date(withMillisecondsSince1970: UInt64(arc4random()))
|
||||
}
|
||||
let value0 = randomValue()
|
||||
let value1 = randomValue()
|
||||
let value2 = randomValue()
|
||||
let value3 = randomValue()
|
||||
let value4 = randomValue()
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store4.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setDate(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setDate(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setDate(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setDate(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setDate(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
|
||||
// Setting as object should work.
|
||||
store4.setObject(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
// Setting as timeIntervalSince1970 should work.
|
||||
store4.setObject(value1.timeIntervalSince1970, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store4.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store4", keyStore: store4, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getDate("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store2.getDate("key0", transaction: transaction))
|
||||
XCTAssertEqual(value2, store3.getDate("key0", transaction: transaction))
|
||||
XCTAssertEqual(value3, store1.getDate("key1", transaction: transaction))
|
||||
XCTAssertEqual(value4, store2.getDate("key1", transaction: transaction))
|
||||
XCTAssertNil(store3.getDate("key1", transaction: transaction))
|
||||
|
||||
// Date edge cases.
|
||||
XCTAssertEqual(2, store4.numberOfKeys(transaction: transaction))
|
||||
XCTAssertTrue(store4.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store4.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store4.hasValue(forKey: "key2", transaction: transaction))
|
||||
XCTAssertEqual(value0, store4.getDate("key0", transaction: transaction))
|
||||
XCTAssertEqual(value1, store4.getDate("key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyValueObject() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let store1 = SDSKeyValueStore(collection: "store1")
|
||||
let store2 = SDSKeyValueStore(collection: "store2")
|
||||
let store3 = SDSKeyValueStore(collection: "store3")
|
||||
|
||||
let randomValue = {
|
||||
return UUID().uuidString
|
||||
}
|
||||
let value0: String = randomValue()
|
||||
let value1: [String] = [randomValue()]
|
||||
let value2: [String: String] = [ randomValue(): randomValue() ]
|
||||
let value3: [String] = [randomValue(), randomValue()]
|
||||
let value4: [String: String] = [
|
||||
randomValue(): randomValue(),
|
||||
randomValue(): randomValue()
|
||||
]
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
store1.setObject(value0, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store2.setObject(value1, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store3.setObject(value2, key: "key0", transaction: transaction.asAnyWrite)
|
||||
store1.setObject(value3, key: "key1", transaction: transaction.asAnyWrite)
|
||||
store2.setObject(value4, key: "key1", transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(0, store3.numberOfKeys(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store1", keyStore: store1, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store2", keyStore: store2, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "store3", keyStore: store3, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, store1.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(2, store2.numberOfKeys(transaction: transaction))
|
||||
XCTAssertEqual(1, store3.numberOfKeys(transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key0", transaction: transaction))
|
||||
XCTAssertTrue(store3.hasValue(forKey: "key0", transaction: transaction))
|
||||
|
||||
XCTAssertTrue(store1.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertTrue(store2.hasValue(forKey: "key1", transaction: transaction))
|
||||
XCTAssertFalse(store3.hasValue(forKey: "key1", transaction: transaction))
|
||||
|
||||
XCTAssertEqual(value0, store1.getObject(forKey: "key0", transaction: transaction) as! String)
|
||||
XCTAssertEqual(value1, store2.getObject(forKey: "key0", transaction: transaction) as! [String])
|
||||
XCTAssertEqual(value2, store3.getObject(forKey: "key0", transaction: transaction) as! [String: String])
|
||||
XCTAssertEqual(value3, store1.getObject(forKey: "key1", transaction: transaction) as! [String])
|
||||
XCTAssertEqual(value4, store2.getObject(forKey: "key1", transaction: transaction) as! [String: String])
|
||||
XCTAssertNil(store3.getObject(forKey: "key1", transaction: transaction))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,862 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import SignalServiceKit
|
||||
@testable import Signal
|
||||
@testable import SignalMessaging
|
||||
|
||||
extension AnyThreadFinder {
|
||||
func visibleThreadUniqueIds(isArchived: Bool, transaction: SDSAnyReadTransaction) throws -> [String] {
|
||||
var result = [String]()
|
||||
try enumerateVisibleThreads(isArchived: isArchived, transaction: transaction) { thread in
|
||||
result.append(thread.uniqueId)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
extension InteractionFinder {
|
||||
func allInteractionIds(transaction: SDSAnyReadTransaction) throws -> [String] {
|
||||
var result = [String]()
|
||||
try enumerateInteractionIds(transaction: transaction) { (uniqueId, _) in
|
||||
result.append(uniqueId)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class YDBToGRDBMigrationModelTest: SignalBaseTest {
|
||||
|
||||
private let legacyDecryptJobLabel = "SSKMessageDecrypt"
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
// ensure local client has necessary "registered" state
|
||||
let localE164Identifier = "+13235551234"
|
||||
let localUUID = UUID()
|
||||
tsAccountManager.registerForTests(withLocalNumber: localE164Identifier, uuid: localUUID)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func randomStickerPackInfo() -> StickerPackInfo {
|
||||
let packId = Randomness.generateRandomBytes(16)
|
||||
let packKey = Randomness.generateRandomBytes(Int32(StickerManager.packKeyLength))
|
||||
|
||||
return StickerPackInfo(packId: packId, packKey: packKey)
|
||||
}
|
||||
|
||||
func testSignalRecipient() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let uuid1 = UUID()
|
||||
let uuid2 = UUID()
|
||||
let uuid3 = UUID()
|
||||
let uuid4 = UUID()
|
||||
let uuid5 = UUID()
|
||||
let uuid6 = UUID()
|
||||
let phoneNumber1 = "+13213214321"
|
||||
let phoneNumber2 = "+13213214322"
|
||||
let phoneNumber3 = "+13213214323"
|
||||
let phoneNumber4 = "+13213214324"
|
||||
let phoneNumber5 = "+13213214325"
|
||||
let phoneNumber6 = "+13213214326"
|
||||
let phoneNumber7 = "+13213214327"
|
||||
let deviceId0 = NSNumber(value: OWSDevicePrimaryDeviceId)
|
||||
let deviceId1 = NSNumber(value: OWSDevicePrimaryDeviceId + 1)
|
||||
let deviceId2 = NSNumber(value: OWSDevicePrimaryDeviceId + 2)
|
||||
let model1 = SignalRecipient(phoneNumber: phoneNumber1, uuid: uuid1, devices: [deviceId0])
|
||||
let model2 = SignalRecipient(phoneNumber: phoneNumber2, uuid: uuid2, devices: [deviceId0, deviceId1])
|
||||
let model3 = SignalRecipient(phoneNumber: phoneNumber3, uuid: uuid3, devices: [deviceId0, deviceId1, deviceId2])
|
||||
// Duplicate uuid. One recipient should be discarded.
|
||||
let model4a = SignalRecipient(phoneNumber: phoneNumber4, uuid: uuid4, devices: [deviceId0])
|
||||
let model4b = SignalRecipient(phoneNumber: phoneNumber5, uuid: uuid4, devices: [deviceId0])
|
||||
// Duplicate phone, unique uuid. One recipient should lose its phone number.
|
||||
let model5a = SignalRecipient(phoneNumber: phoneNumber6, uuid: uuid5, devices: [deviceId0])
|
||||
let model5b = SignalRecipient(phoneNumber: phoneNumber6, uuid: uuid6, devices: [deviceId0])
|
||||
// Duplicate phone, no uuid. One recipient should be discarded.
|
||||
let model6a = SignalRecipient(phoneNumber: phoneNumber7, uuid: nil, devices: [deviceId0])
|
||||
let model6b = SignalRecipient(phoneNumber: phoneNumber7, uuid: nil, devices: [deviceId0])
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model1.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model2.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model3.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model4a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model4b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model5a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model5b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model6a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model6b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, SignalRecipient.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model1.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model2.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model3.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model4a.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model4b.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model5a.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model5b.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model6a.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model6b.uniqueId, transaction: transaction))
|
||||
XCTAssertEqual(0, SignalRecipient.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
model1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
// Don't insert 3.
|
||||
model4a.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model4b.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model5a.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model5b.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model6a.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model6b.anyInsert(transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model1.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model2.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model3.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model4a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model4b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model5a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model5b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model6a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model6b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(8, SignalRecipient.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model1.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model2.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model3.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model4a.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model4b.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model5a.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model5b.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model6a.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model6b.uniqueId, transaction: transaction))
|
||||
XCTAssertEqual(0, SignalRecipient.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBUnorderedRecordMigrator<SignalRecipient>(label: "SignalRecipient", ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model1.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model2.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model3.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model4a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model4b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model5a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model5b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model6a.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model6b.uniqueId, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(8, SignalRecipient.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model1.uniqueId, transaction: transaction))
|
||||
XCTAssertNotNil(SignalRecipient.anyFetch(uniqueId: model2.uniqueId, transaction: transaction))
|
||||
XCTAssertNil(SignalRecipient.anyFetch(uniqueId: model3.uniqueId, transaction: transaction))
|
||||
|
||||
// Exactly one should be migrated and one discarded.
|
||||
let model4aCopy: SignalRecipient? = SignalRecipient.anyFetch(uniqueId: model4a.uniqueId, transaction: transaction)
|
||||
let model4bCopy: SignalRecipient? = SignalRecipient.anyFetch(uniqueId: model4b.uniqueId, transaction: transaction)
|
||||
XCTAssertTrue(model4aCopy == nil || model4bCopy == nil)
|
||||
XCTAssertTrue(model4aCopy != nil || model4bCopy != nil)
|
||||
|
||||
// Both should be migrated; one will no longer have a phone number.
|
||||
let model5aCopy: SignalRecipient? = SignalRecipient.anyFetch(uniqueId: model5a.uniqueId, transaction: transaction)
|
||||
let model5bCopy: SignalRecipient? = SignalRecipient.anyFetch(uniqueId: model5b.uniqueId, transaction: transaction)
|
||||
XCTAssertNotNil(model5aCopy)
|
||||
XCTAssertNotNil(model5bCopy)
|
||||
XCTAssertTrue(model5aCopy?.recipientPhoneNumber == nil || model5bCopy?.recipientPhoneNumber == nil)
|
||||
XCTAssertTrue(model5aCopy?.recipientPhoneNumber != nil || model5bCopy?.recipientPhoneNumber != nil)
|
||||
|
||||
// Exactly one should be migrated and one discarded.
|
||||
let model6aCopy: SignalRecipient? = SignalRecipient.anyFetch(uniqueId: model6a.uniqueId, transaction: transaction)
|
||||
let model6bCopy: SignalRecipient? = SignalRecipient.anyFetch(uniqueId: model6b.uniqueId, transaction: transaction)
|
||||
XCTAssertTrue(model6aCopy == nil || model6bCopy == nil)
|
||||
XCTAssertTrue(model6aCopy != nil || model6bCopy != nil)
|
||||
|
||||
XCTAssertEqual(6, SignalRecipient.anyCount(transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func randomKnownStickerPack() -> KnownStickerPack {
|
||||
return KnownStickerPack(info: randomStickerPackInfo())
|
||||
}
|
||||
|
||||
func testKnownStickerPack() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
let model1 = randomKnownStickerPack()
|
||||
let model2 = randomKnownStickerPack()
|
||||
let model3 = randomKnownStickerPack()
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model1.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model2.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model3.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, KnownStickerPack.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model1.info), transaction: transaction))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model2.info), transaction: transaction))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model3.info), transaction: transaction))
|
||||
XCTAssertEqual(0, KnownStickerPack.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
model1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
model2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
// Don't insert 3.
|
||||
}
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertNotNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model1.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model2.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model3.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, KnownStickerPack.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model1.info), transaction: transaction))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model2.info), transaction: transaction))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model3.info), transaction: transaction))
|
||||
XCTAssertEqual(0, KnownStickerPack.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBUnorderedRecordMigrator<KnownStickerPack>(label: "KnownStickerPack", ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertNotNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model1.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertNotNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model2.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model3.info), transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, KnownStickerPack.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertNotNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model1.info), transaction: transaction))
|
||||
XCTAssertNotNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model2.info), transaction: transaction))
|
||||
XCTAssertNil(KnownStickerPack.anyFetch(uniqueId: KnownStickerPack.uniqueId(for: model3.info), transaction: transaction))
|
||||
XCTAssertEqual(2, KnownStickerPack.anyCount(transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
func testJobs() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
// SSKMessageDecryptJobRecord
|
||||
let messageDecryptData1 = Randomness.generateRandomBytes(1024)
|
||||
let messageDecryptData2 = Randomness.generateRandomBytes(1024)
|
||||
// OWSSessionResetJobRecord
|
||||
let contactThread1 = TSContactThread(contactAddress: SignalServiceAddress(phoneNumber: "+13213334444"))
|
||||
let contactThread2 = TSContactThread(contactAddress: SignalServiceAddress(phoneNumber: "+13213334445"))
|
||||
// SSKMessageSenderJobRecord
|
||||
let outgoingMessage1 = TSOutgoingMessage(in: contactThread1, messageBody: "good heavens", attachmentId: nil)
|
||||
let outgoingMessage2 = TSOutgoingMessage(in: contactThread1, messageBody: "land's sakes", attachmentId: nil)
|
||||
let outgoingMessage3 = TSOutgoingMessage(in: contactThread2, messageBody: "oh my word", attachmentId: nil)
|
||||
// OWSMessageDecryptJob
|
||||
let messageDecryptData3 = Randomness.generateRandomBytes(1024)
|
||||
let messageDecryptData4 = Randomness.generateRandomBytes(1024)
|
||||
|
||||
// SSKMessageDecryptJobRecord
|
||||
let messageDecryptJobFinder1 = AnyJobRecordFinder<SSKMessageDecryptJobRecord>()
|
||||
// OWSSessionResetJobRecord
|
||||
let sessionResetJobFinder = AnyJobRecordFinder<OWSSessionResetJobRecord>()
|
||||
let sessionResetJobQueue = SessionResetJobQueue()
|
||||
// SSKMessageSenderJobRecord
|
||||
let messageSenderJobFinder = AnyJobRecordFinder<SSKMessageSenderJobRecord>()
|
||||
let messageSenderJobQueue = MessageSenderJobQueue()
|
||||
// OWSMessageDecryptJob
|
||||
let messageDecryptJobFinder2 = OWSMessageDecryptJobFinder()
|
||||
|
||||
self.yapRead { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
// OWSMessageDecryptJob
|
||||
XCTAssertNil(messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder2.queuedJobCount(with: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// NOTE: We don't need to verify that GRDB contains no
|
||||
// OWSMessageDecryptJobs; the table doesn't even exist.
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
SSKMessageDecryptJobRecord(
|
||||
envelopeData: messageDecryptData1,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
label: self.legacyDecryptJobLabel
|
||||
).anyInsert(transaction: transaction.asAnyWrite)
|
||||
SSKMessageDecryptJobRecord(
|
||||
envelopeData: messageDecryptData2,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
label: self.legacyDecryptJobLabel
|
||||
).anyInsert(transaction: transaction.asAnyWrite)
|
||||
|
||||
// OWSSessionResetJobRecord
|
||||
sessionResetJobQueue.add(contactThread: contactThread1, transaction: transaction.asAnyWrite)
|
||||
sessionResetJobQueue.add(contactThread: contactThread2, transaction: transaction.asAnyWrite)
|
||||
// SSKMessageSenderJobRecord
|
||||
contactThread1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
contactThread2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage3.anyInsert(transaction: transaction.asAnyWrite)
|
||||
messageSenderJobQueue.add(message: outgoingMessage1.asPreparer, transaction: transaction.asAnyWrite)
|
||||
messageSenderJobQueue.add(message: outgoingMessage2.asPreparer, transaction: transaction.asAnyWrite)
|
||||
messageSenderJobQueue.add(message: outgoingMessage3.asPreparer, transaction: transaction.asAnyWrite)
|
||||
// OWSMessageDecryptJob
|
||||
messageDecryptJobFinder2.addJob(forEnvelopeData: messageDecryptData3,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
transaction: transaction.asAnyWrite)
|
||||
messageDecryptJobFinder2.addJob(forEnvelopeData: messageDecryptData4,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.yapRead { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNotNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([messageDecryptData1, messageDecryptData2 ], messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.envelopeData })
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNotNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId ], sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.contactThreadId })
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNotNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(3, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId ], messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.messageId })
|
||||
// OWSMessageDecryptJob
|
||||
XCTAssertNotNil(messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder2.queuedJobCount(with: transaction.asAnyRead))
|
||||
XCTAssertEqual(messageDecryptData3, messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead)!.envelopeData)
|
||||
}
|
||||
self.read { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// NOTE: We don't need to verify that GRDB contains no
|
||||
// OWSMessageDecryptJobs; the table doesn't even exist.
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBJobRecordMigrator(ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.yapRead { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNotNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([messageDecryptData1, messageDecryptData2 ], messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.envelopeData })
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNotNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId ], sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.contactThreadId })
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNotNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(3, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId ], messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.messageId })
|
||||
// OWSMessageDecryptJob
|
||||
XCTAssertNotNil(messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder2.queuedJobCount(with: transaction.asAnyRead))
|
||||
XCTAssertEqual(messageDecryptData3, messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead)!.envelopeData)
|
||||
}
|
||||
self.read { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNotNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).count)
|
||||
XCTAssertEqual([messageDecryptData1, messageDecryptData2 ], messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).compactMap { $0.envelopeData })
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNotNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(2, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId ], sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).compactMap { $0.contactThreadId })
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNotNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(3, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId ], messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).compactMap { $0.messageId })
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// NOTE: These jobs are _NOT_ migrated.
|
||||
// See testDecryptJobs() which uses GRDBDecryptJobMigrator.
|
||||
//
|
||||
// NOTE: We don't need to verify that GRDB contains no
|
||||
// OWSMessageDecryptJobs; the table doesn't even exist.
|
||||
}
|
||||
}
|
||||
|
||||
func testDecryptJobs() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
// SSKMessageDecryptJobRecord
|
||||
let messageDecryptData1 = Randomness.generateRandomBytes(1024)
|
||||
let messageDecryptData2 = Randomness.generateRandomBytes(1024)
|
||||
// OWSSessionResetJobRecord
|
||||
let contactThread1 = TSContactThread(contactAddress: SignalServiceAddress(phoneNumber: "+13213334444"))
|
||||
let contactThread2 = TSContactThread(contactAddress: SignalServiceAddress(phoneNumber: "+13213334445"))
|
||||
// SSKMessageSenderJobRecord
|
||||
let outgoingMessage1 = TSOutgoingMessage(in: contactThread1, messageBody: "good heavens", attachmentId: nil)
|
||||
let outgoingMessage2 = TSOutgoingMessage(in: contactThread1, messageBody: "land's sakes", attachmentId: nil)
|
||||
let outgoingMessage3 = TSOutgoingMessage(in: contactThread2, messageBody: "oh my word", attachmentId: nil)
|
||||
// OWSMessageDecryptJob
|
||||
let messageDecryptData3 = Randomness.generateRandomBytes(1024)
|
||||
let messageDecryptData4 = Randomness.generateRandomBytes(1024)
|
||||
|
||||
// SSKMessageDecryptJobRecord
|
||||
let messageDecryptJobFinder1 = AnyJobRecordFinder<SSKMessageDecryptJobRecord>()
|
||||
// OWSSessionResetJobRecord
|
||||
let sessionResetJobFinder = AnyJobRecordFinder<OWSSessionResetJobRecord>()
|
||||
let sessionResetJobQueue = SessionResetJobQueue()
|
||||
// SSKMessageSenderJobRecord
|
||||
let messageSenderJobFinder = AnyJobRecordFinder<SSKMessageSenderJobRecord>()
|
||||
let messageSenderJobQueue = MessageSenderJobQueue()
|
||||
// OWSMessageDecryptJob
|
||||
let messageDecryptJobFinder2 = OWSMessageDecryptJobFinder()
|
||||
|
||||
self.yapRead { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
// OWSMessageDecryptJob
|
||||
XCTAssertNil(messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder2.queuedJobCount(with: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// NOTE: We don't need to verify that GRDB contains no
|
||||
// OWSMessageDecryptJobs; the table doesn't even exist.
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
SSKMessageDecryptJobRecord(
|
||||
envelopeData: messageDecryptData1,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
label: self.legacyDecryptJobLabel
|
||||
).anyInsert(transaction: transaction.asAnyWrite)
|
||||
SSKMessageDecryptJobRecord(
|
||||
envelopeData: messageDecryptData2,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
label: self.legacyDecryptJobLabel
|
||||
).anyInsert(transaction: transaction.asAnyWrite)
|
||||
|
||||
// OWSSessionResetJobRecord
|
||||
sessionResetJobQueue.add(contactThread: contactThread1, transaction: transaction.asAnyWrite)
|
||||
sessionResetJobQueue.add(contactThread: contactThread2, transaction: transaction.asAnyWrite)
|
||||
// SSKMessageSenderJobRecord
|
||||
contactThread1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
contactThread2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage3.anyInsert(transaction: transaction.asAnyWrite)
|
||||
messageSenderJobQueue.add(message: outgoingMessage1.asPreparer, transaction: transaction.asAnyWrite)
|
||||
messageSenderJobQueue.add(message: outgoingMessage2.asPreparer, transaction: transaction.asAnyWrite)
|
||||
messageSenderJobQueue.add(message: outgoingMessage3.asPreparer, transaction: transaction.asAnyWrite)
|
||||
// OWSMessageDecryptJob
|
||||
messageDecryptJobFinder2.addJob(forEnvelopeData: messageDecryptData3,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
transaction: transaction.asAnyWrite)
|
||||
messageDecryptJobFinder2.addJob(forEnvelopeData: messageDecryptData4,
|
||||
serverDeliveryTimestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.yapRead { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNotNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([messageDecryptData1, messageDecryptData2 ], messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.envelopeData })
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNotNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId ], sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.contactThreadId })
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNotNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(3, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId ], messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.messageId })
|
||||
// OWSMessageDecryptJob
|
||||
XCTAssertNotNil(messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder2.queuedJobCount(with: transaction.asAnyRead))
|
||||
XCTAssertEqual(messageDecryptData3, messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead)!.envelopeData)
|
||||
}
|
||||
self.read { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// NOTE: We don't need to verify that GRDB contains no
|
||||
// OWSMessageDecryptJobs; the table doesn't even exist.
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBDecryptJobMigrator(ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.yapRead { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
XCTAssertNotNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([messageDecryptData1, messageDecryptData2 ], messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.envelopeData })
|
||||
// OWSSessionResetJobRecord
|
||||
XCTAssertNotNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId ], sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.contactThreadId })
|
||||
// SSKMessageSenderJobRecord
|
||||
XCTAssertNotNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(3, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).count)
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId ], messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction.asAnyRead).compactMap { $0.messageId })
|
||||
// OWSMessageDecryptJob
|
||||
XCTAssertNotNil(messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder2.queuedJobCount(with: transaction.asAnyRead))
|
||||
XCTAssertEqual(messageDecryptData3, messageDecryptJobFinder2.nextJob(transaction: transaction.asAnyRead)!.envelopeData)
|
||||
}
|
||||
self.read { transaction in
|
||||
// SSKMessageDecryptJobRecord
|
||||
//
|
||||
// NOTE: These jobs are migrated from OWSMessageDecryptJob.
|
||||
XCTAssertNotNil(messageDecryptJobFinder1.getNextReady(label: self.legacyDecryptJobLabel, transaction: transaction))
|
||||
XCTAssertEqual(2, messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).count)
|
||||
XCTAssertEqual([messageDecryptData3, messageDecryptData4 ], messageDecryptJobFinder1.allRecords(label: self.legacyDecryptJobLabel, status: .ready, transaction: transaction).compactMap { $0.envelopeData })
|
||||
// OWSSessionResetJobRecord
|
||||
//
|
||||
// NOTE: These jobs are _NOT_ migrated.
|
||||
XCTAssertNil(sessionResetJobFinder.getNextReady(label: sessionResetJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, sessionResetJobFinder.allRecords(label: sessionResetJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// SSKMessageSenderJobRecord
|
||||
//
|
||||
// NOTE: These jobs are _NOT_ migrated.
|
||||
XCTAssertNil(messageSenderJobFinder.getNextReady(label: MessageSenderJobQueue.jobRecordLabel, transaction: transaction))
|
||||
XCTAssertEqual(0, messageSenderJobFinder.allRecords(label: MessageSenderJobQueue.jobRecordLabel, status: .ready, transaction: transaction).count)
|
||||
// OWSMessageDecryptJob
|
||||
//
|
||||
// NOTE: These jobs are migrated to SSKMessageDecryptJobRecord.
|
||||
//
|
||||
// NOTE: We don't need to verify that GRDB contains no
|
||||
// OWSMessageDecryptJobs; the table doesn't even exist.
|
||||
}
|
||||
}
|
||||
|
||||
func testInteractions() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
// Threads
|
||||
let contactThread1 = TSContactThread(contactAddress: SignalServiceAddress(phoneNumber: "+13213334444"))
|
||||
let contactThread2 = TSContactThread(contactAddress: SignalServiceAddress(phoneNumber: "+13213334445"))
|
||||
// Attachments
|
||||
let attachmentData1 = Randomness.generateRandomBytes(1024)
|
||||
let attachment1 = TSAttachmentStream(contentType: OWSMimeTypeImageGif,
|
||||
byteCount: UInt32(attachmentData1.count),
|
||||
sourceFilename: "some.gif", caption: nil, albumMessageId: nil)
|
||||
let attachmentData2 = Randomness.generateRandomBytes(2048)
|
||||
let attachment2 = TSAttachmentStream(contentType: OWSMimeTypePdf,
|
||||
byteCount: UInt32(attachmentData2.count),
|
||||
sourceFilename: "some.df", caption: nil, albumMessageId: nil)
|
||||
// Messages
|
||||
let outgoingMessage1 = TSOutgoingMessage(in: contactThread1, messageBody: "good heavens", attachmentId: attachment1.uniqueId)
|
||||
let outgoingMessage2 = TSOutgoingMessage(in: contactThread2, messageBody: "land's sakes", attachmentId: attachment2.uniqueId)
|
||||
let outgoingMessage3 = TSOutgoingMessage(in: contactThread2, messageBody: "oh my word", attachmentId: nil)
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertEqual(0, TSThread.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, TSThread.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSInteraction.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
self.yapWrite { transaction in
|
||||
// Threads
|
||||
contactThread1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
contactThread2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
// Attachments
|
||||
attachment1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
attachment2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
// Messages
|
||||
outgoingMessage1.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage2.anyInsert(transaction: transaction.asAnyWrite)
|
||||
outgoingMessage3.anyInsert(transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertEqual(2, TSThread.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId].sorted(), TSThread.anyAllUniqueIds(transaction: transaction.asAnyRead).sorted())
|
||||
XCTAssertEqual(3, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId].sorted(), TSInteraction.anyAllUniqueIds(transaction: transaction.asAnyRead).sorted())
|
||||
XCTAssertEqual([outgoingMessage1, outgoingMessage2, outgoingMessage3].compactMap { $0.body }.sorted(), TSInteraction.anyFetchAll(transaction: transaction.asAnyRead).compactMap { ($0 as! TSMessage).body }.sorted())
|
||||
XCTAssertEqual(2, TSAttachment.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([attachment1.uniqueId, attachment2.uniqueId].sorted(), TSAttachment.anyAllUniqueIds(transaction: transaction.asAnyRead).sorted())
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, TSThread.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSInteraction.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBUnorderedRecordMigrator<TSAttachment>(label: "attachments", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<TSThread>(label: "threads", ydbTransaction: ydbTransaction)
|
||||
]
|
||||
},
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBInteractionMigrator(ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertEqual(2, TSThread.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId].sorted(), TSThread.anyAllUniqueIds(transaction: transaction.asAnyRead).sorted())
|
||||
XCTAssertEqual(3, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId].sorted(), TSInteraction.anyAllUniqueIds(transaction: transaction.asAnyRead).sorted())
|
||||
XCTAssertEqual([outgoingMessage1, outgoingMessage2, outgoingMessage3].compactMap { $0.body }.sorted(), TSInteraction.anyFetchAll(transaction: transaction.asAnyRead).compactMap { ($0 as! TSMessage).body }.sorted())
|
||||
XCTAssertEqual(2, TSAttachment.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([attachment1.uniqueId, attachment2.uniqueId].sorted(), TSAttachment.anyAllUniqueIds(transaction: transaction.asAnyRead).sorted())
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(2, TSThread.anyCount(transaction: transaction))
|
||||
XCTAssertEqual([contactThread1.uniqueId, contactThread2.uniqueId].sorted(), TSThread.anyAllUniqueIds(transaction: transaction).sorted())
|
||||
XCTAssertEqual(3, TSInteraction.anyCount(transaction: transaction))
|
||||
XCTAssertEqual([outgoingMessage1.uniqueId, outgoingMessage2.uniqueId, outgoingMessage3.uniqueId].sorted(), TSInteraction.anyAllUniqueIds(transaction: transaction).sorted())
|
||||
XCTAssertEqual([outgoingMessage1, outgoingMessage2, outgoingMessage3].compactMap { $0.body }.sorted(), TSInteraction.anyFetchAll(transaction: transaction).compactMap { ($0 as! TSMessage).body }.sorted())
|
||||
XCTAssertEqual(2, TSAttachment.anyCount(transaction: transaction))
|
||||
XCTAssertEqual([attachment1.uniqueId, attachment2.uniqueId].sorted(), TSAttachment.anyAllUniqueIds(transaction: transaction).sorted())
|
||||
}
|
||||
}
|
||||
|
||||
func testThreadAndInteractionOrdering() {
|
||||
storageCoordinator.useGRDBForTests()
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertEqual(0, TSThread.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, TSThread.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSInteraction.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
// Threads
|
||||
let contactThreadFactory = ContactThreadFactory()
|
||||
let groupThreadFactory = GroupThreadFactory()
|
||||
var thread1: TSThread!
|
||||
var thread2: TSThread!
|
||||
var thread3: TSThread!
|
||||
var thread4: TSThread!
|
||||
|
||||
var message1: TSInteraction!
|
||||
var message2: TSInteraction!
|
||||
var message3: TSInteraction!
|
||||
var message4: TSInteraction!
|
||||
var message5: TSInteraction!
|
||||
var message6: TSInteraction!
|
||||
var message7: TSInteraction!
|
||||
var message8: TSInteraction!
|
||||
self.yapWrite { transaction in
|
||||
thread1 = contactThreadFactory.create(transaction: transaction.asAnyWrite)
|
||||
thread2 = groupThreadFactory.create(transaction: transaction.asAnyWrite)
|
||||
thread3 = contactThreadFactory.create(transaction: transaction.asAnyWrite)
|
||||
thread4 = groupThreadFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
// There should be 2 "group update" info messages.
|
||||
XCTAssertEqual(2, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
// For simplicity, remove the "group update" info messages.
|
||||
do {
|
||||
let interactions = TSInteraction.anyFetchAll(transaction: transaction.asAnyRead)
|
||||
for interaction in interactions {
|
||||
interaction.anyRemove(transaction: transaction.asAnyWrite)
|
||||
}
|
||||
}
|
||||
|
||||
let messageFactory = IncomingMessageFactory()
|
||||
|
||||
// We deliberately interleave message order across different
|
||||
// threads.
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread1 }
|
||||
message1 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread2 }
|
||||
message2 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread3 }
|
||||
message3 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread4 }
|
||||
message4 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread1 }
|
||||
message5 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread2 }
|
||||
message6 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread3 }
|
||||
message7 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
|
||||
messageFactory.threadCreator = { _ in return thread4 }
|
||||
message8 = messageFactory.create(transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertEqual(4, TSThread.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(8, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction.asAnyRead))
|
||||
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread1.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread2.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread3.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread4.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(0, TSThread.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSInteraction.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction))
|
||||
}
|
||||
|
||||
let migratorGroups = [
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBUnorderedRecordMigrator<TSAttachment>(label: "attachments", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<TSThread>(label: "threads", ydbTransaction: ydbTransaction)
|
||||
]
|
||||
},
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [
|
||||
GRDBInteractionMigrator(ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
try! YDBToGRDBMigration().migrate(migratorGroups: migratorGroups)
|
||||
|
||||
self.yapRead { transaction in
|
||||
XCTAssertEqual(4, TSThread.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(8, TSInteraction.anyCount(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction.asAnyRead))
|
||||
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread1.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread2.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread3.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread4.uniqueId).count(transaction: transaction.asAnyRead))
|
||||
|
||||
XCTAssertEqual(4, try! AnyThreadFinder().visibleThreadCount(isArchived: false, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([thread4.uniqueId, thread3.uniqueId, thread2.uniqueId, thread1.uniqueId ], try! AnyThreadFinder().visibleThreadUniqueIds(isArchived: false, transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([message5.uniqueId, message1.uniqueId ], try! InteractionFinder(threadUniqueId: thread1.uniqueId).allInteractionIds(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([message6.uniqueId, message2.uniqueId ], try! InteractionFinder(threadUniqueId: thread2.uniqueId).allInteractionIds(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([message7.uniqueId, message3.uniqueId ], try! InteractionFinder(threadUniqueId: thread3.uniqueId).allInteractionIds(transaction: transaction.asAnyRead))
|
||||
XCTAssertEqual([message8.uniqueId, message4.uniqueId ], try! InteractionFinder(threadUniqueId: thread4.uniqueId).allInteractionIds(transaction: transaction.asAnyRead))
|
||||
}
|
||||
self.read { transaction in
|
||||
XCTAssertEqual(4, TSThread.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(8, TSInteraction.anyCount(transaction: transaction))
|
||||
XCTAssertEqual(0, TSAttachment.anyCount(transaction: transaction))
|
||||
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread1.uniqueId).count(transaction: transaction))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread2.uniqueId).count(transaction: transaction))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread3.uniqueId).count(transaction: transaction))
|
||||
XCTAssertEqual(2, InteractionFinder(threadUniqueId: thread4.uniqueId).count(transaction: transaction))
|
||||
|
||||
XCTAssertEqual(4, try! AnyThreadFinder().visibleThreadCount(isArchived: false, transaction: transaction))
|
||||
XCTAssertEqual([thread4.uniqueId, thread3.uniqueId, thread2.uniqueId, thread1.uniqueId ], try! AnyThreadFinder().visibleThreadUniqueIds(isArchived: false, transaction: transaction))
|
||||
XCTAssertEqual([message5.uniqueId, message1.uniqueId ], try! InteractionFinder(threadUniqueId: thread1.uniqueId).allInteractionIds(transaction: transaction))
|
||||
XCTAssertEqual([message6.uniqueId, message2.uniqueId ], try! InteractionFinder(threadUniqueId: thread2.uniqueId).allInteractionIds(transaction: transaction))
|
||||
XCTAssertEqual([message7.uniqueId, message3.uniqueId ], try! InteractionFinder(threadUniqueId: thread3.uniqueId).allInteractionIds(transaction: transaction))
|
||||
XCTAssertEqual([message8.uniqueId, message4.uniqueId ], try! InteractionFinder(threadUniqueId: thread4.uniqueId).allInteractionIds(transaction: transaction))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3226,6 +3226,12 @@
|
||||
/* Title of the 'onboarding Captcha' view. */
|
||||
"ONBOARDING_CAPTCHA_TITLE" = "Add a touch of humanity to your messages";
|
||||
|
||||
/* Explanation on the 'onboarding after dropped YDB' view. */
|
||||
"ONBOARDING_DROPPED_YDB_EXPLANATION" = "Because you’ve been inactive for a long period of time, you must register again to use Signal.";
|
||||
|
||||
/* Title of the 'onboarding after dropped YDB' view. */
|
||||
"ONBOARDING_DROPPED_YDB_TITLE" = "Register for Signal";
|
||||
|
||||
/* button indicating that the user will register their ipad */
|
||||
"ONBOARDING_MODE_SWITCH_BUTTON_PROVISIONING" = "Register iPad";
|
||||
|
||||
|
||||
@ -21,15 +21,6 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
|
||||
#import <SignalMessaging/CountryCodeViewController.h>
|
||||
#import <SignalMessaging/DebugLogger.h>
|
||||
#import <SignalMessaging/Environment.h>
|
||||
#import <SignalMessaging/OWS100RemoveTSRecipientsMigration.h>
|
||||
#import <SignalMessaging/OWS101ExistingUsersBlockOnIdentityChange.h>
|
||||
#import <SignalMessaging/OWS102MoveLoggingPreferenceToUserDefaults.h>
|
||||
#import <SignalMessaging/OWS103EnableVideoCalling.h>
|
||||
#import <SignalMessaging/OWS104CreateRecipientIdentities.h>
|
||||
#import <SignalMessaging/OWS105AttachmentFilePaths.h>
|
||||
#import <SignalMessaging/OWS107LegacySounds.h>
|
||||
#import <SignalMessaging/OWS108CallLoggingPreference.h>
|
||||
#import <SignalMessaging/OWS109OutgoingMessageState.h>
|
||||
#import <SignalMessaging/OWSAnyTouchGestureRecognizer.h>
|
||||
#import <SignalMessaging/OWSAudioPlayer.h>
|
||||
#import <SignalMessaging/OWSBubbleShapeView.h>
|
||||
@ -37,7 +28,6 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
|
||||
#import <SignalMessaging/OWSContactAvatarBuilder.h>
|
||||
#import <SignalMessaging/OWSContactsManager.h>
|
||||
#import <SignalMessaging/OWSConversationColor.h>
|
||||
#import <SignalMessaging/OWSDatabaseMigration.h>
|
||||
#import <SignalMessaging/OWSGroupAvatarBuilder.h>
|
||||
#import <SignalMessaging/OWSMessageTextView.h>
|
||||
#import <SignalMessaging/OWSNavigationController.h>
|
||||
@ -52,7 +42,6 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
|
||||
#import <SignalMessaging/OWSTextField.h>
|
||||
#import <SignalMessaging/OWSTextView.h>
|
||||
#import <SignalMessaging/OWSWindowManager.h>
|
||||
#import <SignalMessaging/PrivateMethodsForMigration.h>
|
||||
#import <SignalMessaging/ScreenLockViewController.h>
|
||||
#import <SignalMessaging/SelectThreadViewController.h>
|
||||
#import <SignalMessaging/Theme.h>
|
||||
|
||||
@ -5,18 +5,15 @@
|
||||
#import "ThreadViewHelper.h"
|
||||
#import <SignalServiceKit/AppContext.h>
|
||||
#import <SignalServiceKit/AppReadiness.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/SSKEnvironment.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/StorageCoordinator.h>
|
||||
#import <SignalServiceKit/TSDatabaseView.h>
|
||||
#import <SignalServiceKit/TSThread.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ThreadViewHelper () <UIDatabaseSnapshotDelegate>
|
||||
|
||||
@property (nonatomic, nullable) YapDatabaseViewMappings *threadMappings;
|
||||
@property (nonatomic) BOOL shouldObserveDBModifications;
|
||||
|
||||
@end
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#import "Environment.h"
|
||||
#import "Theme.h"
|
||||
#import "VersionMigrations.h"
|
||||
#import <SignalMessaging/OWSDatabaseMigration.h>
|
||||
#import <SignalMessaging/OWSProfileManager.h>
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalMetadataKit/SignalMetadataKit-Swift.h>
|
||||
@ -18,7 +17,6 @@
|
||||
#import <SignalServiceKit/OWSMessageManager.h>
|
||||
#import <SignalServiceKit/OWSOutgoingReceiptManager.h>
|
||||
#import <SignalServiceKit/OWSReadReceiptManager.h>
|
||||
#import <SignalServiceKit/OWSStorage.h>
|
||||
#import <SignalServiceKit/SSKEnvironment.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TSSocketManager.h>
|
||||
@ -48,10 +46,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
StorageCoordinator *storageCoordinator = [StorageCoordinator new];
|
||||
SDSDatabaseStorage *databaseStorage = storageCoordinator.databaseStorage;
|
||||
OWSPrimaryStorage *_Nullable primaryStorage;
|
||||
if (databaseStorage.canLoadYdb) {
|
||||
primaryStorage = databaseStorage.yapPrimaryStorage;
|
||||
}
|
||||
|
||||
// AFNetworking (via CFNetworking) spools it's attachments to NSTemporaryDirectory().
|
||||
// If you receive a media message while the device is locked, the download will fail if the temporary directory
|
||||
@ -136,7 +130,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageSenderJobQueue:messageSenderJobQueue
|
||||
pendingReadReceiptRecorder:pendingReadReceiptRecorder
|
||||
profileManager:profileManager
|
||||
primaryStorage:primaryStorage
|
||||
networkManager:networkManager
|
||||
messageManager:messageManager
|
||||
blockingManager:blockingManager
|
||||
@ -183,7 +176,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Register renamed classes.
|
||||
[NSKeyedUnarchiver setClass:[OWSUserProfile class] forClassName:[OWSUserProfile collection]];
|
||||
[NSKeyedUnarchiver setClass:[OWSDatabaseMigration class] forClassName:[OWSDatabaseMigration collection]];
|
||||
[NSKeyedUnarchiver setClass:[ExperienceUpgrade class] forClassName:[ExperienceUpgrade collection]];
|
||||
[NSKeyedUnarchiver setClass:[ExperienceUpgrade class] forClassName:@"Signal.ExperienceUpgrade"];
|
||||
[NSKeyedUnarchiver setClass:[OWSGroupInfoRequestMessage class] forClassName:@"OWSSyncGroupsRequestMessage"];
|
||||
@ -230,11 +222,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
});
|
||||
};
|
||||
|
||||
if (databaseStorage.canLoadYdb) {
|
||||
[OWSStorage registerExtensionsWithCompletionBlock:completionBlock];
|
||||
} else {
|
||||
completionBlock();
|
||||
}
|
||||
completionBlock();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -4,17 +4,14 @@
|
||||
|
||||
#import "VersionMigrations.h"
|
||||
#import "Environment.h"
|
||||
#import "OWSDatabaseMigrationRunner.h"
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalServiceKit/AppContext.h>
|
||||
#import <SignalServiceKit/AppVersion.h>
|
||||
#import <SignalServiceKit/NSUserDefaults+OWS.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/OWSRequestFactory.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TSAccountManager.h>
|
||||
#import <SignalServiceKit/TSNetworkManager.h>
|
||||
#import <YapDatabase/YapDatabase.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -43,52 +40,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
if (!lastCompletedLaunchAppVersion) {
|
||||
OWSLogInfo(@"No previous version found. Probably first launch since install - nothing to migrate.");
|
||||
if (self.databaseStorage.canReadFromGrdb) {
|
||||
[self.databaseStorage runGrdbSchemaMigrationsWithCompletion:completion];
|
||||
} else {
|
||||
OWSDatabaseMigrationRunner *runner = [OWSDatabaseMigrationRunner new];
|
||||
[runner assumeAllExistingMigrationsRun];
|
||||
dispatch_async(dispatch_get_main_queue(), completion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self isVersion:lastCompletedLaunchAppVersion atLeast:@"1.0.2" andLessThan:@"2.0"]) {
|
||||
OWSLogError(@"Migrating from RedPhone no longer supported. Quitting.");
|
||||
// Not translating these as so few are affected.
|
||||
ActionSheetController *actionSheet = [[ActionSheetController alloc]
|
||||
initWithTitle:@"You must reinstall Signal"
|
||||
message:@"Sorry, your installation is too old for us to update. You'll have to start fresh."];
|
||||
|
||||
ActionSheetAction *quitAction = [[ActionSheetAction alloc] initWithTitle:@"Quit"
|
||||
style:ActionSheetActionStyleDefault
|
||||
handler:^(ActionSheetAction *_Nonnull action) {
|
||||
OWSFail(@"Obsolete install.");
|
||||
}];
|
||||
[actionSheet addAction:quitAction];
|
||||
|
||||
[CurrentAppContext().frontmostViewController presentActionSheet:actionSheet];
|
||||
}
|
||||
|
||||
if ([self isVersion:lastCompletedLaunchAppVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] &&
|
||||
[self.tsAccountManager isRegistered]) {
|
||||
[self clearVideoCache];
|
||||
}
|
||||
|
||||
if ([self isVersion:lastCompletedLaunchAppVersion atLeast:@"2.0.0" andLessThan:@"2.3.0"] &&
|
||||
[self.tsAccountManager isRegistered]) {
|
||||
[self clearBloomFilterCache];
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
if (self.databaseStorage.canReadFromGrdb) {
|
||||
[self.databaseStorage runGrdbSchemaMigrationsWithCompletion:completion];
|
||||
} else {
|
||||
[[[OWSDatabaseMigrationRunner alloc] init] runAllOutstandingWithCompletion:^{
|
||||
completion();
|
||||
}];
|
||||
}
|
||||
});
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
^{ [self.databaseStorage runGrdbSchemaMigrationsWithCompletion:completion]; });
|
||||
}
|
||||
|
||||
+ (BOOL)isVersion:(NSString *)thisVersionString
|
||||
@ -109,55 +64,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending;
|
||||
}
|
||||
|
||||
#pragma mark Upgrading to 2.1 - Removing video cache folder
|
||||
|
||||
+ (void)clearVideoCache
|
||||
{
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
|
||||
basePath = [basePath stringByAppendingPathComponent:@"videos"];
|
||||
|
||||
NSError *error;
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:basePath]) {
|
||||
[NSFileManager.defaultManager removeItemAtPath:basePath error:&error];
|
||||
}
|
||||
|
||||
if (error) {
|
||||
OWSLogError(
|
||||
@"An error occured while removing the videos cache folder from old location: %@", error.debugDescription);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Upgrading to 2.3.0
|
||||
|
||||
// We removed bloom filter contact discovery. Clean up any local bloom filter data.
|
||||
+ (void)clearBloomFilterCache
|
||||
{
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSArray *cachesDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *bloomFilterPath = [[cachesDir objectAtIndex:0] stringByAppendingPathComponent:@"bloomfilter"];
|
||||
|
||||
if ([fm fileExistsAtPath:bloomFilterPath]) {
|
||||
NSError *deleteError;
|
||||
if ([fm removeItemAtPath:bloomFilterPath error:&deleteError]) {
|
||||
OWSLogInfo(@"Successfully removed bloom filter cache.");
|
||||
|
||||
if (self.databaseStorage.canLoadYdb) {
|
||||
[OWSPrimaryStorage.dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[transaction removeAllObjectsInCollection:@"TSRecipient"];
|
||||
}];
|
||||
OWSLogInfo(
|
||||
@"Removed all TSRecipient records - will be replaced by SignalRecipients at next address sync.");
|
||||
}
|
||||
} else {
|
||||
OWSLogError(@"Failed to remove bloom filter cache with error: %@", deleteError.localizedDescription);
|
||||
}
|
||||
} else {
|
||||
OWSLogDebug(@"No bloom filter cache to remove.");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS100RemoveTSRecipientsMigration : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,31 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS100RemoveTSRecipientsMigration.h"
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS100RemoveTSRecipientsMigrationId = @"100";
|
||||
|
||||
@implementation OWS100RemoveTSRecipientsMigration
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS100RemoveTSRecipientsMigrationId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
NSUInteger legacyRecipientCount = [transaction numberOfKeysInCollection:@"TSRecipient"];
|
||||
OWSLogWarn(@"Removing %lu objects from TSRecipient collection", (unsigned long)legacyRecipientCount);
|
||||
[transaction removeAllObjectsInCollection:@"TSRecipient"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS101ExistingUsersBlockOnIdentityChange : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,34 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS101ExistingUsersBlockOnIdentityChange.h"
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS101ExistingUsersBlockOnIdentityChangeMigrationId = @"101";
|
||||
|
||||
/**
|
||||
* This migration is no longer necessary, but deleting a class is complicated in Yap
|
||||
* and involves writing another migration to remove the previous. It seemed like the
|
||||
* simplest/safest thing to do would be to just leave it.
|
||||
*/
|
||||
@implementation OWS101ExistingUsersBlockOnIdentityChange
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS101ExistingUsersBlockOnIdentityChangeMigrationId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
OWSFailDebug(@"[OWS101ExistingUsersBlockOnIdentityChange] has been obviated.");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,9 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
@interface OWS102MoveLoggingPreferenceToUserDefaults : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
@ -1,47 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS102MoveLoggingPreferenceToUserDefaults.h"
|
||||
#import "DebugLogger.h"
|
||||
#import "Environment.h"
|
||||
#import "OWSPreferences.h"
|
||||
#import <YapDatabase/YapDatabase.h>
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS102MoveLoggingPreferenceToUserDefaultsMigrationId = @"102";
|
||||
|
||||
@implementation OWS102MoveLoggingPreferenceToUserDefaults
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS102MoveLoggingPreferenceToUserDefaultsMigrationId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
OWSLogWarn(@"[OWS102MoveLoggingPreferenceToUserDefaultsMigrationId] copying existing logging preference to "
|
||||
@"NSUserDefaults");
|
||||
|
||||
NSNumber *_Nullable existingValue =
|
||||
[transaction objectForKey:OWSPreferencesKeyEnableDebugLog inCollection:OWSPreferencesSignalDatabaseCollection];
|
||||
|
||||
if (existingValue) {
|
||||
OWSLogInfo(@"assigning existing value: %@", existingValue);
|
||||
[OWSPreferences setIsLoggingEnabled:[existingValue boolValue]];
|
||||
|
||||
if (![existingValue boolValue]) {
|
||||
OWSLogInfo(@"Disabling file logger after one-time log settings migration.");
|
||||
// Since we're migrating, we didn't have the appropriate value on startup, and incorrectly started logging.
|
||||
[DebugLogger.sharedLogger disableFileLogging];
|
||||
} else {
|
||||
OWSLogInfo(@"Continuing to log after one-time log settings migration.");
|
||||
}
|
||||
} else {
|
||||
OWSLogInfo(@"not assigning any value, since no previous value was stored.");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,9 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
@interface OWS103EnableVideoCalling : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
@ -1,57 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS103EnableVideoCalling.h"
|
||||
#import <SignalServiceKit/OWSRequestFactory.h>
|
||||
#import <SignalServiceKit/SSKEnvironment.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TSAccountManager.h>
|
||||
#import <SignalServiceKit/TSNetworkManager.h>
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS103EnableVideoCallingMigrationId = @"103";
|
||||
|
||||
@implementation OWS103EnableVideoCalling
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS103EnableVideoCallingMigrationId;
|
||||
}
|
||||
|
||||
// Override parent migration
|
||||
- (void)runUpWithCompletion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAssertDebug(completion);
|
||||
|
||||
OWSLogWarn(@"running migration...");
|
||||
if ([self.tsAccountManager isRegistered]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
TSRequest *request = [OWSRequestFactory updatePrimaryDeviceAttributesRequest];
|
||||
[[TSNetworkManager shared] makeRequest:request
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
OWSLogInfo(@"successfully ran");
|
||||
[self markAsCompleteWithSneakyTransaction];
|
||||
|
||||
completion();
|
||||
}
|
||||
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
if (!IsNetworkConnectivityFailure(error)) {
|
||||
OWSProdError([OWSAnalyticsEvents errorEnableVideoCallingRequestFailed]);
|
||||
}
|
||||
OWSLogError(@"failed with error: %@", error);
|
||||
|
||||
completion();
|
||||
}];
|
||||
});
|
||||
} else {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
OWSLogInfo(@"skipping; not registered");
|
||||
[self markAsCompleteWithSneakyTransaction];
|
||||
|
||||
completion();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS104CreateRecipientIdentities : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,64 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS104CreateRecipientIdentities.h"
|
||||
#import <SignalServiceKit/OWSIdentityManager.h>
|
||||
#import <SignalServiceKit/OWSRecipientIdentity.h>
|
||||
#import <YapDatabase/YapDatabaseConnection.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS104CreateRecipientIdentitiesMigrationId = @"104";
|
||||
|
||||
/**
|
||||
* New SN behavior requires tracking additional state - not just the identity key data.
|
||||
* So we wrap the key, along with the new meta-data in an OWSRecipientIdentity.
|
||||
*/
|
||||
@implementation OWS104CreateRecipientIdentities
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS104CreateRecipientIdentitiesMigrationId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
NSMutableDictionary<NSString *, NSData *> *identityKeys = [NSMutableDictionary new];
|
||||
|
||||
NSString *const OWSPrimaryStorageTrustedKeysCollection = @"TSStorageManagerTrustedKeysCollection";
|
||||
[transaction
|
||||
enumerateKeysAndObjectsInCollection:OWSPrimaryStorageTrustedKeysCollection
|
||||
usingBlock:^(NSString *_Nonnull recipientId, id _Nonnull object, BOOL *_Nonnull stop) {
|
||||
if (![object isKindOfClass:[NSData class]]) {
|
||||
OWSFailDebug(
|
||||
@"Unexpected object in trusted keys collection key: %@ object: %@",
|
||||
recipientId,
|
||||
[object class]);
|
||||
return;
|
||||
}
|
||||
NSData *identityKey = (NSData *)object;
|
||||
[identityKeys setObject:identityKey forKey:recipientId];
|
||||
}];
|
||||
|
||||
[identityKeys enumerateKeysAndObjectsUsingBlock:^(
|
||||
NSString *_Nonnull recipientId, NSData *_Nonnull identityKey, BOOL *_Nonnull stop) {
|
||||
OWSLogInfo(@"Migrating identity key for recipient: %@", recipientId);
|
||||
OWSRecipientIdentity *recipientIdentity =
|
||||
[[OWSRecipientIdentity alloc] initWithAccountId:recipientId
|
||||
identityKey:identityKey
|
||||
isFirstKnownKey:NO
|
||||
createdAt:[NSDate dateWithTimeIntervalSince1970:0]
|
||||
verificationState:OWSVerificationStateDefault];
|
||||
// All pre-GRDB migrations should be YAP-only.
|
||||
[recipientIdentity ydb_saveWithTransaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS105AttachmentFilePaths : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,48 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS105AttachmentFilePaths.h"
|
||||
#import <SignalServiceKit/TSAttachmentStream.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS105AttachmentFilePathsMigrationId = @"105";
|
||||
|
||||
@implementation OWS105AttachmentFilePaths
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS105AttachmentFilePathsMigrationId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
NSMutableArray<TSAttachmentStream *> *attachmentStreams = [NSMutableArray new];
|
||||
[transaction enumerateKeysAndObjectsInCollection:TSAttachmentStream.collection
|
||||
usingBlock:^(NSString *key, TSAttachment *attachment, BOOL *stop) {
|
||||
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
return;
|
||||
}
|
||||
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment;
|
||||
[attachmentStreams addObject:attachmentStream];
|
||||
}];
|
||||
|
||||
OWSLogInfo(@"Saving %lu attachment streams.", (unsigned long)attachmentStreams.count);
|
||||
|
||||
// Persist the new localRelativeFilePath property of TSAttachmentStream.
|
||||
// For performance, we want to upgrade all existing attachment streams in
|
||||
// a single transaction.
|
||||
for (TSAttachmentStream *attachmentStream in attachmentStreams) {
|
||||
// NOTE: Use legacy save.
|
||||
[attachmentStream ydb_saveWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,117 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import PromiseKit
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class OWS106EnsureProfileComplete: YDBDatabaseMigration {
|
||||
|
||||
private static var sharedCompleteRegistrationFixerJob: CompleteRegistrationFixerJob?
|
||||
|
||||
// increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
return "106"
|
||||
}
|
||||
|
||||
// Overriding runUp since we have some specific completion criteria which
|
||||
// is more likely to fail since it involves network requests.
|
||||
override public func runUp(completion:@escaping () -> Void) {
|
||||
let job = CompleteRegistrationFixerJob(completionHandler: { (didSucceed) in
|
||||
|
||||
if didSucceed {
|
||||
Logger.info("Completed. Saving.")
|
||||
|
||||
self.markAsCompleteWithSneakyTransaction()
|
||||
} else {
|
||||
Logger.error("Failed.")
|
||||
}
|
||||
|
||||
completion()
|
||||
})
|
||||
|
||||
type(of: self).sharedCompleteRegistrationFixerJob = job
|
||||
|
||||
job.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* A previous client bug made it possible for re-registering users to register their new account
|
||||
* but never upload new pre-keys. The symptom is that there will be accounts with no uploaded
|
||||
* identity key. We detect that here and fix the situation
|
||||
*/
|
||||
private class CompleteRegistrationFixerJob: NSObject {
|
||||
|
||||
// Duration between retries if update fails.
|
||||
let kRetryInterval: TimeInterval = 5
|
||||
|
||||
let completionHandler: (Bool) -> Void
|
||||
|
||||
init(completionHandler: @escaping (Bool) -> Void) {
|
||||
self.completionHandler = completionHandler
|
||||
}
|
||||
|
||||
func start() {
|
||||
guard tsAccountManager.isRegistered else {
|
||||
self.completionHandler(true)
|
||||
return
|
||||
}
|
||||
|
||||
self.ensureProfileComplete().done {
|
||||
Logger.info("complete. Canceling timer and saving.")
|
||||
self.completionHandler(true)
|
||||
}.catch { error in
|
||||
let nserror = error as NSError
|
||||
if nserror.domain == TSNetworkManagerErrorDomain {
|
||||
// Don't retry if we had an unrecoverable error.
|
||||
// In particular, 401 (invalid auth) is unrecoverable.
|
||||
let isUnrecoverableError = nserror.code == 401
|
||||
if isUnrecoverableError {
|
||||
Logger.error("failed due to unrecoverable error: \(error). Aborting.")
|
||||
self.completionHandler(true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Logger.error("failed with \(error).")
|
||||
self.completionHandler(false)
|
||||
}
|
||||
}
|
||||
|
||||
func ensureProfileComplete() -> Promise<Void> {
|
||||
guard let localAddress = TSAccountManager.localAddress, localAddress.isValid else {
|
||||
// local app doesn't think we're registered, so nothing to worry about.
|
||||
return Promise.value(())
|
||||
}
|
||||
|
||||
return firstly {
|
||||
return ProfileFetcherJob.fetchProfilePromise(address: localAddress,
|
||||
ignoreThrottling: true)
|
||||
}.done { _ in
|
||||
Logger.info("verified recipient profile is in good shape: \(localAddress)")
|
||||
}.recover { error -> Promise<Void> in
|
||||
switch error {
|
||||
case SignalServiceProfile.ValidationError.invalidIdentityKey(let description):
|
||||
Logger.warn("detected incomplete profile for \(localAddress) error: \(description)")
|
||||
|
||||
let (promise, resolver) = Promise<Void>.pending()
|
||||
// This is the error condition we're looking for. Update prekeys to properly set the identity key, completing registration.
|
||||
TSPreKeyManager.createPreKeys(success: {
|
||||
Logger.info("successfully uploaded pre-keys. Profile should be fixed.")
|
||||
resolver.fulfill(())
|
||||
},
|
||||
failure: { _ in
|
||||
resolver.reject(OWSErrorWithCodeDescription(.signalServiceFailure, "\(self.logTag) Unknown error"))
|
||||
})
|
||||
|
||||
return promise
|
||||
default:
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS107LegacySounds : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,31 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS107LegacySounds.h"
|
||||
#import "OWSSounds.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS107LegacySoundsMigrationId = @"107";
|
||||
|
||||
@implementation OWS107LegacySounds
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS107LegacySoundsMigrationId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
[OWSSounds setGlobalNotificationSound:OWSStandardSound_SignalClassic transaction:transaction.asAnyWrite];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS108CallLoggingPreference : YDBDatabaseMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,32 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS108CallLoggingPreference.h"
|
||||
#import "Environment.h"
|
||||
#import "OWSPreferences.h"
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS108CallLoggingPreferenceId = @"108";
|
||||
|
||||
@implementation OWS108CallLoggingPreference
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS108CallLoggingPreferenceId;
|
||||
}
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
[self.preferences applyCallLoggingSettingsForLegacyUsersWithTransaction:transaction];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSResaveCollectionDBMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWS109OutgoingMessageState : OWSResaveCollectionDBMigration
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,44 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWS109OutgoingMessageState.h"
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TSOutgoingMessage.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Increment a similar constant for every future DBMigration
|
||||
static NSString *const OWS109OutgoingMessageStateMigrationId = @"109";
|
||||
|
||||
@implementation OWS109OutgoingMessageState
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
return OWS109OutgoingMessageStateMigrationId;
|
||||
}
|
||||
|
||||
// Override parent migration
|
||||
- (void)runUpWithCompletion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAssertDebug(completion);
|
||||
|
||||
OWSDatabaseConnection *dbConnection = (OWSDatabaseConnection *)self.primaryStorage.newDatabaseConnection;
|
||||
|
||||
[self resaveDBCollection:TSOutgoingMessage.collection
|
||||
filter:^(id entity) {
|
||||
return [entity isKindOfClass:[TSOutgoingMessage class]];
|
||||
}
|
||||
dbConnection:dbConnection
|
||||
completion:^{
|
||||
[self markAsCompleteWithSneakyTransaction];
|
||||
|
||||
completion();
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,118 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class OWS110SortIdMigration: YDBDatabaseMigration {
|
||||
// increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
// append char "x" because we want to rerun on some internal devices which
|
||||
// have already run this migration.
|
||||
return "110x"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
Logger.debug("")
|
||||
BenchAsync(title: "Sort Migration") { completeBenchmark in
|
||||
self.doMigration {
|
||||
completeBenchmark()
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func doMigration(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
// TODO batch this?
|
||||
self.ydbReadWriteConnection.readWrite { transaction in
|
||||
|
||||
var archivedThreads: [TSThread] = []
|
||||
|
||||
// get archived threads before migration
|
||||
TSThread.ydb_enumerateCollectionObjects(with: transaction) { (object, _) in
|
||||
guard let thread = object as? TSThread else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
|
||||
if thread.isArchivedByLegacyTimestampForSorting {
|
||||
archivedThreads.append(thread)
|
||||
}
|
||||
}
|
||||
|
||||
guard let legacySorting = transaction.safeAutoViewTransaction(TSMessageDatabaseViewExtensionName_Legacy) else {
|
||||
owsFailDebug("legacySorting was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
let totalCount: UInt = legacySorting.numberOfItemsInAllGroups()
|
||||
var completedCount: UInt = 0
|
||||
|
||||
var allGroups = [String]()
|
||||
legacySorting.enumerateGroups { group, _ in
|
||||
allGroups.append(group)
|
||||
}
|
||||
|
||||
var seenGroups: Set<String> = Set()
|
||||
for group in allGroups {
|
||||
autoreleasepool {
|
||||
// Sanity Check #1
|
||||
// Make sure our enumeration is monotonically increasing.
|
||||
// Note: sortIds increase monotonically WRT timestampForLegacySorting, but only WRT the interaction's thread.
|
||||
//
|
||||
// e.g. When we migrate the **next** thread, we start with that thread's oldest interaction. So it's possible and expected
|
||||
// that thread2's oldest interaction will have a smaller timestampForLegacySorting, but a greater sortId then an interaction
|
||||
// in thread1. That's OK because we only sort messages with respect to the thread they belong in. We don't have any sort of
|
||||
// "global sort" of messages across all threads.
|
||||
var previousTimestampForLegacySorting: UInt64 = 0
|
||||
|
||||
// Sanity Check #2
|
||||
// Ensure we only process a DB View's group (i.e. threadId) once.
|
||||
guard !seenGroups.contains(group) else {
|
||||
owsFail("unexpectedly seeing a repeated group: \(group)")
|
||||
}
|
||||
seenGroups.insert(group)
|
||||
|
||||
var groupKeys = [String]()
|
||||
legacySorting.enumerateKeys(inGroup: group, using: { (_, key, _, _) in
|
||||
groupKeys.append(key)
|
||||
})
|
||||
let groupKeyBatchSize: Int = 1024
|
||||
for batch in groupKeys.chunked(by: groupKeyBatchSize) {
|
||||
autoreleasepool {
|
||||
for uniqueId in batch {
|
||||
guard let interaction = TSInteraction.ydb_fetch(uniqueId: uniqueId, transaction: transaction) else {
|
||||
owsFailDebug("Could not load interaction: \(uniqueId)")
|
||||
return
|
||||
}
|
||||
if interaction.timestampForLegacySorting() < previousTimestampForLegacySorting {
|
||||
owsFailDebug("unexpected object ordering previousTimestampForLegacySorting: \(previousTimestampForLegacySorting) interaction.timestampForLegacySorting: \(interaction.timestampForLegacySorting())")
|
||||
}
|
||||
previousTimestampForLegacySorting = interaction.timestampForLegacySorting()
|
||||
|
||||
interaction.ydb_saveNextSortId(transaction: transaction)
|
||||
|
||||
completedCount += 1
|
||||
if completedCount % 100 == 0 {
|
||||
// Legit usage of legacy sorting for migration to new sorting
|
||||
Logger.info("thread: \(interaction.uniqueThreadId), timestampForLegacySorting:\(interaction.timestampForLegacySorting()), sortId: \(interaction.sortId) totalCount: \(totalCount), completedcount: \(completedCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.info("re-archiving \(archivedThreads.count) threads which were previously archived")
|
||||
for archivedThread in archivedThreads {
|
||||
archivedThread.archiveThread(updateStorageService: false, transaction: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
self.markAsComplete(with: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
completion()
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
import PromiseKit
|
||||
|
||||
@objc
|
||||
public class OWS111UDAttributesMigration: YDBDatabaseMigration {
|
||||
|
||||
// increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
// NOTE: Changes were made to the service after this migration was initially
|
||||
// merged, so we need to re-migrate any developer devices.
|
||||
return "111.1"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
Logger.debug("")
|
||||
Bench(title: "UD Attributes Migration") {
|
||||
self.doMigration()
|
||||
}
|
||||
completion()
|
||||
}
|
||||
|
||||
private func doMigration() {
|
||||
firstly {
|
||||
tsAccountManager.updateAccountAttributes()
|
||||
}.catch { error in
|
||||
owsFailDebug("Error: \(error)")
|
||||
}
|
||||
|
||||
self.ydbReadWriteConnection.readWrite { transaction in
|
||||
self.markAsComplete(with: transaction.asAnyWrite)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class OWS112TypingIndicatorsMigration: YDBDatabaseMigration {
|
||||
|
||||
// Increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
return "112"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
Logger.debug("")
|
||||
BenchAsync(title: "Typing Indicators Migration") { (benchCompletion) in
|
||||
self.doMigrationAsync(completion: {
|
||||
benchCompletion()
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func doMigrationAsync(completion : @escaping OWSDatabaseMigrationCompletion) {
|
||||
DispatchQueue.main.async {
|
||||
// Typing indicators should be disabled by default for
|
||||
// legacy users.
|
||||
self.typingIndicatorsImpl.setTypingIndicatorsEnabledAndSendSyncMessage(value: false)
|
||||
|
||||
DispatchQueue.global().async {
|
||||
self.markAsCompleteWithSneakyTransaction()
|
||||
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class OWS113MultiAttachmentMediaMessages: YDBDatabaseMigration {
|
||||
|
||||
// Increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
// NOTE: that we use .1 since there was a bug in the logic to
|
||||
// set albumMessageId.
|
||||
return "113.1"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
Logger.debug("")
|
||||
BenchAsync(title: "\(self.logTag)") { (benchCompletion) in
|
||||
self.doMigrationAsync(completion: {
|
||||
benchCompletion()
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func doMigrationAsync(completion : @escaping OWSDatabaseMigrationCompletion) {
|
||||
DispatchQueue.global().async {
|
||||
var legacyAttachments: [(attachmentId: String, messageId: String)] = []
|
||||
|
||||
self.ydbReadWriteConnection.read { transaction in
|
||||
TSMessage.ydb_enumerateCollectionObjects(with: transaction) { object, _ in
|
||||
autoreleasepool {
|
||||
guard let message: TSMessage = object as? TSMessage else {
|
||||
Logger.debug("ignoring message with type: \(object)")
|
||||
return
|
||||
}
|
||||
|
||||
let messageId = message.uniqueId
|
||||
for attachmentId in message.attachmentIds {
|
||||
legacyAttachments.append((attachmentId: attachmentId, messageId: messageId))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ydbReadWriteConnection.readWrite { transaction in
|
||||
for (attachmentId, messageId) in legacyAttachments {
|
||||
autoreleasepool {
|
||||
// NOTE: Use legacy fetch.
|
||||
guard let attachment = TSAttachment.ydb_fetch(uniqueId: attachmentId, transaction: transaction) else {
|
||||
Logger.warn("missing attachment for messageId: \(messageId)")
|
||||
return
|
||||
}
|
||||
|
||||
attachment.migrateAlbumMessageId(messageId)
|
||||
// NOTE: Use legacy save.
|
||||
attachment.ydb_save(with: transaction)
|
||||
}
|
||||
}
|
||||
self.markAsComplete(with: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class OWS114RemoveDynamicInteractions: YDBDatabaseMigration {
|
||||
|
||||
// Increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
return "114"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
Logger.debug("")
|
||||
BenchAsync(title: "\(self.logTag)") { (benchCompletion) in
|
||||
self.doMigrationAsync(completion: {
|
||||
benchCompletion()
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func doMigrationAsync(completion : @escaping OWSDatabaseMigrationCompletion) {
|
||||
DispatchQueue.global().async {
|
||||
self.ydbReadWriteConnection.readWrite { transaction in
|
||||
guard let dbView = TSDatabaseView.threadSpecialMessagesDatabaseView(transaction) as? YapDatabaseViewTransaction else {
|
||||
owsFailDebug("Couldn't load db view.")
|
||||
return
|
||||
}
|
||||
|
||||
var interactionsToDelete = [TSInteraction]()
|
||||
let groupIds = dbView.allGroups()
|
||||
for groupId in groupIds {
|
||||
dbView.enumerateKeysAndObjects(inGroup: groupId) { (_: String, _: String, object: Any, _: UInt, _: UnsafeMutablePointer<ObjCBool>) in
|
||||
guard let interaction = object as? TSInteraction else {
|
||||
owsFailDebug("Invalid database entity: \(type(of: object)).")
|
||||
return
|
||||
}
|
||||
guard interaction.isDynamicInteraction() else {
|
||||
return
|
||||
}
|
||||
interactionsToDelete.append(interaction)
|
||||
}
|
||||
}
|
||||
|
||||
for interaction in interactionsToDelete {
|
||||
Logger.debug("Cleaning up interaction: \(type(of: interaction)).")
|
||||
interaction.ydb_remove(with: transaction)
|
||||
}
|
||||
|
||||
self.markAsComplete(with: transaction.asAnyWrite)
|
||||
}
|
||||
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class OWS115EnsureProfileAvatars: YDBDatabaseMigration {
|
||||
|
||||
// Increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
return "115"
|
||||
}
|
||||
|
||||
var fileManager: FileManager {
|
||||
return FileManager.default
|
||||
}
|
||||
|
||||
override public func runUp(with transaction: YapDatabaseReadWriteTransaction) {
|
||||
Bench(title: "\(self.logTag)") {
|
||||
var profilesWithMissingAvatars: [String] = []
|
||||
OWSUserProfile.anyEnumerate(transaction: transaction.asAnyWrite,
|
||||
batched: true) { profile, _ in
|
||||
guard let filename = profile.avatarFileName else {
|
||||
return
|
||||
}
|
||||
|
||||
let filepath = OWSUserProfile.profileAvatarFilepath(withFilename: filename)
|
||||
guard !self.fileManager.fileExists(atPath: filepath) else {
|
||||
return
|
||||
}
|
||||
profilesWithMissingAvatars.append(profile.uniqueId)
|
||||
}
|
||||
|
||||
for uniqueId in profilesWithMissingAvatars {
|
||||
guard let profile = OWSUserProfile.anyFetch(uniqueId: uniqueId, transaction: transaction.asAnyRead) else {
|
||||
owsFailDebug("profile was unexpectedly nil")
|
||||
continue
|
||||
}
|
||||
Logger.info("removing reference to non-existant avatar file")
|
||||
profile.update(withAvatarFileName: nil, transaction: transaction.asAnyWrite)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class OWS116UpdatePrekeys: YDBDatabaseMigration {
|
||||
|
||||
// Increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
return "116"
|
||||
}
|
||||
|
||||
override public func runUp(with transaction: YapDatabaseReadWriteTransaction) {
|
||||
Bench(title: "\(self.logTag)") {
|
||||
let keyStore = self.preKeyStore.keyStore
|
||||
do {
|
||||
var keys: [String] = keyStore.allKeys(transaction: transaction.asAnyRead)
|
||||
try Batching.loop(batchSize: Batching.kDefaultBatchSize,
|
||||
loopBlock: { stop in
|
||||
guard let key = keys.popLast() else {
|
||||
stop.pointee = true
|
||||
return
|
||||
}
|
||||
guard let record = keyStore.getObject(forKey: key, transaction: transaction.asAnyRead) as? PreKeyRecord else {
|
||||
owsFailDebug("Missing record.")
|
||||
return
|
||||
}
|
||||
guard record.createdAt == nil else {
|
||||
owsFailDebug("Unexpected createdAt.")
|
||||
return
|
||||
}
|
||||
record.setCreatedAtToNow()
|
||||
keyStore.setObject(record, key: key, transaction: transaction.asAnyWrite)
|
||||
})
|
||||
} catch {
|
||||
owsFail("Migration failed.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import SignalServiceKit
|
||||
|
||||
extension StorageCoordinatorState: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return NSStringFromStorageCoordinatorState(self)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public class OWS1XXGRDBMigration: YDBDatabaseMigration {
|
||||
|
||||
// Increment a similar constant for each migration.
|
||||
@objc
|
||||
public override class var migrationId: String {
|
||||
return "1XX"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
Logger.debug("")
|
||||
|
||||
DispatchQueue.global().async {
|
||||
if self.storageCoordinator.state != .beforeYDBToGRDBMigration {
|
||||
owsFail("unexpected storage coordinator state: \(self.storageCoordinator.state)")
|
||||
} else {
|
||||
|
||||
self.databaseStorage.write { transaction in
|
||||
do {
|
||||
// We need to dedupe the recipients *before* migrating to
|
||||
// GRDB since GRDB enforces uniqueness constraints on SignalRecipients.
|
||||
try dedupeSignalRecipients(transaction: transaction)
|
||||
} catch {
|
||||
// we don't bother failing hard here.
|
||||
// If for some reason duplicates remain, then the YDBToGRDBMigration will
|
||||
// fail hard anyway. And conversely, if it doesn't fail then there were
|
||||
// no duplicate SignalRecipients.
|
||||
owsFailDebug("error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
self.storageCoordinator.migrationYDBToGRDBWillBegin()
|
||||
assert(self.storageCoordinator.state == .duringYDBToGRDBMigration)
|
||||
|
||||
Bench(title: "\(self.logTag)") {
|
||||
do {
|
||||
try YDBToGRDBMigration().run()
|
||||
} catch {
|
||||
owsFail("error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
self.storageCoordinator.migrationYDBToGRDBDidComplete()
|
||||
assert(self.storageCoordinator.state == .GRDB)
|
||||
}
|
||||
|
||||
self.databaseStorage.write { transaction in
|
||||
switch transaction.writeTransaction {
|
||||
case .grdbWrite:
|
||||
self.markAsComplete(with: transaction)
|
||||
case .yapWrite:
|
||||
owsFail("wrong transaction type")
|
||||
}
|
||||
}
|
||||
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
public override var shouldBeSaved: Bool {
|
||||
if SDSDatabaseStorage.shouldUseDisposableGrdb {
|
||||
// Do nothing so as to re-run every launch.
|
||||
// Useful while actively developing the migration.
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <SignalServiceKit/BaseModel.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^OWSDatabaseMigrationCompletion)(void);
|
||||
|
||||
@class OWSPrimaryStorage;
|
||||
@class SDSAnyReadTransaction;
|
||||
@class SDSAnyWriteTransaction;
|
||||
@class SDSKeyValueStore;
|
||||
@class YapDatabaseConnection;
|
||||
@class YapDatabaseReadWriteTransaction;
|
||||
|
||||
// Although OWSDatabaseMigration is still a TSYapDatabaseObject
|
||||
// to enable deserialization of legacy values, OWSDatabaseMigration
|
||||
// now uses a key-value store to persist migration completion.
|
||||
//
|
||||
// Therefore, we do _not_ need to subclass BaseModel here.
|
||||
@interface OWSDatabaseMigration : TSYapDatabaseObject
|
||||
|
||||
+ (SDSKeyValueStore *)keyValueStore;
|
||||
|
||||
@property (class, nonatomic, readonly) NSString *migrationId;
|
||||
@property (nonatomic, readonly) NSString *migrationId;
|
||||
|
||||
// Prefer nonblocking (async) migrations by overriding `runUpWithTransaction:` in a subclass.
|
||||
// Blocking migrations running too long will crash the app, effectively bricking install
|
||||
// because the user will never get past it.
|
||||
// If you must write a launch-blocking migration, override runUp.
|
||||
- (void)runUpWithCompletion:(OWSDatabaseMigrationCompletion)completion;
|
||||
|
||||
- (void)markAsCompleteWithTransaction:(SDSAnyWriteTransaction *)transaction;
|
||||
|
||||
+ (void)markMigrationIdAsComplete:(NSString *)migrationId transaction:(SDSAnyWriteTransaction *)transaction;
|
||||
|
||||
+ (void)markMigrationIdAsIncomplete:(NSString *)migrationId transaction:(SDSAnyWriteTransaction *)transaction;
|
||||
|
||||
- (void)markAsCompleteWithSneakyTransaction;
|
||||
|
||||
// We use a sneaky transaction since YDBDatabaseMigration will
|
||||
// want to consult YDB and GRDBDatabaseMigration will want to
|
||||
// consult GRDB.
|
||||
- (BOOL)isCompleteWithSneakyTransaction;
|
||||
|
||||
+ (NSArray<NSString *> *)allCompleteMigrationIdsWithTransaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// A base class for migrations run before the YDB-to-GRDB migration.
|
||||
// These migrations are run against the YDB store.
|
||||
@interface YDBDatabaseMigration : OWSDatabaseMigration
|
||||
|
||||
// Subclasses should override this convenience method or runUpWithCompletion.
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
|
||||
#pragma mark - Database Connections
|
||||
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *ydbReadWriteConnection;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,161 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <SignalMessaging/OWSDatabaseMigration.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/SSKEnvironment.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSDatabaseMigration
|
||||
|
||||
// This key-value store is used to persist completion of migrations.
|
||||
// Note that it uses the YDB collection previously used to persist migration models.
|
||||
// Since we just check "has key", this is backwards-compatible.
|
||||
+ (SDSKeyValueStore *)keyValueStore
|
||||
{
|
||||
static SDSKeyValueStore *keyValueStore = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
keyValueStore = [[SDSKeyValueStore alloc] initWithCollection:OWSDatabaseMigration.collection];
|
||||
});
|
||||
return keyValueStore;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [super initWithUniqueId:[self.class migrationId]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
+ (NSString *)migrationId
|
||||
{
|
||||
OWSAbstractMethod();
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString *)migrationId
|
||||
{
|
||||
return self.class.migrationId;
|
||||
}
|
||||
|
||||
+ (NSString *)collection
|
||||
{
|
||||
// We want all subclasses in the same collection
|
||||
return @"OWSDatabaseMigration";
|
||||
}
|
||||
|
||||
- (void)runUpWithCompletion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAbstractMethod();
|
||||
}
|
||||
|
||||
- (void)markAsCompleteWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
if (!self.shouldBeSaved) {
|
||||
OWSLogInfo(@"NOT Marking migration as incomplete: %@ %@", [self class], self.migrationId);
|
||||
return;
|
||||
}
|
||||
|
||||
[OWSDatabaseMigration markMigrationIdAsComplete:self.migrationId transaction:transaction];
|
||||
}
|
||||
|
||||
+ (void)markMigrationIdAsComplete:(NSString *)migrationId transaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
OWSLogInfo(@"Marking migration as complete: %@", migrationId);
|
||||
|
||||
[self.keyValueStore setBool:YES key:migrationId transaction:transaction];
|
||||
}
|
||||
|
||||
+ (void)markMigrationIdAsIncomplete:(NSString *)migrationId transaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
OWSLogInfo(@"Marking migration as incomplete: %@", migrationId);
|
||||
|
||||
[self.keyValueStore removeValueForKey:migrationId transaction:transaction];
|
||||
}
|
||||
|
||||
- (void)markAsCompleteWithSneakyTransaction
|
||||
{
|
||||
DatabaseStorageWrite(self.databaseStorage, ^(SDSAnyWriteTransaction *transaction) {
|
||||
[self markAsCompleteWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)isCompleteWithSneakyTransaction
|
||||
{
|
||||
__block BOOL result;
|
||||
[self.databaseStorage readWithBlock:^(SDSAnyReadTransaction *transaction) {
|
||||
result = [self isCompleteWithTransaction:transaction];
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)isCompleteWithTransaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return [OWSDatabaseMigration.keyValueStore hasValueForKey:self.migrationId transaction:transaction];
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> *)allCompleteMigrationIdsWithTransaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return [self.keyValueStore allKeysWithTransaction:transaction];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation YDBDatabaseMigration
|
||||
|
||||
- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAbstractMethod();
|
||||
}
|
||||
|
||||
- (void)runUpWithCompletion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAssertDebug(completion);
|
||||
|
||||
OWSDatabaseConnection *dbConnection = (OWSDatabaseConnection *)self.primaryStorage.newDatabaseConnection;
|
||||
|
||||
[dbConnection
|
||||
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self runUpWithTransaction:transaction];
|
||||
}
|
||||
completionBlock:^{
|
||||
[dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self markAsCompleteWithTransaction:transaction.asAnyWrite];
|
||||
}];
|
||||
|
||||
completion();
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Database Connections
|
||||
|
||||
+ (YapDatabaseConnection *)ydbReadConnection
|
||||
{
|
||||
return self.ydbReadWriteConnection;
|
||||
}
|
||||
|
||||
+ (YapDatabaseConnection *)ydbReadWriteConnection
|
||||
{
|
||||
return SSKEnvironment.shared.migrationDBConnection;
|
||||
}
|
||||
|
||||
- (YapDatabaseConnection *)ydbReadConnection
|
||||
{
|
||||
return YDBDatabaseMigration.ydbReadConnection;
|
||||
}
|
||||
|
||||
- (YapDatabaseConnection *)ydbReadWriteConnection
|
||||
{
|
||||
return YDBDatabaseMigration.ydbReadWriteConnection;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,23 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^OWSDatabaseMigrationCompletion)(void);
|
||||
|
||||
@interface OWSDatabaseMigrationRunner : NSObject
|
||||
|
||||
/**
|
||||
* Run any outstanding version migrations.
|
||||
*/
|
||||
- (void)runAllOutstandingWithCompletion:(OWSDatabaseMigrationCompletion)completion;
|
||||
|
||||
/**
|
||||
* On new installations, no need to migrate anything.
|
||||
*/
|
||||
- (void)assumeAllExistingMigrationsRun;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,134 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigrationRunner.h"
|
||||
#import "OWS100RemoveTSRecipientsMigration.h"
|
||||
#import "OWS102MoveLoggingPreferenceToUserDefaults.h"
|
||||
#import "OWS103EnableVideoCalling.h"
|
||||
#import "OWS104CreateRecipientIdentities.h"
|
||||
#import "OWS105AttachmentFilePaths.h"
|
||||
#import "OWS107LegacySounds.h"
|
||||
#import "OWS108CallLoggingPreference.h"
|
||||
#import "OWS109OutgoingMessageState.h"
|
||||
#import "OWSDatabaseMigration.h"
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalServiceKit/AppContext.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSDatabaseMigrationRunner
|
||||
|
||||
// This should all migrations which do NOT qualify as safeBlockingMigrations:
|
||||
- (NSArray<OWSDatabaseMigration *> *)allMigrations
|
||||
{
|
||||
NSArray<OWSDatabaseMigration *> *prodMigrations = @[
|
||||
[[OWS100RemoveTSRecipientsMigration alloc] init],
|
||||
[[OWS102MoveLoggingPreferenceToUserDefaults alloc] init],
|
||||
[[OWS103EnableVideoCalling alloc] init],
|
||||
[[OWS104CreateRecipientIdentities alloc] init],
|
||||
[[OWS105AttachmentFilePaths alloc] init],
|
||||
[[OWS106EnsureProfileComplete alloc] init],
|
||||
[[OWS107LegacySounds alloc] init],
|
||||
[[OWS108CallLoggingPreference alloc] init],
|
||||
[[OWS109OutgoingMessageState alloc] init],
|
||||
[OWS110SortIdMigration new],
|
||||
[[OWS111UDAttributesMigration alloc] init],
|
||||
[[OWS112TypingIndicatorsMigration alloc] init],
|
||||
[[OWS113MultiAttachmentMediaMessages alloc] init],
|
||||
[[OWS114RemoveDynamicInteractions alloc] init],
|
||||
[OWS115EnsureProfileAvatars new],
|
||||
[OWS116UpdatePrekeys new]
|
||||
];
|
||||
|
||||
if (StorageCoordinator.dataStoreForUI == DataStoreGrdb) {
|
||||
return [prodMigrations arrayByAddingObjectsFromArray:@ [[OWS1XXGRDBMigration new]]];
|
||||
} else {
|
||||
return prodMigrations;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)assumeAllExistingMigrationsRun
|
||||
{
|
||||
DatabaseStorageWrite(self.databaseStorage, ^(SDSAnyWriteTransaction *transaction) {
|
||||
for (OWSDatabaseMigration *migration in self.allMigrations) {
|
||||
OWSLogInfo(@"Skipping migration on new install: %@", migration);
|
||||
|
||||
[migration markAsCompleteWithTransaction:transaction];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)runAllOutstandingWithCompletion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
[self removeUnknownMigrations];
|
||||
|
||||
[self runMigrations:[self.allMigrations mutableCopy] completion:completion];
|
||||
}
|
||||
|
||||
// Some users (especially internal users) will move back and forth between
|
||||
// app versions. Whenever they move "forward" in the version history, we
|
||||
// want them to re-run any new migrations. Therefore, when they move "backward"
|
||||
// in the version history, we cull any unknown migrations.
|
||||
- (void)removeUnknownMigrations
|
||||
{
|
||||
NSMutableSet<NSString *> *knownMigrationIds = [NSMutableSet new];
|
||||
for (OWSDatabaseMigration *migration in self.allMigrations) {
|
||||
[knownMigrationIds addObject:migration.migrationId];
|
||||
}
|
||||
|
||||
DatabaseStorageWrite(self.databaseStorage, ^(SDSAnyWriteTransaction *transaction) {
|
||||
NSArray<NSString *> *savedMigrationIds =
|
||||
[OWSDatabaseMigration allCompleteMigrationIdsWithTransaction:transaction];
|
||||
|
||||
NSMutableSet<NSString *> *unknownMigrationIds = [NSMutableSet new];
|
||||
[unknownMigrationIds addObjectsFromArray:savedMigrationIds];
|
||||
[unknownMigrationIds minusSet:knownMigrationIds];
|
||||
|
||||
for (NSString *unknownMigrationId in unknownMigrationIds) {
|
||||
OWSLogInfo(@"Culling unknown migration: %@", unknownMigrationId);
|
||||
[OWSDatabaseMigration markMigrationIdAsIncomplete:unknownMigrationId transaction:transaction];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Run migrations serially to:
|
||||
//
|
||||
// * Ensure predictable ordering.
|
||||
// * Prevent them from interfering with each other (e.g. deadlock).
|
||||
- (void)runMigrations:(NSMutableArray<OWSDatabaseMigration *> *)migrations
|
||||
completion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAssertDebug(migrations);
|
||||
OWSAssertDebug(completion);
|
||||
|
||||
// If there are no more migrations to run, complete.
|
||||
if (migrations.count < 1) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Pop next migration from front of queue.
|
||||
OWSDatabaseMigration *migration = migrations.firstObject;
|
||||
[migrations removeObjectAtIndex:0];
|
||||
|
||||
// If migration has already been run, skip it.
|
||||
if (migration.isCompleteWithSneakyTransaction) {
|
||||
[self runMigrations:migrations completion:completion];
|
||||
return;
|
||||
}
|
||||
|
||||
OWSLogInfo(@"Running migration: %@ %@", migration, migration.migrationId);
|
||||
|
||||
[migration runUpWithCompletion:^{
|
||||
OWSLogInfo(@"Migration complete: %@ %@", migration, migration.migrationId);
|
||||
|
||||
[self runMigrations:migrations completion:completion];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,24 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef BOOL (^DBRecordFilterBlock)(id record);
|
||||
|
||||
@class YapDatabaseConnection;
|
||||
|
||||
// Base class for migrations that resave all or a subset of
|
||||
// records in a database collection.
|
||||
@interface OWSResaveCollectionDBMigration : YDBDatabaseMigration
|
||||
|
||||
- (void)resaveDBCollection:(NSString *)collection
|
||||
filter:(nullable DBRecordFilterBlock)filter
|
||||
dbConnection:(YapDatabaseConnection *)dbConnection
|
||||
completion:(OWSDatabaseMigrationCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,80 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSResaveCollectionDBMigration.h"
|
||||
#import <YapDatabase/YapDatabaseConnection.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSResaveCollectionDBMigration
|
||||
|
||||
- (void)resaveDBCollection:(NSString *)collection
|
||||
filter:(nullable DBRecordFilterBlock)filter
|
||||
dbConnection:(YapDatabaseConnection *)dbConnection
|
||||
completion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAssertDebug(collection.length > 0);
|
||||
OWSAssertDebug(dbConnection);
|
||||
OWSAssertDebug(completion);
|
||||
|
||||
NSMutableArray<NSString *> *recordIds = [NSMutableArray new];
|
||||
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[recordIds addObjectsFromArray:[transaction allKeysInCollection:collection]];
|
||||
OWSLogInfo(@"Migrating %lu records from: %@.", (unsigned long)recordIds.count, collection);
|
||||
}
|
||||
completionQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
|
||||
completionBlock:^{
|
||||
[self resaveBatch:recordIds
|
||||
collection:collection
|
||||
filter:filter
|
||||
dbConnection:dbConnection
|
||||
completion:completion];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)resaveBatch:(NSMutableArray<NSString *> *)recordIds
|
||||
collection:(NSString *)collection
|
||||
filter:(nullable DBRecordFilterBlock)filter
|
||||
dbConnection:(YapDatabaseConnection *)dbConnection
|
||||
completion:(OWSDatabaseMigrationCompletion)completion
|
||||
{
|
||||
OWSAssertDebug(recordIds);
|
||||
OWSAssertDebug(collection.length > 0);
|
||||
OWSAssertDebug(dbConnection);
|
||||
OWSAssertDebug(completion);
|
||||
|
||||
OWSLogVerbose(@"%lu", (unsigned long)recordIds.count);
|
||||
|
||||
if (recordIds.count < 1) {
|
||||
completion();
|
||||
return;
|
||||
}
|
||||
|
||||
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
const int kBatchSize = 1000;
|
||||
for (int i = 0; i < kBatchSize && recordIds.count > 0; i++) {
|
||||
NSString *messageId = [recordIds lastObject];
|
||||
[recordIds removeLastObject];
|
||||
id record = [transaction objectForKey:messageId inCollection:collection];
|
||||
if (filter && !filter(record)) {
|
||||
continue;
|
||||
}
|
||||
TSYapDatabaseObject *entity = (TSYapDatabaseObject *)record;
|
||||
[entity ydb_saveWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
completionBlock:^{
|
||||
// Process the next batch.
|
||||
[self resaveBatch:recordIds
|
||||
collection:collection
|
||||
filter:filter
|
||||
dbConnection:dbConnection
|
||||
completion:completion];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,52 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <SignalServiceKit/OWSIdentityManager.h>
|
||||
#import <SignalServiceKit/SSKPreKeyStore.h>
|
||||
#import <SignalServiceKit/SSKSignedPreKeyStore.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TSAccountManager.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
// We need access to this for migration purposes
|
||||
|
||||
@class SDSKeyValueStore;
|
||||
|
||||
@interface SSKSessionStore (PrivateMethodsForMigration)
|
||||
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *keyValueStore;
|
||||
|
||||
@end
|
||||
|
||||
@interface SSKPreKeyStore (PrivateMethodsForMigration)
|
||||
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *keyStore;
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *metadataStore;
|
||||
|
||||
@end
|
||||
|
||||
@interface SSKSignedPreKeyStore (PrivateMethodsForMigration)
|
||||
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *keyStore;
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *metadataStore;
|
||||
|
||||
@end
|
||||
|
||||
@interface OWSIdentityManager (PrivateMethodsForMigration)
|
||||
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *ownIdentityKeyValueStore;
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *queuedVerificationStateSyncMessagesKeyValueStore;
|
||||
|
||||
@end
|
||||
|
||||
@interface TSAccountManager (PrivateMethodsForMigration)
|
||||
|
||||
@property (nonatomic, readonly) SDSKeyValueStore *keyValueStore;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,731 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public class YDBToGRDBMigration: NSObject {
|
||||
|
||||
// MARK: - Other key stores
|
||||
|
||||
// This migration class resides in SignalMessaging. It ensures that we
|
||||
// migrate an kv stores in SignalMessaging or its dependency SSK.
|
||||
//
|
||||
// However it doesn't know about any key-value stores defined in the
|
||||
// Signal (or hypothetically the SignalShareExtension) target(s).
|
||||
// So the migration logic needs to be informed of those stores.
|
||||
private static var otherKeyStores = [String: SDSKeyValueStore]()
|
||||
|
||||
@objc
|
||||
public class func add(keyStore: SDSKeyValueStore,
|
||||
label: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
guard otherKeyStores[label] == nil else {
|
||||
owsFailDebug("Keystore added twice.")
|
||||
return
|
||||
}
|
||||
otherKeyStores[label] = keyStore
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public class GRDBMigratorGroup: NSObject {
|
||||
public typealias MigratorBlock = (YapDatabaseReadTransaction) -> [GRDBMigrator]
|
||||
public typealias CompletionBlock = () -> Void
|
||||
|
||||
private let block: MigratorBlock
|
||||
|
||||
fileprivate let completionBlock: CompletionBlock?
|
||||
|
||||
@objc
|
||||
public required init(completionBlock: CompletionBlock? = nil,
|
||||
block: @escaping MigratorBlock) {
|
||||
self.block = block
|
||||
self.completionBlock = completionBlock
|
||||
}
|
||||
|
||||
func migrators(ydbTransaction: YapDatabaseReadTransaction) -> [GRDBMigrator] {
|
||||
return block(ydbTransaction)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension YDBToGRDBMigration {
|
||||
|
||||
func run() throws {
|
||||
Logger.info("")
|
||||
|
||||
let startDate = Date()
|
||||
|
||||
// We migrate the data store contents in phases
|
||||
// or batches. Each "group" defines the data to
|
||||
// migrate in a given batch.
|
||||
let migratorGroups = [
|
||||
// Migrate the key-value and unordered records first;
|
||||
// The later migrations may use these values in
|
||||
// "sneaky" transactions.
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return self.allKeyValueMigrators(ydbTransaction: ydbTransaction)
|
||||
},
|
||||
// We need to migrate the user profiles before other models since they
|
||||
// are used when indexing various other models.
|
||||
GRDBMigratorGroup(completionBlock: {
|
||||
self.profileManager.warmCaches()
|
||||
}) { ydbTransaction in
|
||||
return self.profileRecordMigrators(ydbTransaction: ydbTransaction)
|
||||
},
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return self.allUnorderedRecordMigrators(ydbTransaction: ydbTransaction)
|
||||
},
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [GRDBJobRecordMigrator(ydbTransaction: ydbTransaction)]
|
||||
},
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [GRDBInteractionMigrator(ydbTransaction: ydbTransaction)]
|
||||
},
|
||||
GRDBMigratorGroup { ydbTransaction in
|
||||
return [GRDBDecryptJobMigrator(ydbTransaction: ydbTransaction)]
|
||||
}
|
||||
]
|
||||
|
||||
GRDBSchemaMigrator().runSchemaMigrations()
|
||||
|
||||
try self.migrate(migratorGroups: migratorGroups)
|
||||
|
||||
try grdbStorageAdapter.write { transaction in
|
||||
do {
|
||||
try createInitialGalleryRecords(transaction: transaction)
|
||||
} catch {
|
||||
owsFail("error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
removeYdb()
|
||||
|
||||
let migrationDuration = abs(startDate.timeIntervalSinceNow)
|
||||
Logger.info("Migration duration: \(OWSFormat.formatDurationSeconds(Int(migrationDuration))) (\(migrationDuration))")
|
||||
}
|
||||
|
||||
func removeYdb() {
|
||||
guard FeatureFlags.storageMode != .grdbThrowawayIfMigrating else {
|
||||
return
|
||||
}
|
||||
|
||||
// Don't set this flag for "throwaway" migrations.
|
||||
//
|
||||
// It's critical that we do this _before_ deleting the YDB contents,
|
||||
// since the GRDB database is considered disposable until this flag
|
||||
// is set if there are YDB files.
|
||||
SSKPreferences.setIsYdbMigrated(true)
|
||||
|
||||
guard let primaryStorage = primaryStorage else {
|
||||
owsFail("Missing primaryStorage.")
|
||||
}
|
||||
let ydbReadConnection = primaryStorage.newDatabaseConnection()
|
||||
if let owsDatabaseConnection = ydbReadConnection as? OWSDatabaseConnection {
|
||||
// Bless this connection to make YDB writes despite migration
|
||||
// being complete.
|
||||
owsDatabaseConnection.isCleanupConnection = true
|
||||
} else {
|
||||
owsFailDebug("Unexpected connection type.")
|
||||
}
|
||||
ydbReadConnection.readWrite { ydbTransaction in
|
||||
// Note: we deliberately _DO NOT_ deserialize the
|
||||
// models as we delete them from YDB. That would
|
||||
// have undesired side effects, e.g. deleting
|
||||
// attachments on disk.
|
||||
ydbTransaction.removeAllObjectsInAllCollections()
|
||||
}
|
||||
|
||||
OWSStorage.deleteDBKeys()
|
||||
OWSStorage.deleteDatabaseFiles()
|
||||
}
|
||||
|
||||
func migrate(migratorGroups: [GRDBMigratorGroup]) throws {
|
||||
Logger.info("")
|
||||
|
||||
// We can't nest ydbTransactions in GRDB and vice-versa
|
||||
// each has their own serial-queue based concurrency model, which wants to be on
|
||||
// _their own_ serial queue.
|
||||
//
|
||||
// GRDB at least supports nesting multiple database transactions, but the _both_
|
||||
// have to be accessed via GRDB
|
||||
//
|
||||
// TODO: see if we can get reasonable perf by avoiding the nested transactions and
|
||||
// instead doing work in non-overlapping batches.
|
||||
guard let primaryStorage = primaryStorage else {
|
||||
owsFail("Missing primaryStorage.")
|
||||
}
|
||||
let ydbReadConnection = primaryStorage.newDatabaseConnection()
|
||||
ydbReadConnection.ignoreQueues = true
|
||||
ydbReadConnection.beginLongLivedReadTransaction()
|
||||
|
||||
UIDatabaseObserver.serializedSync {
|
||||
UIDatabaseObserver.skipTouchObservations = true
|
||||
}
|
||||
|
||||
for migratorGroup in migratorGroups {
|
||||
try migrate(migratorGroup: migratorGroup,
|
||||
ydbReadConnection: ydbReadConnection)
|
||||
}
|
||||
|
||||
UIDatabaseObserver.serializedSync {
|
||||
UIDatabaseObserver.skipTouchObservations = false
|
||||
}
|
||||
}
|
||||
|
||||
private func migrate(migratorGroup: GRDBMigratorGroup,
|
||||
ydbReadConnection: YapDatabaseConnection) throws {
|
||||
Logger.info("")
|
||||
|
||||
// Logging queries is helpful for normal debugging, but expensive during a migration
|
||||
SDSDatabaseStorage.shouldLogDBQueries = false
|
||||
|
||||
try ydbReadConnection.read { ydbTransaction in
|
||||
let migrators = migratorGroup.migrators(ydbTransaction: ydbTransaction)
|
||||
// Migrate migrators.
|
||||
for migrator in migrators {
|
||||
try autoreleasepool {
|
||||
try self.grdbStorageAdapter.write { grdbTransaction in
|
||||
try! migrator.migrate(grdbTransaction: grdbTransaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let completionBlock = migratorGroup.completionBlock {
|
||||
completionBlock()
|
||||
}
|
||||
|
||||
SDSDatabaseStorage.shouldLogDBQueries = DebugFlags.logSQLQueries
|
||||
}
|
||||
|
||||
private func allKeyValueMigrators(ydbTransaction: YapDatabaseReadTransaction) -> [GRDBMigrator] {
|
||||
LegacySessionRecord.setUpKeyedArchiverSubstitutions()
|
||||
var result: [GRDBMigrator] = [
|
||||
GRDBKeyValueStoreMigrator<PreKeyRecord>(label: "preKey Store", keyStore: preKeyStore.keyStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "preKey Metadata", keyStore: preKeyStore.metadataStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<SignedPreKeyRecord>(label: "signedPreKey Store", keyStore: signedPreKeyStore.keyStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "signedPreKey Metadata", keyStore: signedPreKeyStore.metadataStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<ECKeyPair>(label: "ownIdentity", keyStore: identityManager.ownIdentityKeyValueStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<[Int: LegacySessionRecord]>(label: "sessionStore", keyStore: sessionStore.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<String>(label: "queuedVerificationStateSyncMessages", keyStore: identityManager.queuedVerificationStateSyncMessagesKeyValueStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "tsAccountManager", keyStore: tsAccountManager.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "AppPreferences", keyStore: AppPreferences.store, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "SSKPreferences", keyStore: SSKPreferences.store, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "StickerManager.store", keyStore: StickerManager.store, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "StickerManager.emojiMapStore", keyStore: StickerManager.emojiMapStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "preferences", keyStore: Self.preferences.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSOrphanDataCleaner", keyStore: OWSOrphanDataCleaner.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "contactsManager", keyStore: contactsManagerImpl.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSDeviceManager", keyStore: OWSDeviceManager.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSReadReceiptManager", keyStore: OWSReadReceiptManager.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWS2FAManager", keyStore: OWS2FAManager.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSBlockingManager", keyStore: OWSBlockingManager.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "typingIndicators", keyStore: typingIndicatorsImpl.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "udManager.keyValueStore", keyStore: udManager.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "udManager.phoneNumberAccessStore", keyStore: udManager.phoneNumberAccessStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "udManager.uuidAccessStore", keyStore: udManager.uuidAccessStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "CallKitIdStore.phoneNumber", keyStore: CallKitIdStore.phoneNumber(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "CallKitIdStore.uuid", keyStore: CallKitIdStore.uuidStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "signalService", keyStore: signalService.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSStorageServiceOperation", keyStore: StorageServiceOperation.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSDatabaseMigration", keyStore: OWSDatabaseMigration.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSProfileManager.whitelistedPhoneNumbersStore", keyStore: profileManagerImpl.whitelistedPhoneNumbersStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSProfileManager.whitelistedUUIDsStore", keyStore: profileManagerImpl.whitelistedUUIDsStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSProfileManager.whitelistedGroupsStore", keyStore: profileManagerImpl.whitelistedGroupsStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSProfileManager.settingsStore", keyStore: OWSProfileManager.settingsStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSScreenLock.keyValueStore", keyStore: OWSScreenLock.shared.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSSounds", keyStore: OWSSounds.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "Theme", keyStore: Theme.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSSyncManager", keyStore: OWSSyncManager.keyValueStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSOutgoingReceiptManager.deliveryReceiptStore", keyStore: OWSOutgoingReceiptManager.deliveryReceiptStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "OWSOutgoingReceiptManager.readReceiptStore", keyStore: OWSOutgoingReceiptManager.readReceiptStore(), ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "VersionedProfiles.credentialStore", keyStore: VersionedProfilesImpl.credentialStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "KeyBackupService.keyValueStore", keyStore: KeyBackupService.keyValueStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "KeyBackupService.tokenStore", keyStore: KeyBackupService.tokenStore, ydbTransaction: ydbTransaction),
|
||||
GRDBKeyValueStoreMigrator<Any>(label: "StorageServiceOperation", keyStore: StorageServiceOperation.keyValueStore, ydbTransaction: ydbTransaction)
|
||||
]
|
||||
|
||||
for (label, keyStore) in YDBToGRDBMigration.otherKeyStores {
|
||||
result.append(GRDBKeyValueStoreMigrator<Any>(label: label, keyStore: keyStore, ydbTransaction: ydbTransaction))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private func profileRecordMigrators(ydbTransaction: YapDatabaseReadTransaction) -> [GRDBMigrator] {
|
||||
return [
|
||||
GRDBUnorderedRecordMigrator<OWSUserProfile>(label: "OWSUserProfile", ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
|
||||
private func allUnorderedRecordMigrators(ydbTransaction: YapDatabaseReadTransaction) -> [GRDBMigrator] {
|
||||
return [
|
||||
GRDBUnorderedRecordMigrator<TSAttachment>(label: "TSAttachment", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<OWSMessageContentJob>(label: "OWSMessageContentJob", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<OWSRecipientIdentity>(label: "OWSRecipientIdentity", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<TSThread>(label: "TSThread", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<ExperienceUpgrade>(label: "ExperienceUpgrade", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<StickerPack>(label: "StickerPack", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<InstalledSticker>(label: "InstalledSticker", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<KnownStickerPack>(label: "KnownStickerPack", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<OWSBackupFragment>(label: "OWSBackupFragment", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<SignalRecipient>(label: "SignalRecipient", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<OWSDisappearingMessagesConfiguration>(label: "OWSDisappearingMessagesConfiguration", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<SignalAccount>(label: "SignalAccount", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<OWSDevice>(label: "OWSDevice", ydbTransaction: ydbTransaction),
|
||||
GRDBUnorderedRecordMigrator<OWSReaction>(label: "OWSReaction", ydbTransaction: ydbTransaction)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LegacyObjectFinder<T> {
|
||||
let collection: String
|
||||
|
||||
let transaction: YapDatabaseReadTransaction
|
||||
|
||||
init(collection: String, transaction: YapDatabaseReadTransaction) {
|
||||
self.collection = collection
|
||||
self.transaction = transaction
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
return transaction.numberOfKeys(inCollection: collection)
|
||||
}
|
||||
|
||||
public func enumerateLegacyKeysAndObjects(block: @escaping (String, T) throws -> Void ) throws {
|
||||
var knownCollectionKeys = Set<String>()
|
||||
try transaction.enumerateKeysAndObjects(inCollection: collection) { (collectionKey: String, collectionObj: Any, _: UnsafeMutablePointer<ObjCBool>) throws -> Void in
|
||||
guard let legacyObj = collectionObj as? T else {
|
||||
owsFailDebug("unexpected collectionObj: \(type(of: collectionObj)) collectionKey: \(collectionKey)")
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore duplicates in YDB enumerations.
|
||||
guard !knownCollectionKeys.contains(collectionKey) else {
|
||||
owsFailDebug("Ignoring duplicate collectionKey: \(collectionKey)")
|
||||
return
|
||||
}
|
||||
knownCollectionKeys.insert(collectionKey)
|
||||
|
||||
try block(collectionKey, legacyObj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LegacyKeyValueFinder<T>: LegacyObjectFinder<T> {
|
||||
let store: SDSKeyValueStore
|
||||
|
||||
init(store: SDSKeyValueStore, transaction: YapDatabaseReadTransaction) {
|
||||
self.store = store
|
||||
super.init(collection: store.collection, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LegacyUnorderedFinder<RecordType>: LegacyObjectFinder<RecordType> where RecordType: TSYapDatabaseObject {
|
||||
init(transaction: YapDatabaseReadTransaction) {
|
||||
super.init(collection: RecordType.collection(), transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LegacyInteractionFinder {
|
||||
let transaction: YapDatabaseReadTransaction
|
||||
|
||||
init(transaction: YapDatabaseReadTransaction) {
|
||||
self.transaction = transaction
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
let collection = TSInteraction.collection()
|
||||
return transaction.numberOfKeys(inCollection: collection)
|
||||
}
|
||||
|
||||
// We need to enumerate in ascending order of sort id.
|
||||
public func enumerateLegacyKeysAndObjects(block: @escaping (String, TSInteraction) -> Void ) throws {
|
||||
guard let view = transaction.safeAutoViewTransaction(TSInteractionsBySortIdDatabaseViewExtensionName) else {
|
||||
owsFail("Missing interaction view.")
|
||||
}
|
||||
var knownUniqueIds = Set<String>()
|
||||
view.safe_enumerateKeysAndObjects(inGroup: TSInteractionsBySortIdGroup,
|
||||
extensionName: TSInteractionsBySortIdDatabaseViewExtensionName) { (_, _, object, _, _) in
|
||||
guard let interaction = object as? TSInteraction else {
|
||||
owsFailDebug("unexpected interaction: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore duplicates in YDB enumerations.
|
||||
let uniqueId = interaction.uniqueId
|
||||
guard !knownUniqueIds.contains(uniqueId) else {
|
||||
owsFailDebug("Ignoring duplicate uniqueId: \(uniqueId)")
|
||||
return
|
||||
}
|
||||
knownUniqueIds.insert(uniqueId)
|
||||
|
||||
block(uniqueId, interaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LegacyJobRecordFinder {
|
||||
|
||||
let extensionName = YAPDBJobRecordFinder.dbExtensionName
|
||||
|
||||
var ext: YapDatabaseSecondaryIndexTransaction?
|
||||
|
||||
init(transaction: YapDatabaseReadTransaction) {
|
||||
self.ext = transaction.safeSecondaryIndexTransaction(extensionName)
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
guard let ext = ext else {
|
||||
owsFailDebug("Missing view transcation.")
|
||||
return 0
|
||||
}
|
||||
var count: UInt = 0
|
||||
ext.getNumberOfRows(&count, matching: query)
|
||||
return count
|
||||
}
|
||||
|
||||
private var query: YapDatabaseQuery {
|
||||
let queryFormat = String(format: "ORDER BY %@", "sortId")
|
||||
return YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
}
|
||||
|
||||
public func enumerateJobRecords(block: @escaping (SSKJobRecord) throws -> Void) throws {
|
||||
try enumerateJobRecords(ext: ext, block: block)
|
||||
}
|
||||
|
||||
func enumerateJobRecords(ext: YapDatabaseSecondaryIndexTransaction?, block: @escaping (SSKJobRecord) throws -> Void) throws {
|
||||
guard let ext = ext else {
|
||||
owsFailDebug("Missing ext.")
|
||||
return
|
||||
}
|
||||
|
||||
var errorToRaise: Error?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stopPtr in
|
||||
do {
|
||||
guard let jobRecord = object as? SSKJobRecord else {
|
||||
owsFailDebug("expecting jobRecord but found: \(object)")
|
||||
return
|
||||
}
|
||||
try block(jobRecord)
|
||||
} catch {
|
||||
owsFailDebug("error: \(error)")
|
||||
errorToRaise = error
|
||||
stopPtr.pointee = true
|
||||
}
|
||||
}
|
||||
|
||||
if let errorToRaise = errorToRaise {
|
||||
throw errorToRaise
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LegacyDecryptJobFinder {
|
||||
|
||||
let ydbTransaction: YapDatabaseReadTransaction
|
||||
|
||||
init(transaction: YapDatabaseReadTransaction) {
|
||||
ydbTransaction = transaction
|
||||
}
|
||||
|
||||
var count: UInt {
|
||||
|
||||
let legacyFinder = OWSMessageDecryptJobFinder()
|
||||
return legacyFinder.queuedJobCount(with: ydbTransaction.asAnyRead)
|
||||
}
|
||||
|
||||
func enumerateJobRecords(block: @escaping (OWSMessageDecryptJob) throws -> Void) throws {
|
||||
var errorToRaise: Error?
|
||||
let legacyFinder = OWSMessageDecryptJobFinder()
|
||||
try legacyFinder.enumerateJobs(transaction: ydbTransaction.asAnyRead) { (job, stop) in
|
||||
do {
|
||||
try block(job)
|
||||
} catch {
|
||||
owsFailDebug("error: \(error)")
|
||||
errorToRaise = error
|
||||
stop.pointee = true
|
||||
}
|
||||
}
|
||||
|
||||
if let errorToRaise = errorToRaise {
|
||||
throw errorToRaise
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public protocol GRDBMigrator {
|
||||
var label: String { get }
|
||||
|
||||
var count: UInt { get }
|
||||
|
||||
func migrate(grdbTransaction: GRDBWriteTransaction) throws
|
||||
}
|
||||
|
||||
extension GRDBMigrator {
|
||||
func memorySamplerRatio(count: UInt) -> Float {
|
||||
// Sample no more than N times for a given migration.
|
||||
let maxSampleCount: Float = 100
|
||||
|
||||
let count = Float(self.count)
|
||||
guard count > maxSampleCount else {
|
||||
return 1
|
||||
}
|
||||
return maxSampleCount / count
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public class GRDBKeyValueStoreMigrator<T>: GRDBMigrator {
|
||||
public let label: String
|
||||
private let keyStore: SDSKeyValueStore
|
||||
private let finder: LegacyKeyValueFinder<T>
|
||||
|
||||
init(label: String, keyStore: SDSKeyValueStore, ydbTransaction: YapDatabaseReadTransaction) {
|
||||
self.label = "Migrate \(label)"
|
||||
self.keyStore = keyStore
|
||||
self.finder = LegacyKeyValueFinder(store: keyStore, transaction: ydbTransaction)
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
return finder.count
|
||||
}
|
||||
|
||||
public func migrate(grdbTransaction: GRDBWriteTransaction) throws {
|
||||
let count = self.count
|
||||
Logger.info("\(label): \(count)")
|
||||
try Bench(title: label, memorySamplerRatio: memorySamplerRatio(count: count), logInProduction: true) { memorySampler in
|
||||
var recordCount = 0
|
||||
try finder.enumerateLegacyKeysAndObjects { legacyKey, legacyObject in
|
||||
recordCount += 1
|
||||
if let legacyData = legacyObject as? Data {
|
||||
self.finder.store.setData(legacyData, key: legacyKey, transaction: grdbTransaction.asAnyWrite)
|
||||
} else {
|
||||
self.finder.store.setObject(legacyObject, key: legacyKey, transaction: grdbTransaction.asAnyWrite)
|
||||
}
|
||||
memorySampler.sample()
|
||||
}
|
||||
Logger.info("Completed with recordCount: \(recordCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public class GRDBUnorderedRecordMigrator<T>: GRDBMigrator where T: SDSModel {
|
||||
public let label: String
|
||||
private let finder: LegacyUnorderedFinder<T>
|
||||
|
||||
init(label: String, ydbTransaction: YapDatabaseReadTransaction) {
|
||||
self.label = "Migrate \(label)"
|
||||
self.finder = LegacyUnorderedFinder(transaction: ydbTransaction)
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
return finder.count
|
||||
}
|
||||
|
||||
public func migrate(grdbTransaction: GRDBWriteTransaction) throws {
|
||||
let count = self.count
|
||||
Logger.info("\(label): \(count)")
|
||||
|
||||
var signalRecipientUuids = Set<String>()
|
||||
var signalRecipientPhoneNumbers = Set<String>()
|
||||
try Bench(title: label, memorySamplerRatio: memorySamplerRatio(count: count), logInProduction: true) { memorySampler in
|
||||
var recordCount = 0
|
||||
try finder.enumerateLegacyKeysAndObjects { (_, legacyRecord) in
|
||||
|
||||
// SignalRecipients have GRDB uniqueness constraints on the
|
||||
// phone number and uuid columns. Therefore we need to
|
||||
// de-duplicate during the migration or migration will fail.
|
||||
if let signalRecipient = legacyRecord as? SignalRecipient {
|
||||
if let uuidString = signalRecipient.recipientUUID,
|
||||
signalRecipientUuids.contains(uuidString) {
|
||||
// If YDB contains two recipients with the same UUID, discard one.
|
||||
Logger.warn("Discarding duplicate SignalRecipient: \(uuidString)")
|
||||
return
|
||||
}
|
||||
if let phoneNumber = signalRecipient.recipientPhoneNumber,
|
||||
signalRecipientPhoneNumbers.contains(phoneNumber) {
|
||||
// If YDB contains two recipients with the same phone, try to
|
||||
// discard just the phone number. If the recipient has a uuid,
|
||||
// we can preserve it. If not, discard the recipient.
|
||||
if signalRecipient.recipientUUID == nil {
|
||||
Logger.warn("Discarding duplicate SignalRecipient: \(phoneNumber)")
|
||||
return
|
||||
} else {
|
||||
Logger.warn("Discarding duplicate SignalRecipient phone number: \(phoneNumber)")
|
||||
signalRecipient.removePhoneNumberForDatabaseMigration()
|
||||
}
|
||||
}
|
||||
if let uuidString = signalRecipient.recipientUUID {
|
||||
signalRecipientUuids.insert(uuidString)
|
||||
}
|
||||
if let phoneNumber = signalRecipient.recipientPhoneNumber {
|
||||
signalRecipientPhoneNumbers.insert(phoneNumber)
|
||||
}
|
||||
}
|
||||
|
||||
recordCount += 1
|
||||
legacyRecord.anyInsert(transaction: grdbTransaction.asAnyWrite)
|
||||
memorySampler.sample()
|
||||
}
|
||||
Logger.info("Completed with recordCount: \(recordCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public class GRDBJobRecordMigrator: GRDBMigrator {
|
||||
public let label: String
|
||||
private let finder: LegacyJobRecordFinder
|
||||
|
||||
init(ydbTransaction: YapDatabaseReadTransaction) {
|
||||
self.label = "Migrate SSKJobRecord"
|
||||
self.finder = LegacyJobRecordFinder(transaction: ydbTransaction)
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
return finder.count
|
||||
}
|
||||
|
||||
public func migrate(grdbTransaction: GRDBWriteTransaction) throws {
|
||||
let count = self.count
|
||||
Logger.info("\(label): \(count)")
|
||||
try Bench(title: label, memorySamplerRatio: memorySamplerRatio(count: count), logInProduction: true) { memorySampler in
|
||||
var recordCount = 0
|
||||
try finder.enumerateJobRecords { legacyRecord in
|
||||
recordCount += 1
|
||||
legacyRecord.anyInsert(transaction: grdbTransaction.asAnyWrite)
|
||||
memorySampler.sample()
|
||||
}
|
||||
Logger.info("Completed with recordCount: \(recordCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public class GRDBInteractionMigrator: GRDBMigrator {
|
||||
public let label: String
|
||||
private let finder: LegacyInteractionFinder
|
||||
|
||||
init(ydbTransaction: YapDatabaseReadTransaction) {
|
||||
self.label = "Migrate Interactions"
|
||||
self.finder = LegacyInteractionFinder(transaction: ydbTransaction)
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
return finder.count
|
||||
}
|
||||
|
||||
public func migrate(grdbTransaction: GRDBWriteTransaction) throws {
|
||||
let count = self.count
|
||||
Logger.info("\(label): \(count)")
|
||||
var prevSortId: UInt64?
|
||||
try Bench(title: label, memorySamplerRatio: memorySamplerRatio(count: count), logInProduction: true) { memorySampler in
|
||||
var recordCount = 0
|
||||
// This must enumerate the interactions in ascending order of sort id.
|
||||
try finder.enumerateLegacyKeysAndObjects { (_, interaction) in
|
||||
|
||||
// Ensure all interactions have valid, monotonically increasing sort ids.
|
||||
let minSortId: UInt64
|
||||
if let previousSortId = prevSortId {
|
||||
minSortId = previousSortId + 1
|
||||
} else {
|
||||
minSortId = 1
|
||||
}
|
||||
let sortId: UInt64
|
||||
if interaction.sortId >= minSortId {
|
||||
// Interaction already has valid sort id.
|
||||
sortId = interaction.sortId
|
||||
} else {
|
||||
if interaction.sortId > 0 {
|
||||
owsFailDebug("Replacing invalid sort id: \(interaction.sortId) -> \(minSortId)")
|
||||
} else {
|
||||
owsFailDebug("Setting missing sort id: \(minSortId)")
|
||||
}
|
||||
// NOTE: "replaced" sort ids will not be written to YDB.
|
||||
interaction.replaceSortId(minSortId)
|
||||
sortId = minSortId
|
||||
}
|
||||
prevSortId = sortId
|
||||
|
||||
interaction.anyInsert(transaction: grdbTransaction.asAnyWrite)
|
||||
recordCount += 1
|
||||
memorySampler.sample()
|
||||
}
|
||||
Logger.info("Completed with recordCount: \(recordCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public class GRDBDecryptJobMigrator: GRDBMigrator {
|
||||
public let label: String
|
||||
private let finder: LegacyDecryptJobFinder
|
||||
|
||||
init(ydbTransaction: YapDatabaseReadTransaction) {
|
||||
self.label = "Migrate Jobs"
|
||||
self.finder = LegacyDecryptJobFinder(transaction: ydbTransaction)
|
||||
}
|
||||
|
||||
public var count: UInt {
|
||||
return finder.count
|
||||
}
|
||||
|
||||
public func migrate(grdbTransaction: GRDBWriteTransaction) throws {
|
||||
let count = self.count
|
||||
Logger.info("\(label): \(count)")
|
||||
try Bench(title: label, memorySamplerRatio: memorySamplerRatio(count: count), logInProduction: true) { memorySampler in
|
||||
var recordCount = 0
|
||||
try finder.enumerateJobRecords { legacyJob in
|
||||
let newJob = SSKMessageDecryptJobRecord(
|
||||
envelopeData: legacyJob.envelopeData,
|
||||
serverDeliveryTimestamp: 0,
|
||||
label: "SSKMessageDecrypt"
|
||||
)
|
||||
newJob.anyInsert(transaction: grdbTransaction.asAnyWrite)
|
||||
recordCount += 1
|
||||
memorySampler.sample()
|
||||
}
|
||||
Logger.info("Completed with recordCount: \(recordCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,6 @@
|
||||
#import <SignalServiceKit/OWSFileSystem.h>
|
||||
#import <SignalServiceKit/OWSIncomingContactSyncJobRecord.h>
|
||||
#import <SignalServiceKit/OWSIncomingGroupSyncJobRecord.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
#import <SignalServiceKit/OWSReaction.h>
|
||||
#import <SignalServiceKit/OWSUserProfile.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
@ -315,10 +314,9 @@ typedef void (^OrphanDataBlock)(OWSOrphanData *);
|
||||
// ever accidentally removing the YDB or GRDB databases during
|
||||
// orphan clean up.
|
||||
NSString *grdbDirectoryPath = [SDSDatabaseStorage grdbDatabaseDirUrl].path;
|
||||
NSString *ydbDirectoryPath = [OWSPrimaryStorage sharedDataDatabaseDirPath];
|
||||
NSMutableSet<NSString *> *databaseFilePaths = [NSMutableSet new];
|
||||
for (NSString *filePath in allOnDiskFilePaths) {
|
||||
if ([filePath hasPrefix:grdbDirectoryPath] || [filePath hasPrefix:ydbDirectoryPath]) {
|
||||
if ([filePath hasPrefix:grdbDirectoryPath]) {
|
||||
OWSLogInfo(@"Protecting database file: %@", filePath);
|
||||
[databaseFilePaths addObject:filePath];
|
||||
}
|
||||
@ -326,8 +324,6 @@ typedef void (^OrphanDataBlock)(OWSOrphanData *);
|
||||
[allOnDiskFilePaths minusSet:databaseFilePaths];
|
||||
OWSLogVerbose(
|
||||
@"grdbDirectoryPath: %@ (%d)", grdbDirectoryPath, [OWSFileSystem fileOrFolderExistsAtPath:grdbDirectoryPath]);
|
||||
OWSLogVerbose(
|
||||
@"ydbDirectoryPath: %@ (%d)", ydbDirectoryPath, [OWSFileSystem fileOrFolderExistsAtPath:ydbDirectoryPath]);
|
||||
OWSLogVerbose(@"databaseFilePaths: %lu", (unsigned long)databaseFilePaths.count);
|
||||
|
||||
OWSLogVerbose(@"allOnDiskFilePaths: %lu", (unsigned long)allOnDiskFilePaths.count);
|
||||
|
||||
@ -23,7 +23,6 @@ extern NSString *const OWSPreferencesCallLoggingDidChangeNotification;
|
||||
@class SDSAnyReadTransaction;
|
||||
@class SDSAnyWriteTransaction;
|
||||
@class SDSKeyValueStore;
|
||||
@class YapDatabaseReadWriteTransaction;
|
||||
|
||||
@interface OWSPreferences : NSObject
|
||||
|
||||
@ -37,9 +36,6 @@ extern NSString *const OWSPreferencesCallLoggingDidChangeNotification;
|
||||
|
||||
+ (BOOL)isReadyForAppExtensions;
|
||||
|
||||
+ (BOOL)isYdbReadyForAppExtensions;
|
||||
+ (void)setIsYdbReadyForAppExtensions;
|
||||
|
||||
+ (BOOL)isGrdbReadyForAppExtensions;
|
||||
+ (void)setIsGrdbReadyForAppExtensions;
|
||||
|
||||
@ -99,10 +95,6 @@ extern NSString *const OWSPreferencesCallLoggingDidChangeNotification;
|
||||
- (BOOL)isSystemCallLogEnabled;
|
||||
- (void)setIsSystemCallLogEnabled:(BOOL)value;
|
||||
|
||||
#pragma mark - Legacy CallKit settings
|
||||
|
||||
- (void)applyCallLoggingSettingsForLegacyUsersWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
|
||||
#pragma mark direct call connectivity (non-TURN)
|
||||
|
||||
- (BOOL)doCallsHideIPAddress;
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/StorageCoordinator.h>
|
||||
#import <SignalServiceKit/TSThread.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -44,7 +43,6 @@ NSString *const OWSPreferencesKeyShouldShowUnidentifiedDeliveryIndicators
|
||||
= @"OWSPreferencesKeyShouldShowUnidentifiedDeliveryIndicators";
|
||||
NSString *const OWSPreferencesKeyShouldNotifyOfNewAccountKey = @"OWSPreferencesKeyShouldNotifyOfNewAccountKey";
|
||||
NSString *const OWSPreferencesKeyIOSUpgradeNagDate = @"iOSUpgradeNagDate";
|
||||
NSString *const OWSPreferencesKey_IsYdbReadyForAppExtensions = @"isReadyForAppExtensions_5";
|
||||
NSString *const OWSPreferencesKey_IsGrdbReadyForAppExtensions = @"IsGrdbReadyForAppExtensions";
|
||||
NSString *const OWSPreferencesKey_IsAudibleErrorLoggingEnabled = @"IsAudibleErrorLoggingEnabled";
|
||||
NSString *const OWSPreferencesKeySystemCallLogEnabled = @"OWSPreferencesKeySystemCallLogEnabled";
|
||||
@ -174,20 +172,8 @@ NSString *const OWSPreferencesKeyWasGroupCallTooltipShownCount = @"OWSPreference
|
||||
|
||||
+ (BOOL)isReadyForAppExtensions
|
||||
{
|
||||
if (StorageCoordinator.dataStoreForUI == DataStoreGrdb && !self.isGrdbReadyForAppExtensions) {
|
||||
return NO;
|
||||
}
|
||||
return self.isYdbReadyForAppExtensions;
|
||||
}
|
||||
|
||||
+ (BOOL)isYdbReadyForAppExtensions
|
||||
{
|
||||
return [self appUserDefaultsFlagWithKey:OWSPreferencesKey_IsYdbReadyForAppExtensions];
|
||||
}
|
||||
|
||||
+ (void)setIsYdbReadyForAppExtensions
|
||||
{
|
||||
[self setAppUserDefaultsFlagWithKey:OWSPreferencesKey_IsYdbReadyForAppExtensions];
|
||||
OWSAssertDebug(StorageCoordinator.dataStoreForUI == DataStoreGrdb);
|
||||
return self.isGrdbReadyForAppExtensions;
|
||||
}
|
||||
|
||||
+ (BOOL)isGrdbReadyForAppExtensions
|
||||
@ -352,52 +338,6 @@ NSString *const OWSPreferencesKeyWasGroupCallTooltipShownCount = @"OWSPreference
|
||||
[self setBool:value forKey:OWSPreferencesKeySystemCallLogEnabled];
|
||||
}
|
||||
|
||||
// In iOS 10.2.1, Apple fixed a bug wherein call history was backed up to iCloud.
|
||||
//
|
||||
// See: https://support.apple.com/en-us/HT207482
|
||||
//
|
||||
// In iOS 11, Apple introduced a property CXProviderConfiguration.includesCallsInRecents
|
||||
// that allows us to prevent Signal calls made with CallKit from showing up in the device's
|
||||
// call history.
|
||||
//
|
||||
// Therefore in versions of iOS after 11, we have no need of call privacy.
|
||||
#pragma mark Legacy CallKit
|
||||
|
||||
// Be a little conservative with system call logging with legacy users, even though it's
|
||||
// not synced to iCloud, users could be concerned to suddenly see caller names in their
|
||||
// recent calls list.
|
||||
- (void)applyCallLoggingSettingsForLegacyUsersWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
BOOL wasUsingCallKit =
|
||||
[self.keyValueStore getBool:OWSPreferencesKeyCallKitEnabled defaultValue:YES transaction:transaction.asAnyRead];
|
||||
BOOL wasUsingCallKitPrivacy = [self.keyValueStore getBool:OWSPreferencesKeyCallKitPrivacyEnabled
|
||||
defaultValue:YES
|
||||
transaction:transaction.asAnyRead];
|
||||
|
||||
BOOL shouldLogCallsInRecents = ^{
|
||||
if (wasUsingCallKit && !wasUsingCallKitPrivacy) {
|
||||
// User was using CallKit and explicitly opted in to showing names/numbers,
|
||||
// so it's OK to continue to show names/numbers in the system recents list.
|
||||
return YES;
|
||||
} else {
|
||||
// User was not previously showing names/numbers in the system
|
||||
// recents list, so don't opt them in.
|
||||
return NO;
|
||||
}
|
||||
}();
|
||||
|
||||
OWSLogInfo(@"Migrating setting - System Call Log Enabled: %d", shouldLogCallsInRecents);
|
||||
|
||||
[self.keyValueStore setBool:shouldLogCallsInRecents
|
||||
key:OWSPreferencesKeySystemCallLogEnabled
|
||||
transaction:transaction.asAnyWrite];
|
||||
|
||||
// We need to reload the callService.callUIAdapter here, but SignalMessaging doesn't know about CallService, so we use
|
||||
// notifications to decouple the code. This is admittedly awkward, but it only happens once, and the alternative would
|
||||
// be importing all the call related classes into SignalMessaging.
|
||||
[[NSNotificationCenter defaultCenter] postNotificationNameAsync:OWSPreferencesCallLoggingDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (BOOL)wasViewOnceTooltipShown
|
||||
{
|
||||
return [self boolForKey:OWSPreferencesKeyWasViewOnceTooltipShown defaultValue:NO];
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@ -20,7 +20,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@class TSInteraction;
|
||||
@class TSOutgoingMessage;
|
||||
@class TSThread;
|
||||
@class YapDatabaseReadTransaction;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
@ -44,7 +44,6 @@ An Objective-C library for communicating with the Signal messaging service.
|
||||
s.dependency 'CocoaLumberjack'
|
||||
s.dependency 'AFNetworking/NSURLSession'
|
||||
s.dependency 'Mantle'
|
||||
s.dependency 'YapDatabase/SQLCipher'
|
||||
s.dependency 'Starscream'
|
||||
s.dependency 'libPhoneNumber-iOS'
|
||||
s.dependency 'GRKOpenSSLFramework'
|
||||
|
||||
@ -381,6 +381,9 @@ NSString *NSStringForOWSRegistrationState(OWSRegistrationState value)
|
||||
[self storeLocalNumber:phoneNumber uuid:uuid transaction:transaction];
|
||||
});
|
||||
|
||||
// Clear this flag so we don't show the "dropped ydb" ui during future re-registrations.
|
||||
[SSKPreferences setDidDropYdb:NO];
|
||||
|
||||
[self postRegistrationStateDidChangeNotification];
|
||||
}
|
||||
|
||||
@ -978,8 +981,7 @@ NSString *NSStringForOWSRegistrationState(OWSRegistrationState value)
|
||||
|
||||
- (void)registerForTestsWithLocalNumber:(NSString *)localNumber uuid:(NSUUID *)uuid
|
||||
{
|
||||
OWSAssertDebug(
|
||||
SSKFeatureFlags.storageMode == StorageModeYdbTests || SSKFeatureFlags.storageMode == StorageModeGrdbTests);
|
||||
OWSAssertDebug(SSKFeatureFlags.storageMode == StorageModeGrdbTests);
|
||||
OWSAssertDebug(CurrentAppContext().isRunningTests);
|
||||
OWSAssertDebug(localNumber.length > 0);
|
||||
OWSAssertDebug(uuid != nil);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -7,7 +7,6 @@ import Foundation
|
||||
@objc
|
||||
public class AnyContactThreadFinder: NSObject {
|
||||
let grdbAdapter = GRDBContactThreadFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
@ -18,8 +17,6 @@ public extension AnyContactThreadFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.contactThread(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,8 +25,6 @@ public extension AnyContactThreadFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.contactThreadForUUID(uuid, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOneForUUID(uuid, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,8 +33,6 @@ public extension AnyContactThreadFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.contactThreadForPhoneNumber(phoneNumber, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOneForPhoneNumber(phoneNumber, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,8 +356,6 @@ public extension OWSDisappearingMessagesConfiguration {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return OWSDisappearingMessagesConfiguration.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(DisappearingMessagesConfigurationRecord.databaseTableName) WHERE \(disappearingMessagesConfigurationColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -388,14 +386,6 @@ public extension OWSDisappearingMessagesConfiguration {
|
||||
batchSize: UInt,
|
||||
block: @escaping (OWSDisappearingMessagesConfiguration, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
OWSDisappearingMessagesConfiguration.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? OWSDisappearingMessagesConfiguration else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = OWSDisappearingMessagesConfiguration.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -437,10 +427,6 @@ public extension OWSDisappearingMessagesConfiguration {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: OWSDisappearingMessagesConfiguration.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -472,8 +458,6 @@ public extension OWSDisappearingMessagesConfiguration {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: OWSDisappearingMessagesConfiguration.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return DisappearingMessagesConfigurationRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -483,8 +467,6 @@ public extension OWSDisappearingMessagesConfiguration {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: OWSDisappearingMessagesConfiguration.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try DisappearingMessagesConfigurationRecord.deleteAll(grdbTransaction.database)
|
||||
@ -533,8 +515,6 @@ public extension OWSDisappearingMessagesConfiguration {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: OWSDisappearingMessagesConfiguration.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(DisappearingMessagesConfigurationRecord.databaseTableName) WHERE \(disappearingMessagesConfigurationColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -407,8 +407,6 @@ public extension SignalAccount {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return SignalAccount.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(SignalAccountRecord.databaseTableName) WHERE \(signalAccountColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -439,14 +437,6 @@ public extension SignalAccount {
|
||||
batchSize: UInt,
|
||||
block: @escaping (SignalAccount, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
SignalAccount.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? SignalAccount else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = SignalAccount.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -488,10 +478,6 @@ public extension SignalAccount {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: SignalAccount.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -523,8 +509,6 @@ public extension SignalAccount {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: SignalAccount.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return SignalAccountRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -534,8 +518,6 @@ public extension SignalAccount {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: SignalAccount.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try SignalAccountRecord.deleteAll(grdbTransaction.database)
|
||||
@ -584,8 +566,6 @@ public extension SignalAccount {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: SignalAccount.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(SignalAccountRecord.databaseTableName) WHERE \(signalAccountColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -7,7 +7,6 @@ import Foundation
|
||||
@objc
|
||||
public class AnySignalAccountFinder: NSObject {
|
||||
let grdbAdapter = GRDBSignalAccountFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnySignalAccountFinder {
|
||||
@ -16,8 +15,6 @@ extension AnySignalAccountFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalAccount(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,8 +370,6 @@ public extension SignalRecipient {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return SignalRecipient.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(SignalRecipientRecord.databaseTableName) WHERE \(signalRecipientColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -402,14 +400,6 @@ public extension SignalRecipient {
|
||||
batchSize: UInt,
|
||||
block: @escaping (SignalRecipient, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
SignalRecipient.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? SignalRecipient else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = SignalRecipient.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -451,10 +441,6 @@ public extension SignalRecipient {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: SignalRecipient.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -486,8 +472,6 @@ public extension SignalRecipient {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: SignalRecipient.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return SignalRecipientRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -497,8 +481,6 @@ public extension SignalRecipient {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: SignalRecipient.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try SignalRecipientRecord.deleteAll(grdbTransaction.database)
|
||||
@ -547,8 +529,6 @@ public extension SignalRecipient {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: SignalRecipient.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(SignalRecipientRecord.databaseTableName) WHERE \(signalRecipientColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -7,7 +7,6 @@ import Foundation
|
||||
@objc
|
||||
public class AnySignalRecipientFinder: NSObject {
|
||||
let grdbAdapter = GRDBSignalRecipientFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnySignalRecipientFinder {
|
||||
@ -16,8 +15,6 @@ extension AnySignalRecipientFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalRecipientForUUID(uuid, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOneForUUID(uuid, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,8 +23,6 @@ extension AnySignalRecipientFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalRecipientForPhoneNumber(phoneNumber, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOneForPhoneNumber(phoneNumber, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,8 +31,6 @@ extension AnySignalRecipientFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalRecipient(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,8 +38,6 @@ extension AnySignalRecipientFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalRecipients(for: addresses, transaction: transaction)
|
||||
case .yapRead:
|
||||
fatalError("yap not supported")
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,8 +49,6 @@ extension AnySignalRecipientFinder {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.registeredRecipientsWithoutUUID(transaction: transaction)
|
||||
case .yapRead:
|
||||
fatalError("yap not supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -678,8 +678,6 @@ public extension TSThread {
|
||||
}
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return TSThread.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -710,14 +708,6 @@ public extension TSThread {
|
||||
batchSize: UInt,
|
||||
block: @escaping (TSThread, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
TSThread.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? TSThread else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = TSThread.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -759,10 +749,6 @@ public extension TSThread {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: TSThread.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -794,8 +780,6 @@ public extension TSThread {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: TSThread.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return ThreadRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -805,8 +789,6 @@ public extension TSThread {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: TSThread.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try ThreadRecord.deleteAll(grdbTransaction.database)
|
||||
@ -855,8 +837,6 @@ public extension TSThread {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: TSThread.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -462,16 +462,12 @@ lastVisibleSortIdOnScreenPercentageObsolete:(double)lastVisibleSortIdOnScreenPer
|
||||
|
||||
- (int64_t)messageSortIdForMessage:(TSInteraction *)message transaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
if (transaction.transitional_yapWriteTransaction) {
|
||||
return message.sortId;
|
||||
if (message.grdbId == nil) {
|
||||
OWSFailDebug(@"Missing messageSortId.");
|
||||
} else if (message.grdbId.unsignedLongLongValue == 0) {
|
||||
OWSFailDebug(@"Invalid messageSortId.");
|
||||
} else {
|
||||
if (message.grdbId == nil) {
|
||||
OWSFailDebug(@"Missing messageSortId.");
|
||||
} else if (message.grdbId.unsignedLongLongValue == 0) {
|
||||
OWSFailDebug(@"Invalid messageSortId.");
|
||||
} else {
|
||||
return message.grdbId.longLongValue;
|
||||
}
|
||||
return message.grdbId.longLongValue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,156 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol YAPDBSignalServiceAddressIndexable: class {
|
||||
var indexableUUIDValue: String? { get }
|
||||
var indexablePhoneNumberValue: String? { get }
|
||||
}
|
||||
|
||||
extension SignalAccount: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
extension SignalRecipient: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
extension TSContactThread: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return contactUUID }
|
||||
var indexablePhoneNumberValue: String? { return contactPhoneNumber }
|
||||
}
|
||||
|
||||
extension OWSUserProfile: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalServiceAddressIndex: NSObject {
|
||||
private static let indexableTypes: [YAPDBSignalServiceAddressIndexable.Type] = [
|
||||
SignalAccount.self,
|
||||
SignalRecipient.self,
|
||||
TSContactThread.self
|
||||
]
|
||||
|
||||
private static let uuidKey = "uuidKey"
|
||||
private static let phoneNumberKey = "phoneNumberKey"
|
||||
private static let classNameKey = "classNameKey"
|
||||
|
||||
private static let phoneNumberIndexName = "index_on_recipientPhoneNumber"
|
||||
private static let uuidIndexName = "index_on_recipientUUID"
|
||||
|
||||
func fetchOne<T: YAPDBSignalServiceAddressIndexable>(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
if let result: T = fetchOneForUUID(address.uuid, transaction: transaction) {
|
||||
return result
|
||||
} else if let result: T = fetchOneForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return result
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func fetchOneForUUID<T: YAPDBSignalServiceAddressIndexable>(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalServiceAddressIndex.uuidIndexName) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(
|
||||
format: "WHERE %@ = \"%@\" AND %@ = \"%@\"",
|
||||
YAPDBSignalServiceAddressIndex.uuidKey,
|
||||
uuidString,
|
||||
YAPDBSignalServiceAddressIndex.classNameKey,
|
||||
NSStringFromClass(T.self)
|
||||
)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: T?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? T else {
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
func fetchOneForPhoneNumber<T: YAPDBSignalServiceAddressIndexable>(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalServiceAddressIndex.phoneNumberIndexName) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(
|
||||
format: "WHERE %@ = \"%@\" AND %@ = \"%@\"",
|
||||
YAPDBSignalServiceAddressIndex.phoneNumberKey,
|
||||
phoneNumber,
|
||||
YAPDBSignalServiceAddressIndex.classNameKey,
|
||||
NSStringFromClass(T.self)
|
||||
)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: T?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? T else {
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndexName)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndexName)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(uuidKey, with: .text)
|
||||
setup.addColumn(classNameKey, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let indexableObject = object as? YAPDBSignalServiceAddressIndexable else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[uuidKey] = indexableObject.indexableUUIDValue
|
||||
dict[classNameKey] = NSStringFromClass(type(of: indexableObject))
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "2")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(phoneNumberKey, with: .text)
|
||||
setup.addColumn(classNameKey, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let indexableObject = object as? YAPDBSignalServiceAddressIndexable else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[phoneNumberKey] = indexableObject.indexablePhoneNumberValue
|
||||
dict[classNameKey] = NSStringFromClass(type(of: indexableObject))
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "2")
|
||||
}
|
||||
}
|
||||
@ -376,8 +376,6 @@ public extension OWSDevice {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return OWSDevice.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(DeviceRecord.databaseTableName) WHERE \(deviceColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -408,14 +406,6 @@ public extension OWSDevice {
|
||||
batchSize: UInt,
|
||||
block: @escaping (OWSDevice, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
OWSDevice.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? OWSDevice else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = OWSDevice.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -457,10 +447,6 @@ public extension OWSDevice {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: OWSDevice.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -492,8 +478,6 @@ public extension OWSDevice {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: OWSDevice.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return DeviceRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -503,8 +487,6 @@ public extension OWSDevice {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: OWSDevice.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try DeviceRecord.deleteAll(grdbTransaction.database)
|
||||
@ -553,8 +535,6 @@ public extension OWSDevice {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: OWSDevice.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(DeviceRecord.databaseTableName) WHERE \(deviceColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -732,8 +732,6 @@ public extension TSAttachment {
|
||||
}
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return TSAttachment.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(AttachmentRecord.databaseTableName) WHERE \(attachmentColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -764,14 +762,6 @@ public extension TSAttachment {
|
||||
batchSize: UInt,
|
||||
block: @escaping (TSAttachment, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
TSAttachment.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? TSAttachment else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = TSAttachment.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -813,10 +803,6 @@ public extension TSAttachment {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: TSAttachment.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -848,8 +834,6 @@ public extension TSAttachment {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: TSAttachment.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return AttachmentRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -859,8 +843,6 @@ public extension TSAttachment {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: TSAttachment.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try AttachmentRecord.deleteAll(grdbTransaction.database)
|
||||
@ -909,8 +891,6 @@ public extension TSAttachment {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: TSAttachment.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(AttachmentRecord.databaseTableName) WHERE \(attachmentColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -350,13 +350,6 @@ NSString *NSStringForTSAttachmentPointerState(TSAttachmentPointerState value)
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)ydb_saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
[self checkForStreamOverwrite:transaction.asAnyRead];
|
||||
|
||||
[super ydb_saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
- (void)anyWillInsertWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
[super anyWillInsertWithTransaction:transaction];
|
||||
|
||||
@ -506,7 +506,7 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail);
|
||||
|
||||
- (BOOL)canAsyncUpdate
|
||||
{
|
||||
return (!CurrentAppContext().isRunningTests && !self.storageCoordinator.isMigrating);
|
||||
return !CurrentAppContext().isRunningTests;
|
||||
}
|
||||
|
||||
- (BOOL)isValidVideo
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#import "OWSReadReceiptManager.h"
|
||||
#import "TSAttachmentPointer.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "TSDatabaseSecondaryIndexes.h"
|
||||
#import "TSGroupThread.h"
|
||||
#import <SignalCoreKit/NSDate+OWS.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
@ -3635,8 +3635,6 @@ public extension TSInteraction {
|
||||
}
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return TSInteraction.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -3667,14 +3665,6 @@ public extension TSInteraction {
|
||||
batchSize: UInt,
|
||||
block: @escaping (TSInteraction, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
TSInteraction.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? TSInteraction else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = TSInteraction.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -3716,10 +3706,6 @@ public extension TSInteraction {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: TSInteraction.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -3751,8 +3737,6 @@ public extension TSInteraction {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: TSInteraction.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return InteractionRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -3762,8 +3746,6 @@ public extension TSInteraction {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: TSInteraction.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try InteractionRecord.deleteAll(grdbTransaction.database)
|
||||
@ -3812,8 +3794,6 @@ public extension TSInteraction {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: TSInteraction.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(InteractionRecord.databaseTableName) WHERE \(interactionColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BaseModel.h"
|
||||
@ -92,17 +92,6 @@ NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:receivedAtTimestamp
|
||||
|
||||
#pragma mark Utility Method
|
||||
|
||||
// POST GRDB TODO: Remove this method.
|
||||
+ (NSArray<TSInteraction *> *)ydb_interactionsWithTimestamp:(uint64_t)timestamp
|
||||
ofClass:(Class)clazz
|
||||
withTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||
|
||||
|
||||
// POST GRDB TODO: Remove this method.
|
||||
+ (NSArray<TSInteraction *> *)ydb_interactionsWithTimestamp:(uint64_t)timestamp
|
||||
filter:(BOOL (^_Nonnull)(TSInteraction *))filter
|
||||
withTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||
|
||||
- (uint64_t)timestampForLegacySorting;
|
||||
- (NSComparisonResult)compareForSorting:(TSInteraction *)other;
|
||||
|
||||
@ -114,11 +103,6 @@ NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:receivedAtTimestamp
|
||||
// unseen message indicators, etc.
|
||||
- (BOOL)isDynamicInteraction;
|
||||
|
||||
// NOTE: This is only for use by a legacy migration.
|
||||
- (void)ydb_saveNextSortIdWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
NS_SWIFT_NAME(ydb_saveNextSortId(transaction:));
|
||||
|
||||
// NOTE: This is only for use by the YDB-to-GRDB legacy migration.
|
||||
- (void)replaceSortId:(uint64_t)sortId;
|
||||
|
||||
#if TESTABLE_BUILD
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
//
|
||||
|
||||
#import "TSInteraction.h"
|
||||
#import "TSDatabaseSecondaryIndexes.h"
|
||||
#import "TSThread.h"
|
||||
#import <SignalCoreKit/NSDate+OWS.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
@ -54,43 +53,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (NSArray<TSInteraction *> *)ydb_interactionsWithTimestamp:(uint64_t)timestamp
|
||||
ofClass:(Class)clazz
|
||||
withTransaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(timestamp > 0);
|
||||
|
||||
// Accept any interaction.
|
||||
return [self ydb_interactionsWithTimestamp:timestamp
|
||||
filter:^(TSInteraction *interaction) {
|
||||
return [interaction isKindOfClass:clazz];
|
||||
}
|
||||
withTransaction:transaction];
|
||||
}
|
||||
|
||||
+ (NSArray<TSInteraction *> *)ydb_interactionsWithTimestamp:(uint64_t)timestamp
|
||||
filter:(BOOL (^_Nonnull)(TSInteraction *))filter
|
||||
withTransaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(timestamp > 0);
|
||||
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
|
||||
[TSDatabaseSecondaryIndexes enumerateMessagesWithTimestamp:timestamp
|
||||
withBlock:^(NSString *collection, NSString *key, BOOL *stop) {
|
||||
TSInteraction *interaction =
|
||||
[TSInteraction anyFetchWithUniqueId:key
|
||||
transaction:transaction.asAnyRead];
|
||||
if (!filter(interaction)) {
|
||||
return;
|
||||
}
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
usingTransaction:transaction];
|
||||
|
||||
return [interactions copy];
|
||||
}
|
||||
|
||||
+ (NSString *)collection {
|
||||
return @"TSInteraction";
|
||||
}
|
||||
@ -298,29 +260,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
|
||||
|
||||
#pragma mark - Any Transaction Hooks
|
||||
|
||||
- (void)anyWillInsertWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
[super anyWillInsertWithTransaction:transaction];
|
||||
|
||||
if (transaction.transitional_yapWriteTransaction != nil) {
|
||||
[self ensureIdsWithTransaction:transaction.transitional_yapWriteTransaction];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)ensureIdsWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(transaction);
|
||||
|
||||
if (self.uniqueId.length < 1) {
|
||||
OWSFailDebug(@"Missing uniqueId.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.sortId == 0) {
|
||||
self.sortId = [SSKIncrementingIdFinder nextIdWithKey:[TSInteraction collection] transaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)anyDidInsertWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
[super anyDidInsertWithTransaction:transaction];
|
||||
@ -370,19 +309,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
|
||||
|
||||
#pragma mark - sorting migration
|
||||
|
||||
- (void)ydb_saveNextSortIdWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
if (self.sortId != 0) {
|
||||
// This could happen if something else in our startup process saved the interaction
|
||||
// e.g. another migration ran.
|
||||
// During the migration, since we're enumerating the interactions in the proper order,
|
||||
// we want to ignore any previously assigned sortId
|
||||
self.sortId = 0;
|
||||
}
|
||||
[self ydb_saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
// NOTE: This is only for use by the YDB-to-GRDB legacy migration.
|
||||
- (void)replaceSortId:(uint64_t)sortId {
|
||||
_sortId = sortId;
|
||||
}
|
||||
|
||||
@ -10,9 +10,6 @@ extension TSInteraction {
|
||||
@objc
|
||||
public func fillInMissingSortIdForJustInsertedInteraction(transaction: SDSAnyReadTransaction) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead:
|
||||
owsFailDebug("Unexpected transaction.")
|
||||
return
|
||||
case .grdbRead(let grdbRead):
|
||||
fillInMissingSortIdForJustInsertedInteraction(transaction: grdbRead)
|
||||
}
|
||||
|
||||
@ -375,8 +375,6 @@ public extension TSMention {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return TSMention.ydb_fetch(uniqueId: uniqueId, transaction: ydbTransaction)
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT * FROM \(MentionRecord.databaseTableName) WHERE \(mentionColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: grdbTransaction)
|
||||
@ -407,14 +405,6 @@ public extension TSMention {
|
||||
batchSize: UInt,
|
||||
block: @escaping (TSMention, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
TSMention.ydb_enumerateCollectionObjects(with: ydbTransaction) { (object, stop) in
|
||||
guard let value = object as? TSMention else {
|
||||
owsFailDebug("unexpected object: \(type(of: object))")
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
do {
|
||||
let cursor = TSMention.grdbFetchCursor(transaction: grdbTransaction)
|
||||
@ -456,10 +446,6 @@ public extension TSMention {
|
||||
batchSize: UInt,
|
||||
block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
ydbTransaction.enumerateKeys(inCollection: TSMention.collection()) { (uniqueId, stop) in
|
||||
block(uniqueId, stop)
|
||||
}
|
||||
case .grdbRead(let grdbTransaction):
|
||||
grdbEnumerateUniqueIds(transaction: grdbTransaction,
|
||||
sql: """
|
||||
@ -491,8 +477,6 @@ public extension TSMention {
|
||||
|
||||
class func anyCount(transaction: SDSAnyReadTransaction) -> UInt {
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.numberOfKeys(inCollection: TSMention.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
return MentionRecord.ows_fetchCount(grdbTransaction.database)
|
||||
}
|
||||
@ -502,8 +486,6 @@ public extension TSMention {
|
||||
// in their anyWillRemove(), anyDidRemove() methods.
|
||||
class func anyRemoveAllWithoutInstantation(transaction: SDSAnyWriteTransaction) {
|
||||
switch transaction.writeTransaction {
|
||||
case .yapWrite(let ydbTransaction):
|
||||
ydbTransaction.removeAllObjects(inCollection: TSMention.collection())
|
||||
case .grdbWrite(let grdbTransaction):
|
||||
do {
|
||||
try MentionRecord.deleteAll(grdbTransaction.database)
|
||||
@ -552,8 +534,6 @@ public extension TSMention {
|
||||
assert(uniqueId.count > 0)
|
||||
|
||||
switch transaction.readTransaction {
|
||||
case .yapRead(let ydbTransaction):
|
||||
return ydbTransaction.hasObject(forKey: uniqueId, inCollection: TSMention.collection())
|
||||
case .grdbRead(let grdbTransaction):
|
||||
let sql = "SELECT EXISTS ( SELECT 1 FROM \(MentionRecord.databaseTableName) WHERE \(mentionColumn: .uniqueId) = ? )"
|
||||
let arguments: StatementArguments = [uniqueId]
|
||||
|
||||
@ -661,12 +661,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
|
||||
|
||||
[self removeAllReactionsWithTransaction:transaction];
|
||||
|
||||
// This path gets hit during the YDB->GRDB migration *tests*, at which point
|
||||
// it's unsafe to assume we have a GRDB transaction. We can safely skip this
|
||||
// step during the tests when we don't.
|
||||
if (!transaction.isYapWrite) {
|
||||
[self removeAllMentionsWithTransaction:transaction];
|
||||
}
|
||||
[self removeAllMentionsWithTransaction:transaction];
|
||||
}
|
||||
|
||||
- (void)removeAllAttachmentsWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
|
||||
@ -19,8 +19,6 @@
|
||||
#import <SignalCoreKit/NSString+OWS.h>
|
||||
#import <SignalServiceKit/AppReadiness.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <YapDatabase/YapDatabase.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -201,28 +199,7 @@ NSUInteger const TSOutgoingMessageSchemaVersion = 1;
|
||||
self = [super initWithCoder:coder];
|
||||
|
||||
if (self) {
|
||||
if (self.outgoingMessageSchemaVersion < 1) {
|
||||
OWSAssertDebug(_recipientAddressStates == nil);
|
||||
|
||||
NSMutableDictionary<SignalServiceAddress *, TSOutgoingMessageRecipientState *> *recipientAddressStates =
|
||||
[NSMutableDictionary new];
|
||||
|
||||
NSDictionary<NSString *, TSOutgoingMessageRecipientState *> *_Nullable legacyStateMap =
|
||||
[coder decodeObjectForKey:@"recipientStateMap"];
|
||||
if (legacyStateMap == nil) {
|
||||
legacyStateMap = [self createLegacyRecipientStateMapWithCoder:coder];
|
||||
}
|
||||
OWSAssertDebug(legacyStateMap);
|
||||
for (NSString *phoneNumber in legacyStateMap) {
|
||||
SignalServiceAddress *address = [[SignalServiceAddress alloc] initWithPhoneNumber:phoneNumber];
|
||||
if (!address.isValid) {
|
||||
OWSFailDebug(@"Ignoring invalid address.");
|
||||
continue;
|
||||
}
|
||||
recipientAddressStates[address] = legacyStateMap[phoneNumber];
|
||||
}
|
||||
_recipientAddressStates = recipientAddressStates;
|
||||
}
|
||||
OWSAssertDebug(self.outgoingMessageSchemaVersion >= 1);
|
||||
|
||||
_outgoingMessageSchemaVersion = TSOutgoingMessageSchemaVersion;
|
||||
}
|
||||
@ -231,126 +208,6 @@ NSUInteger const TSOutgoingMessageSchemaVersion = 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, TSOutgoingMessageRecipientState *> *)createLegacyRecipientStateMapWithCoder:(NSCoder *)coder
|
||||
{
|
||||
OWSAssertDebug(SSKEnvironment.shared.databaseStorage.canReadFromYdb);
|
||||
OWSAssertDebug(coder);
|
||||
|
||||
// Determine the "overall message state."
|
||||
TSOutgoingMessageState oldMessageState = TSOutgoingMessageStateFailed;
|
||||
NSNumber *_Nullable messageStateValue = [coder decodeObjectForKey:@"messageState"];
|
||||
if (messageStateValue) {
|
||||
oldMessageState = (TSOutgoingMessageState)messageStateValue.intValue;
|
||||
}
|
||||
_hasLegacyMessageState = YES;
|
||||
_legacyMessageState = oldMessageState;
|
||||
|
||||
OWSOutgoingMessageRecipientState defaultState;
|
||||
switch (oldMessageState) {
|
||||
case TSOutgoingMessageStateFailed:
|
||||
defaultState = OWSOutgoingMessageRecipientStateFailed;
|
||||
break;
|
||||
case TSOutgoingMessageStateSending:
|
||||
defaultState = OWSOutgoingMessageRecipientStateSending;
|
||||
break;
|
||||
case TSOutgoingMessageStateSent:
|
||||
case TSOutgoingMessageStateSent_OBSOLETE:
|
||||
case TSOutgoingMessageStateDelivered_OBSOLETE:
|
||||
// Convert legacy values.
|
||||
defaultState = OWSOutgoingMessageRecipientStateSent;
|
||||
break;
|
||||
}
|
||||
|
||||
// Try to leverage the "per-recipient state."
|
||||
NSDictionary<NSString *, NSNumber *> *_Nullable recipientDeliveryMap =
|
||||
[coder decodeObjectForKey:@"recipientDeliveryMap"];
|
||||
NSDictionary<NSString *, NSNumber *> *_Nullable recipientReadMap = [coder decodeObjectForKey:@"recipientReadMap"];
|
||||
NSArray<NSString *> *_Nullable sentRecipients = [coder decodeObjectForKey:@"sentRecipients"];
|
||||
|
||||
NSMutableDictionary<NSString *, TSOutgoingMessageRecipientState *> *recipientStateMap = [NSMutableDictionary new];
|
||||
__block BOOL isGroupThread = NO;
|
||||
// Our default recipient list is the current thread members.
|
||||
__block NSArray<NSString *> *recipientIds = @[];
|
||||
// To avoid deadlock while migrating these records, we use a dedicated
|
||||
// migration connection. For legacy records (created more than ~9 months
|
||||
// before the migration), we need to infer the recipient list for this
|
||||
// message from the current thread membership. This inference isn't
|
||||
// always accurate, so not using the same connection for both reads is
|
||||
// acceptable.
|
||||
[TSOutgoingMessage.dbMigrationConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
TSThread *thread = [self threadWithTransaction:transaction.asAnyRead];
|
||||
NSMutableArray<NSString *> *idsFromAddresses = [NSMutableArray new];
|
||||
for (SignalServiceAddress *address in [thread recipientAddresses]) {
|
||||
if (!address.phoneNumber) {
|
||||
continue;
|
||||
}
|
||||
[idsFromAddresses addObject:address.phoneNumber];
|
||||
}
|
||||
recipientIds = [idsFromAddresses copy];
|
||||
isGroupThread = [thread isGroupThread];
|
||||
}];
|
||||
|
||||
NSNumber *_Nullable wasDelivered = [coder decodeObjectForKey:@"wasDelivered"];
|
||||
_legacyWasDelivered = wasDelivered && wasDelivered.boolValue;
|
||||
BOOL wasDeliveredToContact = NO;
|
||||
if (isGroupThread) {
|
||||
// If we have a `sentRecipients` list, prefer that as it is more accurate.
|
||||
if (sentRecipients) {
|
||||
recipientIds = sentRecipients;
|
||||
}
|
||||
} else {
|
||||
// Special-case messages in contact threads; if "was delivered", we know
|
||||
// it was delivered to the contact.
|
||||
wasDeliveredToContact = _legacyWasDelivered;
|
||||
}
|
||||
|
||||
NSString *_Nullable singleGroupRecipient = [coder decodeObjectForKey:@"singleGroupRecipient"];
|
||||
if (singleGroupRecipient) {
|
||||
OWSFailDebug(@"unexpected single group recipient message.");
|
||||
// If this is a "single group recipient message", treat it as such.
|
||||
recipientIds = @[
|
||||
singleGroupRecipient,
|
||||
];
|
||||
}
|
||||
|
||||
for (NSString *recipientId in recipientIds) {
|
||||
TSOutgoingMessageRecipientState *recipientState = [TSOutgoingMessageRecipientState new];
|
||||
|
||||
NSNumber *_Nullable readTimestamp = recipientReadMap[recipientId];
|
||||
NSNumber *_Nullable deliveryTimestamp = recipientDeliveryMap[recipientId];
|
||||
if (readTimestamp) {
|
||||
// If we have a read timestamp for this recipient, mark it as read.
|
||||
recipientState.state = OWSOutgoingMessageRecipientStateSent;
|
||||
recipientState.readTimestamp = readTimestamp;
|
||||
// deliveryTimestamp might be nil here.
|
||||
recipientState.deliveryTimestamp = deliveryTimestamp;
|
||||
} else if (deliveryTimestamp) {
|
||||
// If we have a delivery timestamp for this recipient, mark it as delivered.
|
||||
recipientState.state = OWSOutgoingMessageRecipientStateSent;
|
||||
recipientState.deliveryTimestamp = deliveryTimestamp;
|
||||
} else if (wasDeliveredToContact) {
|
||||
OWSAssertDebug(!isGroupThread);
|
||||
recipientState.state = OWSOutgoingMessageRecipientStateSent;
|
||||
// Use message time as an estimate of delivery time.
|
||||
recipientState.deliveryTimestamp = @(self.timestamp);
|
||||
} else if ([sentRecipients containsObject:recipientId]) {
|
||||
// If this recipient is in `sentRecipients`, mark it as sent.
|
||||
recipientState.state = OWSOutgoingMessageRecipientStateSent;
|
||||
} else {
|
||||
// Use the default state for this message.
|
||||
recipientState.state = defaultState;
|
||||
}
|
||||
|
||||
recipientStateMap[recipientId] = recipientState;
|
||||
}
|
||||
return [recipientStateMap copy];
|
||||
}
|
||||
|
||||
+ (YapDatabaseConnection *)dbMigrationConnection
|
||||
{
|
||||
return SSKEnvironment.shared.migrationDBConnection;
|
||||
}
|
||||
|
||||
+ (instancetype)outgoingMessageInThread:(TSThread *)thread
|
||||
messageBody:(nullable NSString *)body
|
||||
attachmentId:(nullable NSString *)attachmentId
|
||||
@ -586,30 +443,18 @@ NSUInteger const TSOutgoingMessageSchemaVersion = 1;
|
||||
return NO;
|
||||
}
|
||||
|
||||
// POST GRDB TODO: Remove this override.
|
||||
- (void)ydb_saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
_storedMessageState = self.messageState;
|
||||
|
||||
[super ydb_saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
- (void)anyWillInsertWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
[super anyWillInsertWithTransaction:transaction];
|
||||
|
||||
if (transaction.transitional_yapWriteTransaction == nil) {
|
||||
_storedMessageState = self.messageState;
|
||||
}
|
||||
_storedMessageState = self.messageState;
|
||||
}
|
||||
|
||||
- (void)anyWillUpdateWithTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
[super anyWillUpdateWithTransaction:transaction];
|
||||
|
||||
if (transaction.transitional_yapWriteTransaction == nil) {
|
||||
_storedMessageState = self.messageState;
|
||||
}
|
||||
_storedMessageState = self.messageState;
|
||||
}
|
||||
|
||||
// This method will be called after every insert and update, so it needs
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user