From a7296db1fedba750500225152b27c0f7cec8a472 Mon Sep 17 00:00:00 2001
From: Matthew Chen <charlesmchen@gmail.com>
Date: Fri, 31 Mar 2017 17:43:42 -0400
Subject: [PATCH 1/4] =?UTF-8?q?Add=20contacts=20list=20to=20=E2=80=9Cadd?=
 =?UTF-8?q?=20blocked=20number=E2=80=9D=20view.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

// FREEBIE
---
 .../AddToBlockListViewController.m            | 188 +++++++++++++++++-
 Signal/src/views/ContactTableViewCell.h       |   6 +
 Signal/src/views/ContactTableViewCell.m       |  42 ++++
 .../translations/en.lproj/Localizable.strings |  19 +-
 4 files changed, 244 insertions(+), 11 deletions(-)

diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.m b/Signal/src/ViewControllers/AddToBlockListViewController.m
index f027edcf7..7a222bce2 100644
--- a/Signal/src/ViewControllers/AddToBlockListViewController.m
+++ b/Signal/src/ViewControllers/AddToBlockListViewController.m
@@ -3,7 +3,11 @@
 //
 
 #import "AddToBlockListViewController.h"
+#import "ContactTableViewCell.h"
+#import "ContactsUpdater.h"
 #import "CountryCodeViewController.h"
+#import "Environment.h"
+#import "OWSContactsManager.h"
 #import "PhoneNumber.h"
 #import "StringUtil.h"
 #import "UIFont+OWS.h"
@@ -17,10 +21,15 @@ NS_ASSUME_NONNULL_BEGIN
 
 NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockListViewControllerCellIdentifier";
 
+NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseIdentifier";
+
 #pragma mark -
 
 // TODO: Add a list of contacts to make it easier to block contacts.
-@interface AddToBlockListViewController () <CountryCodeViewControllerDelegate, UITextFieldDelegate>
+@interface AddToBlockListViewController () <CountryCodeViewControllerDelegate,
+    UITextFieldDelegate,
+    UITableViewDataSource,
+    UITableViewDelegate>
 
 @property (nonatomic, readonly) OWSBlockingManager *blockingManager;
 
@@ -31,20 +40,19 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
 
 @property (nonatomic) UIButton *blockButton;
 
+@property (nonatomic) UITableView *contactsTableView;
+
 @property (nonatomic) NSString *callingCode;
 
+@property (nonatomic, readonly) OWSContactsManager *contactsManager;
+@property (nonatomic) NSArray<Contact *> *contacts;
+
 @end
 
 #pragma mark -
 
 @implementation AddToBlockListViewController
 
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    [self.navigationController.navigationBar setTranslucent:NO];
-}
-
 - (void)loadView
 {
     [super loadView];
@@ -52,6 +60,8 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
     self.view.backgroundColor = [UIColor whiteColor];
     
     _blockingManager = [OWSBlockingManager sharedManager];
+    _contactsManager = [Environment getCurrent].contactsManager;
+    self.contacts = self.contactsManager.signalContacts;
 
     self.title = NSLocalizedString(@"SETTINGS_ADD_TO_BLOCK_LIST_TITLE", @"");
 
@@ -62,12 +72,29 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
     [self addNotificationListeners];
 }
 
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    [self.navigationController.navigationBar setTranslucent:NO];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    [super viewWillAppear:animated];
+
+    [self refreshContacts];
+}
+
 - (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
@@ -164,6 +191,17 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
     [_blockButton autoSetDimension:ALDimensionWidth toSize:160];
     [_blockButton autoSetDimension:ALDimensionHeight toSize:40];
 
+    _contactsTableView = [UITableView new];
+    _contactsTableView.dataSource = self;
+    _contactsTableView.delegate = self;
+    [_contactsTableView registerClass:[ContactTableViewCell class]
+               forCellReuseIdentifier:kContactsTable_CellReuseIdentifier];
+    _contactsTableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
+    [self.view addSubview:_contactsTableView];
+    [_contactsTableView autoPinWidthToSuperview];
+    [_contactsTableView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:blockButtonRow withOffset:30];
+    [_contactsTableView autoPinToBottomLayoutGuideOfViewController:self withInset:0];
+
     [self updateBlockButtonEnabling];
 }
 
@@ -247,10 +285,11 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
     [_blockingManager addBlockedPhoneNumber:[parsedPhoneNumber toE164]];
 
     UIAlertController *controller = [UIAlertController
-        alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE",
+        alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_TITLE",
                                      @"The title of the 'phone number blocked' alert in the block view.")
                          message:[NSString
-                                     stringWithFormat:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT",
+                                     stringWithFormat:NSLocalizedString(
+                                                          @"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_MESSAGE_FORMAT",
                                                           @"The message format of the 'phone number blocked' alert in "
                                                           @"the block view. Embeds {{the blocked phone number}}."),
                                      [parsedPhoneNumber toE164]]
@@ -295,6 +334,19 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
     // TODO: Once we have a list of contacts, we should update it here.
 }
 
+- (void)signalRecipientsDidChange:(NSNotification *)notification
+{
+    [self updateContacts];
+}
+
+- (void)updateContacts
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        self.contacts = self.contactsManager.signalContacts;
+        [self.contactsTableView reloadData];
+    });
+}
+
 #pragma mark - CountryCodeViewControllerDelegate
 
 - (void)countryCodeViewController:(CountryCodeViewController *)vc
@@ -332,6 +384,124 @@ NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockList
     return NO;
 }
 
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+    return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    return (NSInteger)self.contacts.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    Contact *contact = self.contacts[(NSUInteger)indexPath.item];
+
+    ContactTableViewCell *cell = [_contactsTableView cellForRowAtIndexPath:indexPath];
+    if (!cell) {
+        cell = [ContactTableViewCell new];
+    }
+    [cell configureWithContact:contact contactsManager:self.contactsManager];
+    return cell;
+}
+
+- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
+{
+    return NSLocalizedString(
+        @"BLOCK_LIST_VIEW_CONTACTS_SECTION_TITLE", @"A title for the contacts section of the blocklist view.");
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    return [ContactTableViewCell rowHeight];
+}
+
+#pragma mark - UITableViewDelegate
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    [tableView deselectRowAtIndexPath:indexPath animated:YES];
+
+    Contact *contact = self.contacts[(NSUInteger)indexPath.item];
+    [self showBlockActionSheet:contact];
+}
+
+- (void)showBlockActionSheet:(Contact *)contact
+{
+    OWSAssert(contact);
+
+    NSString *displayName = contact.fullName;
+
+    NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_BLOCK_TITLE_FORMAT",
+                                                     @"A format for the 'block phone number' action sheet title."),
+                                displayName];
+
+    UIAlertController *actionSheetController =
+        [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
+
+    __weak AddToBlockListViewController *weakSelf = self;
+    UIAlertAction *unblockAction = [UIAlertAction
+        actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", @"Button label for the 'block' button")
+                  style:UIAlertActionStyleDefault
+                handler:^(UIAlertAction *_Nonnull action) {
+                    [weakSelf blockContact:contact displayName:displayName];
+                }];
+    [actionSheetController addAction:unblockAction];
+
+    UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
+                                                            style:UIAlertActionStyleCancel
+                                                          handler:nil];
+    [actionSheetController addAction:dismissAction];
+
+    [self presentViewController:actionSheetController animated:YES completion:nil];
+}
+
+- (void)blockContact:(Contact *)contact displayName:(NSString *)displayName
+{
+    for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
+        if (phoneNumber.toE164.length > 0) {
+            [_blockingManager addBlockedPhoneNumber:phoneNumber.toE164];
+        }
+    }
+
+    UIAlertController *controller = [UIAlertController
+        alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_TITLE",
+                                     @"The title of the 'contact blocked' alert in the block view.")
+                         message:[NSString stringWithFormat:NSLocalizedString(
+                                                                @"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_MESSAGE_FORMAT",
+                                                                @"The message format of the 'contact blocked' "
+                                                                @"alert in the block view. It is populated with the "
+                                                                @"blocked contact's name."),
+                                           displayName]
+                  preferredStyle:UIAlertControllerStyleAlert];
+
+    [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
+                                                   style:UIAlertActionStyleDefault
+                                                 handler:nil]];
+    [self presentViewController:controller animated:YES completion:nil];
+}
+
+- (void)refreshContacts
+{
+    [[ContactsUpdater sharedUpdater] updateSignalContactIntersectionWithABContacts:self.contactsManager.allContacts
+        success:^{
+            [self updateContacts];
+        }
+        failure:^(NSError *error) {
+            DDLogError(@"%@ Error updating contacts", self.tag);
+        }];
+}
+
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView
+{
+    [self.phoneNumberTextField resignFirstResponder];
+}
+
 #pragma mark - Logging
 
 + (NSString *)tag
