From 10c00501fdee212b9d671e2aa03b864a325da5a1 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 2 Oct 2017 11:47:46 -0400 Subject: [PATCH] Fix the "is contact" test. // FREEBIE --- Signal/src/AppDelegate.m | 1 + .../ConversationViewController.m | 6 +-- Signal/src/contact/OWSContactsManager.h | 20 ++++++++-- Signal/src/contact/OWSContactsManager.m | 39 +++++++++++++------ Signal/src/util/ThreadUtil.m | 2 +- 5 files changed, 49 insertions(+), 19 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 4e9ef4246..01f9bdd9a 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -837,6 +837,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; [OWSProfileManager.sharedManager fetchLocalUsersProfile]; [[OWSReadReceiptManager sharedManager] prepareCachedValues]; + [[Environment getCurrent].contactsManager loadLastKnownContactRecipientIds]; } - (void)registrationStateDidChange diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index ffe61c717..0c632ead9 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -423,8 +423,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { name:kNSNotificationName_ProfileWhitelistDidChange object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(contactsDidChange:) - name:OWSContactsManagerContactListDidChangeNotification + selector:@selector(signalAccountsDidChange:) + name:OWSContactsManagerSignalAccountsDidChangeNotification object:nil]; } @@ -446,7 +446,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil]; } -- (void)contactsDidChange:(NSNotification *)notification +- (void)signalAccountsDidChange:(NSNotification *)notification { OWSAssert([NSThread isMainThread]); diff --git a/Signal/src/contact/OWSContactsManager.h b/Signal/src/contact/OWSContactsManager.h index 4f4f104ca..26ead6b21 100644 --- a/Signal/src/contact/OWSContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -8,9 +8,6 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; -// Fired when the list of contact phone numbers changes, not when -// other contact properties change. -extern NSString *const OWSContactsManagerContactListDidChangeNotification; @class ImageCache; @class SignalAccount; @@ -39,10 +36,27 @@ extern NSString *const OWSContactsManagerContactListDidChangeNotification; @property (atomic, readonly) NSDictionary *signalAccountMap; @property (atomic, readonly) NSArray *signalAccounts; +// This value is cached and is available immediately, before system contacts +// fetch or contacts intersection. +// +// In some cases, its better if our UI reflects these values +// which haven't been updated yet rather than assume that +// we have no contacts until the first contacts intersection +// successfully completes. +// +// This significantly improves the user experience when: +// +// * No contacts intersection has completed because the app has just launched. +// * Contacts intersection can't complete due to an unreliable connection or +// the contacts intersection rate limit. +@property (atomic, readonly) NSArray *lastKnownContactRecipientIds; + - (nullable SignalAccount *)signalAccountForRecipientId:(NSString *)recipientId; - (Contact *)getOrBuildContactForPhoneIdentifier:(NSString *)identifier; +- (void)loadLastKnownContactRecipientIds; + #pragma mark - System Contact Fetching // Must call `requestSystemContactsOnce` before accessing this method diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 13952ada9..34701d367 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -16,14 +16,14 @@ @import Contacts; -NSString *const OWSContactsManagerSignalAccountsDidChangeNotification = -@"OWSContactsManagerSignalAccountsDidChangeNotification"; -NSString *const OWSContactsManagerContactListDidChangeNotification = -@"OWSContactsManagerContactListDidChangeNotification"; +NSString *const OWSContactsManagerSignalAccountsDidChangeNotification + = @"OWSContactsManagerSignalAccountsDidChangeNotification"; NSString *const kTSStorageManager_AccountDisplayNames = @"kTSStorageManager_AccountDisplayNames"; NSString *const kTSStorageManager_AccountFirstNames = @"kTSStorageManager_AccountFirstNames"; NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_AccountLastNames"; +NSString *const kTSStorageManager_OWSContactsManager = @"kTSStorageManager_OWSContactsManager"; +NSString *const kTSStorageManager_lastKnownContactRecipientIds = @"lastKnownContactRecipientIds"; @interface OWSContactsManager () @@ -36,6 +36,7 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account @property (atomic) NSDictionary *allContactsMap; @property (atomic) NSArray *signalAccounts; @property (atomic) NSDictionary *signalAccountMap; +@property (atomic) NSArray *lastKnownContactRecipientIds; @property (nonatomic, readonly) SystemContactsFetcher *systemContactsFetcher; @property (atomic) NSDictionary *cachedAccountNameMap; @@ -58,6 +59,7 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account _allContactsMap = @{}; _signalAccountMap = @{}; _signalAccounts = @[]; + _lastKnownContactRecipientIds = @[]; _systemContactsFetcher = [SystemContactsFetcher new]; _systemContactsFetcher.delegate = self; @@ -68,6 +70,18 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account return self; } +- (void)loadLastKnownContactRecipientIds +{ + [TSStorageManager.sharedManager.newDatabaseConnection readWithBlock:^( + YapDatabaseReadTransaction *_Nonnull transaction) { + NSArray *_Nullable value = [transaction objectForKey:kTSStorageManager_lastKnownContactRecipientIds + inCollection:kTSStorageManager_OWSContactsManager]; + if (value) { + self.lastKnownContactRecipientIds = value; + } + }]; +} + #pragma mark - System Contact Fetching // Request contacts access if you haven't asked recently. @@ -178,8 +192,6 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account } dispatch_async(dispatch_get_main_queue(), ^{ - BOOL didContactListChange = ![self.allContactsMap isEqual:allContactsMap]; - self.allContacts = contacts; self.allContactsMap = [allContactsMap copy]; @@ -190,12 +202,6 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account [self updateSignalAccounts]; [self updateCachedDisplayNames]; - - if (didContactListChange) { - [[NSNotificationCenter defaultCenter] - postNotificationNameAsync:OWSContactsManagerContactListDidChangeNotification - object:nil]; - } }); }); } @@ -237,7 +243,16 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account } } + NSArray *lastKnownContactRecipientIds = [signalAccountMap allKeys]; + [TSStorageManager.sharedManager.newDatabaseConnection + readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + [transaction setObject:lastKnownContactRecipientIds + forKey:kTSStorageManager_lastKnownContactRecipientIds + inCollection:kTSStorageManager_OWSContactsManager]; + }]; + dispatch_async(dispatch_get_main_queue(), ^{ + self.lastKnownContactRecipientIds = lastKnownContactRecipientIds; self.signalAccountMap = [signalAccountMap copy]; self.signalAccounts = [signalAccounts copy]; diff --git a/Signal/src/util/ThreadUtil.m b/Signal/src/util/ThreadUtil.m index 9ec55c4c0..2171afeb9 100644 --- a/Signal/src/util/ThreadUtil.m +++ b/Signal/src/util/ThreadUtil.m @@ -385,7 +385,7 @@ NS_ASSUME_NONNULL_BEGIN shouldHaveAddToProfileWhitelistOffer = NO; } - BOOL isContact = contactsManager.allContactsMap[recipientId] != nil; + BOOL isContact = [contactsManager.lastKnownContactRecipientIds containsObject:recipientId]; if (isContact) { // Only create "add to contacts" offers for non-contacts. shouldHaveAddToContactsOffer = NO;