diff --git a/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m index b9698efe9..40d8b7631 100644 --- a/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m @@ -280,7 +280,6 @@ cell.contentView.preservesSuperviewLayoutMargins = YES; cell.selectionStyle = UITableViewCellSelectionStyleNone; - const NSUInteger kAvatarSize = 68; // TODO: Replace this icon. UIImage *_Nullable localProfileAvatarImage = [OWSProfileManager.sharedManager localProfileAvatarImage]; UIImage *avatarImage = (localProfileAvatarImage @@ -295,8 +294,8 @@ [cell.contentView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; [avatarView autoPinLeadingToSuperviewMargin]; - [avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSize]; - [avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSize]; + [avatarView autoSetDimension:ALDimensionWidth toSize:kLargeAvatarSize]; + [avatarView autoSetDimension:ALDimensionHeight toSize:kLargeAvatarSize]; if (!localProfileAvatarImage) { UIImage *cameraImage = [UIImage imageNamed:@"settings-avatar-camera"]; diff --git a/Signal/src/ViewControllers/AppSettings/BlockListViewController.m b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m index 5b18d3eb9..601276b87 100644 --- a/Signal/src/ViewControllers/AppSettings/BlockListViewController.m +++ b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m @@ -117,7 +117,14 @@ NS_ASSUME_NONNULL_BEGIN @"BLOCK_LIST_BLOCKED_GROUPS_SECTION", @"Section header for groups that have been blocked"); for (TSGroupModel *blockedGroup in blockedGroups) { - UIImage *image = blockedGroup.groupImage ?: OWSGroupAvatarBuilder.defaultGroupAvatarImage; + UIImage *_Nullable image = blockedGroup.groupImage; + if (!image) { + NSString *conversationColorName = + [TSGroupThread defaultConversationColorNameForGroupId:blockedGroup.groupId]; + image = [OWSGroupAvatarBuilder defaultAvatarForGroupId:blockedGroup.groupId + conversationColorName:conversationColorName + diameter:kStandardAvatarSize]; + } NSString *groupName = blockedGroup.groupName.length > 0 ? blockedGroup.groupName : TSGroupThread.defaultGroupName; diff --git a/Signal/src/ViewControllers/NewGroupViewController.m b/Signal/src/ViewControllers/NewGroupViewController.m index c0a6a4990..ca3a7c22a 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.m +++ b/Signal/src/ViewControllers/NewGroupViewController.m @@ -29,8 +29,6 @@ NS_ASSUME_NONNULL_BEGIN -const NSUInteger kNewGroupViewControllerAvatarWidth = 68; - @interface NewGroupViewController () *memberRecipientIds; @@ -86,6 +86,8 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; - (void)commonInit { + self.groupId = [Randomness generateRandomBytes:16]; + _messageSender = SSKEnvironment.shared.messageSender; _contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self]; _avatarViewHelper = [AvatarViewHelper new]; @@ -151,8 +153,8 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; [threadInfoView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; [avatarView autoPinLeadingToSuperviewMargin]; - [avatarView autoSetDimension:ALDimensionWidth toSize:kNewGroupViewControllerAvatarWidth]; - [avatarView autoSetDimension:ALDimensionHeight toSize:kNewGroupViewControllerAvatarWidth]; + [avatarView autoSetDimension:ALDimensionWidth toSize:kLargeAvatarSize]; + [avatarView autoSetDimension:ALDimensionHeight toSize:kLargeAvatarSize]; [self updateAvatarView]; UITextField *groupNameTextField = [OWSTextField new]; @@ -505,8 +507,10 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; NSString *groupName = [self.groupNameTextField.text ows_stripped]; NSMutableArray *recipientIds = [self.memberRecipientIds.allObjects mutableCopy]; [recipientIds addObject:[self.contactsViewHelper localNumber]]; - NSData *groupId = [Randomness generateRandomBytes:16]; - return [[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:self.groupAvatar groupId:groupId]; + return [[TSGroupModel alloc] initWithTitle:groupName + memberIds:recipientIds + image:self.groupAvatar + groupId:self.groupId]; } #pragma mark - Group Avatar @@ -529,7 +533,14 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; - (void)updateAvatarView { - self.avatarView.image = (self.groupAvatar ?: [OWSGroupAvatarBuilder defaultGroupAvatarImage]); + UIImage *_Nullable groupAvatar = self.groupAvatar; + if (!groupAvatar) { + NSString *conversationColorName = [TSGroupThread defaultConversationColorNameForGroupId:self.groupId]; + groupAvatar = [OWSGroupAvatarBuilder defaultAvatarForGroupId:self.groupId + conversationColorName:conversationColorName + diameter:kLargeAvatarSize]; + } + self.avatarView.image = groupAvatar; } #pragma mark - Event Handling diff --git a/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m index f9759a59c..2715b0dd0 100644 --- a/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m @@ -758,8 +758,7 @@ const CGFloat kIconViewLength = 24; [threadInfoView autoPinWidthToSuperviewWithMargin:16.f]; [threadInfoView autoPinHeightToSuperviewWithMargin:16.f]; - const NSUInteger kAvatarSize = 68; - UIImage *avatarImage = [OWSAvatarBuilder buildImageForThread:self.thread diameter:kAvatarSize]; + UIImage *avatarImage = [OWSAvatarBuilder buildImageForThread:self.thread diameter:kLargeAvatarSize]; OWSAssertDebug(avatarImage); AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatarImage]; @@ -767,8 +766,8 @@ const CGFloat kIconViewLength = 24; [threadInfoView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; [avatarView autoPinLeadingToSuperviewMargin]; - [avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSize]; - [avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSize]; + [avatarView autoSetDimension:ALDimensionWidth toSize:kLargeAvatarSize]; + [avatarView autoSetDimension:ALDimensionHeight toSize:kLargeAvatarSize]; UIView *threadNameView = [UIView containerView]; [threadInfoView addSubview:threadNameView]; diff --git a/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m b/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m index ed73e42e3..00923f0f3 100644 --- a/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m @@ -179,15 +179,14 @@ NS_ASSUME_NONNULL_BEGIN [threadInfoView autoPinWidthToSuperviewWithMargin:16.f]; [threadInfoView autoPinHeightToSuperviewWithMargin:16.f]; - const CGFloat kAvatarSize = 68.f; AvatarImageView *avatarView = [AvatarImageView new]; _avatarView = avatarView; [threadInfoView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; [avatarView autoPinLeadingToSuperviewMargin]; - [avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSize]; - [avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSize]; + [avatarView autoSetDimension:ALDimensionWidth toSize:kLargeAvatarSize]; + [avatarView autoSetDimension:ALDimensionHeight toSize:kLargeAvatarSize]; _groupAvatar = self.thread.groupModel.groupImage; [self updateAvatarView]; @@ -397,7 +396,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateAvatarView { - self.avatarView.image = (self.groupAvatar ?: [OWSGroupAvatarBuilder defaultGroupAvatarImage]); + UIImage *_Nullable groupAvatar = self.groupAvatar; + if (!groupAvatar) { + groupAvatar = [[[OWSGroupAvatarBuilder alloc] initWithThread:self.thread diameter:kLargeAvatarSize] build]; + } + self.avatarView.image = groupAvatar; } #pragma mark - Event Handling diff --git a/SignalMessaging/utils/OWSAvatarBuilder.h b/SignalMessaging/utils/OWSAvatarBuilder.h index 36926c423..81e7bd785 100644 --- a/SignalMessaging/utils/OWSAvatarBuilder.h +++ b/SignalMessaging/utils/OWSAvatarBuilder.h @@ -5,6 +5,7 @@ NS_ASSUME_NONNULL_BEGIN extern const NSUInteger kStandardAvatarSize; +extern const NSUInteger kLargeAvatarSize; @class TSThread; @class UIImage; diff --git a/SignalMessaging/utils/OWSAvatarBuilder.m b/SignalMessaging/utils/OWSAvatarBuilder.m index 3082012bf..2e597948a 100644 --- a/SignalMessaging/utils/OWSAvatarBuilder.m +++ b/SignalMessaging/utils/OWSAvatarBuilder.m @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN const NSUInteger kStandardAvatarSize = 48; +const NSUInteger kLargeAvatarSize = 68; typedef void (^OWSAvatarDrawBlock)(CGContextRef context); diff --git a/SignalMessaging/utils/OWSContactAvatarBuilder.m b/SignalMessaging/utils/OWSContactAvatarBuilder.m index cb80d9f0b..b59d6d3a3 100644 --- a/SignalMessaging/utils/OWSContactAvatarBuilder.m +++ b/SignalMessaging/utils/OWSContactAvatarBuilder.m @@ -90,7 +90,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable UIImage *)buildDefaultImage { - UIImage *cachedAvatar = + UIImage *_Nullable cachedAvatar = [OWSContactAvatarBuilder.contactsManager.avatarCache imageForKey:self.cacheKey diameter:(CGFloat)self.diameter]; if (cachedAvatar) { return cachedAvatar; diff --git a/SignalMessaging/utils/OWSGroupAvatarBuilder.h b/SignalMessaging/utils/OWSGroupAvatarBuilder.h index 19e3f3143..2662310e0 100644 --- a/SignalMessaging/utils/OWSGroupAvatarBuilder.h +++ b/SignalMessaging/utils/OWSGroupAvatarBuilder.h @@ -12,7 +12,9 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithThread:(TSGroupThread *)thread diameter:(NSUInteger)diameter; -+ (nullable UIImage *)defaultGroupAvatarImage; ++ (nullable UIImage *)defaultAvatarForGroupId:(NSData *)groupId + conversationColorName:(NSString *)conversationColorName + diameter:(NSUInteger)diameter; @end diff --git a/SignalMessaging/utils/OWSGroupAvatarBuilder.m b/SignalMessaging/utils/OWSGroupAvatarBuilder.m index ecf497d75..08e420a1d 100644 --- a/SignalMessaging/utils/OWSGroupAvatarBuilder.m +++ b/SignalMessaging/utils/OWSGroupAvatarBuilder.m @@ -45,51 +45,42 @@ NS_ASSUME_NONNULL_BEGIN - (nullable UIImage *)buildDefaultImage { - NSString *cacheKey = [NSString stringWithFormat:@"%@-%d", self.thread.uniqueId, Theme.isDarkThemeEnabled]; - - UIImage *cachedAvatar = - [OWSGroupAvatarBuilder.contactsManager.avatarCache imageForKey:cacheKey diameter:(CGFloat)self.diameter]; - if (cachedAvatar) { - return cachedAvatar; - } - - UIColor *backgroundColor = - [UIColor ows_conversationColorForColorName:self.thread.conversationColorName isShaded:Theme.isDarkThemeEnabled]; - UIImage *_Nullable image = - [OWSGroupAvatarBuilder groupAvatarImageWithBackgroundColor:backgroundColor diameter:self.diameter]; - if (!image) { - return nil; - } - - [OWSGroupAvatarBuilder.contactsManager.avatarCache setImage:image forKey:cacheKey diameter:self.diameter]; - return image; + return [self.class defaultAvatarForGroupId:self.thread.groupModel.groupId + conversationColorName:self.thread.conversationColorName + diameter:self.diameter]; } -+ (nullable UIImage *)defaultGroupAvatarImage ++ (nullable UIImage *)defaultAvatarForGroupId:(NSData *)groupId + conversationColorName:(NSString *)conversationColorName + diameter:(NSUInteger)diameter { - NSUInteger diameter = 200; - NSString *cacheKey = [NSString stringWithFormat:@"default-group-avatar-%d", Theme.isDarkThemeEnabled]; + NSString *cacheKey = [NSString stringWithFormat:@"%@-%d", groupId.hexadecimalString, Theme.isDarkThemeEnabled]; - UIImage *cachedAvatar = [self.contactsManager.avatarCache imageForKey:cacheKey diameter:(CGFloat)diameter]; + UIImage *_Nullable cachedAvatar = + [OWSGroupAvatarBuilder.contactsManager.avatarCache imageForKey:cacheKey diameter:(CGFloat)diameter]; if (cachedAvatar) { return cachedAvatar; } - // TODO: Verify with Myles. - UIColor *backgroundColor = UIColor.ows_signalBlueColor; - UIImage *_Nullable image = [self groupAvatarImageWithBackgroundColor:backgroundColor diameter:diameter]; + UIColor *backgroundColor = + [UIColor ows_conversationColorForColorName:conversationColorName isShaded:Theme.isDarkThemeEnabled]; + UIImage *_Nullable image = + [OWSGroupAvatarBuilder groupAvatarImageWithBackgroundColor:backgroundColor diameter:diameter]; if (!image) { return nil; } - [self.contactsManager.avatarCache setImage:image forKey:cacheKey diameter:diameter]; + [OWSGroupAvatarBuilder.contactsManager.avatarCache setImage:image forKey:cacheKey diameter:diameter]; return image; } + (nullable UIImage *)groupAvatarImageWithBackgroundColor:(UIColor *)backgroundColor diameter:(NSUInteger)diameter { UIImage *icon = [UIImage imageNamed:@"group-avatar"]; - CGSize iconSize = CGSizeScale(icon.size, diameter / kStandardAvatarSize); + // The group-avatar asset is designed for the kStandardAvatarSize. + // Adjust its size to reflect the actual output diameter. + CGFloat scaling = diameter / (CGFloat)kStandardAvatarSize; + CGSize iconSize = CGSizeScale(icon.size, scaling); return [OWSAvatarBuilder avatarImageWithIcon:icon iconSize:iconSize backgroundColor:backgroundColor diameter:diameter]; } diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h index 5a937f509..2f9445089 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h @@ -44,6 +44,8 @@ extern NSString *const TSGroupThread_NotificationKey_UniqueId; - (void)fireAvatarChangedNotification; ++ (NSString *)defaultConversationColorNameForGroupId:(NSData *)groupId; + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m index 255e7def4..248a5ae22 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m @@ -242,6 +242,13 @@ NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_Notific userInfo:userInfo]; } ++ (NSString *)defaultConversationColorNameForGroupId:(NSData *)groupId +{ + OWSAssertDebug(groupId.length > 0); + + return [self.class stableConversationColorNameForString:[self threadIdFromGroupId:groupId]]; +} + @end NS_ASSUME_NONNULL_END