diff --git a/Signal/src/Models/OWSAvatarBuilder.h b/Signal/src/Models/OWSAvatarBuilder.h index 6ec98ef70..1f5234432 100644 --- a/Signal/src/Models/OWSAvatarBuilder.h +++ b/Signal/src/Models/OWSAvatarBuilder.h @@ -14,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN diameter:(NSUInteger)diameter contactsManager:(OWSContactsManager *)contactsManager NS_SWIFT_NAME(buildImage(thread:diameter:contactsManager:)); ++ (UIImage *)buildRandomAvatarWithDiameter:(NSUInteger)diameter; + - (nullable UIImage *)buildSavedImage; - (UIImage *)buildDefaultImage; - (UIImage *)build; diff --git a/Signal/src/Models/OWSAvatarBuilder.m b/Signal/src/Models/OWSAvatarBuilder.m index 25026d4c1..143ddcec9 100644 --- a/Signal/src/Models/OWSAvatarBuilder.m +++ b/Signal/src/Models/OWSAvatarBuilder.m @@ -3,10 +3,12 @@ // #import "OWSAvatarBuilder.h" +#import "JSQMessagesAvatarImageFactory.h" #import "OWSContactAvatarBuilder.h" #import "OWSGroupAvatarBuilder.h" #import "TSContactThread.h" #import "TSGroupThread.h" +#import "UIColor+OWS.h" NS_ASSUME_NONNULL_BEGIN @@ -27,6 +29,45 @@ NS_ASSUME_NONNULL_BEGIN return [avatarBuilder build]; } ++ (UIImage *)buildRandomAvatarWithDiameter:(NSUInteger)diameter +{ + NSArray *eyes = @[ @":", @"=", @"8", @"B" ]; + NSArray *mouths = @[ @"3", @")", @"(", @"|", @"\\", @"P", @"D", @"o" ]; + // eyebrows are rare + NSArray *eyebrows = @[ @">", @"", @"", @"", @"" ]; + + NSString *randomEye = eyes[arc4random_uniform((uint32_t)eyes.count)]; + NSString *randomMouth = mouths[arc4random_uniform((uint32_t)mouths.count)]; + NSString *randomEyebrow = eyebrows[arc4random_uniform((uint32_t)eyebrows.count)]; + NSString *face = [NSString stringWithFormat:@"%@%@%@", randomEyebrow, randomEye, randomMouth]; + + CGFloat fontSize = (CGFloat)(diameter / 2.4); + + UIImage *srcImage = + [[JSQMessagesAvatarImageFactory avatarImageWithUserInitials:face + backgroundColor:[UIColor colorWithRGBHex:0xaca6633] + textColor:[UIColor whiteColor] + font:[UIFont boldSystemFontOfSize:fontSize] + diameter:diameter] avatarImage]; + + UIGraphicsBeginImageContext(srcImage.size); + + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGFloat width = srcImage.size.width; + + // Rotate + CGContextTranslateCTM(context, width / 2, width / 2); + CGContextRotateCTM(context, (CGFloat)M_PI_2); + CGContextTranslateCTM(context, -width / 2, -width / 2); + + [srcImage drawAtPoint:CGPointMake(0, 0)]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + - (UIImage *)build { UIImage *_Nullable savedImage = [self buildSavedImage]; diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m b/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m index 665cfeeef..0f0bdff24 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m @@ -1134,7 +1134,7 @@ NS_ASSUME_NONNULL_BEGIN } } -+ (void)createRandomContacts:(int)count ++ (void)createRandomContacts:(NSUInteger)count { OWSAssert(count > 0); [self createRandomContacts:count contactHandler:nil]; @@ -1163,16 +1163,34 @@ NS_ASSUME_NONNULL_BEGIN } CNSaveRequest *request = [[CNSaveRequest alloc] init]; - for (int i = 0; i < count; i++) { + for (NSUInteger i = 0; i < count; i++) { CNMutableContact *contact = [[CNMutableContact alloc] init]; contact.familyName = [@"Rando-" stringByAppendingString:[self randomLastName]]; contact.givenName = [self randomFirstName]; + NSString *phoneString = [self randomPhoneNumber]; CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome - value:[CNPhoneNumber phoneNumberWithStringValue:[self randomPhoneNumber]]]; + value:[CNPhoneNumber phoneNumberWithStringValue:phoneString]]; contact.phoneNumbers = @[ homePhone ]; + // 50% chance of fake contact having an avatar + const NSUInteger kPercentWithAvatar = 50; + const NSUInteger kMinimumAvatarDiameter = 200; + const NSUInteger kMaximumAvatarDiameter = 800; + OWSAssert(kMaximumAvatarDiameter >= kMinimumAvatarDiameter); + if (arc4random_uniform(100) < kPercentWithAvatar) { + NSUInteger avatarDiameter + = arc4random_uniform(kMaximumAvatarDiameter - kMinimumAvatarDiameter) + + kMinimumAvatarDiameter; + // Note this doesn't work on iOS9, since iOS9 doesn't generate the imageThumbnailData from + // programmatically assigned imageData. We could make our own thumbnail in Contact.m, but + // it's not worth it for the sake of debug UI. + contact.imageData = UIImageJPEGRepresentation( + [OWSAvatarBuilder buildRandomAvatarWithDiameter:avatarDiameter], (CGFloat)0.9); + DDLogDebug(@"avatar size: %lu bytes", (unsigned long)contact.imageData.length); + } + [contacts addObject:contact]; [request addContact:contact toContainerWithIdentifier:nil]; }