diff --git a/Signal/src/views/ContactTableViewCell.h b/Signal/src/views/ContactTableViewCell.h
index 72f253dd0..91011d6c2 100644
--- a/Signal/src/views/ContactTableViewCell.h
+++ b/Signal/src/views/ContactTableViewCell.h
@@ -1,3 +1,7 @@
+//
+//  Copyright (c) 2017 Open Whisper Systems. All rights reserved.
+//
+
 #import <UIKit/UIKit.h>
 #import "OWSContactsManager.h"
 
@@ -13,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface ContactTableViewCell : UITableViewCell
 
++ (CGFloat)rowHeight;
+
 - (void)configureWithContact:(Contact *)contact contactsManager:(OWSContactsManager *)contactsManager;
 
 @end
diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m
index f3a8a2b23..c45f4fd3c 100644
--- a/Signal/src/views/ContactTableViewCell.m
+++ b/Signal/src/views/ContactTableViewCell.m
@@ -6,7 +6,9 @@
 #import "Environment.h"
 #import "OWSContactAvatarBuilder.h"
 #import "OWSContactsManager.h"
+#import "UIFont+OWS.h"
 #import "UIUtil.h"
+#import "UIView+OWS.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -19,11 +21,51 @@ NS_ASSUME_NONNULL_BEGIN
 
 @implementation ContactTableViewCell
 
+- (instancetype)init
+{
+    if (self = [super init]) {
+        [self configureProgrammatically];
+    }
+    return self;
+}
+
 - (nullable NSString *)reuseIdentifier
 {
     return NSStringFromClass(self.class);
 }
 
