diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 39224f74c..a86d066eb 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -243,6 +243,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; [[TSStorageManager sharedManager] setupDatabaseWithSafeBlockingMigrations:^{ [VersionMigrations runSafeBlockingMigrations]; }]; + [[Environment getCurrent].contactsManager startObserving]; self.incomingMessageReadObserver = [[OWSIncomingMessageReadObserver alloc] initWithMessageSender:[Environment getCurrent].messageSender]; diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index b0177ce0d..2211ee870 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -48,7 +48,14 @@ NS_ASSUME_NONNULL_BEGIN diameter:(NSUInteger)diameter contactsManager:(OWSContactsManager *)contactsManager { - NSString *name = [contactsManager displayNameForPhoneIdentifier:signalId]; + // Name for avatar initialis. + NSString *_Nullable name = [contactsManager nameFromSystemContactsForRecipientId:signalId]; + if (name.length == 0) { + name = [contactsManager profileNameForRecipientId:signalId]; + } + if (name.length == 0) { + name = signalId; + } return [self initWithContactId:signalId name:name diameter:diameter contactsManager:contactsManager]; } diff --git a/Signal/src/contact/OWSContactsManager.h b/Signal/src/contact/OWSContactsManager.h index e3d4fa464..4cbc6fcc4 100644 --- a/Signal/src/contact/OWSContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -17,6 +17,12 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; */ @interface OWSContactsManager : NSObject +#pragma mark - Setup + +- (void)startObserving; + +#pragma mark - Accessors + @property (nonnull, readonly) NSCache *avatarCache; @property (atomic, readonly) NSArray *allContacts; @@ -54,7 +60,14 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; - (BOOL)hasNameInSystemContactsForRecipientId:(NSString *)recipientId; - (NSString *)displayNameForPhoneIdentifier:(nullable NSString *)identifier; - (NSString *)displayNameForSignalAccount:(SignalAccount *)signalAccount; + +// Generally we prefer the formattedProfileName over the raw profileName so as to +// distinguish a profile name apart from a name pulled from the system's contacts. +// This helps clarify when the remote person chooses a potentially confusing profile name. - (nullable NSString *)formattedProfileNameForRecipientId:(NSString *)recipientId; +- (nullable NSString *)profileNameForRecipientId:(NSString *)recipientId; +- (nullable NSString *)nameFromSystemContactsForRecipientId:(NSString *)recipientId; + - (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier; - (NSAttributedString *)formattedDisplayNameForSignalAccount:(SignalAccount *)signalAccount font:(UIFont *_Nonnull)font; - (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font; diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 735f7348a..acfc16157 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -136,6 +136,24 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account failure:failure]; } +- (void)startObserving +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(otherUsersProfileDidChange:) + name:kNSNotificationName_OtherUsersProfileDidChange + object:nil]; +} + +- (void)otherUsersProfileDidChange:(NSNotification *)notification +{ + OWSAssert([NSThread isMainThread]); + + NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId]; + OWSAssert(recipientId.length > 0); + + [self clearAvatarCacheForRecipientId:recipientId]; +} + - (void)updateWithContacts:(NSArray *)contacts { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -165,6 +183,11 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account }); } +- (void)clearAvatarCacheForRecipientId:(NSString *)recipientId +{ + [self.avatarCache removeObjectForKey:recipientId]; +} + - (void)updateSignalAccounts { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -423,16 +446,25 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account return [NSString stringWithFormat:profileNameFormatString, profileName]; } +- (nullable NSString *)profileNameForRecipientId:(NSString *)recipientId +{ + return [self.profileManager profileNameForRecipientId:recipientId]; +} + +- (nullable NSString *)nameFromSystemContactsForRecipientId:(NSString *)recipientId +{ + return [self cachedDisplayNameForRecipientId:recipientId]; +} + - (NSString *_Nonnull)displayNameForPhoneIdentifier:(NSString *_Nullable)recipientId { if (!recipientId) { return self.unknownContactName; } - // Prefer a saved name from system contacts, if available - NSString *_Nullable displayName = [self cachedDisplayNameForRecipientId:recipientId]; + NSString *_Nullable displayName = [self nameFromSystemContactsForRecipientId:recipientId]; - // Else fall back to just using their recipientId + // Fall back to just using their recipientId if (displayName.length < 1) { displayName = recipientId; }