diff --git a/Signal/src/ViewControllers/AppSettingsViewController.m b/Signal/src/ViewControllers/AppSettingsViewController.m index ee385d514e..2b66f48c76 100644 --- a/Signal/src/ViewControllers/AppSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettingsViewController.m @@ -172,7 +172,7 @@ [weakSelf showAbout]; }]]; -#ifdef DEBUG +#ifdef USE_DEBUG_UI [section addItem:[OWSTableItem disclosureItemWithText:@"Debug UI" actionBlock:^{ [weakSelf showDebugUI]; diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 2dd5a2faa3..283f939dd9 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -1221,7 +1221,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { [self.navigationBarTitleView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(navigationTitleTapped:)]]; -#ifdef DEBUG +#ifdef USE_DEBUG_UI [self.navigationBarTitleView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(navigationTitleLongPressed:)]]; @@ -4148,7 +4148,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { } } -#ifdef DEBUG +#ifdef USE_DEBUG_UI - (void)navigationTitleLongPressed:(UIGestureRecognizer *)gestureRecognizer { if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m b/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m index 0f0bdff24a..1cba89339d 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m @@ -1136,7 +1136,6 @@ NS_ASSUME_NONNULL_BEGIN + (void)createRandomContacts:(NSUInteger)count { - OWSAssert(count > 0); [self createRandomContacts:count contactHandler:nil]; } @@ -1144,6 +1143,33 @@ NS_ASSUME_NONNULL_BEGIN contactHandler: (nullable void (^)(CNContact *_Nonnull contact, NSUInteger idx, BOOL *_Nonnull stop))contactHandler { + OWSAssert(count > 0); + + NSUInteger remainder = count; + const NSUInteger kMaxBatchSize = 20; + NSUInteger batch = MIN(kMaxBatchSize, remainder); + remainder -= batch; + [self createRandomContactsBatch:batch + contactHandler:contactHandler + batchCompletionHandler:^{ + if (remainder > 0) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self createRandomContacts:remainder contactHandler:contactHandler]; + }); + } + }]; +} + ++ (void)createRandomContactsBatch:(NSUInteger)count + contactHandler:(nullable void (^)( + CNContact *_Nonnull contact, NSUInteger idx, BOOL *_Nonnull stop))contactHandler + batchCompletionHandler:(nullable void (^)())batchCompletionHandler +{ + OWSAssert(count > 0); + OWSAssert(batchCompletionHandler); + + DDLogDebug(@"createRandomContactsBatch: %zd", count); + CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) { [OWSAlerts showAlertWithTitle:@"Error" message:@"No contacts access."]; @@ -1164,45 +1190,53 @@ NS_ASSUME_NONNULL_BEGIN CNSaveRequest *request = [[CNSaveRequest alloc] init]; for (NSUInteger i = 0; i < count; i++) { - CNMutableContact *contact = [[CNMutableContact alloc] init]; - contact.familyName = [@"Rando-" stringByAppendingString:[self randomLastName]]; - contact.givenName = [self randomFirstName]; + @autoreleasepool { + 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:phoneString]]; - contact.phoneNumbers = @[ homePhone ]; + NSString *phoneString = [self randomPhoneNumber]; + CNLabeledValue *homePhone = [CNLabeledValue + labeledValueWithLabel:CNLabelHome + 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); + // 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]; } - - [contacts addObject:contact]; - [request addContact:contact toContainerWithIdentifier:nil]; } + + DDLogError(@"Saving fake contacts: %zd", contacts.count); + NSError *saveError = nil; if (![store executeSaveRequest:request error:&saveError]) { - NSLog(@"error = %@", saveError); + DDLogError(@"Error saving fake contacts: %@", saveError); [OWSAlerts showAlertWithTitle:@"Error" message:saveError.localizedDescription]; } else { if (contactHandler) { [contacts enumerateObjectsUsingBlock:contactHandler]; } } + if (batchCompletionHandler) { + batchCompletionHandler(); + } }]; } @@ -1243,10 +1277,10 @@ NS_ASSUME_NONNULL_BEGIN NSError *saveError = nil; if (!result || fetchError) { - NSLog(@"error = %@", fetchError); + DDLogError(@"error = %@", fetchError); [OWSAlerts showAlertWithTitle:@"Error" message:fetchError.localizedDescription]; } else if (![store executeSaveRequest:request error:&saveError]) { - NSLog(@"error = %@", saveError); + DDLogError(@"error = %@", saveError); [OWSAlerts showAlertWithTitle:@"Error" message:saveError.localizedDescription]; } }]; diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m index 6ed15e8ff1..4954f979d9 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m @@ -85,6 +85,10 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [DebugUIMessages sendFakeMessages:10 thread:thread]; }], + [OWSTableItem itemWithTitle:@"Create 1 fake thread with 1 message" + actionBlock:^{ + [DebugUIMessages createFakeThreads:1 withFakeMessages:1]; + }], [OWSTableItem itemWithTitle:@"Create 100 fake threads with 10 messages" actionBlock:^{ [DebugUIMessages createFakeThreads:100 withFakeMessages:10]; @@ -101,6 +105,10 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [DebugUIMessages createFakeThreads:100 withFakeMessages:100]; }], + [OWSTableItem itemWithTitle:@"Create 1k fake threads with 1 message" + actionBlock:^{ + [DebugUIMessages createFakeThreads:1000 withFakeMessages:1]; + }], [OWSTableItem itemWithTitle:@"Create 1k fake messages" actionBlock:^{ [DebugUIMessages sendFakeMessages:1000 thread:thread]; @@ -883,6 +891,9 @@ NS_ASSUME_NONNULL_BEGIN TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:phoneNumber.toE164]; [self sendFakeMessages:messageCount thread:contactThread]; + DDLogError(@"Create fake thread: %@, interactions: %zd", + phoneNumber.toE164, + contactThread.numberOfInteractions); }]; } diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIPage.h b/Signal/src/ViewControllers/DebugUI/DebugUIPage.h index 4fb2c075bb..d56c8fd75b 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIPage.h +++ b/Signal/src/ViewControllers/DebugUI/DebugUIPage.h @@ -4,6 +4,13 @@ #import "DebugUIPage.h" +// This preprocessor symbol controls whether or not the Debug UI is active. +// +// To show the DebugUI in production builds, comment out the #ifdef and #endif +#ifdef DEBUG +#define USE_DEBUG_UI +#endif + NS_ASSUME_NONNULL_BEGIN @class OWSTableSection; diff --git a/Signal/src/ViewControllers/DebugUI/DebugUITableViewController.h b/Signal/src/ViewControllers/DebugUI/DebugUITableViewController.h index 096866ca7d..12ad423443 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUITableViewController.h +++ b/Signal/src/ViewControllers/DebugUI/DebugUITableViewController.h @@ -2,6 +2,7 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "DebugUIPage.h" #import "OWSTableViewController.h" NS_ASSUME_NONNULL_BEGIN