++ (CGFloat)rowHeight
+{
+    return 59.f;
+}
+
+- (void)configureProgrammatically
+{
+    _avatarView = [UIImageView new];
+    _avatarView.contentMode = UIViewContentModeScaleToFill;
+    _avatarView.image = [UIImage imageNamed:@"empty-group-avatar"];
+    [self.contentView addSubview:_avatarView];
+
+    _nameLabel = [UILabel new];
+    _nameLabel.contentMode = UIViewContentModeLeft;
+    _nameLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+    _nameLabel.font = [UIFont ows_dynamicTypeBodyFont];
+    [self.contentView addSubview:_nameLabel];
+
+    [_avatarView autoVCenterInSuperview];
+    [_avatarView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:8.f];
+    [_avatarView autoSetDimension:ALDimensionWidth toSize:40.f];
+    [_avatarView autoSetDimension:ALDimensionHeight toSize:40.f];
+
+    [_nameLabel autoPinEdgeToSuperviewEdge:ALEdgeRight];
+    [_nameLabel autoPinEdgeToSuperviewEdge:ALEdgeTop];
+    [_nameLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom];
+    [_nameLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:_avatarView withOffset:12.f];
+
+    // Force layout, since imageView isn't being initally rendered on App Store optimized build.
+    [self layoutSubviews];
+}
+
 - (void)configureWithContact:(Contact *)contact contactsManager:(OWSContactsManager *)contactsManager
 {
     self.nameLabel.attributedText = [contactsManager formattedFullNameForContact:contact font:self.nameLabel.font];
diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings
index f69a496b3..b496d7a7f 100644
--- a/Signal/translations/en.lproj/Localizable.strings
+++ b/Signal/translations/en.lproj/Localizable.strings
@@ -97,6 +97,12 @@
 /* No comment provided by engineer. */
 "ATTACHMENT_QUEUED" = "New attachment queued for retrieval.";
 
+/* Button label for the 'block' button */
+"BLOCK_LIST_BLOCK_BUTTON" = "Block";
+
+/* A format for the 'block phone number' action sheet title. */
+"BLOCK_LIST_BLOCK_TITLE_FORMAT" = "Block %@?";
+
 /* Button label for the 'unblock' button */
 "BLOCK_LIST_UNBLOCK_BUTTON" = "Unblock";
 
@@ -106,11 +112,20 @@
 /* A label for the block button in the block list view */
 "BLOCK_LIST_VIEW_BLOCK_BUTTON" = "Block";
 
+/* The message format of the 'contact blocked' alert in the block view. It is populated with the blocked contact's name. */
+"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked";
+
+/* The title of the 'contact blocked' alert in the block view. */
+"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_TITLE" = "Contact Blocked";
+
+/* A title for the contacts section of the blocklist view. */
+"BLOCK_LIST_VIEW_CONTACTS_SECTION_TITLE" = "Contacts";
+
 /* The message format of the 'phone number blocked' alert in the block view. It is populated with the blocked phone number. */
-"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
+"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked";
 
 /* The title of the 'phone number blocked' alert in the block view. */
-"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Phone Number Blocked";
+"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_TITLE" = "Phone Number Blocked";
 
 /* The message format of the 'phone number unblocked' alert in the block view. It is populated with the blocked phone number. */
 "BLOCK_LIST_VIEW_UNBLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been unblocked.";

From 6c1d46c4d7624707a9f1bde20cb8dac704fe93ff Mon Sep 17 00:00:00 2001
From: Matthew Chen <charlesmchen@gmail.com>
Date: Fri, 31 Mar 2017 17:56:39 -0400
Subject: [PATCH 2/4] Use contact names where possible in the block list view.

// FREEBIE
---
 .../AddToBlockListViewController.m            |   1 -
 .../ViewControllers/BlockListViewController.m | 111 ++++++++++++++----
 2 files changed, 90 insertions(+), 22 deletions(-)

diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.m b/Signal/src/ViewControllers/AddToBlockListViewController.m
index 7a222bce2..917ba04aa 100644
--- a/Signal/src/ViewControllers/AddToBlockListViewController.m
+++ b/Signal/src/ViewControllers/AddToBlockListViewController.m
@@ -25,7 +25,6 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI
 
 #pragma mark -
 
-// TODO: Add a list of contacts to make it easier to block contacts.
 @interface AddToBlockListViewController () <CountryCodeViewControllerDelegate,
     UITextFieldDelegate,
     UITableViewDataSource,
diff --git a/Signal/src/ViewControllers/BlockListViewController.m b/Signal/src/ViewControllers/BlockListViewController.m
index 8365a3e3c..9eef95d60 100644
--- a/Signal/src/ViewControllers/BlockListViewController.m
+++ b/Signal/src/ViewControllers/BlockListViewController.m
@@ -3,19 +3,25 @@
 //
 
 #import "BlockListViewController.h"
-#import "UIFont+OWS.h"
-#import "PhoneNumber.h"
 #import "AddToBlockListViewController.h"
+#import "ContactsUpdater.h"
+#import "Environment.h"
+#import "OWSContactsManager.h"
+#import "PhoneNumber.h"
+#import "UIFont+OWS.h"
 #import <SignalServiceKit/OWSBlockingManager.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
-// TODO: We should label phone numbers with contact names where possible.
 @interface BlockListViewController ()
 
 @property (nonatomic, readonly) OWSBlockingManager *blockingManager;
 @property (nonatomic, readonly) NSArray<NSString *> *blockedPhoneNumbers;
 
+@property (nonatomic, readonly) OWSContactsManager *contactsManager;
+@property (nonatomic) NSArray<Contact *> *contacts;
+@property (nonatomic) NSDictionary<NSString *, Contact *> *contactMap;
+
 @end
 
 #pragma mark -
@@ -39,6 +45,8 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     
     _blockingManager = [OWSBlockingManager sharedManager];
     _blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers];
