diff --git a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsViewController.m index 72708639e..ddc528090 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsViewController.m @@ -294,16 +294,7 @@ NS_ASSUME_NONNULL_BEGIN }]]; } - BOOL isOnProfileWhitelist = NO; - if (self.isGroupThread) { - TSGroupThread *groupThread = (TSGroupThread *)self.thread; - NSData *groupId = groupThread.groupModel.groupId; - isOnProfileWhitelist = [OWSProfilesManager.sharedManager isGroupIdInProfileWhitelist:groupId]; - } else { - NSString *recipientId = self.thread.contactIdentifier; - isOnProfileWhitelist = [OWSProfilesManager.sharedManager isUserInProfileWhitelist:recipientId]; - } - if (isOnProfileWhitelist) { + if ([OWSProfilesManager.sharedManager isThreadInProfileWhitelist:self.thread]) { [mainSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ return [weakSelf labelCellWithName:(self.isGroupThread diff --git a/Signal/src/ViewControllers/ProfileViewController.m b/Signal/src/ViewControllers/ProfileViewController.m index 0f3fede74..0e7b5e952 100644 --- a/Signal/src/ViewControllers/ProfileViewController.m +++ b/Signal/src/ViewControllers/ProfileViewController.m @@ -213,14 +213,14 @@ NS_ASSUME_NONNULL_BEGIN { __weak ProfileViewController *weakSelf = self; [OWSProfilesManager.sharedManager - updateLocalProfileName:self.nameTextField.text - localProfileAvatarImage:self.avatar - success:^{ - [weakSelf.navigationController popViewControllerAnimated:YES]; - } - failure:^{ - // <#code#> - }]; + updateLocalProfileName:self.nameTextField.text + avatarImage:self.avatar + success:^{ + [weakSelf.navigationController popViewControllerAnimated:YES]; + } + failure:^{ + // <#code#> + }]; } #pragma mark - UITextFieldDelegate diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m index c22437580..30a53ffd4 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m @@ -480,17 +480,8 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec // recipient OR the group is in the whitelist. if ([OWSProfilesManager.sharedManager isUserInProfileWhitelist:recipient.recipientId]) { shouldIncludeProfileKey = YES; - } else if (self.thread.isGroupThread) { - TSGroupThread *groupThread = (TSGroupThread *)self.thread; - NSData *groupId = groupThread.groupModel.groupId; - - if ([OWSProfilesManager.sharedManager isGroupIdInProfileWhitelist:groupId]) { - [contentBuilder setProfileKey:OWSProfilesManager.sharedManager.localProfileKey]; - } - } else { - TSContactThread *contactThread = (TSContactThread *)self.thread; - NSString *recipientId = contactThread.contactIdentifier; - OWSAssert([recipientId isEqualToString:recipient.recipientId]); + } else if ([OWSProfilesManager.sharedManager isThreadInProfileWhitelist:self.thread]) { + shouldIncludeProfileKey = YES; } } diff --git a/SignalServiceKit/src/Profiles/OWSProfilesManager.h b/SignalServiceKit/src/Profiles/OWSProfilesManager.h index 3c02ac00a..b991c6bff 100644 --- a/SignalServiceKit/src/Profiles/OWSProfilesManager.h +++ b/SignalServiceKit/src/Profiles/OWSProfilesManager.h @@ -7,6 +7,8 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const kNSNotificationName_LocalProfileDidChange; extern NSString *const kNSNotificationName_OtherUsersProfileDidChange; +@class TSThread; + // This class can be safely accessed and used from any thread. @interface OWSProfilesManager : NSObject @@ -43,10 +45,10 @@ extern NSString *const kNSNotificationName_OtherUsersProfileDidChange; - (void)addGroupIdToProfileWhitelist:(NSData *)groupId; -- (BOOL)isGroupIdInProfileWhitelist:(NSData *)groupId; - - (void)setContactRecipientIds:(NSArray *)contactRecipientIds; +- (BOOL)isThreadInProfileWhitelist:(TSThread *)thread; + #pragma mark - Other User's Profiles - (void)setProfileKey:(NSData *)profileKey forRecipientId:(NSString *)recipientId; diff --git a/SignalServiceKit/src/Profiles/OWSProfilesManager.m b/SignalServiceKit/src/Profiles/OWSProfilesManager.m index 80bc6e346..f34860be1 100644 --- a/SignalServiceKit/src/Profiles/OWSProfilesManager.m +++ b/SignalServiceKit/src/Profiles/OWSProfilesManager.m @@ -8,7 +8,9 @@ #import "OWSMessageSender.h" #import "SecurityUtils.h" #import "TSAccountManager.h" +#import "TSGroupThread.h" #import "TSStorageManager.h" +#import "TSThread.h" #import "TSYapDatabaseObject.h" #import "TextSecureKitEnv.h" @@ -60,11 +62,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } -+ (NSString *)collection -{ - return @"UserProfile"; -} - #pragma mark - NSObject - (BOOL)isEqual:(UserProfile *)other @@ -113,7 +110,7 @@ static const NSInteger kProfileKeyLength = 16; // This property should only be mutated on the main thread, @property (nonatomic, nullable) UIImage *localCachedAvatarImage; -// These caches are lazy-populated. The single point truth is the database. +// These caches are lazy-populated. The single point of truth is the database. // // These three properties can be accessed on any thread. @property (atomic, readonly) NSMutableDictionary *userProfileWhitelistCache; @@ -440,12 +437,37 @@ static const NSInteger kProfileKeyLength = 16; - (void)addUserToProfileWhitelist:(NSString *)recipientId { + OWSAssert([NSThread isMainThread]); OWSAssert(recipientId.length > 0); - [self.dbConnection setObject:@(1) forKey:recipientId inCollection:kOWSProfilesManager_UserWhitelistCollection]; + [self.dbConnection setBool:YES forKey:recipientId inCollection:kOWSProfilesManager_UserWhitelistCollection]; self.userProfileWhitelistCache[recipientId] = @(YES); } +- (void)addUsersToProfileWhitelist:(NSArray *)recipientIds +{ + OWSAssert([NSThread isMainThread]); + OWSAssert(recipientIds); + + NSMutableArray *newRecipientIds = [NSMutableArray new]; + for (NSString *recipientId in recipientIds) { + if (!self.userProfileWhitelistCache[recipientId]) { + [newRecipientIds addObject:recipientId]; + } + } + + if (newRecipientIds.count < 1) { + return; + } + + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + for (NSString *recipientId in recipientIds) { + [transaction setObject:@(YES) forKey:recipientId inCollection:kOWSProfilesManager_UserWhitelistCollection]; + self.userProfileWhitelistCache[recipientId] = @(YES); + } + }]; +} + - (BOOL)isUserInProfileWhitelist:(NSString *)recipientId { OWSAssert(recipientId.length > 0); @@ -455,8 +477,7 @@ static const NSInteger kProfileKeyLength = 16; return [value boolValue]; } - value = - @(nil != [self.dbConnection objectForKey:recipientId inCollection:kOWSProfilesManager_UserWhitelistCollection]); + value = @([self.dbConnection hasObjectForKey:recipientId inCollection:kOWSProfilesManager_UserWhitelistCollection]); self.userProfileWhitelistCache[recipientId] = value; return [value boolValue]; } @@ -486,8 +507,23 @@ static const NSInteger kProfileKeyLength = 16; return [value boolValue]; } +- (BOOL)isThreadInProfileWhitelist:(TSThread *)thread +{ + OWSAssert(thread); + + if (thread.isGroupThread) { + TSGroupThread *groupThread = (TSGroupThread *)thread; + NSData *groupId = groupThread.groupModel.groupId; + return [OWSProfilesManager.sharedManager isGroupIdInProfileWhitelist:groupId]; + } else { + NSString *recipientId = thread.contactIdentifier; + return [OWSProfilesManager.sharedManager isUserInProfileWhitelist:recipientId]; + } +} + - (void)setContactRecipientIds:(NSArray *)contactRecipientIds { + OWSAssert([NSThread isMainThread]); OWSAssert(contactRecipientIds); // TODO: The persisted whitelist could either be: @@ -495,9 +531,7 @@ static const NSInteger kProfileKeyLength = 16; // * Just users manually added to the whitelist. // * Also include users auto-added by, for example, being in the user's // contacts or when the user initiates a 1:1 conversation with them, etc. - for (NSString *recipientId in contactRecipientIds) { - [self addUserToProfileWhitelist:recipientId]; - } + [self addUsersToProfileWhitelist:contactRecipientIds]; } #pragma mark - Other User's Profiles @@ -533,7 +567,7 @@ static const NSInteger kProfileKeyLength = 16; } profileKey = - [self.dbConnection objectForKey:recipientId inCollection:kOWSProfilesManager_OtherUsersProfileKeysCollection]; + [self.dbConnection dataForKey:recipientId inCollection:kOWSProfilesManager_OtherUsersProfileKeysCollection]; if (profileKey) { OWSAssert(profileKey.length == kProfileKeyLength); self.otherUsersProfileKeyCache[recipientId] = profileKey; diff --git a/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h index a568529bb..d54ccb19f 100644 --- a/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h +++ b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h @@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface YapDatabaseConnection (OWS) +- (BOOL)hasObjectForKey:(NSString *)key inCollection:(NSString *)collection; - (BOOL)boolForKey:(NSString *)key inCollection:(NSString *)collection; - (int)intForKey:(NSString *)key inCollection:(NSString *)collection; - (nullable id)objectForKey:(NSString *)key inCollection:(NSString *)collection; @@ -26,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection; +- (void)setBool:(BOOL)value forKey:(NSString *)key inCollection:(NSString *)collection; - (void)removeObjectForKey:(NSString *)string inCollection:(NSString *)collection; - (void)setInt:(int)integer forKey:(NSString *)key inCollection:(NSString *)collection; - (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection; diff --git a/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m index acf2c3c29..d01d846ee 100644 --- a/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m +++ b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m @@ -12,6 +12,14 @@ NS_ASSUME_NONNULL_BEGIN @implementation YapDatabaseConnection (OWS) +- (BOOL)hasObjectForKey:(NSString *)key inCollection:(NSString *)collection +{ + OWSAssert(key.length > 0); + OWSAssert(collection.length > 0); + + return nil != [self objectForKey:key inCollection:collection]; +} + - (nullable id)objectForKey:(NSString *)key inCollection:(NSString *)collection { OWSAssert(key.length > 0); @@ -104,6 +112,14 @@ NS_ASSUME_NONNULL_BEGIN }]; } +- (void)setBool:(BOOL)value forKey:(NSString *)key inCollection:(NSString *)collection +{ + OWSAssert(key.length > 0); + OWSAssert(collection.length > 0); + + [self setObject:@(value) forKey:key inCollection:collection]; +} + - (void)removeObjectForKey:(NSString *)key inCollection:(NSString *)collection { OWSAssert(key.length > 0); @@ -114,12 +130,12 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)setInt:(int)integer forKey:(NSString *)key inCollection:(NSString *)collection +- (void)setInt:(int)value forKey:(NSString *)key inCollection:(NSString *)collection { OWSAssert(key.length > 0); OWSAssert(collection.length > 0); - [self setObject:@(integer) forKey:key inCollection:collection]; + [self setObject:@(value) forKey:key inCollection:collection]; } - (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection