session-ios/Signal/src/ViewControllers/ShowGroupMembersViewController.m
Matthew Chen ee765df4b1 Respond to CR.
// FREEBIE
2017-04-19 11:39:13 -04:00

386 lines
16 KiB
Objective-C

//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "ShowGroupMembersViewController.h"
#import "BlockListUIUtils.h"
#import "ContactTableViewCell.h"
#import "Environment.h"
#import "GroupContactsResult.h"
#import "OWSContactsManager.h"
#import "SignalsViewController.h"
#import "UIUtil.h"
#import <AddressBookUI/AddressBookUI.h>
#import <SignalServiceKit/OWSBlockingManager.h>
NS_ASSUME_NONNULL_BEGIN
static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue";
@interface ShowGroupMembersViewController ()
@property GroupContactsResult *groupContacts;
@property TSGroupThread *thread;
@property (nonatomic, readonly) OWSContactsManager *_Nonnull contactsManager;
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
@property (nonatomic, readonly) NSArray<NSString *> *blockedPhoneNumbers;
@end
@implementation ShowGroupMembersViewController
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
[self commonInit];
return self;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self) {
return self;
}
[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;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationController.navigationBar setTranslucent:NO];
self.title = _thread.groupModel.groupName;
[self initializeTableView];
self.groupContacts =
[[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil];
__weak ShowGroupMembersViewController *weakSelf = self;
[self.contactsManager.getObservableContacts watchLatestValue:^(id latestValue) {
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];
}
#pragma mark - Initializers
- (void)initializeTableView {
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[self.tableView registerClass:[ContactTableViewCell class]
forCellReuseIdentifier:kContactsTable_CellReuseIdentifier];
}
#pragma mark - Actions
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return (NSInteger)[self.groupContacts numberOfMembers] + 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
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;
}
// 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 {
if (indexPath.row == 0) {
OWSAssert(0);
return;
}
[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:UIAlertActionStyleDefault
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:UIAlertActionStyleDefault
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:UIAlertActionStyleDefault
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:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
[self showConversationViewForMember:indexPath];
}]];
[actionSheetController
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"GROUP_MEMBERS_CALL",
@"Button label for the 'call group member' button")
style:UIAlertActionStyleDefault
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:indexPath];
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil);
view.displayedPerson
= ABAddressBookGetPersonWithRecordID(addressBookRef, contact.recordID); // Assume person is already defined.
view.allowsActions = NO;
view.allowsEditing = YES;
[self.navigationController pushViewController:view animated:YES];
} else {
ABUnknownPersonViewController *view = [[ABUnknownPersonViewController alloc] init];
ABRecordRef aContact = ABPersonCreate();
CFErrorRef anError = NULL;
ABMultiValueRef phone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(phone,
(__bridge CFTypeRef)[self.tableView cellForRowAtIndexPath:indexPath].textLabel.text,
kABPersonPhoneMainLabel,
NULL);
ABRecordSetValue(aContact, kABPersonPhoneProperty, phone, &anError);
CFRelease(phone);
if (!anError && aContact) {
view.displayedPerson = aContact; // Assume person is already defined.
view.allowsAddingToAddressBook = YES;
[self.navigationController pushViewController:view 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 {
Contact *contact = [self.groupContacts contactForIndexPath:indexPath];
return contact;
}
- (BOOL)isContactBlocked:(Contact *)contact
{
if (contact.parsedPhoneNumbers.count < 1) {
// Do not consider contacts without any valid phone numbers to be blocked.
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