+    _contactsManager = [Environment getCurrent].contactsManager;
+    self.contacts = self.contactsManager.signalContacts;
 
     self.title
         = NSLocalizedString(@"SETTINGS_BLOCK_LIST_TITLE", @"Label for the block list section of the settings view");
@@ -46,12 +54,23 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     [self addNotificationListeners];
 }
 
+- (void)viewWillAppear:(BOOL)animated
+{
+    [super viewWillAppear:animated];
+
+    [self refreshContacts];
+}
+
 - (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
@@ -109,15 +128,8 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
             cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
             break;
         case BlockListViewControllerSection_BlockList: {
-            NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger) indexPath.item];
-            PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber];
-            // Try to parse and present the phone number in E164.
-            // It should already be in E164, so this should always work.
-            // If an invalid or unparsable phone number is already in the block list,
-            // present it as-is.
-            cell.textLabel.text = (parsedPhoneNumber
-                                   ? parsedPhoneNumber.toE164
-                                   : phoneNumber);
+            NSString *displayName = [self displayNameForIndexPath:indexPath];
+            cell.textLabel.text = displayName;
             cell.textLabel.font = [UIFont ows_mediumFontWithSize:18.f];
             cell.accessoryType = UITableViewCellAccessoryCheckmark;
             break;
@@ -130,6 +142,24 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     return cell;
 }
 
+- (NSString *)displayNameForIndexPath:(NSIndexPath *)indexPath
+{
+    NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger)indexPath.item];
+    PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber];
+
+    // Try to parse and present the phone number in E164.
+    // It should already be in E164, so this should always work.
+    // If an invalid or unparsable phone number is already in the block list,
+    // present it as-is.
+    NSString *displayName = (parsedPhoneNumber ? parsedPhoneNumber.toE164 : phoneNumber);
+    Contact *contact = self.contactMap[displayName];
+    if (contact && [contact fullName].length > 0) {
+        displayName = [contact fullName];
+    }
+
+    return displayName;
+}
+
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
     [tableView deselectRowAtIndexPath:indexPath animated:YES];
@@ -145,7 +175,8 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
         }
         case BlockListViewControllerSection_BlockList: {
             NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger)indexPath.item];
-            [self showUnblockActionSheet:phoneNumber];
+            NSString *displayName = [self displayNameForIndexPath:indexPath];
+            [self showUnblockActionSheet:phoneNumber displayName:displayName];
             break;
         }
         default:
@@ -153,16 +184,14 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     }
 }
 
-- (void)showUnblockActionSheet:(NSString *)phoneNumber
+- (void)showUnblockActionSheet:(NSString *)phoneNumber displayName:(NSString *)displayName
 {
     OWSAssert(phoneNumber.length > 0);
-
-    PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber];
-    NSString *displayPhoneNumber = (parsedPhoneNumber ? parsedPhoneNumber.toE164 : phoneNumber);
+    OWSAssert(displayName.length > 0);
 
     NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_TITLE_FORMAT",
                                                      @"A format for the 'unblock phone number' action sheet title."),
