diff --git a/Signal/src/Profiles/OWSProfileManager.h b/Signal/src/Profiles/OWSProfileManager.h index d55b676e3..f9280d3f9 100644 --- a/Signal/src/Profiles/OWSProfileManager.h +++ b/Signal/src/Profiles/OWSProfileManager.h @@ -8,6 +8,9 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const kNSNotificationName_LocalProfileDidChange; extern NSString *const kNSNotificationName_OtherUsersProfileDidChange; +extern NSString *const kNSNotificationName_ProfileWhitelistDidChange; +extern NSString *const kNSNotificationName_ProfileRecipientId; +extern NSString *const kNSNotificationName_ProfileGroupId; extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter; diff --git a/Signal/src/Profiles/OWSProfileManager.m b/Signal/src/Profiles/OWSProfileManager.m index a80abaadb..161b4a5a2 100644 --- a/Signal/src/Profiles/OWSProfileManager.m +++ b/Signal/src/Profiles/OWSProfileManager.m @@ -87,6 +87,9 @@ NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId"; NSString *const kNSNotificationName_LocalProfileDidChange = @"kNSNotificationName_LocalProfileDidChange"; NSString *const kNSNotificationName_OtherUsersProfileDidChange = @"kNSNotificationName_OtherUsersProfileDidChange"; +NSString *const kNSNotificationName_ProfileWhitelistDidChange = @"kNSNotificationName_ProfileWhitelistDidChange"; +NSString *const kNSNotificationName_ProfileRecipientId = @"kNSNotificationName_ProfileRecipientId"; +NSString *const kNSNotificationName_ProfileGroupId = @"kNSNotificationName_ProfileGroupId"; NSString *const kOWSProfileManager_UserWhitelistCollection = @"kOWSProfileManager_UserWhitelistCollection"; NSString *const kOWSProfileManager_GroupWhitelistCollection = @"kOWSProfileManager_GroupWhitelistCollection"; @@ -251,7 +254,9 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; [[NSNotificationCenter defaultCenter] postNotificationName:kNSNotificationName_OtherUsersProfileDidChange object:nil - userInfo:nil]; + userInfo:@{ + kNSNotificationName_ProfileRecipientId : userProfile.recipientId, + }]; } }); } @@ -655,9 +660,22 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized(self) { + // We just consult the lazy cache, not the db. + if (self.userProfileWhitelistCache[recipientId]) { + return; + } + self.userProfileWhitelistCache[recipientId] = @(YES); [self.dbConnection setBool:YES forKey:recipientId inCollection:kOWSProfileManager_UserWhitelistCollection]; } + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:kNSNotificationName_ProfileWhitelistDidChange + object:nil + userInfo:@{ + kNSNotificationName_ProfileRecipientId : recipientId, + }]; + }); }); } @@ -666,9 +684,11 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; OWSAssert(recipientIds); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSMutableArray *newRecipientIds = [NSMutableArray new]; + @synchronized(self) { - NSMutableArray *newRecipientIds = [NSMutableArray new]; + // We just consult the lazy cache, not the db. for (NSString *recipientId in recipientIds) { if (!self.userProfileWhitelistCache[recipientId]) { [newRecipientIds addObject:recipientId]; @@ -688,6 +708,17 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; } }]; } + + dispatch_async(dispatch_get_main_queue(), ^{ + for (NSString *recipientId in newRecipientIds) { + [[NSNotificationCenter defaultCenter] + postNotificationName:kNSNotificationName_ProfileWhitelistDidChange + object:nil + userInfo:@{ + kNSNotificationName_ProfileRecipientId : recipientId, + }]; + } + }); }); } @@ -713,12 +744,30 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; { OWSAssert(groupId.length > 0); - @synchronized(self) - { - NSString *groupIdKey = [groupId hexadecimalString]; - [self.dbConnection setObject:@(1) forKey:groupIdKey inCollection:kOWSProfileManager_GroupWhitelistCollection]; - self.groupProfileWhitelistCache[groupIdKey] = @(YES); - } + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + @synchronized(self) + { + NSString *groupIdKey = [groupId hexadecimalString]; + + // We just consult the lazy cache, not the db. + if (self.groupProfileWhitelistCache[groupIdKey]) { + return; + } + + [self.dbConnection setObject:@(1) + forKey:groupIdKey + inCollection:kOWSProfileManager_GroupWhitelistCollection]; + self.groupProfileWhitelistCache[groupIdKey] = @(YES); + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:kNSNotificationName_ProfileWhitelistDidChange + object:nil + userInfo:@{ + kNSNotificationName_ProfileGroupId : groupId, + }]; + }); + } + }); } - (void)addThreadToProfileWhitelist:(TSThread *)thread diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 6cd3e0481..3379a6e3a 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -337,6 +337,43 @@ typedef enum : NSUInteger { selector:@selector(cancelReadTimer) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(otherUsersProfileDidChange:) + name:kNSNotificationName_OtherUsersProfileDidChange + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(profileWhitelistDidChange:) + name:kNSNotificationName_ProfileWhitelistDidChange + object:nil]; +} + +- (void)otherUsersProfileDidChange:(NSNotification *)notification +{ + OWSAssert([NSThread isMainThread]); + + NSString *recipientId = notification.userInfo[kNSNotificationName_ProfileRecipientId]; + OWSAssert(recipientId.length > 0); + if (recipientId.length > 0 && [self.thread.recipientIdentifiers containsObject:recipientId]) { + // Reload all cells. + [self resetContentAndLayout]; + } +} + +- (void)profileWhitelistDidChange:(NSNotification *)notification +{ + OWSAssert([NSThread isMainThread]); + + // If profile whitelist just changed, we may want to hide a profile whitelist offer. + NSString *_Nullable recipientId = notification.userInfo[kNSNotificationName_ProfileRecipientId]; + NSData *_Nullable groupId = notification.userInfo[kNSNotificationName_ProfileGroupId]; + if (recipientId.length > 0 && [self.thread.recipientIdentifiers containsObject:recipientId]) { + [self ensureDynamicInteractions]; + } else if (groupId.length > 0 && self.thread.isGroupThread) { + TSGroupThread *groupThread = (TSGroupThread *)self.thread; + if ([groupThread.groupModel.groupId isEqualToData:groupId]) { + [self ensureDynamicInteractions]; + } + } } - (void)blockedPhoneNumbersDidChange:(id)notification