Persist signal accounts (and their embedded Contact)
// FREEBIE
This commit is contained in:
parent
9cea6971ba
commit
7ea4b85a2a
|
@ -881,7 +881,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
|||
|
||||
[OWSProfileManager.sharedManager fetchLocalUsersProfile];
|
||||
[[OWSReadReceiptManager sharedManager] prepareCachedValues];
|
||||
[[Environment getCurrent].contactsManager loadLastKnownContactRecipientIds];
|
||||
}
|
||||
|
||||
- (void)registrationStateDidChange
|
||||
|
|
|
@ -171,7 +171,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssert([self.thread isKindOfClass:[TSContactThread class]]);
|
||||
TSContactThread *contactThread = (TSContactThread *)self.thread;
|
||||
NSString *recipientId = contactThread.contactIdentifier;
|
||||
return [self.contactsManager.lastKnownContactRecipientIds containsObject:recipientId];
|
||||
return [self.contactsManager signalAccountForRecipientId:recipientId] != nil;
|
||||
}
|
||||
|
||||
#pragma mark - ContactEditingDelegate
|
||||
|
|
|
@ -30,33 +30,10 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
|
|||
|
||||
@property (atomic, readonly) NSDictionary<NSString *, Contact *> *allContactsMap;
|
||||
|
||||
// signalAccountMap and signalAccounts hold the same data.
|
||||
// signalAccountMap is for lookup. signalAccounts contains the accounts
|
||||
// ordered by display order.
|
||||
@property (atomic, readonly) NSDictionary<NSString *, SignalAccount *> *signalAccountMap;
|
||||
// order of the signalAccounts array respects the systems contact sorting preference
|
||||
@property (atomic, readonly) NSArray<SignalAccount *> *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<NSString *> *lastKnownContactRecipientIds;
|
||||
|
||||
- (nullable SignalAccount *)signalAccountForRecipientId:(NSString *)recipientId;
|
||||
|
||||
- (Contact *)getOrBuildContactForPhoneIdentifier:(NSString *)identifier;
|
||||
|
||||
- (void)loadLastKnownContactRecipientIds;
|
||||
|
||||
#pragma mark - System Contact Fetching
|
||||
|
||||
// Must call `requestSystemContactsOnce` before accessing this method
|
||||
|
|
|
@ -23,7 +23,6 @@ NSString *const kTSStorageManager_AccountDisplayNames = @"kTSStorageManager_Acco
|
|||
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 () <SystemContactsFetcherDelegate>
|
||||
|
||||
|
@ -34,7 +33,6 @@ NSString *const kTSStorageManager_lastKnownContactRecipientIds = @"lastKnownCont
|
|||
@property (atomic) NSDictionary<NSString *, Contact *> *allContactsMap;
|
||||
@property (atomic) NSArray<SignalAccount *> *signalAccounts;
|
||||
@property (atomic) NSDictionary<NSString *, SignalAccount *> *signalAccountMap;
|
||||
@property (atomic) NSArray<NSString *> *lastKnownContactRecipientIds;
|
||||
@property (nonatomic, readonly) SystemContactsFetcher *systemContactsFetcher;
|
||||
|
||||
@property (atomic) NSDictionary<NSString *, NSString *> *cachedAccountNameMap;
|
||||
|
@ -57,7 +55,6 @@ NSString *const kTSStorageManager_lastKnownContactRecipientIds = @"lastKnownCont
|
|||
_allContactsMap = @{};
|
||||
_signalAccountMap = @{};
|
||||
_signalAccounts = @[];
|
||||
_lastKnownContactRecipientIds = @[];
|
||||
_systemContactsFetcher = [SystemContactsFetcher new];
|
||||
_systemContactsFetcher.delegate = self;
|
||||
|
||||
|
@ -68,18 +65,6 @@ NSString *const kTSStorageManager_lastKnownContactRecipientIds = @"lastKnownCont
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void)loadLastKnownContactRecipientIds
|
||||
{
|
||||
[TSStorageManager.sharedManager.newDatabaseConnection readWithBlock:^(
|
||||
YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
NSArray<NSString *> *_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.
|
||||
|
@ -245,16 +230,18 @@ NSString *const kTSStorageManager_lastKnownContactRecipientIds = @"lastKnownCont
|
|||
}
|
||||
}
|
||||
|
||||
NSArray<NSString *> *lastKnownContactRecipientIds = [signalAccountMap allKeys];
|
||||
[TSStorageManager.sharedManager.newDatabaseConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[transaction setObject:lastKnownContactRecipientIds
|
||||
forKey:kTSStorageManager_lastKnownContactRecipientIds
|
||||
inCollection:kTSStorageManager_OWSContactsManager];
|
||||
// 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];
|
||||
}
|
||||
}];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.lastKnownContactRecipientIds = lastKnownContactRecipientIds;
|
||||
self.signalAccountMap = [signalAccountMap copy];
|
||||
self.signalAccounts = [signalAccounts copy];
|
||||
|
||||
|
@ -682,25 +669,22 @@ NSString *const kTSStorageManager_lastKnownContactRecipientIds = @"lastKnownCont
|
|||
{
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
return self.signalAccountMap[recipientId];
|
||||
}
|
||||
SignalAccount *signalAccount = self.signalAccountMap[recipientId];
|
||||
|
||||
- (Contact *)getOrBuildContactForPhoneIdentifier:(NSString *)identifier
|
||||
{
|
||||
Contact *savedContact = self.allContactsMap[identifier];
|
||||
if (savedContact) {
|
||||
return savedContact;
|
||||
} else {
|
||||
return [[Contact alloc] initWithContactWithFirstName:self.unknownContactName
|
||||
andLastName:nil
|
||||
andUserTextPhoneNumbers:@[ identifier ]
|
||||
andImage:nil
|
||||
andContactID:0];
|
||||
// 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];
|
||||
}
|
||||
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
- (UIImage * _Nullable)imageForPhoneIdentifier:(NSString * _Nullable)identifier {
|
||||
Contact *contact = self.allContactsMap[identifier];
|
||||
if (!contact) {
|
||||
contact = [self signalAccountForRecipientId:identifier].contact;
|
||||
}
|
||||
|
||||
// Prefer the contact image from the local address book if available
|
||||
UIImage *_Nullable image = contact.image;
|
||||
|
|
|
@ -388,7 +388,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
shouldHaveAddToProfileWhitelistOffer = NO;
|
||||
}
|
||||
|
||||
BOOL isContact = [contactsManager.lastKnownContactRecipientIds containsObject:recipientId];
|
||||
BOOL isContact = [contactsManager signalAccountForRecipientId:recipientId] != nil;
|
||||
if (isContact) {
|
||||
// Only create "add to contacts" offers for non-contacts.
|
||||
shouldHaveAddToContactsOffer = NO;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
|
||||
#import <AddressBook/AddressBook.h>
|
||||
#import <Mantle/MTLModel.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
@ -19,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@class SignalRecipient;
|
||||
@class YapDatabaseReadTransaction;
|
||||
|
||||
@interface Contact : NSObject
|
||||
@interface Contact : MTLModel
|
||||
|
||||
@property (nullable, readonly, nonatomic) NSString *firstName;
|
||||
@property (nullable, readonly, nonatomic) NSString *lastName;
|
||||
|
@ -30,13 +31,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (readonly, nonatomic) NSArray<NSString *> *userTextPhoneNumbers;
|
||||
@property (readonly, nonatomic) NSArray<NSString *> *emails;
|
||||
@property (readonly, nonatomic) NSString *uniqueId;
|
||||
@property (nonatomic, readonly) BOOL isSignalContact;
|
||||
#if TARGET_OS_IOS
|
||||
@property (nullable, readonly, nonatomic) UIImage *image;
|
||||
@property (readonly, nonatomic) ABRecordID recordID;
|
||||
@property (nullable, nonatomic, readonly) CNContact *cnContact;
|
||||
#endif // TARGET_OS_IOS
|
||||
|
||||
- (BOOL)isSignalContact;
|
||||
- (NSArray<SignalRecipient *> *)signalRecipientsWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||
// TODO: Remove this method.
|
||||
- (NSArray<NSString *> *)textSecureIdentifiers;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSYapDatabaseObject.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class Contact;
|
||||
|
@ -14,10 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
// multiple instances of SignalAccount.
|
||||
// * For non-contacts, the contact property will be nil.
|
||||
//
|
||||
// New instances of SignalAccount for active accounts are
|
||||
// created every time we do a contacts intersection (e.g.
|
||||
// in response to a change to the device contacts).
|
||||
@interface SignalAccount : NSObject
|
||||
@interface SignalAccount : TSYapDatabaseObject
|
||||
|
||||
// An E164 value identifying the signal account.
|
||||
//
|
||||
|
|
|
@ -46,6 +46,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return [SignalRecipient recipientWithTextSecureIdentifier:self.recipientId withTransaction:transaction];
|
||||
}
|
||||
|
||||
- (nullable NSString *)uniqueId
|
||||
{
|
||||
return _recipientId;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
Loading…
Reference in New Issue