-                                displayPhoneNumber];
+                                displayName];
 
     UIAlertController *actionSheetController =
         [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
@@ -172,7 +201,7 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
         actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", @"Button label for the 'unblock' button")
                   style:UIAlertActionStyleDefault
                 handler:^(UIAlertAction *_Nonnull action) {
-                    [weakSelf unblockPhoneNumber:phoneNumber displayPhoneNumber:displayPhoneNumber];
+                    [weakSelf unblockPhoneNumber:phoneNumber displayName:displayName];
                 }];
     [actionSheetController addAction:unblockAction];
 
@@ -184,7 +213,7 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     [self presentViewController:actionSheetController animated:YES completion:nil];
 }
 
-- (void)unblockPhoneNumber:(NSString *)phoneNumber displayPhoneNumber:(NSString *)displayPhoneNumber
+- (void)unblockPhoneNumber:(NSString *)phoneNumber displayName:(NSString *)displayName
 {
     [_blockingManager removeBlockedPhoneNumber:phoneNumber];
 
@@ -196,7 +225,7 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
                                                                 @"The message format of the 'phone number unblocked' "
                                                                 @"alert in the block view. It is populated with the "
                                                                 @"blocked phone number."),
-                                           displayPhoneNumber]
+                                           displayName]
                   preferredStyle:UIAlertControllerStyleAlert];
 
     [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
@@ -214,6 +243,46 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     [self.tableView reloadData];
 }
 
+- (void)signalRecipientsDidChange:(NSNotification *)notification
+{
+    [self updateContacts];
+}
+
+- (void)updateContacts
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        self.contacts = self.contactsManager.signalContacts;
+        [self.tableView reloadData];
+    });
+}
+
+- (void)refreshContacts
+{
+    [[ContactsUpdater sharedUpdater] updateSignalContactIntersectionWithABContacts:self.contactsManager.allContacts
+        success:^{
+            [self updateContacts];
+        }
+        failure:^(NSError *error) {
+            DDLogError(@"%@ Error updating contacts", self.tag);
+        }];
+}
+
+- (void)setContacts:(NSArray<Contact *> *)contacts
+{
+    _contacts = contacts;
+
+    NSMutableDictionary<NSString *, Contact *> *contactMap = [NSMutableDictionary new];
+    for (Contact *contact in contacts) {
+        for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
+            NSString *phoneNumberE164 = phoneNumber.toE164;
+            if (phoneNumberE164.length > 0) {
+                contactMap[phoneNumberE164] = contact;
+            }
+        }
+    }
+    self.contactMap = contactMap;
+}
+
 #pragma mark - Logging
 
 + (NSString *)tag

From 8dadc3ba22d84087e3d283f317eb4f3d1740eae2 Mon Sep 17 00:00:00 2001
From: Matthew Chen <charlesmchen@gmail.com>
Date: Fri, 31 Mar 2017 18:02:35 -0400
Subject: [PATCH 3/4] =?UTF-8?q?Don=E2=80=99t=20update=20contacts=20in=20th?=
 =?UTF-8?q?e=20blacklist=20views.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

// FREEBIE
---
 .../AddToBlockListViewController.m            | 19 -------------------
 .../ViewControllers/BlockListViewController.m | 19 -------------------
 2 files changed, 38 deletions(-)

diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.m b/Signal/src/ViewControllers/AddToBlockListViewController.m
index 917ba04aa..ccc5fc369 100644
--- a/Signal/src/ViewControllers/AddToBlockListViewController.m
+++ b/Signal/src/ViewControllers/AddToBlockListViewController.m
@@ -4,7 +4,6 @@
 
 #import "AddToBlockListViewController.h"
 #import "ContactTableViewCell.h"
-#import "ContactsUpdater.h"
 #import "CountryCodeViewController.h"
 #import "Environment.h"
 #import "OWSContactsManager.h"
