From f5cd39ea3510e64bf40d4c46b8d118e8783783e1 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 28 Apr 2017 13:59:19 -0400 Subject: [PATCH] Apply ContactsViewHelper to SelectThreadViewController. // FREEBIE --- Signal/src/ViewControllers/BlockListUIUtils.h | 16 -- Signal/src/ViewControllers/BlockListUIUtils.m | 62 ------ .../src/ViewControllers/ContactsViewHelper.h | 2 + .../src/ViewControllers/ContactsViewHelper.m | 49 +++++ .../SelectThreadViewController.m | 186 +++++------------- .../ShowGroupMembersViewController.m | 24 ++- 6 files changed, 113 insertions(+), 226 deletions(-) diff --git a/Signal/src/ViewControllers/BlockListUIUtils.h b/Signal/src/ViewControllers/BlockListUIUtils.h index ba5278d34..ab37f4943 100644 --- a/Signal/src/ViewControllers/BlockListUIUtils.h +++ b/Signal/src/ViewControllers/BlockListUIUtils.h @@ -19,14 +19,6 @@ typedef void (^BlockActionCompletionBlock)(BOOL isBlocked); #pragma mark - Block -// TODO: Still necessary? -+ (void)showBlockContactActionSheet:(Contact *)contact - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock; - -// TODO: Still necessary? + (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber fromViewController:(UIViewController *)fromViewController blockingManager:(OWSBlockingManager *)blockingManager @@ -41,14 +33,6 @@ typedef void (^BlockActionCompletionBlock)(BOOL isBlocked); #pragma mark - Unblock -// TODO: Still necessary? -+ (void)showUnblockContactActionSheet:(Contact *)contact - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock; - -// TODO: Still necessary? + (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber fromViewController:(UIViewController *)fromViewController blockingManager:(OWSBlockingManager *)blockingManager diff --git a/Signal/src/ViewControllers/BlockListUIUtils.m b/Signal/src/ViewControllers/BlockListUIUtils.m index 5c016e0dd..9780d7843 100644 --- a/Signal/src/ViewControllers/BlockListUIUtils.m +++ b/Signal/src/ViewControllers/BlockListUIUtils.m @@ -18,37 +18,6 @@ typedef void (^BlockAlertCompletionBlock)(); #pragma mark - Block -+ (void)showBlockContactActionSheet:(Contact *)contact - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock -{ - NSMutableArray *phoneNumbers = [NSMutableArray new]; - for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { - if (phoneNumber.toE164.length > 0) { - [phoneNumbers addObject:phoneNumber.toE164]; - } - } - if (phoneNumbers.count < 1) { - DDLogError(@"%@ Contact has no phone numbers", self.tag); - OWSAssert(0); - [self showBlockFailedAlert:fromViewController - completionBlock:^{ - if (completionBlock) { - completionBlock(NO); - } - }]; - return; - } - NSString *displayName = [contactsManager displayNameForContact:contact]; - [self showBlockPhoneNumbersActionSheet:phoneNumbers - displayName:displayName - fromViewController:fromViewController - blockingManager:blockingManager - completionBlock:completionBlock]; -} - + (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber fromViewController:(UIViewController *)fromViewController blockingManager:(OWSBlockingManager *)blockingManager @@ -176,37 +145,6 @@ typedef void (^BlockAlertCompletionBlock)(); #pragma mark - Unblock -+ (void)showUnblockContactActionSheet:(Contact *)contact - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock -{ - NSMutableArray *phoneNumbers = [NSMutableArray new]; - for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { - if (phoneNumber.toE164.length > 0) { - [phoneNumbers addObject:phoneNumber.toE164]; - } - } - if (phoneNumbers.count < 1) { - DDLogError(@"%@ Contact has no phone numbers", self.tag); - OWSAssert(0); - [self showUnblockFailedAlert:fromViewController - completionBlock:^{ - if (completionBlock) { - completionBlock(NO); - } - }]; - return; - } - NSString *displayName = [contactsManager displayNameForContact:contact]; - [self showUnblockPhoneNumbersActionSheet:phoneNumbers - displayName:displayName - fromViewController:fromViewController - blockingManager:blockingManager - completionBlock:completionBlock]; -} - + (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber fromViewController:(UIViewController *)fromViewController blockingManager:(OWSBlockingManager *)blockingManager diff --git a/Signal/src/ViewControllers/ContactsViewHelper.h b/Signal/src/ViewControllers/ContactsViewHelper.h index f5d010031..2ce1a8721 100644 --- a/Signal/src/ViewControllers/ContactsViewHelper.h +++ b/Signal/src/ViewControllers/ContactsViewHelper.h @@ -56,6 +56,8 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)localNumber; +- (NSArray *)contactAccountsMatchingSearchString:(NSString *)searchText; + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ContactsViewHelper.m b/Signal/src/ViewControllers/ContactsViewHelper.m index 9f6131de8..f0dc336cf 100644 --- a/Signal/src/ViewControllers/ContactsViewHelper.m +++ b/Signal/src/ViewControllers/ContactsViewHelper.m @@ -207,6 +207,55 @@ NS_ASSUME_NONNULL_BEGIN return [result copy]; } +- (BOOL)doesContactAccount:(ContactAccount *)contactAccount matchSearchTerm:(NSString *)searchTerm +{ + OWSAssert(contactAccount); + OWSAssert(searchTerm.length > 0); + + if ([contactAccount.contact.fullName.lowercaseString containsString:searchTerm.lowercaseString]) { + return YES; + } + + NSString *asPhoneNumber = [PhoneNumber removeFormattingCharacters:searchTerm]; + if (asPhoneNumber.length > 0 && [contactAccount.recipientId containsString:asPhoneNumber]) { + return YES; + } + + return NO; +} + +- (BOOL)doesContactAccount:(ContactAccount *)contactAccount matchSearchTerms:(NSArray *)searchTerms +{ + OWSAssert(contactAccount); + OWSAssert(searchTerms.count > 0); + + for (NSString *searchTerm in searchTerms) { + if (![self doesContactAccount:contactAccount matchSearchTerm:searchTerm]) { + return NO; + } + } + + return YES; +} + +- (NSArray *)contactAccountsMatchingSearchString:(NSString *)searchText +{ + + NSArray *searchTerms = + [[searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] + componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + if (searchTerms.count < 1) { + return self.allRecipientContactAccounts; + } + + return [self.allRecipientContactAccounts + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(ContactAccount *contactAccount, + NSDictionary *_Nullable bindings) { + return [self doesContactAccount:contactAccount matchSearchTerms:searchTerms]; + }]]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/SelectThreadViewController.m b/Signal/src/ViewControllers/SelectThreadViewController.m index 76dc1df58..0c243a434 100644 --- a/Signal/src/ViewControllers/SelectThreadViewController.m +++ b/Signal/src/ViewControllers/SelectThreadViewController.m @@ -4,7 +4,9 @@ #import "SelectThreadViewController.h" #import "BlockListUIUtils.h" +#import "ContactAccount.h" #import "ContactTableViewCell.h" +#import "ContactsViewHelper.h" #import "Environment.h" #import "InboxTableViewCell.h" #import "OWSContactsManager.h" @@ -14,20 +16,18 @@ #import "UIColor+OWS.h" #import "UIFont+OWS.h" #import "UIView+OWS.h" -#import #import #import #import NS_ASSUME_NONNULL_BEGIN -@interface SelectThreadViewController () +@interface SelectThreadViewController () -@property (nonatomic, readonly) OWSBlockingManager *blockingManager; -@property (nonatomic) NSSet *blockedPhoneNumberSet; - -@property (nonatomic, readonly) OWSContactsManager *contactsManager; -@property (nonatomic) NSArray *contacts; +@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper; @property (nonatomic, readonly) ThreadViewHelper *threadViewHelper; @@ -51,17 +51,13 @@ NS_ASSUME_NONNULL_BEGIN self.view.backgroundColor = [UIColor whiteColor]; - _blockingManager = [OWSBlockingManager sharedManager]; - _blockedPhoneNumberSet = [NSSet setWithArray:[_blockingManager blockedPhoneNumbers]]; - _contactsManager = [Environment getCurrent].contactsManager; - self.contacts = [self filteredContacts]; + _contactsViewHelper = [ContactsViewHelper new]; + _contactsViewHelper.delegate = self; _threadViewHelper = [ThreadViewHelper new]; _threadViewHelper.delegate = self; [self createViews]; - [self addNotificationListeners]; - [self updateTableContents]; } @@ -71,23 +67,6 @@ NS_ASSUME_NONNULL_BEGIN [self.navigationController.navigationBar setTranslucent:NO]; } -- (void)addNotificationListeners -{ - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(blockedPhoneNumbersDidChange:) - name:kNSNotificationName_BlockedPhoneNumbersDidChange - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(signalRecipientsDidChange:) - name:OWSContactsManagerSignalRecipientsDidChangeNotification - object:nil]; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - - (void)createViews { OWSAssert(self.delegate); @@ -149,6 +128,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateTableContents { __weak SelectThreadViewController *weakSelf = self; + ContactsViewHelper *helper = self.contactsViewHelper; OWSTableContents *contents = [OWSTableContents new]; OWSTableSection *section = [OWSTableSection new]; @@ -163,7 +143,7 @@ NS_ASSUME_NONNULL_BEGIN // To be consistent with the threads (above), we use ContactTableViewCell // instead of InboxTableViewCell to present contacts and threads. ContactTableViewCell *cell = [ContactTableViewCell new]; - [cell configureWithThread:thread contactsManager:strongSelf.contactsManager]; + [cell configureWithThread:thread contactsManager:helper.contactsManager]; return cell; } customRowHeight:[ContactTableViewCell rowHeight] @@ -173,8 +153,8 @@ NS_ASSUME_NONNULL_BEGIN } // Contacts - NSArray *filteredContacts = [self filteredContactsWithSearchText]; - for (Contact *contact in filteredContacts) { + NSArray *filteredContactAccounts = [self filteredContactAccountsWithSearchText]; + for (ContactAccount *contactAccount in filteredContactAccounts) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectThreadViewController *strongSelf = weakSelf; if (!strongSelf) { @@ -182,19 +162,20 @@ NS_ASSUME_NONNULL_BEGIN } ContactTableViewCell *cell = [ContactTableViewCell new]; - BOOL isBlocked = [strongSelf isContactBlocked:contact]; + BOOL isBlocked = [helper isRecipientIdBlocked:contactAccount.recipientId]; if (isBlocked) { cell.accessoryMessage = NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); } else { OWSAssert(cell.accessoryMessage == nil); } - [cell configureWithContact:contact contactsManager:strongSelf.contactsManager]; + // TODO: Use contact account + [cell configureWithContact:contactAccount.contact contactsManager:helper.contactsManager]; return cell; } customRowHeight:[ContactTableViewCell rowHeight] actionBlock:^{ - [weakSelf contactWasSelected:contact]; + [weakSelf contactAccountWasSelected:contactAccount]; }]]; } @@ -215,33 +196,31 @@ NS_ASSUME_NONNULL_BEGIN self.tableViewController.contents = contents; } -- (void)contactWasSelected:(Contact *)contact +- (void)contactAccountWasSelected:(ContactAccount *)contactAccount { - OWSAssert(contact); + OWSAssert(contactAccount); OWSAssert(self.delegate); - // TODO: Use ContactAccount. - NSString *recipientId = contact.textSecureIdentifiers.firstObject; - - if ([self isRecipientIdBlocked:recipientId] && - ![self.delegate canSelectBlockedContact]) { - + ContactsViewHelper *helper = self.contactsViewHelper; + + if ([helper isRecipientIdBlocked:contactAccount.recipientId] && ![self.delegate canSelectBlockedContact]) { + __weak SelectThreadViewController *weakSelf = self; - [BlockListUIUtils showUnblockContactActionSheet:contact - fromViewController:self - blockingManager:self.blockingManager - contactsManager:self.contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf contactWasSelected:contact]; - } - }]; + [BlockListUIUtils showUnblockContactAccountActionSheet:contactAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf contactAccountWasSelected:contactAccount]; + } + }]; return; } __block TSThread *thread = nil; [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction]; + thread = [TSContactThread getOrCreateThreadWithContactId:contactAccount.recipientId transaction:transaction]; }]; OWSAssert(thread); @@ -278,7 +257,7 @@ NS_ASSUME_NONNULL_BEGIN } // TODO: Move this to contacts view helper. -- (NSArray *)filteredContactsWithSearchText +- (NSArray *)filteredContactAccountsWithSearchText { // We don't want to show a 1:1 thread with Alice and Alice's contact, // so we de-duplicate by recipientId. @@ -293,87 +272,12 @@ NS_ASSUME_NONNULL_BEGIN NSString *searchString = [self.searchBar text]; - NSArray *nonRedundantContacts = - [self.contacts filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Contact *contact, - NSDictionary *_Nullable bindings) { - return ![contactIdsToIgnore containsObject:contact.textSecureIdentifiers.firstObject]; + ContactsViewHelper *helper = self.contactsViewHelper; + return [[helper contactAccountsMatchingSearchString:searchString] + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(ContactAccount *contactAccount, + NSDictionary *_Nullable bindings) { + return ![contactIdsToIgnore containsObject:contactAccount.recipientId]; }]]; - - // TODO: Move this to contacts view helper. - OWSContactsSearcher *contactsSearcher = [[OWSContactsSearcher alloc] initWithContacts:nonRedundantContacts]; - NSArray *filteredContacts = [contactsSearcher filterWithString:searchString]; - - return filteredContacts; -} - -#pragma mark - Contacts and Blocking - -- (void)blockedPhoneNumbersDidChange:(id)notification -{ - dispatch_async(dispatch_get_main_queue(), ^{ - _blockedPhoneNumberSet = [NSSet setWithArray:[_blockingManager blockedPhoneNumbers]]; - - [self updateContacts]; - }); -} - -- (void)signalRecipientsDidChange:(NSNotification *)notification -{ - dispatch_async(dispatch_get_main_queue(), ^{ - [self updateContacts]; - }); -} - -- (void)updateContacts -{ - OWSAssert([NSThread isMainThread]); - - self.contacts = [self filteredContacts]; - [self updateTableContents]; -} - -- (BOOL)isContactBlocked:(Contact *)contact -{ - if (contact.parsedPhoneNumbers.count < 1) { - // Hide contacts without any valid phone numbers. - return NO; - } - - for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { - if ([_blockedPhoneNumberSet containsObject:phoneNumber.toE164]) { - return YES; - } - } - - return NO; -} - -- (BOOL)isRecipientIdBlocked:(NSString *)recipientId -{ - OWSAssert(recipientId.length > 0); - - return [_blockedPhoneNumberSet containsObject:recipientId]; -} - -- (BOOL)isContactHidden:(Contact *)contact -{ - if (contact.parsedPhoneNumbers.count < 1) { - // Hide contacts without any valid phone numbers. - return YES; - } - - return NO; -} - -- (NSArray *_Nonnull)filteredContacts -{ - NSMutableArray *result = [NSMutableArray new]; - for (Contact *contact in self.contactsManager.signalContacts) { - if (![self isContactHidden:contact]) { - [result addObject:contact]; - } - } - return [result copy]; } #pragma mark - Events @@ -398,6 +302,18 @@ NS_ASSUME_NONNULL_BEGIN [self updateTableContents]; } +#pragma mark - ContactsViewHelperDelegate + +- (void)contactsViewHelperDidUpdateContacts +{ + [self updateTableContents]; +} + +- (BOOL)shouldHideLocalNumber +{ + return NO; +} + #pragma mark - Logging + (NSString *)tag diff --git a/Signal/src/ViewControllers/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ShowGroupMembersViewController.m index 391d1ce5a..d3d7288aa 100644 --- a/Signal/src/ViewControllers/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ShowGroupMembersViewController.m @@ -154,9 +154,7 @@ NS_ASSUME_NONNULL_BEGIN BOOL isBlocked; if (contactAccount) { - Contact *contact = contactAccount.contact; - - isBlocked = [helper isContactBlocked:contact]; + isBlocked = [helper isRecipientIdBlocked:contactAccount.recipientId]; if (isBlocked) { [actionSheetController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", @@ -164,11 +162,11 @@ NS_ASSUME_NONNULL_BEGIN style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) { [BlockListUIUtils - showUnblockContactActionSheet:contact - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:nil]; + showUnblockContactAccountActionSheet:contactAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:nil]; }]]; } else { [actionSheetController @@ -177,11 +175,11 @@ NS_ASSUME_NONNULL_BEGIN style:UIAlertActionStyleDestructive handler:^(UIAlertAction *_Nonnull action) { [BlockListUIUtils - showBlockContactActionSheet:contact - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:nil]; + showBlockContactAccountActionSheet:contactAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:nil]; }]]; } } else {