From e36b5a46029f9c37b725ad011d410290c30e1808 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 18 Apr 2017 16:08:01 -0400 Subject: [PATCH] Improve group members view. // FREEBIE --- .../AddToBlockListViewController.m | 2 - .../ViewControllers/MessagesViewController.h | 4 +- .../ViewControllers/MessagesViewController.m | 22 +- .../ShowGroupMembersViewController.m | 284 ++++++++++++++++-- .../ViewControllers/SignalsViewController.h | 4 +- .../ViewControllers/SignalsViewController.m | 23 +- Signal/src/contact/OWSContactsManager.h | 1 + Signal/src/contact/OWSContactsManager.m | 13 +- Signal/src/environment/Environment.h | 1 + Signal/src/environment/Environment.m | 17 +- Signal/src/views/ContactTableViewCell.h | 4 + Signal/src/views/ContactTableViewCell.m | 32 +- .../translations/en.lproj/Localizable.strings | 9 + 13 files changed, 357 insertions(+), 59 deletions(-) diff --git a/Signal/src/ViewControllers/AddToBlockListViewController.m b/Signal/src/ViewControllers/AddToBlockListViewController.m index 54b56e766..370ad7260 100644 --- a/Signal/src/ViewControllers/AddToBlockListViewController.m +++ b/Signal/src/ViewControllers/AddToBlockListViewController.m @@ -22,8 +22,6 @@ NS_ASSUME_NONNULL_BEGIN NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockListViewControllerCellIdentifier"; -NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseIdentifier"; - #pragma mark - @interface AddToBlockListViewController () +#import NS_ASSUME_NONNULL_BEGIN @@ -20,6 +23,9 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" @property TSGroupThread *thread; @property (nonatomic, readonly) OWSContactsManager *_Nonnull contactsManager; +@property (nonatomic, readonly) OWSBlockingManager *blockingManager; +@property (nonatomic, readonly) NSArray *blockedPhoneNumbers; + @end @implementation ShowGroupMembersViewController @@ -31,7 +37,7 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" return self; } - _contactsManager = [Environment getCurrent].contactsManager; + [self commonInit]; return self; } @@ -43,11 +49,43 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" return self; } - _contactsManager = [Environment getCurrent].contactsManager; + [self commonInit]; return self; } + +- (void)commonInit +{ + _blockingManager = [OWSBlockingManager sharedManager]; + _blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; + _contactsManager = [Environment getCurrent].contactsManager; + + [self addNotificationListeners]; +} + +- (void)addNotificationListeners +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(blockedPhoneNumbersDidChange:) + name:kNSNotificationName_BlockedPhoneNumbersDidChange + object:nil]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)blockedPhoneNumbersDidChange:(id)notification +{ + dispatch_async(dispatch_get_main_queue(), ^{ + _blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; + + [self.tableView reloadData]; + }); +} + - (void)configWithThread:(TSGroupThread *)gThread { _thread = gThread; } @@ -62,11 +100,15 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" self.groupContacts = [[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil]; - + __weak ShowGroupMembersViewController *weakSelf = self; [self.contactsManager.getObservableContacts watchLatestValue:^(id latestValue) { - self.groupContacts = - [[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil]; - [self.tableView reloadData]; + ShowGroupMembersViewController *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + strongSelf.groupContacts = + [[GroupContactsResult alloc] initWithMembersId:strongSelf.thread.groupModel.groupMemberIds without:nil]; + [strongSelf.tableView reloadData]; } onThread:[NSThread mainThread] untilCancelled:nil]; @@ -76,6 +118,8 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" - (void)initializeTableView { self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + [self.tableView registerClass:[ContactTableViewCell class] + forCellReuseIdentifier:kContactsTable_CellReuseIdentifier]; } #pragma mark - Actions @@ -90,44 +134,176 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" return (NSInteger)[self.groupContacts numberOfMembers] + 1; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchCell"]; +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ - if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:indexPath.row == 0 ? @"HeaderCell" : @"GroupSearchCell"]; - } - if (indexPath.row > 0) { - NSIndexPath *relativeIndexPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]; - if ([self.groupContacts isContactAtIndexPath:relativeIndexPath]) { - Contact *contact = [self contactForIndexPath:relativeIndexPath]; - cell.textLabel.attributedText = - [self.contactsManager formattedFullNameForContact:contact font:cell.textLabel.font]; - } else { - cell.textLabel.text = [self.groupContacts identifierForIndexPath:relativeIndexPath]; - } - } else { + if (indexPath.row == 0) { + UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = NSLocalizedString(@"GROUP_MEMBERS_HEADER", @"header for table which lists the members of this group thread"); cell.textLabel.textColor = [UIColor lightGrayColor]; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.userInteractionEnabled = NO; + return cell; } - tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + // Adjust index path for the header row. + indexPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]; + + ContactTableViewCell *cell = [ContactTableViewCell new]; + + if ([self.groupContacts isContactAtIndexPath:indexPath]) { + Contact *contact = [self contactForIndexPath:indexPath]; + BOOL isBlocked = [self isContactBlocked:contact]; + if (isBlocked) { + cell.accessoryMessage + = NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); + } else { + OWSAssert(cell.accessoryMessage == nil); + } + [cell configureWithContact:contact contactsManager:self.contactsManager]; + } else { + NSString *recipientId = [self.groupContacts identifierForIndexPath:indexPath]; + BOOL isBlocked = [self isRecipientIdBlocked:recipientId]; + if (isBlocked) { + cell.accessoryMessage + = NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); + } else { + OWSAssert(cell.accessoryMessage == nil); + } + [cell configureWithRecipientId:recipientId contactsManager:self.contactsManager]; + } return cell; } +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.row == 0) { + return 45.f; + } else { + return [ContactTableViewCell rowHeight]; + } +} + - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSIndexPath *relativeIndexPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]; + if (indexPath.row == 0) { + OWSAssert(0); + return; + } - if (indexPath.row > 0 && [self.groupContacts isContactAtIndexPath:relativeIndexPath]) { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + // Adjust index path for the header row. + indexPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]; + + UIAlertController *actionSheetController = + [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"GROUP_MEMBERS_VIEW_CONTACT_INFO", + @"Button label for the 'show contact info' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [self showContactInfoViewForMember:indexPath]; + }]]; + + BOOL isBlocked; + if ([self.groupContacts isContactAtIndexPath:indexPath]) { + Contact *contact = [self contactForIndexPath:indexPath]; + + isBlocked = [self isContactBlocked:contact]; + if (isBlocked) { + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", + @"Button label for the 'unblock' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [BlockListUIUtils + showUnblockContactActionSheet:contact + fromViewController:self + blockingManager:self.blockingManager + contactsManager:self.contactsManager + completionBlock:nil]; + }]]; + } else { + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", + @"Button label for the 'block' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [BlockListUIUtils showBlockContactActionSheet:contact + fromViewController:self + blockingManager:self.blockingManager + contactsManager:self.contactsManager + completionBlock:nil]; + }]]; + } + } else { + NSString *recipientId = [self.groupContacts identifierForIndexPath:indexPath]; + isBlocked = [self isRecipientIdBlocked:recipientId]; + if (isBlocked) { + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", + @"Button label for the 'unblock' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [BlockListUIUtils + showUnblockPhoneNumberActionSheet:recipientId + fromViewController:self + blockingManager:self.blockingManager + contactsManager:self.contactsManager + completionBlock:nil]; + }]]; + } else { + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", + @"Button label for the 'block' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [BlockListUIUtils + showBlockPhoneNumberActionSheet:recipientId + fromViewController:self + blockingManager:self.blockingManager + contactsManager:self.contactsManager + completionBlock:nil]; + }]]; + } + } + + if (!isBlocked) { + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"GROUP_MEMBERS_SEND_MESSAGE", + @"Button label for the 'send message to group member' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [self showConversationViewForMember:indexPath]; + }]]; + [actionSheetController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"GROUP_MEMBERS_CALL", + @"Button label for the 'call group member' button") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [self callMember:indexPath]; + }]]; + } + + UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + style:UIAlertActionStyleCancel + handler:nil]; + [actionSheetController addAction:dismissAction]; + + [self presentViewController:actionSheetController animated:YES completion:nil]; +} + +- (void)showContactInfoViewForMember:(NSIndexPath *)indexPath +{ + if ([self.groupContacts isContactAtIndexPath:indexPath]) { ABPersonViewController *view = [[ABPersonViewController alloc] init]; - Contact *contact = [self.groupContacts contactForIndexPath:relativeIndexPath]; + Contact *contact = [self.groupContacts contactForIndexPath:indexPath]; ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil); - view.displayedPerson = - ABAddressBookGetPersonWithRecordID(addressBookRef, contact.recordID); // Assume person is already defined. + view.displayedPerson + = ABAddressBookGetPersonWithRecordID(addressBookRef, contact.recordID); // Assume person is already defined. view.allowsActions = NO; view.allowsEditing = YES; @@ -139,8 +315,7 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" CFErrorRef anError = NULL; ABMultiValueRef phone = ABMultiValueCreateMutable(kABMultiStringPropertyType); - ABMultiValueAddValueAndLabel( - phone, + ABMultiValueAddValueAndLabel(phone, (__bridge CFTypeRef)[self.tableView cellForRowAtIndexPath:indexPath].textLabel.text, kABPersonPhoneMainLabel, NULL); @@ -154,8 +329,30 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" [self.navigationController pushViewController:view animated:YES]; } } +} - [tableView deselectRowAtIndexPath:indexPath animated:YES]; +- (void)showConversationViewForMember:(NSIndexPath *)indexPath +{ + NSString *recipientId; + if ([self.groupContacts isContactAtIndexPath:indexPath]) { + Contact *contact = [self.groupContacts contactForIndexPath:indexPath]; + recipientId = [[contact textSecureIdentifiers] firstObject]; + } else { + recipientId = [self.groupContacts identifierForIndexPath:indexPath]; + } + [Environment messageIdentifier:recipientId withCompose:YES]; +} + +- (void)callMember:(NSIndexPath *)indexPath +{ + NSString *recipientId; + if ([self.groupContacts isContactAtIndexPath:indexPath]) { + Contact *contact = [self.groupContacts contactForIndexPath:indexPath]; + recipientId = [[contact textSecureIdentifiers] firstObject]; + } else { + recipientId = [self.groupContacts identifierForIndexPath:indexPath]; + } + [Environment callUserWithIdentifier:recipientId]; } - (Contact *)contactForIndexPath:(NSIndexPath *)indexPath { @@ -163,6 +360,27 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" return contact; } +- (BOOL)isContactBlocked:(Contact *)contact +{ + if (contact.parsedPhoneNumbers.count < 1) { + // Hide contacts without any valid phone numbers. + return NO; + } + + for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { + if ([_blockedPhoneNumbers containsObject:phoneNumber.toE164]) { + return YES; + } + } + + return NO; +} + +- (BOOL)isRecipientIdBlocked:(NSString *)recipientId +{ + return [_blockedPhoneNumbers containsObject:recipientId]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/SignalsViewController.h b/Signal/src/ViewControllers/SignalsViewController.h index ae877d1af..b24c0dfd7 100644 --- a/Signal/src/ViewControllers/SignalsViewController.h +++ b/Signal/src/ViewControllers/SignalsViewController.h @@ -14,7 +14,9 @@ @property (nonatomic, strong) IBOutlet UILabel *emptyBoxLabel; @property (nonatomic) BOOL newlyRegisteredUser; -- (void)presentThread:(TSThread *)thread keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing; +- (void)presentThread:(TSThread *)thread + keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing + callOnViewAppearing:(BOOL)callOnViewAppearing; - (NSNumber *)updateInboxCountLabel; - (void)composeNew; diff --git a/Signal/src/ViewControllers/SignalsViewController.m b/Signal/src/ViewControllers/SignalsViewController.m index 5535d3692..d4bb955bd 100644 --- a/Signal/src/ViewControllers/SignalsViewController.m +++ b/Signal/src/ViewControllers/SignalsViewController.m @@ -131,12 +131,12 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS object:nil]; [self selectedInbox:self]; - [[[Environment getCurrent] contactsManager] - .getObservableContacts watchLatestValue:^(id latestValue) { - [self.tableView reloadData]; + __weak SignalsViewController *weakSelf = self; + [[[Environment getCurrent] contactsManager].getObservableContacts watchLatestValue:^(id latestValue) { + [weakSelf.tableView reloadData]; } - onThread:[NSThread mainThread] - untilCancelled:nil]; + onThread:[NSThread mainThread] + untilCancelled:nil]; self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[ NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil), @@ -210,7 +210,7 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS MessagesViewController *vc = [MessagesViewController new]; TSThread *thread = [self threadForIndexPath:indexPath]; - [vc configureForThread:thread keyboardOnViewAppearing:NO]; + [vc configureForThread:thread keyboardOnViewAppearing:NO callOnViewAppearing:NO]; [vc peekSetup]; return vc; @@ -524,12 +524,15 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { TSThread *thread = [self threadForIndexPath:indexPath]; - [self presentThread:thread keyboardOnViewAppearing:NO]; + [self presentThread:thread keyboardOnViewAppearing:NO callOnViewAppearing:NO]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; } -- (void)presentThread:(TSThread *)thread keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing { +- (void)presentThread:(TSThread *)thread + keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing + callOnViewAppearing:(BOOL)callOnViewAppearing +{ dispatch_async(dispatch_get_main_queue(), ^{ MessagesViewController *mvc = [[MessagesViewController alloc] initWithNibName:@"MessagesViewController" bundle:nil]; @@ -539,7 +542,9 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS } [self.navigationController popToRootViewControllerAnimated:YES]; - [mvc configureForThread:thread keyboardOnViewAppearing:keyboardOnViewAppearing]; + [mvc configureForThread:thread + keyboardOnViewAppearing:keyboardOnViewAppearing + callOnViewAppearing:callOnViewAppearing]; [self.navigationController pushViewController:mvc animated:YES]; }); } diff --git a/Signal/src/contact/OWSContactsManager.h b/Signal/src/contact/OWSContactsManager.h index eb25b1360..aa7bf6b47 100644 --- a/Signal/src/contact/OWSContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -42,6 +42,7 @@ extern NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification; - (NSString *)displayNameForContact:(Contact *)contact; - (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier; - (NSAttributedString *)formattedFullNameForContact:(Contact *)contact font:(UIFont *)font; +- (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font; - (BOOL)hasAddressBook; diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 60e482a12..b5bcb29ef 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -102,9 +102,10 @@ NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification = [self setupAddressBookIfNecessary]; + __weak OWSContactsManager *weakSelf = self; [self.observableContactsController watchLatestValueOnArbitraryThread:^(NSArray *latestContacts) { @synchronized(self) { - [self setupLatestContacts:latestContacts]; + [weakSelf setupLatestContacts:latestContacts]; } } untilCancelled:_life.token]; @@ -559,6 +560,16 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in return fullNameString; } +- (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font +{ + NSDictionary *normalFontAttributes = + @{ NSFontAttributeName : font, NSForegroundColorAttributeName : [UIColor ows_darkGrayColor] }; + + return [[NSAttributedString alloc] + initWithString:[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:recipientId] + attributes:normalFontAttributes]; +} + - (Contact * _Nullable)contactForPhoneIdentifier:(NSString * _Nullable)identifier { if (!identifier) { return nil; diff --git a/Signal/src/environment/Environment.h b/Signal/src/environment/Environment.h index ad6a3a5d3..6a5e7b25c 100644 --- a/Signal/src/environment/Environment.h +++ b/Signal/src/environment/Environment.h @@ -64,6 +64,7 @@ + (void)messageThreadId:(NSString *)threadId; + (void)messageIdentifier:(NSString *)identifier withCompose:(BOOL)compose; ++ (void)callUserWithIdentifier:(NSString *)identifier; + (void)messageGroup:(TSGroupThread *)groupThread; @end diff --git a/Signal/src/environment/Environment.m b/Signal/src/environment/Environment.m index a2f3d474c..f37b37659 100644 --- a/Signal/src/environment/Environment.m +++ b/Signal/src/environment/Environment.m @@ -212,16 +212,27 @@ static Environment *environment = nil; [[TSStorageManager sharedManager] .dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:identifier transaction:transaction]; - [vc presentThread:thread keyboardOnViewAppearing:YES]; - + [vc presentThread:thread keyboardOnViewAppearing:YES callOnViewAppearing:NO]; }]; } ++ (void)callUserWithIdentifier:(NSString *)identifier +{ + Environment *env = [self getCurrent]; + SignalsViewController *vc = env.signalsViewController; + + [[TSStorageManager sharedManager].dbConnection + asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:identifier transaction:transaction]; + [vc presentThread:thread keyboardOnViewAppearing:NO callOnViewAppearing:YES]; + }]; +} + + (void)messageGroup:(TSGroupThread *)groupThread { Environment *env = [self getCurrent]; SignalsViewController *vc = env.signalsViewController; - [vc presentThread:groupThread keyboardOnViewAppearing:YES]; + [vc presentThread:groupThread keyboardOnViewAppearing:YES callOnViewAppearing:NO]; } + (void)resetAppData { diff --git a/Signal/src/views/ContactTableViewCell.h b/Signal/src/views/ContactTableViewCell.h index d9687eb72..25080871a 100644 --- a/Signal/src/views/ContactTableViewCell.h +++ b/Signal/src/views/ContactTableViewCell.h @@ -13,6 +13,8 @@ NS_ASSUME_NONNULL_BEGIN +extern NSString *const kContactsTable_CellReuseIdentifier; + @class OWSContactsManager; @interface ContactTableViewCell : UITableViewCell @@ -25,6 +27,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)configureWithContact:(Contact *)contact contactsManager:(OWSContactsManager *)contactsManager; +- (void)configureWithRecipientId:(NSString *)recipientId contactsManager:(OWSContactsManager *)contactsManager; + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index f77c4320a..acddb70e8 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN +NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseIdentifier"; + @interface ContactTableViewCell () @property (nonatomic) IBOutlet UILabel *nameLabel; @@ -53,6 +55,8 @@ NS_ASSUME_NONNULL_BEGIN // applyRoundedBorderToImageView requires the avatar to have // the correct size. _avatarView.frame = CGRectMake(0, 0, kAvatarSize, kAvatarSize); + _avatarView.layer.minificationFilter = kCAFilterTrilinear; + _avatarView.layer.magnificationFilter = kCAFilterTrilinear; [self.contentView addSubview:_avatarView]; _nameLabel = [UILabel new]; @@ -77,8 +81,27 @@ NS_ASSUME_NONNULL_BEGIN - (void)configureWithContact:(Contact *)contact contactsManager:(OWSContactsManager *)contactsManager { - NSMutableAttributedString *attributedText = - [[contactsManager formattedFullNameForContact:contact font:self.nameLabel.font] mutableCopy]; + [self configureWithRecipientId:contact.textSecureIdentifiers.firstObject + avatarName:contact.fullName + displayName:[contactsManager formattedFullNameForContact:contact font:self.nameLabel.font] + contactsManager:contactsManager]; +} + +- (void)configureWithRecipientId:(NSString *)recipientId contactsManager:(OWSContactsManager *)contactsManager +{ + [self + configureWithRecipientId:recipientId + avatarName:@"" + displayName:[contactsManager formattedFullNameForRecipientId:recipientId font:self.nameLabel.font] + contactsManager:contactsManager]; +} + +- (void)configureWithRecipientId:(NSString *)recipientId + avatarName:(NSString *)avatarName + displayName:(NSAttributedString *)displayName + contactsManager:(OWSContactsManager *)contactsManager +{ + NSMutableAttributedString *attributedText = [displayName mutableCopy]; if (self.accessoryMessage) { UILabel *blockedLabel = [[UILabel alloc] init]; blockedLabel.textAlignment = NSTextAlignmentRight; @@ -91,9 +114,8 @@ NS_ASSUME_NONNULL_BEGIN } self.nameLabel.attributedText = attributedText; self.avatarView.image = - [[[OWSContactAvatarBuilder alloc] initWithContactId:contact.textSecureIdentifiers.firstObject - name:contact.fullName - contactsManager:contactsManager] build]; + [[[OWSContactAvatarBuilder alloc] initWithContactId:recipientId name:avatarName contactsManager:contactsManager] + build]; // Force layout, since imageView isn't being initally rendered on App Store optimized build. [self layoutSubviews]; diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index d5b4e9461..886ea8715 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -460,9 +460,18 @@ /* No comment provided by engineer. */ "GROUP_MEMBER_LEFT" = " %@ left the group. "; +/* Button label for the 'call group member' button */ +"GROUP_MEMBERS_CALL" = "Call"; + /* header for table which lists the members of this group thread */ "GROUP_MEMBERS_HEADER" = "Group Members"; +/* Button label for the 'send message to group member' button */ +"GROUP_MEMBERS_SEND_MESSAGE" = "Send Message"; + +/* Button label for the 'show contact info' button */ +"GROUP_MEMBERS_VIEW_CONTACT_INFO" = "Contact Info"; + /* No comment provided by engineer. */ "GROUP_REMOVING" = "Leaving group %@";