diff --git a/Signal/src/ViewControllers/SignalAccount.h b/Signal/src/ViewControllers/SignalAccount.h index cebae981c..34994efe9 100644 --- a/Signal/src/ViewControllers/SignalAccount.h +++ b/Signal/src/ViewControllers/SignalAccount.h @@ -15,12 +15,13 @@ NS_ASSUME_NONNULL_BEGIN // // New instances of SignalAccount for active accounts are // created every time we do a contacts intersection (e.g. -// in response to a +// in response to a change to the device contacts). @interface SignalAccount : NSObject -@property (nonatomic) SignalRecipient *signalRecipient; - // An E164 value identifying the signal account. +// +// This is the key property of this class and it +// will always be non-null. @property (nonatomic, readonly) NSString *recipientId; // This property is optional and will not be set for @@ -33,6 +34,19 @@ NS_ASSUME_NONNULL_BEGIN // this is a label for the account. @property (nonatomic) NSString *multipleAccountLabel; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithSignalRecipient:(SignalRecipient *)signalRecipient; + +- (instancetype)initWithRecipientId:(NSString *)recipientId; + +// In most cases this should be non-null. This should only +// be non-null in the case where the SignalRecipient was +// deleted before this property was accessed. +// +// NOTE: This may create a database transaction. +- (nullable SignalRecipient *)signalRecipient; + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/SignalAccount.m b/Signal/src/ViewControllers/SignalAccount.m index fdcc78eca..51922df21 100644 --- a/Signal/src/ViewControllers/SignalAccount.m +++ b/Signal/src/ViewControllers/SignalAccount.m @@ -4,16 +4,57 @@ #import "SignalAccount.h" #import +#import NS_ASSUME_NONNULL_BEGIN +@interface SignalAccount () + +@property (nonatomic, nullable) SignalRecipient *signalRecipient; + +// This property may be modified after construction, so it should +// only be modified on the main thread. +@property (nonatomic) NSString *recipientId; + +@end + +#pragma mark - + @implementation SignalAccount -- (NSString *)recipientId +- (instancetype)initWithSignalRecipient:(SignalRecipient *)signalRecipient { - OWSAssert(self.signalRecipient); + if (self = [super init]) { + OWSAssert(signalRecipient); + + _signalRecipient = signalRecipient; + _recipientId = signalRecipient.uniqueId; + } + return self; +} + +- (instancetype)initWithRecipientId:(NSString *)recipientId +{ + if (self = [super init]) { + OWSAssert(recipientId.length > 0); + + _recipientId = recipientId; + } + return self; +} + +- (nullable SignalRecipient *)signalRecipient +{ + OWSAssert([NSThread isMainThread]); + + if (!_signalRecipient) { + [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + _signalRecipient = + [SignalRecipient recipientWithTextSecureIdentifier:self.recipientId withTransaction:transaction]; + }]; + } - return self.signalRecipient.uniqueId; + return _signalRecipient; } @end diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 7393fc84e..84c46f1f4 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -216,25 +216,21 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in NSArray *signalRecipients = contact.signalRecipients; for (SignalRecipient *signalRecipient in contact.signalRecipients) { - - if (signalRecipients.count == 1) { - SignalAccount *signalAccount = [SignalAccount new]; - signalAccount.signalRecipient = signalRecipient; + for (NSString *recipientId in + [contact.textSecureIdentifiers sortedArrayUsingSelector:@selector(compare:)]) { + SignalAccount *signalAccount = [[SignalAccount alloc] initWithSignalRecipient:signalRecipient]; signalAccount.contact = contact; - signalAccountMap[signalAccount.recipientId] = signalAccount; - [signalAccounts addObject:signalAccount]; - } else if (contact.textSecureIdentifiers.count > 1) { - for (NSString *recipientId in - [contact.textSecureIdentifiers sortedArrayUsingSelector:@selector(compare:)]) { - SignalAccount *signalAccount = [SignalAccount new]; - signalAccount.signalRecipient = signalRecipient; - signalAccount.contact = contact; + if (signalRecipients.count > 1) { signalAccount.isMultipleAccountContact = YES; signalAccount.multipleAccountLabel = [[self class] accountLabelForContact:contact recipientId:recipientId]; - signalAccountMap[signalAccount.recipientId] = signalAccount; - [signalAccounts addObject:signalAccount]; } + if (signalAccountMap[signalAccount.recipientId]) { + DDLogInfo(@"Ignoring duplicate contact: %@, %@", signalAccount.recipientId, contact.fullName); + continue; + } + signalAccountMap[signalAccount.recipientId] = signalAccount; + [signalAccounts addObject:signalAccount]; } } } @@ -441,7 +437,8 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in NSArray *filteredContacts = [sortedPeople filteredArrayUsingPredicate:predicate]; return [filteredContacts map:^id(id item) { - return [self contactForRecord:(__bridge ABRecordRef)item]; + Contact *contact = [self contactForRecord:(__bridge ABRecordRef)item]; + return contact; }]; } diff --git a/Signal/src/util/ObservableValue.m b/Signal/src/util/ObservableValue.m index 7035102aa..51c1b0b9e 100644 --- a/Signal/src/util/ObservableValue.m +++ b/Signal/src/util/ObservableValue.m @@ -95,6 +95,7 @@ } }]; } + - (void)adjustValue:(id (^)(id))adjustment { ows_require(adjustment != nil); [self queueRun:^{