@@ -77,13 +76,6 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI
     [self.navigationController.navigationBar setTranslucent:NO];
 }
 
-- (void)viewWillAppear:(BOOL)animated
-{
-    [super viewWillAppear:animated];
-
-    [self refreshContacts];
-}
-
 - (void)addNotificationListeners
 {
     [[NSNotificationCenter defaultCenter] addObserver:self
@@ -483,17 +475,6 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI
     [self presentViewController:controller animated:YES completion:nil];
 }
 
-- (void)refreshContacts
-{
-    [[ContactsUpdater sharedUpdater] updateSignalContactIntersectionWithABContacts:self.contactsManager.allContacts
-        success:^{
-            [self updateContacts];
-        }
-        failure:^(NSError *error) {
-            DDLogError(@"%@ Error updating contacts", self.tag);
-        }];
-}
-
 #pragma mark - UIScrollViewDelegate
 
 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
diff --git a/Signal/src/ViewControllers/BlockListViewController.m b/Signal/src/ViewControllers/BlockListViewController.m
index 9eef95d60..41534e71e 100644
--- a/Signal/src/ViewControllers/BlockListViewController.m
+++ b/Signal/src/ViewControllers/BlockListViewController.m
@@ -4,7 +4,6 @@
 
 #import "BlockListViewController.h"
 #import "AddToBlockListViewController.h"
-#import "ContactsUpdater.h"
 #import "Environment.h"
 #import "OWSContactsManager.h"
 #import "PhoneNumber.h"
@@ -54,13 +53,6 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     [self addNotificationListeners];
 }
 
-- (void)viewWillAppear:(BOOL)animated
-{
-    [super viewWillAppear:animated];
-
-    [self refreshContacts];
-}
-
 - (void)addNotificationListeners
 {
     [[NSNotificationCenter defaultCenter] addObserver:self
@@ -256,17 +248,6 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
     });
 }
 
-- (void)refreshContacts
-{
-    [[ContactsUpdater sharedUpdater] updateSignalContactIntersectionWithABContacts:self.contactsManager.allContacts
-        success:^{
-            [self updateContacts];
-        }
-        failure:^(NSError *error) {
-            DDLogError(@"%@ Error updating contacts", self.tag);
-        }];
-}
-
 - (void)setContacts:(NSArray<Contact *> *)contacts
 {
     _contacts = contacts;

From 5fa1a3630f9d627ff39bc1ad0b80872e48dcc0ff Mon Sep 17 00:00:00 2001
From: Matthew Chen <charlesmchen@gmail.com>
Date: Tue, 4 Apr 2017 09:32:26 -0400
Subject: [PATCH 4/4] Respond to CR.

// FREEBIE
---
 Signal/src/ViewControllers/BlockListViewController.m | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Signal/src/ViewControllers/BlockListViewController.m b/Signal/src/ViewControllers/BlockListViewController.m
index 41534e71e..701a85549 100644
--- a/Signal/src/ViewControllers/BlockListViewController.m
+++ b/Signal/src/ViewControllers/BlockListViewController.m
@@ -116,13 +116,13 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
         case BlockListViewControllerSection_Add:
             cell.textLabel.text = NSLocalizedString(
                                                     @"SETTINGS_BLOCK_LIST_ADD_BUTTON", @"A label for the 'add phone number' button in the block list table.");
-            cell.textLabel.font = [UIFont ows_mediumFontWithSize:18.f];
+            cell.textLabel.font = [UIFont ows_regularFontWithSize:18.f];
             cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
             break;
         case BlockListViewControllerSection_BlockList: {
             NSString *displayName = [self displayNameForIndexPath:indexPath];
             cell.textLabel.text = displayName;
-            cell.textLabel.font = [UIFont ows_mediumFontWithSize:18.f];
+            cell.textLabel.font = [UIFont ows_regularFontWithSize:18.f];
             cell.accessoryType = UITableViewCellAccessoryCheckmark;
             break;
         }