mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
use dedicated read connection to pre-populate cache
// FREEBIE
This commit is contained in:
parent
336c92ddab
commit
42dc872c9a
|
@ -38,7 +38,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.19.2</string>
|
||||
<string>2.19.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
@ -55,7 +55,7 @@
|
|||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.19.2.0</string>
|
||||
<string>2.19.3.0</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LOGS_EMAIL</key>
|
||||
|
@ -101,10 +101,10 @@
|
|||
<string>Signal uses your contacts to find users you know. We do not store your contacts on the server.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Signal needs access to your microphone to make and receive phone calls and record voice messages.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Signal will let you choose which photos from your library to send.</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>Signal will save photos to your library.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Signal will let you choose which photos from your library to send.</string>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>dripicons-v2.ttf</string>
|
||||
|
|
|
@ -858,6 +858,8 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
|||
|
||||
[AppVersion.instance appLaunchDidComplete];
|
||||
|
||||
[[Environment getCurrent].contactsManager loadSignalAccountsFromCache];
|
||||
|
||||
[self ensureRootViewController];
|
||||
|
||||
// If there were any messages in our local queue which we hadn't yet processed.
|
||||
|
|
|
@ -34,6 +34,7 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
|
|||
@property (atomic, readonly) NSArray<SignalAccount *> *signalAccounts;
|
||||
- (nullable SignalAccount *)signalAccountForRecipientId:(NSString *)recipientId;
|
||||
|
||||
- (void)loadSignalAccountsFromCache;
|
||||
#pragma mark - System Contact Fetching
|
||||
|
||||
// Must call `requestSystemContactsOnce` before accessing this method
|
||||
|
|
|
@ -29,6 +29,8 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
@property (atomic) NSArray<SignalAccount *> *signalAccounts;
|
||||
@property (atomic) NSDictionary<NSString *, SignalAccount *> *signalAccountMap;
|
||||
@property (nonatomic, readonly) SystemContactsFetcher *systemContactsFetcher;
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbReadConnection;
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbWriteConnection;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -42,18 +44,36 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
|
||||
// TODO: We need to configure the limits of this cache.
|
||||
_avatarCache = [ImageCache new];
|
||||
|
||||
_dbReadConnection = [TSStorageManager sharedManager].newDatabaseConnection;
|
||||
_dbWriteConnection = [TSStorageManager sharedManager].newDatabaseConnection;
|
||||
|
||||
_allContacts = @[];
|
||||
_allContactsMap = @{};
|
||||
_signalAccountMap = @{};
|
||||
_signalAccounts = @[];
|
||||
_systemContactsFetcher = [SystemContactsFetcher new];
|
||||
_systemContactsFetcher.delegate = self;
|
||||
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadSignalAccountsFromCache
|
||||
{
|
||||
__block NSMutableArray<SignalAccount *> *signalAccounts;
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
|
||||
signalAccounts = [[NSMutableArray alloc] initWithCapacity:[SignalAccount numberOfKeysInCollectionWithTransaction:transaction]];
|
||||
|
||||
[SignalAccount enumerateCollectionObjectsWithTransaction:transaction usingBlock:^(SignalAccount *signalAccount, BOOL * _Nonnull stop) {
|
||||
[signalAccounts addObject:signalAccount];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self updateSignalAccounts:signalAccounts];
|
||||
}
|
||||
|
||||
#pragma mark - System Contact Fetching
|
||||
|
||||
// Request contacts access if you haven't asked recently.
|
||||
|
@ -111,7 +131,7 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
{
|
||||
void (^success)(void) = ^{
|
||||
DDLogInfo(@"%@ Successfully intersected contacts.", self.logTag);
|
||||
[self updateSignalAccounts];
|
||||
[self buildSignalAccounts];
|
||||
};
|
||||
void (^failure)(NSError *error) = ^(NSError *error) {
|
||||
if ([error.domain isEqualToString:OWSSignalServiceKitErrorDomain]
|
||||
|
@ -175,12 +195,12 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
|
||||
[self intersectContacts];
|
||||
|
||||
[self updateSignalAccounts];
|
||||
[self buildSignalAccounts];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)updateSignalAccounts
|
||||
- (void)buildSignalAccounts
|
||||
{
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSMutableDictionary<NSString *, SignalAccount *> *signalAccountMap = [NSMutableDictionary new];
|
||||
|
@ -191,7 +211,7 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
// in order to avoid database deadlock.
|
||||
NSMutableDictionary<NSString *, NSArray<SignalRecipient *> *> *contactIdToSignalRecipientsMap =
|
||||
[NSMutableDictionary new];
|
||||
[[TSStorageManager sharedManager].dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
for (Contact *contact in contacts) {
|
||||
NSArray<SignalRecipient *> *signalRecipients = [contact signalRecipientsWithTransaction:transaction];
|
||||
contactIdToSignalRecipientsMap[contact.uniqueId] = signalRecipients;
|
||||
|
@ -212,31 +232,48 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
DDLogDebug(@"Ignoring duplicate contact: %@, %@", signalAccount.recipientId, contact.fullName);
|
||||
continue;
|
||||
}
|
||||
signalAccountMap[signalAccount.recipientId] = signalAccount;
|
||||
[signalAccounts addObject:signalAccount];
|
||||
}
|
||||
}
|
||||
|
||||
[TSStorageManager.sharedManager.newDatabaseConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
// TODO we can be more efficient here.
|
||||
// - only save the ones that changed
|
||||
// - only remove the ones which no longer exist
|
||||
[transaction removeAllObjectsInCollection:[SignalAccount collection]];
|
||||
for (SignalAccount *signalAccount in signalAccounts) {
|
||||
[signalAccount saveWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
// Update cached SignalAccounts on disk
|
||||
[self.dbWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
NSArray<NSString *> *allKeys = [transaction allKeysInCollection:[SignalAccount collection]];
|
||||
NSMutableSet<NSString *> *orphanedKeys = [NSMutableSet setWithArray:allKeys];
|
||||
|
||||
for (SignalAccount *signalAccount in signalAccounts) {
|
||||
// TODO only save the ones that changed
|
||||
[orphanedKeys removeObject:signalAccount.uniqueId];
|
||||
[signalAccount saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
if (orphanedKeys.count > 0) {
|
||||
DDLogInfo(@"%@ Removing %lu orphaned SignalAccounts", self.logTag, (unsigned long)orphanedKeys.count);
|
||||
[transaction removeObjectsForKeys:orphanedKeys.allObjects inCollection:[SignalAccount collection]];
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.signalAccountMap = [signalAccountMap copy];
|
||||
self.signalAccounts = [signalAccounts copy];
|
||||
|
||||
[self.profileManager setContactRecipientIds:signalAccountMap.allKeys];
|
||||
[self updateSignalAccounts:signalAccounts];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)updateSignalAccounts:(NSArray<SignalAccount *> *)signalAccounts
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
NSMutableDictionary<NSString *, SignalAccount *> *signalAccountMap = [NSMutableDictionary new];
|
||||
for (SignalAccount *signalAccount in signalAccounts) {
|
||||
signalAccountMap[signalAccount.recipientId] = signalAccount;
|
||||
}
|
||||
|
||||
self.signalAccountMap = [signalAccountMap copy];
|
||||
self.signalAccounts = [signalAccounts copy];
|
||||
[self.profileManager setContactRecipientIds:signalAccountMap.allKeys];
|
||||
}
|
||||
|
||||
// TODO dependency inject, avoid circular dependencies.
|
||||
- (OWSProfileManager *)profileManager
|
||||
{
|
||||
|
@ -543,12 +580,14 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
|||
{
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
SignalAccount *signalAccount = self.signalAccountMap[recipientId];
|
||||
__block SignalAccount *signalAccount = self.signalAccountMap[recipientId];
|
||||
|
||||
// If contact intersection hasn't completed, it might exist on disk
|
||||
// even if it doesn't exist in memory yet.
|
||||
if (!signalAccount) {
|
||||
signalAccount = [SignalAccount fetchObjectWithUniqueID:recipientId];
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
|
||||
signalAccount = [SignalAccount fetchObjectWithUniqueID:recipientId transaction: transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
return signalAccount;
|
||||
|
|
Loading…
Reference in a new issue