From 6801963a1b61f2f63d2c3f5d92beba480c84557e Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 1 May 2017 12:51:59 -0400 Subject: [PATCH] Add SignalAccount class. // FREEBIE --- Signal.xcodeproj/project.pbxproj | 18 +- Signal/src/Signal-Bridging-Header.h | 1 + .../AddToBlockListViewController.m | 28 +- .../AddToGroupViewController.m | 28 +- Signal/src/ViewControllers/BlockListUIUtils.h | 22 +- Signal/src/ViewControllers/BlockListUIUtils.m | 30 +- .../ViewControllers/BlockListViewController.h | 2 +- .../ViewControllers/BlockListViewController.m | 204 +++++--------- Signal/src/ViewControllers/ContactAccount.h | 27 -- Signal/src/ViewControllers/ContactAccount.m | 13 - .../src/ViewControllers/ContactsViewHelper.h | 20 +- .../src/ViewControllers/ContactsViewHelper.m | 191 +++---------- Signal/src/ViewControllers/GroupViewHelper.h | 10 +- Signal/src/ViewControllers/GroupViewHelper.m | 12 +- .../ViewControllers/NewGroupViewController.m | 74 ++--- .../SelectRecipientViewController.h | 4 +- .../SelectRecipientViewController.m | 14 +- .../SelectThreadViewController.m | 47 ++-- .../ShowGroupMembersViewController.m | 40 +-- Signal/src/ViewControllers/SignalAccount.h | 38 +++ Signal/src/ViewControllers/SignalAccount.m | 21 ++ .../UpdateGroupViewController.m | 56 ++-- Signal/src/call/CallService.swift | 2 +- Signal/src/contact/GroupContactsResult.h | 24 -- Signal/src/contact/GroupContactsResult.m | 133 --------- Signal/src/contact/OWSContactsManager.h | 26 +- Signal/src/contact/OWSContactsManager.m | 266 ++++++++++-------- Signal/src/util/ThreadUtil.m | 4 +- Signal/src/views/ContactTableViewCell.h | 7 +- Signal/src/views/ContactTableViewCell.m | 13 +- 30 files changed, 552 insertions(+), 823 deletions(-) delete mode 100644 Signal/src/ViewControllers/ContactAccount.h delete mode 100644 Signal/src/ViewControllers/ContactAccount.m create mode 100644 Signal/src/ViewControllers/SignalAccount.h create mode 100644 Signal/src/ViewControllers/SignalAccount.m delete mode 100644 Signal/src/contact/GroupContactsResult.h delete mode 100644 Signal/src/contact/GroupContactsResult.m diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 7244270c9..79cecbd9c 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -25,7 +25,6 @@ 345671011E89A5F1006EE662 /* ThreadUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 345671001E89A5F1006EE662 /* ThreadUtil.m */; }; 3456710A1E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 345671091E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m */; }; 3472229F1EB22FFE00E53955 /* AddToGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3472229E1EB22FFE00E53955 /* AddToGroupViewController.m */; }; - 34B3F8321E8DF11D0035BE1A /* GroupContactsResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8311E8DF11D0035BE1A /* GroupContactsResult.m */; }; 34B3F8711E8DF1700035BE1A /* AboutTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8351E8DF1700035BE1A /* AboutTableViewController.m */; }; 34B3F8721E8DF1700035BE1A /* AdvancedSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8371E8DF1700035BE1A /* AdvancedSettingsTableViewController.m */; }; 34B3F8731E8DF1700035BE1A /* AttachmentApprovalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8381E8DF1700035BE1A /* AttachmentApprovalViewController.swift */; }; @@ -70,7 +69,7 @@ 34D5CCA61EA934A4005515DB /* NSTimer+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCA51EA934A4005515DB /* NSTimer+OWS.m */; }; 34D5CCA91EAE3D30005515DB /* GroupViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCA81EAE3D30005515DB /* GroupViewHelper.m */; }; 34D5CCB11EAE7E7F005515DB /* SelectRecipientViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCB01EAE7E7F005515DB /* SelectRecipientViewController.m */; }; - 34D5CCB41EAEA225005515DB /* ContactAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCB31EAEA225005515DB /* ContactAccount.m */; }; + 34D5CCB41EAEA225005515DB /* SignalAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCB31EAEA225005515DB /* SignalAccount.m */; }; 34DFCB851E8E04B500053165 /* AddToBlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */; }; 34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */; }; 450573FE1E78A06D00615BB4 /* OWS103EnableVideoCalling.m in Sources */ = {isa = PBXBuildFile; fileRef = 450573FD1E78A06D00615BB4 /* OWS103EnableVideoCalling.m */; }; @@ -386,8 +385,6 @@ 345671091E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSGenericAttachmentAdapter.m; sourceTree = ""; }; 3472229D1EB22FFE00E53955 /* AddToGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToGroupViewController.h; sourceTree = ""; }; 3472229E1EB22FFE00E53955 /* AddToGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToGroupViewController.m; sourceTree = ""; }; - 34B3F8301E8DF11D0035BE1A /* GroupContactsResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupContactsResult.h; sourceTree = ""; }; - 34B3F8311E8DF11D0035BE1A /* GroupContactsResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupContactsResult.m; sourceTree = ""; }; 34B3F8341E8DF1700035BE1A /* AboutTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutTableViewController.h; sourceTree = ""; }; 34B3F8351E8DF1700035BE1A /* AboutTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutTableViewController.m; sourceTree = ""; }; 34B3F8361E8DF1700035BE1A /* AdvancedSettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdvancedSettingsTableViewController.h; sourceTree = ""; }; @@ -467,8 +464,8 @@ 34D5CCAB1EAE7136005515DB /* OWSConversationSettingsViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsViewDelegate.h; sourceTree = ""; }; 34D5CCAF1EAE7E7F005515DB /* SelectRecipientViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectRecipientViewController.h; sourceTree = ""; }; 34D5CCB01EAE7E7F005515DB /* SelectRecipientViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectRecipientViewController.m; sourceTree = ""; }; - 34D5CCB21EAEA225005515DB /* ContactAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactAccount.h; sourceTree = ""; }; - 34D5CCB31EAEA225005515DB /* ContactAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactAccount.m; sourceTree = ""; }; + 34D5CCB21EAEA225005515DB /* SignalAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalAccount.h; sourceTree = ""; }; + 34D5CCB31EAEA225005515DB /* SignalAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalAccount.m; sourceTree = ""; }; 34DFCB831E8E04B400053165 /* AddToBlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToBlockListViewController.h; sourceTree = ""; }; 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToBlockListViewController.m; sourceTree = ""; }; 34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWSAnyTouchGestureRecognizer.h; path = views/OWSAnyTouchGestureRecognizer.h; sourceTree = ""; }; @@ -878,8 +875,6 @@ 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */, 34B3F83C1E8DF1700035BE1A /* CodeVerificationViewController.h */, 34B3F83D1E8DF1700035BE1A /* CodeVerificationViewController.m */, - 34D5CCB21EAEA225005515DB /* ContactAccount.h */, - 34D5CCB31EAEA225005515DB /* ContactAccount.m */, 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */, 34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */, 340CB2221EAC155C0001CAA1 /* ContactsViewHelper.h */, @@ -941,6 +936,8 @@ 34B3F8691E8DF1700035BE1A /* SettingsTableViewController.m */, 34B3F86A1E8DF1700035BE1A /* ShowGroupMembersViewController.h */, 34B3F86B1E8DF1700035BE1A /* ShowGroupMembersViewController.m */, + 34D5CCB21EAEA225005515DB /* SignalAccount.h */, + 34D5CCB31EAEA225005515DB /* SignalAccount.m */, 34B3F86C1E8DF1700035BE1A /* SignalAttachment.swift */, 34B3F86D1E8DF1700035BE1A /* SignalsNavigationController.h */, 34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */, @@ -1193,8 +1190,6 @@ 76EB040318170B33006006FC /* contact */ = { isa = PBXGroup; children = ( - 34B3F8301E8DF11D0035BE1A /* GroupContactsResult.h */, - 34B3F8311E8DF11D0035BE1A /* GroupContactsResult.m */, 76EB040818170B33006006FC /* OWSContactsManager.h */, 76EB040918170B33006006FC /* OWSContactsManager.m */, 45843D1D1D2236B30013E85A /* OWSContactsSearcher.h */, @@ -2040,7 +2035,7 @@ 34D5CCB11EAE7E7F005515DB /* SelectRecipientViewController.m in Sources */, 34B3F88F1E8DF1710035BE1A /* RegistrationViewController.m in Sources */, 34B3F8901E8DF1710035BE1A /* SettingsTableViewController.m in Sources */, - 34D5CCB41EAEA225005515DB /* ContactAccount.m in Sources */, + 34D5CCB41EAEA225005515DB /* SignalAccount.m in Sources */, 34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */, 343D3D9B1E9283F100165CA4 /* BlockListUIUtils.m in Sources */, 34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */, @@ -2076,7 +2071,6 @@ 452ECA4D1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */, 452EA0971EA662330078744B /* AttachmentPointerAdapter.swift in Sources */, 34DFCB851E8E04B500053165 /* AddToBlockListViewController.m in Sources */, - 34B3F8321E8DF11D0035BE1A /* GroupContactsResult.m in Sources */, 45855F371D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */, 45666EC61D99483D008FE134 /* OWSAvatarBuilder.m in Sources */, 45E615161E8C590B0018AD52 /* DisplayableTextFilter.swift in Sources */, diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index dce5e82ca..f5f9cd6b3 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -23,6 +23,7 @@ #import "PrivacySettingsTableViewController.h" #import "PropertyListPreferences.h" #import "PushManager.h" +#import "SignalAccount.h" #import "TSSocketManager.h" #import "TSStorageManager+Calling.h" #import "UIColor+OWS.h" diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.m b/Signal/src/ViewControllers/AddToBlockListViewController.m index 301d92d72..d9072d9f9 100644 --- a/Signal/src/ViewControllers/AddToBlockListViewController.m +++ b/Signal/src/ViewControllers/AddToBlockListViewController.m @@ -4,9 +4,9 @@ #import "AddToBlockListViewController.h" #import "BlockListUIUtils.h" -#import "ContactAccount.h" #import "ContactsViewHelper.h" #import "OWSContactsManager.h" +#import "SignalAccount.h" NS_ASSUME_NONNULL_BEGIN @@ -60,14 +60,14 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)contactAccountWasSelected:(ContactAccount *)contactAccount +- (void)signalAccountWasSelected:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); __weak AddToBlockListViewController *weakSelf = self; ContactsViewHelper *helper = self.contactsViewHelper; - if ([helper isRecipientIdBlocked:contactAccount.recipientId]) { - NSString *displayName = [helper.contactsManager displayNameForContactAccount:contactAccount]; + if ([helper isRecipientIdBlocked:signalAccount.recipientId]) { + NSString *displayName = [helper.contactsManager displayNameForSignalAccount:signalAccount]; UIAlertController *controller = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_ALREADY_BLOCKED_ALERT_TITLE", @"A title of the alert if user tries to block a " @@ -88,15 +88,15 @@ NS_ASSUME_NONNULL_BEGIN [self presentViewController:controller animated:YES completion:nil]; return; } - [BlockListUIUtils showBlockContactAccountActionSheet:contactAccount - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:^(BOOL isBlocked) { - if (isBlocked) { - [weakSelf.navigationController popViewControllerAnimated:YES]; - } - }]; + [BlockListUIUtils showBlockSignalAccountActionSheet:signalAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:^(BOOL isBlocked) { + if (isBlocked) { + [weakSelf.navigationController popViewControllerAnimated:YES]; + } + }]; } - (BOOL)shouldHideLocalNumber diff --git a/Signal/src/ViewControllers/AddToGroupViewController.m b/Signal/src/ViewControllers/AddToGroupViewController.m index f6b89f806..a9caca929 100644 --- a/Signal/src/ViewControllers/AddToGroupViewController.m +++ b/Signal/src/ViewControllers/AddToGroupViewController.m @@ -4,9 +4,9 @@ #import "AddToGroupViewController.h" #import "BlockListUIUtils.h" -#import "ContactAccount.h" #import "ContactsViewHelper.h" #import "OWSContactsManager.h" +#import "SignalAccount.h" NS_ASSUME_NONNULL_BEGIN @@ -66,24 +66,24 @@ NS_ASSUME_NONNULL_BEGIN } } -- (void)contactAccountWasSelected:(ContactAccount *)contactAccount +- (void)signalAccountWasSelected:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); __weak AddToGroupViewController *weakSelf = self; ContactsViewHelper *helper = self.contactsViewHelper; - if ([helper isRecipientIdBlocked:contactAccount.recipientId]) { - [BlockListUIUtils showUnblockContactAccountActionSheet:contactAccount - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:^(BOOL isBlocked) { - if (isBlocked) { - [weakSelf addToGroup:contactAccount.recipientId]; - } - }]; + if ([helper isRecipientIdBlocked:signalAccount.recipientId]) { + [BlockListUIUtils showUnblockSignalAccountActionSheet:signalAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:^(BOOL isBlocked) { + if (isBlocked) { + [weakSelf addToGroup:signalAccount.recipientId]; + } + }]; } else { - [self addToGroup:contactAccount.recipientId]; + [self addToGroup:signalAccount.recipientId]; } } diff --git a/Signal/src/ViewControllers/BlockListUIUtils.h b/Signal/src/ViewControllers/BlockListUIUtils.h index ab37f4943..949bc57c8 100644 --- a/Signal/src/ViewControllers/BlockListUIUtils.h +++ b/Signal/src/ViewControllers/BlockListUIUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN @class Contact; -@class ContactAccount; +@class SignalAccount; @class OWSBlockingManager; @class OWSContactsManager; @@ -25,11 +25,11 @@ typedef void (^BlockActionCompletionBlock)(BOOL isBlocked); contactsManager:(OWSContactsManager *)contactsManager completionBlock:(nullable BlockActionCompletionBlock)completionBlock; -+ (void)showBlockContactAccountActionSheet:(ContactAccount *)contactAccount - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock; ++ (void)showBlockSignalAccountActionSheet:(SignalAccount *)signalAccount + fromViewController:(UIViewController *)fromViewController + blockingManager:(OWSBlockingManager *)blockingManager + contactsManager:(OWSContactsManager *)contactsManager + completionBlock:(nullable BlockActionCompletionBlock)completionBlock; #pragma mark - Unblock @@ -39,11 +39,11 @@ typedef void (^BlockActionCompletionBlock)(BOOL isBlocked); contactsManager:(OWSContactsManager *)contactsManager completionBlock:(nullable BlockActionCompletionBlock)completionBlock; -+ (void)showUnblockContactAccountActionSheet:(ContactAccount *)contactAccount - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock; ++ (void)showUnblockSignalAccountActionSheet:(SignalAccount *)signalAccount + fromViewController:(UIViewController *)fromViewController + blockingManager:(OWSBlockingManager *)blockingManager + contactsManager:(OWSContactsManager *)contactsManager + completionBlock:(nullable BlockActionCompletionBlock)completionBlock; #pragma mark - UI Utils diff --git a/Signal/src/ViewControllers/BlockListUIUtils.m b/Signal/src/ViewControllers/BlockListUIUtils.m index 9780d7843..adf950ce6 100644 --- a/Signal/src/ViewControllers/BlockListUIUtils.m +++ b/Signal/src/ViewControllers/BlockListUIUtils.m @@ -3,9 +3,9 @@ // #import "BlockListUIUtils.h" -#import "ContactAccount.h" #import "OWSContactsManager.h" #import "PhoneNumber.h" +#import "SignalAccount.h" #import #import #import @@ -32,14 +32,14 @@ typedef void (^BlockAlertCompletionBlock)(); completionBlock:completionBlock]; } -+ (void)showBlockContactAccountActionSheet:(ContactAccount *)contactAccount - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock ++ (void)showBlockSignalAccountActionSheet:(SignalAccount *)signalAccount + fromViewController:(UIViewController *)fromViewController + blockingManager:(OWSBlockingManager *)blockingManager + contactsManager:(OWSContactsManager *)contactsManager + completionBlock:(nullable BlockActionCompletionBlock)completionBlock { - NSString *displayName = [contactsManager displayNameForContactAccount:contactAccount]; - [self showBlockPhoneNumbersActionSheet:@[ contactAccount.recipientId ] + NSString *displayName = [contactsManager displayNameForSignalAccount:signalAccount]; + [self showBlockPhoneNumbersActionSheet:@[ signalAccount.recipientId ] displayName:displayName fromViewController:fromViewController blockingManager:blockingManager @@ -159,14 +159,14 @@ typedef void (^BlockAlertCompletionBlock)(); completionBlock:completionBlock]; } -+ (void)showUnblockContactAccountActionSheet:(ContactAccount *)contactAccount - fromViewController:(UIViewController *)fromViewController - blockingManager:(OWSBlockingManager *)blockingManager - contactsManager:(OWSContactsManager *)contactsManager - completionBlock:(nullable BlockActionCompletionBlock)completionBlock ++ (void)showUnblockSignalAccountActionSheet:(SignalAccount *)signalAccount + fromViewController:(UIViewController *)fromViewController + blockingManager:(OWSBlockingManager *)blockingManager + contactsManager:(OWSContactsManager *)contactsManager + completionBlock:(nullable BlockActionCompletionBlock)completionBlock { - NSString *displayName = [contactsManager displayNameForContactAccount:contactAccount]; - [self showUnblockPhoneNumbersActionSheet:@[ contactAccount.recipientId ] + NSString *displayName = [contactsManager displayNameForSignalAccount:signalAccount]; + [self showUnblockPhoneNumbersActionSheet:@[ signalAccount.recipientId ] displayName:displayName fromViewController:fromViewController blockingManager:blockingManager diff --git a/Signal/src/ViewControllers/BlockListViewController.h b/Signal/src/ViewControllers/BlockListViewController.h index ba9d73b99..79bfd79d1 100644 --- a/Signal/src/ViewControllers/BlockListViewController.h +++ b/Signal/src/ViewControllers/BlockListViewController.h @@ -4,6 +4,6 @@ #import -@interface BlockListViewController : UITableViewController +@interface BlockListViewController : UIViewController @end diff --git a/Signal/src/ViewControllers/BlockListViewController.m b/Signal/src/ViewControllers/BlockListViewController.m index 996306d6c..626846482 100644 --- a/Signal/src/ViewControllers/BlockListViewController.m +++ b/Signal/src/ViewControllers/BlockListViewController.m @@ -5,69 +5,46 @@ #import "BlockListViewController.h" #import "AddToBlockListViewController.h" #import "BlockListUIUtils.h" +#import "ContactsViewHelper.h" #import "Environment.h" #import "OWSContactsManager.h" +#import "OWSTableViewController.h" #import "PhoneNumber.h" #import "UIFont+OWS.h" +#import "UIView+OWS.h" #import NS_ASSUME_NONNULL_BEGIN -@interface BlockListViewController () +@interface BlockListViewController () -@property (nonatomic, readonly) OWSBlockingManager *blockingManager; -@property (nonatomic, readonly) NSArray *blockedPhoneNumbers; +@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper; -@property (nonatomic, readonly) OWSContactsManager *contactsManager; -@property (nonatomic) NSArray *contacts; +@property (nonatomic, readonly) OWSTableViewController *tableViewController; @end #pragma mark - -typedef NS_ENUM(NSInteger, BlockListViewControllerSection) { - BlockListViewControllerSection_Add, - BlockListViewControllerSection_BlockList, - BlockListViewControllerSection_Count // meta section -}; - @implementation BlockListViewController -- (instancetype)init -{ - return [super initWithStyle:UITableViewStyleGrouped]; -} - - (void)loadView { [super loadView]; - - _blockingManager = [OWSBlockingManager sharedManager]; - _blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; - _contactsManager = [Environment getCurrent].contactsManager; - self.contacts = [self.contactsManager.signalContacts copy]; + + _contactsViewHelper = [ContactsViewHelper new]; + _contactsViewHelper.delegate = self; self.title = NSLocalizedString(@"SETTINGS_BLOCK_LIST_TITLE", @"Label for the block list section of the settings view"); - [self addNotificationListeners]; -} + _tableViewController = [OWSTableViewController new]; + [self.view addSubview:self.tableViewController.view]; + [_tableViewController.view autoPinWidthToSuperview]; + [_tableViewController.view autoPinToTopLayoutGuideOfViewController:self withInset:0]; + [_tableViewController.view autoPinToBottomLayoutGuideOfViewController:self withInset:0]; -- (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]; + [self updateTableContents]; } - (void)viewDidLoad @@ -78,120 +55,75 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) { #pragma mark - Table view data source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +- (void)updateTableContents { - return BlockListViewControllerSection_Count; -} + OWSTableContents *contents = [OWSTableContents new]; -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - switch (section) { - case BlockListViewControllerSection_Add: - return 1; - case BlockListViewControllerSection_BlockList: - return (NSInteger) _blockedPhoneNumbers.count; - default: - OWSAssert(0); - return 0; + __weak BlockListViewController *weakSelf = self; + ContactsViewHelper *helper = self.contactsViewHelper; + + // Add section + + OWSTableSection *addSection = [OWSTableSection new]; + addSection.footerTitle = NSLocalizedString( + @"BLOCK_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of blocking another user."); + + [addSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ + UITableViewCell *cell = [UITableViewCell new]; + 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_regularFontWithSize:18.f]; + cell.textLabel.textColor = [UIColor blackColor]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + return cell; } -} + actionBlock:^{ + AddToBlockListViewController *vc = [[AddToBlockListViewController alloc] init]; + NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); + NSAssert(vc != nil, @"Privacy Settings View Controller must not be nil"); + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; + [contents addSection:addSection]; -- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section -{ - switch (section) { - case BlockListViewControllerSection_Add: - return NSLocalizedString(@"BLOCK_BEHAVIOR_EXPLANATION", - @"An explanation of the consequences of blocking another user."); - default: - return nil; - } -} + // Blocklist section -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell *cell = [UITableViewCell new]; - OWSAssert(cell); - - switch (indexPath.section) { - 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_regularFontWithSize:18.f]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - break; - case BlockListViewControllerSection_BlockList: { - NSString *displayName = [self displayNameForIndexPath:indexPath]; + OWSTableSection *blocklistSection = [OWSTableSection new]; + NSArray *blockedPhoneNumbers = + [helper.blockedPhoneNumbers sortedArrayUsingSelector:@selector(compare:)]; + for (NSString *phoneNumber in blockedPhoneNumbers) { + [blocklistSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ + // TODO: Use ContactTableViewCell. + UITableViewCell *cell = [UITableViewCell new]; + NSString *displayName = [helper.contactsManager displayNameForPhoneIdentifier:phoneNumber]; cell.textLabel.text = displayName; cell.textLabel.font = [UIFont ows_regularFontWithSize:18.f]; cell.accessoryType = UITableViewCellAccessoryCheckmark; - break; + cell.textLabel.textColor = [UIColor blackColor]; + return cell; } - default: - OWSAssert(0); - return 0; + actionBlock:^{ + [BlockListUIUtils showUnblockPhoneNumberActionSheet:phoneNumber + fromViewController:weakSelf + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:nil]; + }]]; } - - return cell; + [contents addSection:blocklistSection]; + + self.tableViewController.contents = contents; } -- (NSString *)displayNameForIndexPath:(NSIndexPath *)indexPath +#pragma mark - ContactsViewHelperDelegate + +- (void)contactsViewHelperDidUpdateContacts { - NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger)indexPath.item]; - NSString *displayName = [_contactsManager displayNameForPhoneIdentifier:phoneNumber]; - return displayName; + [self updateTableContents]; } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (BOOL)shouldHideLocalNumber { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - switch (indexPath.section) { - case BlockListViewControllerSection_Add: - { - AddToBlockListViewController *vc = [[AddToBlockListViewController alloc] init]; - NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); - NSAssert(vc != nil, @"Privacy Settings View Controller must not be nil"); - [self.navigationController pushViewController:vc animated:YES]; - break; - } - case BlockListViewControllerSection_BlockList: { - NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger)indexPath.item]; - [BlockListUIUtils showUnblockPhoneNumberActionSheet:phoneNumber - fromViewController:self - blockingManager:_blockingManager - contactsManager:_contactsManager - completionBlock:nil]; - break; - } - default: - OWSAssert(0); - } -} - -#pragma mark - Actions - -- (void)blockedPhoneNumbersDidChange:(id)notification -{ - dispatch_async(dispatch_get_main_queue(), ^{ - _blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; - - [self.tableView reloadData]; - }); -} - -- (void)signalRecipientsDidChange:(NSNotification *)notification -{ - dispatch_async(dispatch_get_main_queue(), ^{ - [self updateContacts]; - }); -} - -- (void)updateContacts -{ - OWSAssert([NSThread isMainThread]); - - self.contacts = [self.contactsManager.signalContacts copy]; - [self.tableView reloadData]; + return YES; } #pragma mark - Logging diff --git a/Signal/src/ViewControllers/ContactAccount.h b/Signal/src/ViewControllers/ContactAccount.h deleted file mode 100644 index 307f8f654..000000000 --- a/Signal/src/ViewControllers/ContactAccount.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. -// - -NS_ASSUME_NONNULL_BEGIN - -@class Contact; - -// We want to be able to present contacts with multiple signal -// accounts in the UI. This class represents a given (contact, -// signal account) tuple. -@interface ContactAccount : NSObject - -@property (nonatomic) Contact *contact; - -// An E164 value identifying the signal account. -@property (nonatomic) NSString *recipientId; - -@property (nonatomic) BOOL isMultipleAccountContact; - -// For contacts with more than one signal account, -// this is a label for the account. -@property (nonatomic) NSString *multipleAccountLabel; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ContactAccount.m b/Signal/src/ViewControllers/ContactAccount.m deleted file mode 100644 index 2a158a562..000000000 --- a/Signal/src/ViewControllers/ContactAccount.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. -// - -#import "ContactAccount.h" - -NS_ASSUME_NONNULL_BEGIN - -@implementation ContactAccount - -@end - -NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ContactsViewHelper.h b/Signal/src/ViewControllers/ContactsViewHelper.h index 2ce1a8721..32249e8e5 100644 --- a/Signal/src/ViewControllers/ContactsViewHelper.h +++ b/Signal/src/ViewControllers/ContactsViewHelper.h @@ -6,7 +6,7 @@ NS_ASSUME_NONNULL_BEGIN @class ContactsViewHelper; @class Contact; -@class ContactAccount; +@class SignalAccount; @protocol ContactsViewHelperDelegate @@ -28,18 +28,12 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) OWSContactsManager *contactsManager; @property (nonatomic, readonly) OWSBlockingManager *blockingManager; -// A list of all of the current user's contacts which have -// at least one signal account. -- (nullable NSArray *)allRecipientContacts; +@property (nonatomic, readonly) NSDictionary *signalAccountMap; +@property (nonatomic, readonly) NSArray *signalAccounts; -// A list of all of the current user's ContactAccounts. -// See the comments on the ContactAccount class. -// -// The list is ordered by contact sorting (by OWSContactsManager) -// and within contacts by phone number, alphabetically. -- (nullable NSArray *)allRecipientContactAccounts; +@property (nonatomic, readonly) NSArray *blockedPhoneNumbers; -- (nullable ContactAccount *)contactAccountForRecipientId:(NSString *)recipientId; +- (nullable SignalAccount *)signalAccountForRecipientId:(NSString *)recipientId; - (nullable NSArray *)blockedPhoneNumbers; @@ -48,6 +42,8 @@ NS_ASSUME_NONNULL_BEGIN // // Returns true if _any_ number associated with this contact // is blocked. +// +// TODO: Is this obsolete? - (BOOL)isContactBlocked:(Contact *)contact; // This method is faster than OWSBlockingManager but @@ -56,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)localNumber; -- (NSArray *)contactAccountsMatchingSearchString:(NSString *)searchText; +- (NSArray *)signalAccountsMatchingSearchString:(NSString *)searchText; @end diff --git a/Signal/src/ViewControllers/ContactsViewHelper.m b/Signal/src/ViewControllers/ContactsViewHelper.m index 91c0d8c27..7cbacfcf6 100644 --- a/Signal/src/ViewControllers/ContactsViewHelper.m +++ b/Signal/src/ViewControllers/ContactsViewHelper.m @@ -3,9 +3,9 @@ // #import "ContactsViewHelper.h" -#import "ContactAccount.h" #import "ContactTableViewCell.h" #import "Environment.h" +#import "SignalAccount.h" #import #import #import @@ -14,12 +14,10 @@ NS_ASSUME_NONNULL_BEGIN @interface ContactsViewHelper () -@property (nonatomic, nullable) NSArray *allRecipientContacts; -@property (nonatomic, nullable) NSArray *allRecipientContactAccounts; -// A map of recipient id-to-contact account. -@property (nonatomic, nullable) NSDictionary *contactAccountMap; +@property (nonatomic) NSDictionary *signalAccountMap; +@property (nonatomic) NSArray *signalAccounts; -@property (nonatomic, nullable) NSArray *blockedPhoneNumbers; +@property (nonatomic) NSArray *blockedPhoneNumbers; @end @@ -38,7 +36,8 @@ NS_ASSUME_NONNULL_BEGIN self.blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; _contactsManager = [Environment getCurrent].contactsManager; - [self updateContacts]; + self.signalAccountMap = self.contactsManager.signalAccountMap; + self.signalAccounts = self.contactsManager.signalAccounts; [self observeNotifications]; @@ -48,8 +47,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)observeNotifications { [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(signalRecipientsDidChange:) - name:OWSContactsManagerSignalRecipientsDidChangeNotification + selector:@selector(signalAccountsDidChange:) + name:OWSContactsManagerSignalAccountsDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(blockedPhoneNumbersDidChange:) @@ -62,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)signalRecipientsDidChange:(NSNotification *)notification +- (void)signalAccountsDidChange:(NSNotification *)notification { dispatch_async(dispatch_get_main_queue(), ^{ [self updateContacts]; @@ -80,131 +79,19 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Contacts -- (nullable ContactAccount *)contactAccountForRecipientId:(NSString *)recipientId +- (nullable SignalAccount *)signalAccountForRecipientId:(NSString *)recipientId { OWSAssert([NSThread isMainThread]); OWSAssert(recipientId.length > 0); - return self.contactAccountMap[recipientId]; + return self.signalAccountMap[recipientId]; } -- (void)updateContacts +- (BOOL)isSignalAccountHidden:(SignalAccount *)signalAccount { OWSAssert([NSThread isMainThread]); - self.allRecipientContacts = [self filteredContacts]; -} - -- (void)setAllRecipientContacts:(nullable NSArray *)allRecipientContacts -{ - OWSAssert([NSThread isMainThread]); - - _allRecipientContacts = allRecipientContacts; - - NSMutableArray *allRecipientContactAccounts = [NSMutableArray new]; - NSMutableDictionary *contactAccountMap = [NSMutableDictionary new]; - for (Contact *contact in allRecipientContacts) { - if (contact.textSecureIdentifiers.count == 1) { - ContactAccount *contactAccount = [ContactAccount new]; - contactAccount.contact = contact; - NSString *recipientId = contact.textSecureIdentifiers[0]; - contactAccount.recipientId = recipientId; - [allRecipientContactAccounts addObject:contactAccount]; - contactAccountMap[recipientId] = contactAccount; - } else if (contact.textSecureIdentifiers.count > 1) { - for (NSString *recipientId in - [contact.textSecureIdentifiers sortedArrayUsingSelector:@selector(compare:)]) { - ContactAccount *contactAccount = [ContactAccount new]; - contactAccount.contact = contact; - contactAccount.recipientId = recipientId; - contactAccount.isMultipleAccountContact = YES; - contactAccount.multipleAccountLabel = [self accountLabelForContact:contact recipientId:recipientId]; - [allRecipientContactAccounts addObject:contactAccount]; - contactAccountMap[recipientId] = contactAccount; - } - } - } - self.allRecipientContactAccounts = [allRecipientContactAccounts copy]; - self.contactAccountMap = [contactAccountMap copy]; - - [self.delegate contactsViewHelperDidUpdateContacts]; -} - -- (NSString *)accountLabelForContact:(Contact *)contact recipientId:(NSString *)recipientId -{ - OWSAssert(contact); - OWSAssert(recipientId.length > 0); - OWSAssert([contact.textSecureIdentifiers containsObject:recipientId]); - - if (contact.textSecureIdentifiers.count <= 1) { - return nil; - } - - // 1. Find the phone number type of this account. - OWSPhoneNumberType phoneNumberType = [contact phoneNumberTypeForPhoneNumber:recipientId]; - - NSString *phoneNumberLabel; - switch (phoneNumberType) { - case OWSPhoneNumberTypeMobile: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_MOBILE", @"Label for 'Mobile' phone numbers."); - break; - case OWSPhoneNumberTypeIPhone: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_IPHONE", @"Label for 'IPhone' phone numbers."); - break; - case OWSPhoneNumberTypeMain: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_MAIN", @"Label for 'Main' phone numbers."); - break; - case OWSPhoneNumberTypeHomeFAX: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_HOME_FAX", @"Label for 'HomeFAX' phone numbers."); - break; - case OWSPhoneNumberTypeWorkFAX: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_WORK_FAX", @"Label for 'Work FAX' phone numbers."); - break; - case OWSPhoneNumberTypeOtherFAX: - phoneNumberLabel - = NSLocalizedString(@"PHONE_NUMBER_TYPE_OTHER_FAX", @"Label for 'Other FAX' phone numbers."); - break; - case OWSPhoneNumberTypePager: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_PAGER", @"Label for 'Pager' phone numbers."); - break; - case OWSPhoneNumberTypeUnknown: - phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_UNKNOWN", @"Label for 'Unknown' phone numbers."); - break; - } - - // 2. Find all phone numbers for this contact of the same type. - NSMutableArray *phoneNumbersOfTheSameType = [NSMutableArray new]; - for (NSString *textSecureIdentifier in contact.textSecureIdentifiers) { - if (phoneNumberType == [contact phoneNumberTypeForPhoneNumber:textSecureIdentifier]) { - [phoneNumbersOfTheSameType addObject:textSecureIdentifier]; - } - } - - OWSAssert([phoneNumbersOfTheSameType containsObject:recipientId]); - if (phoneNumbersOfTheSameType.count > 0) { - NSUInteger index = - [[phoneNumbersOfTheSameType sortedArrayUsingSelector:@selector(compare:)] indexOfObject:recipientId]; - phoneNumberLabel = - [NSString stringWithFormat:NSLocalizedString(@"PHONE_NUMBER_TYPE_AND_INDEX_FORMAT", - @"Format for phone number label with an index. Embeds {{Phone number label " - @"(e.g. 'home')}} and {{index, e.g. 2}}."), - phoneNumberLabel, - (int)index]; - } - - return phoneNumberLabel; -} - -- (BOOL)isContactHidden:(Contact *)contact -{ - OWSAssert([NSThread isMainThread]); - - if (contact.parsedPhoneNumbers.count < 1) { - // Hide contacts without any valid phone numbers. - return YES; - } - - if ([self.delegate shouldHideLocalNumber] && [self isCurrentUserContact:contact]) { + if ([self.delegate shouldHideLocalNumber] && [self isCurrentUser:signalAccount]) { // We never want to add ourselves to a group. return YES; } @@ -212,12 +99,17 @@ NS_ASSUME_NONNULL_BEGIN return NO; } -- (BOOL)isCurrentUserContact:(Contact *)contact +- (BOOL)isCurrentUser:(SignalAccount *)signalAccount { OWSAssert([NSThread isMainThread]); - for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { - if ([[phoneNumber toE164] isEqualToString:[TSAccountManager localNumber]]) { + NSString *localNumber = [TSAccountManager localNumber]; + if ([signalAccount.recipientId isEqualToString:localNumber]) { + return YES; + } + + for (PhoneNumber *phoneNumber in signalAccount.contact.parsedPhoneNumbers) { + if ([[phoneNumber toE164] isEqualToString:localNumber]) { return YES; } } @@ -255,43 +147,48 @@ NS_ASSUME_NONNULL_BEGIN return [_blockedPhoneNumbers containsObject:recipientId]; } -- (NSArray *_Nonnull)filteredContacts +- (void)updateContacts { AssertIsOnMainThread(); - NSMutableArray *result = [NSMutableArray new]; - for (Contact *contact in self.contactsManager.signalContacts) { - if (![self isContactHidden:contact]) { - [result addObject:contact]; + NSMutableDictionary *signalAccountMap = [NSMutableDictionary new]; + NSMutableArray *signalAccounts = [NSMutableArray new]; + for (SignalAccount *signalAccount in self.contactsManager.signalAccounts) { + if (![self isSignalAccountHidden:signalAccount]) { + signalAccountMap[signalAccount.recipientId] = signalAccount; + [signalAccounts addObject:signalAccount]; } } - return [result copy]; + self.signalAccountMap = signalAccountMap; + self.signalAccounts = signalAccounts; + + [self.delegate contactsViewHelperDidUpdateContacts]; } -- (BOOL)doesContactAccount:(ContactAccount *)contactAccount matchSearchTerm:(NSString *)searchTerm +- (BOOL)doesSignalAccount:(SignalAccount *)signalAccount matchSearchTerm:(NSString *)searchTerm { - OWSAssert(contactAccount); + OWSAssert(signalAccount); OWSAssert(searchTerm.length > 0); - if ([contactAccount.contact.fullName.lowercaseString containsString:searchTerm.lowercaseString]) { + if ([signalAccount.contact.fullName.lowercaseString containsString:searchTerm.lowercaseString]) { return YES; } NSString *asPhoneNumber = [PhoneNumber removeFormattingCharacters:searchTerm]; - if (asPhoneNumber.length > 0 && [contactAccount.recipientId containsString:asPhoneNumber]) { + if (asPhoneNumber.length > 0 && [signalAccount.recipientId containsString:asPhoneNumber]) { return YES; } return NO; } -- (BOOL)doesContactAccount:(ContactAccount *)contactAccount matchSearchTerms:(NSArray *)searchTerms +- (BOOL)doesSignalAccount:(SignalAccount *)signalAccount matchSearchTerms:(NSArray *)searchTerms { - OWSAssert(contactAccount); + OWSAssert(signalAccount); OWSAssert(searchTerms.count > 0); for (NSString *searchTerm in searchTerms) { - if (![self doesContactAccount:contactAccount matchSearchTerm:searchTerm]) { + if (![self doesSignalAccount:signalAccount matchSearchTerm:searchTerm]) { return NO; } } @@ -299,20 +196,20 @@ NS_ASSUME_NONNULL_BEGIN return YES; } -- (NSArray *)contactAccountsMatchingSearchString:(NSString *)searchText +- (NSArray *)signalAccountsMatchingSearchString:(NSString *)searchText { NSArray *searchTerms = [[searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; if (searchTerms.count < 1) { - return self.allRecipientContactAccounts; + return self.signalAccounts; } - return [self.allRecipientContactAccounts - filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(ContactAccount *contactAccount, + return [self.signalAccounts + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SignalAccount *signalAccount, NSDictionary *_Nullable bindings) { - return [self doesContactAccount:contactAccount matchSearchTerms:searchTerms]; + return [self doesSignalAccount:signalAccount matchSearchTerms:searchTerms]; }]]; } diff --git a/Signal/src/ViewControllers/GroupViewHelper.h b/Signal/src/ViewControllers/GroupViewHelper.h index 7fb0200f3..57543f155 100644 --- a/Signal/src/ViewControllers/GroupViewHelper.h +++ b/Signal/src/ViewControllers/GroupViewHelper.h @@ -6,7 +6,7 @@ NS_ASSUME_NONNULL_BEGIN -@class ContactAccount; +@class SignalAccount; @class GroupViewHelper; @class OWSContactsManager; @class TSThread; @@ -27,10 +27,10 @@ typedef void (^GroupViewSuccessBlock)(); @property (nonatomic, weak) id delegate; -- (void)showRemoveFromGroupAlertForContactAccount:(ContactAccount *)contactAccount - fromViewController:(UIViewController *)fromViewController - contactsManager:(OWSContactsManager *)contactsManager - successBlock:(GroupViewSuccessBlock)successBlock; +- (void)showRemoveFromGroupAlertForSignalAccount:(SignalAccount *)signalAccount + fromViewController:(UIViewController *)fromViewController + contactsManager:(OWSContactsManager *)contactsManager + successBlock:(GroupViewSuccessBlock)successBlock; - (void)showRemoveFromGroupAlertForRecipientId:(NSString *)recipientId fromViewController:(UIViewController *)fromViewController diff --git a/Signal/src/ViewControllers/GroupViewHelper.m b/Signal/src/ViewControllers/GroupViewHelper.m index 84b7fedcc..4e70df7e6 100644 --- a/Signal/src/ViewControllers/GroupViewHelper.m +++ b/Signal/src/ViewControllers/GroupViewHelper.m @@ -23,17 +23,17 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Alerts -- (void)showRemoveFromGroupAlertForContactAccount:(ContactAccount *)contactAccount - fromViewController:(UIViewController *)fromViewController - contactsManager:(OWSContactsManager *)contactsManager - successBlock:(GroupViewSuccessBlock)successBlock +- (void)showRemoveFromGroupAlertForSignalAccount:(SignalAccount *)signalAccount + fromViewController:(UIViewController *)fromViewController + contactsManager:(OWSContactsManager *)contactsManager + successBlock:(GroupViewSuccessBlock)successBlock { - OWSAssert(contactAccount); + OWSAssert(signalAccount); OWSAssert(fromViewController); OWSAssert(contactsManager); OWSAssert(successBlock); - NSString *displayName = [contactsManager displayNameForContactAccount:contactAccount]; + NSString *displayName = [contactsManager displayNameForSignalAccount:signalAccount]; UIAlertController *controller = [UIAlertController alertControllerWithTitle: NSLocalizedString(@"EDIT_GROUP_REMOVE_MEMBER_ALERT_TITLE", diff --git a/Signal/src/ViewControllers/NewGroupViewController.m b/Signal/src/ViewControllers/NewGroupViewController.m index 3867e8971..b1e601e53 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.m +++ b/Signal/src/ViewControllers/NewGroupViewController.m @@ -4,7 +4,6 @@ #import "NewGroupViewController.h" #import "AddToGroupViewController.h" -#import "ContactAccount.h" #import "ContactTableViewCell.h" #import "ContactsViewHelper.h" #import "Environment.h" @@ -13,6 +12,7 @@ #import "OWSContactsManager.h" #import "OWSTableViewController.h" #import "SecurityUtils.h" +#import "SignalAccount.h" #import "SignalKeyingStorage.h" #import "TSOutgoingMessage.h" #import "UIUtil.h" @@ -185,15 +185,15 @@ NS_ASSUME_NONNULL_BEGIN __weak NewGroupViewController *weakSelf = self; ContactsViewHelper *helper = self.contactsViewHelper; - NSArray *allRecipientContactAccounts = self.contactsViewHelper.allRecipientContactAccounts; + NSArray *signalAccounts = self.contactsViewHelper.signalAccounts; NSMutableSet *nonContactMemberRecipientIds = [self.memberRecipientIds mutableCopy]; - for (ContactAccount *contactAccount in allRecipientContactAccounts) { - [nonContactMemberRecipientIds removeObject:contactAccount.recipientId]; + for (SignalAccount *signalAccount in signalAccounts) { + [nonContactMemberRecipientIds removeObject:signalAccount.recipientId]; } // Non-contact Members - if (nonContactMemberRecipientIds.count > 0 || allRecipientContactAccounts.count < 1) { + if (nonContactMemberRecipientIds.count > 0 || signalAccounts.count < 1) { OWSTableSection *nonContactsSection = [OWSTableSection new]; nonContactsSection.headerTitle = NSLocalizedString( @@ -212,7 +212,7 @@ NS_ASSUME_NONNULL_BEGIN } ContactTableViewCell *cell = [ContactTableViewCell new]; - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; BOOL isCurrentMember = [weakSelf.memberRecipientIds containsObject:recipientId]; BOOL isBlocked = [helper isRecipientIdBlocked:recipientId]; if (isCurrentMember) { @@ -226,8 +226,8 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(cell.accessoryMessage == nil); } - if (contactAccount) { - [cell configureWithContactAccount:contactAccount contactsManager:helper.contactsManager]; + if (signalAccount) { + [cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager]; } else { [cell configureWithRecipientId:recipientId contactsManager:helper.contactsManager]; } @@ -236,15 +236,15 @@ NS_ASSUME_NONNULL_BEGIN } customRowHeight:[ContactTableViewCell rowHeight] actionBlock:^{ - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; - if (contactAccount) { + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; + if (signalAccount) { [weakSelf.groupViewHelper - showRemoveFromGroupAlertForContactAccount:contactAccount - fromViewController:weakSelf - contactsManager:helper.contactsManager - successBlock:^{ - [weakSelf removeContactAccount:contactAccount]; - }]; + showRemoveFromGroupAlertForSignalAccount:signalAccount + fromViewController:weakSelf + contactsManager:helper.contactsManager + successBlock:^{ + [weakSelf removeSignalAccount:signalAccount]; + }]; } else { [weakSelf.groupViewHelper showRemoveFromGroupAlertForRecipientId:recipientId @@ -261,18 +261,18 @@ NS_ASSUME_NONNULL_BEGIN // Contacts - OWSTableSection *contactAccountSection = [OWSTableSection new]; - contactAccountSection.headerTitle = NSLocalizedString( + OWSTableSection *signalAccountSection = [OWSTableSection new]; + signalAccountSection.headerTitle = NSLocalizedString( @"EDIT_GROUP_CONTACTS_SECTION_TITLE", @"a title for the contacts section of the 'new/update group' view."); - if (allRecipientContactAccounts.count > 0) { + if (signalAccounts.count > 0) { if (nonContactMemberRecipientIds.count < 1) { // We always want to offer a way to add non-contacts. - [contactAccountSection addItem:[self createAddNonContactItem]]; + [signalAccountSection addItem:[self createAddNonContactItem]]; } - for (ContactAccount *contactAccount in allRecipientContactAccounts) { - [contactAccountSection + for (SignalAccount *signalAccount in signalAccounts) { + [signalAccountSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ NewGroupViewController *strongSelf = weakSelf; if (!strongSelf) { @@ -281,7 +281,7 @@ NS_ASSUME_NONNULL_BEGIN ContactTableViewCell *cell = [ContactTableViewCell new]; - NSString *recipientId = contactAccount.recipientId; + NSString *recipientId = signalAccount.recipientId; BOOL isCurrentMember = [weakSelf.memberRecipientIds containsObject:recipientId]; BOOL isBlocked = [helper isRecipientIdBlocked:recipientId]; if (isCurrentMember) { @@ -295,29 +295,29 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(cell.accessoryMessage == nil); } - [cell configureWithContactAccount:contactAccount contactsManager:helper.contactsManager]; + [cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager]; return cell; } customRowHeight:[ContactTableViewCell rowHeight] actionBlock:^{ - NSString *recipientId = contactAccount.recipientId; + NSString *recipientId = signalAccount.recipientId; BOOL isCurrentMember = [weakSelf.memberRecipientIds containsObject:recipientId]; if (isCurrentMember) { [weakSelf.groupViewHelper - showRemoveFromGroupAlertForContactAccount:contactAccount - fromViewController:weakSelf - contactsManager:helper.contactsManager - successBlock:^{ - [weakSelf removeContactAccount:contactAccount]; - }]; + showRemoveFromGroupAlertForSignalAccount:signalAccount + fromViewController:weakSelf + contactsManager:helper.contactsManager + successBlock:^{ + [weakSelf removeSignalAccount:signalAccount]; + }]; } else { [weakSelf addRecipientId:recipientId]; } }]]; } } else { - [contactAccountSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ + [signalAccountSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = NSLocalizedString( @"SETTINGS_BLOCK_LIST_NO_CONTACTS", @"A label that indicates the user has no Signal contacts."); @@ -326,9 +326,9 @@ NS_ASSUME_NONNULL_BEGIN cell.textLabel.textAlignment = NSTextAlignmentCenter; return cell; } - actionBlock:nil]]; + actionBlock:nil]]; } - [contents addSection:contactAccountSection]; + [contents addSection:signalAccountSection]; self.tableViewController.contents = contents; } @@ -354,11 +354,11 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)removeContactAccount:(ContactAccount *)contactAccount +- (void)removeSignalAccount:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); - [self.memberRecipientIds removeObject:contactAccount.recipientId]; + [self.memberRecipientIds removeObject:signalAccount.recipientId]; [self updateTableContents]; } diff --git a/Signal/src/ViewControllers/SelectRecipientViewController.h b/Signal/src/ViewControllers/SelectRecipientViewController.h index 5743230fb..519fcda6d 100644 --- a/Signal/src/ViewControllers/SelectRecipientViewController.h +++ b/Signal/src/ViewControllers/SelectRecipientViewController.h @@ -4,7 +4,7 @@ #import -@class ContactAccount; +@class SignalAccount; @protocol SelectRecipientViewControllerDelegate @@ -14,7 +14,7 @@ - (void)phoneNumberWasSelected:(NSString *)phoneNumber; -- (void)contactAccountWasSelected:(ContactAccount *)contactAccount; +- (void)signalAccountWasSelected:(SignalAccount *)signalAccount; - (BOOL)shouldHideLocalNumber; diff --git a/Signal/src/ViewControllers/SelectRecipientViewController.m b/Signal/src/ViewControllers/SelectRecipientViewController.m index 40d565729..83894c85c 100644 --- a/Signal/src/ViewControllers/SelectRecipientViewController.m +++ b/Signal/src/ViewControllers/SelectRecipientViewController.m @@ -3,7 +3,6 @@ // #import "SelectRecipientViewController.h" -#import "ContactAccount.h" #import "ContactTableViewCell.h" #import "ContactsViewHelper.h" #import "CountryCodeViewController.h" @@ -12,6 +11,7 @@ #import "OWSContactsManager.h" #import "OWSTableViewController.h" #import "PhoneNumber.h" +#import "SignalAccount.h" #import "StringUtil.h" #import "UIFont+OWS.h" #import "UIUtil.h" @@ -455,8 +455,8 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien if (![self.delegate shouldHideContacts]) { OWSTableSection *contactsSection = [OWSTableSection new]; contactsSection.headerTitle = [self.delegate contactsSectionTitle]; - NSArray *allRecipientContactAccounts = helper.allRecipientContactAccounts; - if (allRecipientContactAccounts.count == 0) { + NSArray *signalAccounts = helper.signalAccounts; + if (signalAccounts.count == 0) { // No Contacts [contactsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ @@ -473,7 +473,7 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien } else { // Contacts - for (ContactAccount *contactAccount in allRecipientContactAccounts) { + for (SignalAccount *signalAccount in signalAccounts) { [contactsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectRecipientViewController *strongSelf = weakSelf; if (!strongSelf) { @@ -481,19 +481,19 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien } ContactTableViewCell *cell = [ContactTableViewCell new]; - BOOL isBlocked = [helper isRecipientIdBlocked:contactAccount.recipientId]; + BOOL isBlocked = [helper isRecipientIdBlocked:signalAccount.recipientId]; if (isBlocked) { cell.accessoryMessage = NSLocalizedString( @"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); } else { OWSAssert(cell.accessoryMessage == nil); } - [cell configureWithContactAccount:contactAccount contactsManager:helper.contactsManager]; + [cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager]; return cell; } customRowHeight:[ContactTableViewCell rowHeight] actionBlock:^{ - [weakSelf.delegate contactAccountWasSelected:contactAccount]; + [weakSelf.delegate signalAccountWasSelected:signalAccount]; }]]; } } diff --git a/Signal/src/ViewControllers/SelectThreadViewController.m b/Signal/src/ViewControllers/SelectThreadViewController.m index 1f970a807..d9b50820a 100644 --- a/Signal/src/ViewControllers/SelectThreadViewController.m +++ b/Signal/src/ViewControllers/SelectThreadViewController.m @@ -4,7 +4,6 @@ #import "SelectThreadViewController.h" #import "BlockListUIUtils.h" -#import "ContactAccount.h" #import "ContactTableViewCell.h" #import "ContactsViewHelper.h" #import "Environment.h" @@ -12,6 +11,7 @@ #import "OWSContactsManager.h" #import "OWSContactsSearcher.h" #import "OWSTableViewController.h" +#import "SignalAccount.h" #import "ThreadViewHelper.h" #import "UIColor+OWS.h" #import "UIFont+OWS.h" @@ -153,8 +153,8 @@ NS_ASSUME_NONNULL_BEGIN } // Contacts - NSArray *filteredContactAccounts = [self filteredContactAccountsWithSearchText]; - for (ContactAccount *contactAccount in filteredContactAccounts) { + NSArray *filteredSignalAccounts = [self filteredSignalAccountsWithSearchText]; + for (SignalAccount *signalAccount in filteredSignalAccounts) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectThreadViewController *strongSelf = weakSelf; if (!strongSelf) { @@ -162,19 +162,19 @@ NS_ASSUME_NONNULL_BEGIN } ContactTableViewCell *cell = [ContactTableViewCell new]; - BOOL isBlocked = [helper isRecipientIdBlocked:contactAccount.recipientId]; + BOOL isBlocked = [helper isRecipientIdBlocked:signalAccount.recipientId]; if (isBlocked) { cell.accessoryMessage = NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); } else { OWSAssert(cell.accessoryMessage == nil); } - [cell configureWithContactAccount:contactAccount contactsManager:helper.contactsManager]; + [cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager]; return cell; } customRowHeight:[ContactTableViewCell rowHeight] actionBlock:^{ - [weakSelf contactAccountWasSelected:contactAccount]; + [weakSelf signalAccountWasSelected:signalAccount]; }]]; } @@ -195,31 +195,31 @@ NS_ASSUME_NONNULL_BEGIN self.tableViewController.contents = contents; } -- (void)contactAccountWasSelected:(ContactAccount *)contactAccount +- (void)signalAccountWasSelected:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); OWSAssert(self.delegate); ContactsViewHelper *helper = self.contactsViewHelper; - if ([helper isRecipientIdBlocked:contactAccount.recipientId] && ![self.delegate canSelectBlockedContact]) { + if ([helper isRecipientIdBlocked:signalAccount.recipientId] && ![self.delegate canSelectBlockedContact]) { __weak SelectThreadViewController *weakSelf = self; - [BlockListUIUtils showUnblockContactAccountActionSheet:contactAccount - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf contactAccountWasSelected:contactAccount]; - } - }]; + [BlockListUIUtils showUnblockSignalAccountActionSheet:signalAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf signalAccountWasSelected:signalAccount]; + } + }]; return; } __block TSThread *thread = nil; [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [TSContactThread getOrCreateThreadWithContactId:contactAccount.recipientId transaction:transaction]; + thread = [TSContactThread getOrCreateThreadWithContactId:signalAccount.recipientId transaction:transaction]; }]; OWSAssert(thread); @@ -255,8 +255,7 @@ NS_ASSUME_NONNULL_BEGIN return result; } -// TODO: Move this to contacts view helper. -- (NSArray *)filteredContactAccountsWithSearchText +- (NSArray *)filteredSignalAccountsWithSearchText { // We don't want to show a 1:1 thread with Alice and Alice's contact, // so we de-duplicate by recipientId. @@ -272,10 +271,10 @@ NS_ASSUME_NONNULL_BEGIN NSString *searchString = [self.searchBar text]; ContactsViewHelper *helper = self.contactsViewHelper; - return [[helper contactAccountsMatchingSearchString:searchString] - filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(ContactAccount *contactAccount, + return [[helper signalAccountsMatchingSearchString:searchString] + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SignalAccount *signalAccount, NSDictionary *_Nullable bindings) { - return ![contactIdsToIgnore containsObject:contactAccount.recipientId]; + return ![contactIdsToIgnore containsObject:signalAccount.recipientId]; }]]; } diff --git a/Signal/src/ViewControllers/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ShowGroupMembersViewController.m index 4cfe563e9..ed4986a97 100644 --- a/Signal/src/ViewControllers/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ShowGroupMembersViewController.m @@ -4,11 +4,11 @@ #import "ShowGroupMembersViewController.h" #import "BlockListUIUtils.h" -#import "ContactAccount.h" #import "ContactTableViewCell.h" #import "ContactsViewHelper.h" #import "Environment.h" #import "OWSContactsManager.h" +#import "SignalAccount.h" #import "SignalsViewController.h" #import "UIUtil.h" #import @@ -108,15 +108,15 @@ NS_ASSUME_NONNULL_BEGIN } ContactTableViewCell *cell = [ContactTableViewCell new]; - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; BOOL isBlocked = [helper isRecipientIdBlocked:recipientId]; if (isBlocked) { cell.accessoryMessage = NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); } - if (contactAccount) { - [cell configureWithContactAccount:contactAccount contactsManager:helper.contactsManager]; + if (signalAccount) { + [cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager]; } else { [cell configureWithRecipientId:recipientId contactsManager:helper.contactsManager]; } @@ -138,7 +138,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(recipientId.length > 0); ContactsViewHelper *helper = self.contactsViewHelper; - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; @@ -152,8 +152,8 @@ NS_ASSUME_NONNULL_BEGIN }]]; BOOL isBlocked; - if (contactAccount) { - isBlocked = [helper isRecipientIdBlocked:contactAccount.recipientId]; + if (signalAccount) { + isBlocked = [helper isRecipientIdBlocked:signalAccount.recipientId]; if (isBlocked) { [actionSheetController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", @@ -161,11 +161,11 @@ NS_ASSUME_NONNULL_BEGIN style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) { [BlockListUIUtils - showUnblockContactAccountActionSheet:contactAccount - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:nil]; + showUnblockSignalAccountActionSheet:signalAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:nil]; }]]; } else { [actionSheetController @@ -174,11 +174,11 @@ NS_ASSUME_NONNULL_BEGIN style:UIAlertActionStyleDestructive handler:^(UIAlertAction *_Nonnull action) { [BlockListUIUtils - showBlockContactAccountActionSheet:contactAccount - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:nil]; + showBlockSignalAccountActionSheet:signalAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:nil]; }]]; } } else { @@ -242,14 +242,14 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(recipientId.length > 0); ContactsViewHelper *helper = self.contactsViewHelper; - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; - if (contactAccount) { + if (signalAccount) { ABPersonViewController *view = [[ABPersonViewController alloc] init]; ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil); // Assume person is already defined. - view.displayedPerson = ABAddressBookGetPersonWithRecordID(addressBookRef, contactAccount.contact.recordID); + view.displayedPerson = ABAddressBookGetPersonWithRecordID(addressBookRef, signalAccount.contact.recordID); view.allowsActions = NO; view.allowsEditing = YES; diff --git a/Signal/src/ViewControllers/SignalAccount.h b/Signal/src/ViewControllers/SignalAccount.h new file mode 100644 index 000000000..cebae981c --- /dev/null +++ b/Signal/src/ViewControllers/SignalAccount.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +NS_ASSUME_NONNULL_BEGIN + +@class Contact; +@class SignalRecipient; + +// This class represents a single valid Signal account. +// +// * Contacts with multiple signal accounts will correspond to +// multiple instances of SignalAccount. +// * For non-contacts, the contact property will be nil. +// +// New instances of SignalAccount for active accounts are +// created every time we do a contacts intersection (e.g. +// in response to a +@interface SignalAccount : NSObject + +@property (nonatomic) SignalRecipient *signalRecipient; + +// An E164 value identifying the signal account. +@property (nonatomic, readonly) NSString *recipientId; + +// This property is optional and will not be set for +// non-contact account. +@property (nonatomic, nullable) Contact *contact; + +@property (nonatomic) BOOL isMultipleAccountContact; + +// For contacts with more than one signal account, +// this is a label for the account. +@property (nonatomic) NSString *multipleAccountLabel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/SignalAccount.m b/Signal/src/ViewControllers/SignalAccount.m new file mode 100644 index 000000000..fdcc78eca --- /dev/null +++ b/Signal/src/ViewControllers/SignalAccount.m @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "SignalAccount.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@implementation SignalAccount + +- (NSString *)recipientId +{ + OWSAssert(self.signalRecipient); + + return self.signalRecipient.uniqueId; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/UpdateGroupViewController.m b/Signal/src/ViewControllers/UpdateGroupViewController.m index 29ccff350..241b5cfd8 100644 --- a/Signal/src/ViewControllers/UpdateGroupViewController.m +++ b/Signal/src/ViewControllers/UpdateGroupViewController.m @@ -5,7 +5,6 @@ #import "UpdateGroupViewController.h" #import "AddToGroupViewController.h" #import "BlockListUIUtils.h" -#import "ContactAccount.h" #import "ContactTableViewCell.h" #import "ContactsViewHelper.h" #import "Environment.h" @@ -14,6 +13,7 @@ #import "OWSContactsManager.h" #import "OWSTableViewController.h" #import "SecurityUtils.h" +#import "SignalAccount.h" #import "SignalKeyingStorage.h" #import "TSOutgoingMessage.h" #import "UIUtil.h" @@ -245,7 +245,7 @@ NS_ASSUME_NONNULL_BEGIN } ContactTableViewCell *cell = [ContactTableViewCell new]; - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; BOOL isPreviousMember = [strongSelf.previousMemberRecipientIds containsObject:recipientId]; BOOL isBlocked = [helper isRecipientIdBlocked:recipientId]; if (isPreviousMember) { @@ -264,8 +264,8 @@ NS_ASSUME_NONNULL_BEGIN @"EDIT_GROUP_NEW_MEMBER_LABEL", @"An indicator that a user is a new member of the group."); } - if (contactAccount) { - [cell configureWithContactAccount:contactAccount contactsManager:helper.contactsManager]; + if (signalAccount) { + [cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager]; } else { [cell configureWithRecipientId:recipientId contactsManager:helper.contactsManager]; } @@ -274,26 +274,26 @@ NS_ASSUME_NONNULL_BEGIN } customRowHeight:[ContactTableViewCell rowHeight] actionBlock:^{ - ContactAccount *contactAccount = [helper contactAccountForRecipientId:recipientId]; + SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; BOOL isPreviousMember = [weakSelf.previousMemberRecipientIds containsObject:recipientId]; BOOL isBlocked = [helper isRecipientIdBlocked:recipientId]; if (isPreviousMember) { if (isBlocked) { - if (contactAccount) { - [weakSelf showUnblockAlertForContactAccount:contactAccount]; + if (signalAccount) { + [weakSelf showUnblockAlertForSignalAccount:signalAccount]; } else { [weakSelf showUnblockAlertForRecipientId:recipientId]; } } } else { - if (contactAccount) { + if (signalAccount) { [weakSelf.groupViewHelper - showRemoveFromGroupAlertForContactAccount:contactAccount - fromViewController:weakSelf - contactsManager:helper.contactsManager - successBlock:^{ - [weakSelf removeContactAccount:contactAccount]; - }]; + showRemoveFromGroupAlertForSignalAccount:signalAccount + fromViewController:weakSelf + contactsManager:helper.contactsManager + successBlock:^{ + [weakSelf removeSignalAccount:signalAccount]; + }]; } else { [weakSelf.groupViewHelper showRemoveFromGroupAlertForRecipientId:recipientId @@ -311,21 +311,21 @@ NS_ASSUME_NONNULL_BEGIN self.tableViewController.contents = contents; } -- (void)showUnblockAlertForContactAccount:(ContactAccount *)contactAccount +- (void)showUnblockAlertForSignalAccount:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); __weak UpdateGroupViewController *weakSelf = self; ContactsViewHelper *helper = self.contactsViewHelper; - [BlockListUIUtils showUnblockContactAccountActionSheet:contactAccount - fromViewController:self - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf updateTableContents]; - } - }]; + [BlockListUIUtils showUnblockSignalAccountActionSheet:signalAccount + fromViewController:self + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf updateTableContents]; + } + }]; } - (void)showUnblockAlertForRecipientId:(NSString *)recipientId @@ -345,11 +345,11 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)removeContactAccount:(ContactAccount *)contactAccount +- (void)removeSignalAccount:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); - [self.memberRecipientIds removeObject:contactAccount.recipientId]; + [self.memberRecipientIds removeObject:signalAccount.recipientId]; [self updateTableContents]; } diff --git a/Signal/src/call/CallService.swift b/Signal/src/call/CallService.swift index 06281640d..bf25f7a36 100644 --- a/Signal/src/call/CallService.swift +++ b/Signal/src/call/CallService.swift @@ -498,7 +498,7 @@ protocol CallServiceObserver: class { // For contacts not stored in our system contacts, we assume they are an unknown caller, and we force // a TURN connection, so as not to reveal any connectivity information (IP/port) to the caller. - let unknownCaller = self.contactsManager.contact(forPhoneIdentifier: thread.contactIdentifier()) == nil + let unknownCaller = self.contactsManager.signalAccount(forRecipientId: thread.contactIdentifier()) == nil let useTurnOnly = unknownCaller || Environment.getCurrent().preferences.doCallsHideIPAddress() diff --git a/Signal/src/contact/GroupContactsResult.h b/Signal/src/contact/GroupContactsResult.h deleted file mode 100644 index d1f6ecc3e..000000000 --- a/Signal/src/contact/GroupContactsResult.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// GroupContactsResult.h -// Signal -// -// Created by Frederic Jacobs on 17/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import - -@class Contact; - -@interface GroupContactsResult : NSObject - -- (instancetype)initWithMembersId:(NSArray *)memberIdentifiers without:(NSArray *)removeIds; - -- (NSUInteger)numberOfMembers; - -- (BOOL)isContactAtIndexPath:(NSIndexPath *)indexPath; - -- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath; -- (NSString *)identifierForIndexPath:(NSIndexPath *)indexPath; - -@end diff --git a/Signal/src/contact/GroupContactsResult.m b/Signal/src/contact/GroupContactsResult.m deleted file mode 100644 index 4798cab53..000000000 --- a/Signal/src/contact/GroupContactsResult.m +++ /dev/null @@ -1,133 +0,0 @@ -// -// GroupContactsResult.m -// Signal -// -// Created by Frederic Jacobs on 17/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "GroupContactsResult.h" - -#import -#import "Contact.h" -#import "OWSContactsManager.h" -#import "Environment.h" -#import "SignalKeyingStorage.h" - -@interface GroupContactsResult () - -@property NSMutableArray *unknownNumbers; -@property NSMutableArray *knownNumbers; - -@property NSMutableDictionary *associatedContactDict; - -@end - -@implementation GroupContactsResult - -- (instancetype)initWithMembersId:(NSArray *)memberIdentifiers without:(NSArray *)removeIds { - self = [super init]; - - OWSContactsManager *manager = [Environment.getCurrent contactsManager]; - - NSMutableSet *remainingNumbers = [NSMutableSet setWithArray:memberIdentifiers]; - - NSMutableArray *knownNumbers = [NSMutableArray array]; - NSMutableArray *associatedContacts = [NSMutableArray array]; - - for (NSString *identifier in memberIdentifiers) { - if ([identifier isEqualToString:[TSAccountManager localNumber]]) { - // remove local number - - [remainingNumbers removeObject:identifier]; - continue; - } - - if (removeIds && [removeIds containsObject:identifier]) { - // Remove ids - [remainingNumbers removeObject:identifier]; - continue; - } - - PhoneNumber *number = [PhoneNumber phoneNumberFromE164:identifier]; - - if (!number) { - continue; - } - - Contact *contact = [manager latestContactForPhoneNumber:number]; - - if (!contact) { - continue; - } - - [knownNumbers addObject:identifier]; - [associatedContacts addObject:contact]; - - [remainingNumbers removeObject:identifier]; - } - - _unknownNumbers = [NSMutableArray arrayWithArray:[remainingNumbers allObjects]]; - [_unknownNumbers sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { - return [obj1 compare:obj2 options:0]; - }]; - - - // Populate mapping dictionary. - _associatedContactDict = [NSMutableDictionary dictionary]; - for (NSUInteger i = 0; i < [knownNumbers count]; i++) { - NSString *identifier = [knownNumbers objectAtIndex:i]; - Contact *contact = [associatedContacts objectAtIndex:i]; - - [_associatedContactDict setObject:contact forKey:identifier]; - } - - // Known Numbers - _knownNumbers = [NSMutableArray arrayWithArray:knownNumbers]; - [_knownNumbers sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { - Contact *contact1 = [_associatedContactDict objectForKey:obj1]; - Contact *contact2 = [_associatedContactDict objectForKey:obj2]; - - return [[manager class] contactComparator](contact1, contact2); - }]; - - return self; -} - -- (NSUInteger)numberOfMembers { - return [self.knownNumbers count] + [self.unknownNumbers count]; -} - -- (BOOL)isContactAtIndexPath:(NSIndexPath *)indexPath { - if ((NSUInteger)indexPath.row < [self.unknownNumbers count]) { - return NO; - } else { - return YES; - } -} - -- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath { - if ([self isContactAtIndexPath:indexPath]) { - NSString *identifier = [_knownNumbers objectAtIndex:[self knownNumbersIndexForIndexPath:indexPath]]; - return [_associatedContactDict objectForKey:identifier]; - } else { - NSAssert(NO, @"Trying to retrieve contact from array at an index that is not a contact."); - return nil; - } -} - -- (NSString *)identifierForIndexPath:(NSIndexPath *)indexPath { - if ([self isContactAtIndexPath:indexPath]) { - return [_knownNumbers objectAtIndex:[self knownNumbersIndexForIndexPath:indexPath]]; - } else { - return [_unknownNumbers objectAtIndex:(NSUInteger)indexPath.row]; - } -} - -- (NSUInteger)knownNumbersIndexForIndexPath:(NSIndexPath *)indexPath { - NSAssert(((NSUInteger)indexPath.row >= [_unknownNumbers count]), @"Wrong index for known number"); - - return (NSUInteger)indexPath.row - [_unknownNumbers count]; -} - -@end diff --git a/Signal/src/contact/OWSContactsManager.h b/Signal/src/contact/OWSContactsManager.h index f24c3dfcf..e8eff9494 100644 --- a/Signal/src/contact/OWSContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -12,38 +12,46 @@ NS_ASSUME_NONNULL_BEGIN +extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; +// TODO: Remove this. +// TODO: Remove observableContactsController. extern NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification; @class UIFont; -@class ContactAccount; +@class SignalAccount; /** * Get latest Signal contacts, and be notified when they change. */ @interface OWSContactsManager : NSObject -@property (nullable, strong) CNContactStore *contactStore; -@property (nonnull, readonly, strong) NSCache *avatarCache; +@property (nonnull, readonly) NSCache *avatarCache; + +// signalAccountMap and signalAccounts hold the same data. +// signalAccountMap is for lookup. signalAccounts contains the accounts +// ordered by display order. +@property (atomic, readonly) NSDictionary *signalAccountMap; +@property (atomic, readonly) NSArray *signalAccounts; - (nonnull ObservableValue *)getObservableContacts; -- (nullable Contact *)latestContactForPhoneNumber:(nullable PhoneNumber *)phoneNumber; -- (nullable Contact *)contactForPhoneIdentifier:(nullable NSString *)identifier; +- (nullable SignalAccount *)signalAccountForRecipientId:(nullable NSString *)recipientId; + - (Contact *)getOrBuildContactForPhoneIdentifier:(NSString *)identifier; - (void)verifyABPermission; -- (NSArray *)allContacts; +// TODO: Remove this method. - (NSArray *)signalContacts; - (void)doAfterEnvironmentInitSetup; - (NSString *)displayNameForPhoneIdentifier:(nullable NSString *)identifier; - (NSString *)displayNameForContact:(Contact *)contact; -- (NSString *_Nonnull)displayNameForContactAccount:(ContactAccount *)contactAccount; +- (NSString *_Nonnull)displayNameForSignalAccount:(SignalAccount *)signalAccount; - (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier; -- (NSAttributedString *_Nonnull)formattedDisplayNameForContactAccount:(ContactAccount *)contactAccount - font:(UIFont *_Nonnull)font; +- (NSAttributedString *_Nonnull)formattedDisplayNameForSignalAccount:(SignalAccount *)signalAccount + font:(UIFont *_Nonnull)font; - (NSAttributedString *)formattedFullNameForContact:(Contact *)contact font:(UIFont *)font; - (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font; diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 19dfa27f9..7393fc84e 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -3,8 +3,8 @@ // #import "OWSContactsManager.h" -#import "ContactAccount.h" #import "Environment.h" +#import "SignalAccount.h" #import "Util.h" #import #import @@ -13,25 +13,30 @@ typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL *); +NSString *const OWSContactsManagerSignalAccountsDidChangeNotification = + @"OWSContactsManagerSignalAccountsDidChangeNotification"; NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification = @"OWSContactsManagerSignalRecipientsDidChangeNotification"; @interface OWSContactsManager () +@property (atomic, nullable) CNContactStore *contactStore; @property (atomic) id addressBookReference; @property (atomic) TOCFuture *futureAddressBook; @property (atomic) ObservableValueController *observableContactsController; @property (atomic) TOCCancelTokenSource *life; -@property (atomic) NSDictionary *latestContactsById; -@property (atomic) NSDictionary *contactMap; @property (nonatomic) BOOL isContactsUpdateInFlight; +// This reflects the contents of the device phone book and includes +// contacts that do not correspond to any signal account. +@property (atomic) NSArray *allContacts; +@property (atomic) NSDictionary *allContactsMap; +@property (atomic) NSArray *signalAccounts; +@property (atomic) NSDictionary *signalAccountMap; @end @implementation OWSContactsManager -@synthesize latestContactsById = _latestContactsById; - - (void)dealloc { [_life cancel]; } @@ -44,49 +49,16 @@ NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification = _life = [TOCCancelTokenSource new]; _observableContactsController = [ObservableValueController observableValueControllerWithInitialValue:nil]; - _latestContactsById = @{}; _avatarCache = [NSCache new]; + _allContacts = @[]; + _signalAccountMap = @{}; + _signalAccounts = @[]; OWSSingletonAssert(); return self; } -- (NSDictionary *)latestContactsById -{ - @synchronized(self) - { - return _latestContactsById; - } -} - -- (void)setLatestContactsById:(NSDictionary *)latestContactsById -{ - @synchronized(self) - { - _latestContactsById = [latestContactsById copy]; - - NSMutableDictionary *contactMap = [NSMutableDictionary new]; - for (Contact *contact in _latestContactsById.allValues) { - // The allContacts method seems to protect against non-contact instances - // in latestContactsById, so I've done the same here. I'm not sure if - // this is a real issue. - OWSAssert([contact isKindOfClass:[Contact class]]); - if (![contact isKindOfClass:[Contact class]]) { - continue; - } - - for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { - NSString *phoneNumberE164 = phoneNumber.toE164; - if (phoneNumberE164.length > 0) { - contactMap[phoneNumberE164] = contact; - } - } - } - self.contactMap = contactMap; - } -} - - (void)doAfterEnvironmentInitSetup { if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(9, 0) && !self.contactStore) { @@ -106,7 +78,7 @@ NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification = __weak OWSContactsManager *weakSelf = self; [self.observableContactsController watchLatestValueOnArbitraryThread:^(NSArray *latestContacts) { @synchronized(self) { - [weakSelf setupLatestContacts:latestContacts]; + [weakSelf updateSignalAccounts:latestContacts]; } } untilCancelled:_life.token]; @@ -227,10 +199,120 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in [self.observableContactsController updateValue:[self getContactsFromAddressBook:addressBookRef]]; } -- (void)setupLatestContacts:(NSArray *)contacts { - if (contacts) { - self.latestContactsById = [OWSContactsManager keyContactsById:contacts]; +- (void)updateSignalAccounts:(NSArray *)contacts +{ + // This will happen off of the main thread. + + NSMutableDictionary *signalAccountMap = [NSMutableDictionary new]; + NSMutableArray *signalAccounts = [NSMutableArray new]; + NSMutableDictionary *allContactsMap = [NSMutableDictionary new]; + for (Contact *contact in contacts) { + for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { + NSString *phoneNumberE164 = phoneNumber.toE164; + if (phoneNumberE164.length > 0) { + allContactsMap[phoneNumberE164] = contact; + } + } + + NSArray *signalRecipients = contact.signalRecipients; + for (SignalRecipient *signalRecipient in contact.signalRecipients) { + + if (signalRecipients.count == 1) { + SignalAccount *signalAccount = [SignalAccount new]; + signalAccount.signalRecipient = signalRecipient; + signalAccount.contact = contact; + signalAccountMap[signalAccount.recipientId] = signalAccount; + [signalAccounts addObject:signalAccount]; + } else if (contact.textSecureIdentifiers.count > 1) { + for (NSString *recipientId in + [contact.textSecureIdentifiers sortedArrayUsingSelector:@selector(compare:)]) { + SignalAccount *signalAccount = [SignalAccount new]; + signalAccount.signalRecipient = signalRecipient; + signalAccount.contact = contact; + signalAccount.isMultipleAccountContact = YES; + signalAccount.multipleAccountLabel = + [[self class] accountLabelForContact:contact recipientId:recipientId]; + signalAccountMap[signalAccount.recipientId] = signalAccount; + [signalAccounts addObject:signalAccount]; + } + } + } } + + dispatch_async(dispatch_get_main_queue(), ^{ + self.allContacts = contacts; + self.signalAccountMap = [signalAccountMap copy]; + self.signalAccounts = [signalAccounts copy]; + self.allContactsMap = [allContactsMap copy]; + + [[NSNotificationCenter defaultCenter] postNotificationName:OWSContactsManagerSignalAccountsDidChangeNotification + object:nil]; + }); +} + ++ (NSString *)accountLabelForContact:(Contact *)contact recipientId:(NSString *)recipientId +{ + OWSAssert(contact); + OWSAssert(recipientId.length > 0); + OWSAssert([contact.textSecureIdentifiers containsObject:recipientId]); + + if (contact.textSecureIdentifiers.count <= 1) { + return nil; + } + + // 1. Find the phone number type of this account. + OWSPhoneNumberType phoneNumberType = [contact phoneNumberTypeForPhoneNumber:recipientId]; + + NSString *phoneNumberLabel; + switch (phoneNumberType) { + case OWSPhoneNumberTypeMobile: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_MOBILE", @"Label for 'Mobile' phone numbers."); + break; + case OWSPhoneNumberTypeIPhone: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_IPHONE", @"Label for 'IPhone' phone numbers."); + break; + case OWSPhoneNumberTypeMain: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_MAIN", @"Label for 'Main' phone numbers."); + break; + case OWSPhoneNumberTypeHomeFAX: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_HOME_FAX", @"Label for 'HomeFAX' phone numbers."); + break; + case OWSPhoneNumberTypeWorkFAX: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_WORK_FAX", @"Label for 'Work FAX' phone numbers."); + break; + case OWSPhoneNumberTypeOtherFAX: + phoneNumberLabel + = NSLocalizedString(@"PHONE_NUMBER_TYPE_OTHER_FAX", @"Label for 'Other FAX' phone numbers."); + break; + case OWSPhoneNumberTypePager: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_PAGER", @"Label for 'Pager' phone numbers."); + break; + case OWSPhoneNumberTypeUnknown: + phoneNumberLabel = NSLocalizedString(@"PHONE_NUMBER_TYPE_UNKNOWN", @"Label for 'Unknown' phone numbers."); + break; + } + + // 2. Find all phone numbers for this contact of the same type. + NSMutableArray *phoneNumbersOfTheSameType = [NSMutableArray new]; + for (NSString *textSecureIdentifier in contact.textSecureIdentifiers) { + if (phoneNumberType == [contact phoneNumberTypeForPhoneNumber:textSecureIdentifier]) { + [phoneNumbersOfTheSameType addObject:textSecureIdentifier]; + } + } + + OWSAssert([phoneNumbersOfTheSameType containsObject:recipientId]); + if (phoneNumbersOfTheSameType.count > 0) { + NSUInteger index = + [[phoneNumbersOfTheSameType sortedArrayUsingSelector:@selector(compare:)] indexOfObject:recipientId]; + phoneNumberLabel = + [NSString stringWithFormat:NSLocalizedString(@"PHONE_NUMBER_TYPE_AND_INDEX_FORMAT", + @"Format for phone number label with an index. Embeds {{Phone number label " + @"(e.g. 'home')}} and {{index, e.g. 2}}."), + phoneNumberLabel, + (int)index]; + } + + return phoneNumberLabel; } + (void)blockingContactDialog { @@ -394,28 +476,6 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in andContactID:recordID]; } -- (Contact * _Nullable)latestContactForPhoneNumber:(PhoneNumber *)phoneNumber { - NSArray *allContacts = [self allContacts]; - - ContactSearchBlock searchBlock = ^BOOL(Contact *contact, NSUInteger idx, BOOL *stop) { - for (PhoneNumber *number in contact.parsedPhoneNumbers) { - if ([self phoneNumber:number matchesNumber:phoneNumber]) { - *stop = YES; - return YES; - } - } - return NO; - }; - - NSUInteger contactIndex = [allContacts indexOfObjectPassingTest:searchBlock]; - - if (contactIndex != NSNotFound) { - return allContacts[contactIndex]; - } else { - return nil; - } -} - - (BOOL)phoneNumber:(PhoneNumber *)phoneNumber1 matchesNumber:(PhoneNumber *)phoneNumber2 { return [phoneNumber1.toE164 isEqualToString:phoneNumber2.toE164]; } @@ -459,25 +519,6 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } } -+ (NSDictionary *)keyContactsById:(NSArray *)contacts { - return [contacts keyedBy:^id(Contact *contact) { - return @((int)contact.recordID); - }]; -} - -- (NSArray *_Nonnull)allContacts { - NSMutableArray *allContacts = [NSMutableArray array]; - - for (NSString *key in self.latestContactsById.allKeys) { - Contact *contact = [self.latestContactsById objectForKey:key]; - - if ([contact isKindOfClass:[Contact class]]) { - [allContacts addObject:contact]; - } - } - return allContacts; -} - #pragma mark - Whisper User Management - (NSArray *)getSignalUsersFromContactsArray:(NSArray *)contacts { @@ -511,10 +552,12 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in if (!identifier) { return self.unknownContactName; } - Contact *contact = [self contactForPhoneIdentifier:identifier]; - - NSString *displayName = (contact.fullName.length > 0) ? contact.fullName : identifier; - + + // TODO: There's some overlap here with displayNameForSignalAccount. + SignalAccount *signalAccount = [self signalAccountForRecipientId:identifier]; + + NSString *displayName = (signalAccount.contact.fullName.length > 0) ? signalAccount.contact.fullName : identifier; + return displayName; } @@ -527,36 +570,36 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in return displayName; } -- (NSString *_Nonnull)displayNameForContactAccount:(ContactAccount *)contactAccount +- (NSString *_Nonnull)displayNameForSignalAccount:(SignalAccount *)signalAccount { - OWSAssert(contactAccount); + OWSAssert(signalAccount); - NSString *baseName = (contactAccount.contact ? [self displayNameForContact:contactAccount.contact] - : [self displayNameForPhoneIdentifier:contactAccount.recipientId]); - OWSAssert(contactAccount.isMultipleAccountContact == (contactAccount.multipleAccountLabel != nil)); - if (contactAccount.multipleAccountLabel) { - return [NSString stringWithFormat:@"%@ (%@)", baseName, contactAccount.multipleAccountLabel]; + NSString *baseName = (signalAccount.contact ? [self displayNameForContact:signalAccount.contact] + : [self displayNameForPhoneIdentifier:signalAccount.recipientId]); + OWSAssert(signalAccount.isMultipleAccountContact == (signalAccount.multipleAccountLabel != nil)); + if (signalAccount.multipleAccountLabel) { + return [NSString stringWithFormat:@"%@ (%@)", baseName, signalAccount.multipleAccountLabel]; } else { return baseName; } } -- (NSAttributedString *_Nonnull)formattedDisplayNameForContactAccount:(ContactAccount *)contactAccount - font:(UIFont *_Nonnull)font +- (NSAttributedString *_Nonnull)formattedDisplayNameForSignalAccount:(SignalAccount *)signalAccount + font:(UIFont *_Nonnull)font { - OWSAssert(contactAccount); + OWSAssert(signalAccount); OWSAssert(font); - NSAttributedString *baseName = [self formattedFullNameForContact:contactAccount.contact font:font]; - OWSAssert(contactAccount.isMultipleAccountContact == (contactAccount.multipleAccountLabel != nil)); - if (contactAccount.multipleAccountLabel) { + NSAttributedString *baseName = [self formattedFullNameForContact:signalAccount.contact font:font]; + OWSAssert(signalAccount.isMultipleAccountContact == (signalAccount.multipleAccountLabel != nil)); + if (signalAccount.multipleAccountLabel) { NSMutableAttributedString *result = [NSMutableAttributedString new]; [result appendAttributedString:baseName]; [result appendAttributedString:[[NSAttributedString alloc] initWithString:@" (" attributes:@{ NSFontAttributeName : font, }]]; - [result appendAttributedString:[[NSAttributedString alloc] initWithString:contactAccount.multipleAccountLabel]]; + [result appendAttributedString:[[NSAttributedString alloc] initWithString:signalAccount.multipleAccountLabel]]; [result appendAttributedString:[[NSAttributedString alloc] initWithString:@")" attributes:@{ NSFontAttributeName : font, @@ -627,16 +670,16 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in attributes:normalFontAttributes]; } -- (Contact * _Nullable)contactForPhoneIdentifier:(NSString * _Nullable)identifier { - if (!identifier) { - return nil; - } - return self.contactMap[identifier]; +- (nullable SignalAccount *)signalAccountForRecipientId:(nullable NSString *)recipientId +{ + OWSAssert(recipientId.length > 0); + + return self.signalAccountMap[recipientId]; } - (Contact *)getOrBuildContactForPhoneIdentifier:(NSString *)identifier { - Contact *savedContact = [self contactForPhoneIdentifier:identifier]; + Contact *savedContact = self.allContactsMap[identifier]; if (savedContact) { return savedContact; } else { @@ -649,9 +692,8 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } } - - (UIImage * _Nullable)imageForPhoneIdentifier:(NSString * _Nullable)identifier { - Contact *contact = [self contactForPhoneIdentifier:identifier]; + Contact *contact = self.allContactsMap[identifier]; return contact.image; } diff --git a/Signal/src/util/ThreadUtil.m b/Signal/src/util/ThreadUtil.m index c2a5de5b4..473ab5f60 100644 --- a/Signal/src/util/ThreadUtil.m +++ b/Signal/src/util/ThreadUtil.m @@ -89,8 +89,8 @@ NS_ASSUME_NONNULL_BEGIN return; } - Contact *contact = [contactsManager contactForPhoneIdentifier:contactThread.contactIdentifier]; - if (contact) { + SignalAccount *signalAccount = [contactsManager signalAccountForRecipientId:contactThread.contactIdentifier]; + if (signalAccount) { // Only create block offers for non-contacts. return; } diff --git a/Signal/src/views/ContactTableViewCell.h b/Signal/src/views/ContactTableViewCell.h index 5f260679a..e23aaab1b 100644 --- a/Signal/src/views/ContactTableViewCell.h +++ b/Signal/src/views/ContactTableViewCell.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const kContactsTable_CellReuseIdentifier; @class OWSContactsManager; -@class ContactAccount; +@class SignalAccount; @class TSThread; @interface ContactTableViewCell : UITableViewCell @@ -27,11 +27,10 @@ extern NSString *const kContactsTable_CellReuseIdentifier; + (CGFloat)rowHeight; -// TODO: Remove this method once "new 1:1 conversation" view is converted to use ContactAccounts. +// TODO: Remove this method once "new 1:1 conversation" view is converted to use SignalAccounts. - (void)configureWithContact:(Contact *)contact contactsManager:(OWSContactsManager *)contactsManager; -- (void)configureWithContactAccount:(ContactAccount *)contactAccount - contactsManager:(OWSContactsManager *)contactsManager; +- (void)configureWithSignalAccount:(SignalAccount *)signalAccount contactsManager:(OWSContactsManager *)contactsManager; - (void)configureWithRecipientId:(NSString *)recipientId contactsManager:(OWSContactsManager *)contactsManager; diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index 6cd18cdc2..65e69df7c 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -3,10 +3,10 @@ // #import "ContactTableViewCell.h" -#import "ContactAccount.h" #import "Environment.h" #import "OWSContactAvatarBuilder.h" #import "OWSContactsManager.h" +#import "SignalAccount.h" #import "UIFont+OWS.h" #import "UIUtil.h" #import "UIView+OWS.h" @@ -90,13 +90,12 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI contactsManager:contactsManager]; } -- (void)configureWithContactAccount:(ContactAccount *)contactAccount - contactsManager:(OWSContactsManager *)contactsManager +- (void)configureWithSignalAccount:(SignalAccount *)signalAccount contactsManager:(OWSContactsManager *)contactsManager { - [self configureWithRecipientId:contactAccount.recipientId - avatarName:contactAccount.contact.fullName - displayName:[contactsManager formattedDisplayNameForContactAccount:contactAccount - font:self.nameLabel.font] + [self configureWithRecipientId:signalAccount.recipientId + avatarName:signalAccount.contact.fullName + displayName:[contactsManager formattedDisplayNameForSignalAccount:signalAccount + font:self.nameLabel.font] contactsManager:contactsManager]; }