2014-10-29 21:58:58 +01:00
//
2017-02-08 20:25:31 +01:00
// Copyright ( c ) 2017 Open Whisper Systems . All rights reserved .
2014-10-29 21:58:58 +01:00
//
2016-09-02 16:22:06 +02:00
# import "NewGroupViewController.h"
2017-04-06 17:44:03 +02:00
# import "BlockListUIUtils.h"
# import "ContactTableViewCell.h"
2014-11-21 14:38:37 +01:00
# import "Environment.h"
2014-12-24 02:25:10 +01:00
# import "FunctionalUtil.h"
2016-09-02 16:22:06 +02:00
# import "OWSContactsManager.h"
2014-12-17 06:44:36 +01:00
# import "SecurityUtils.h"
# import "SignalKeyingStorage.h"
2015-12-22 12:45:09 +01:00
# import "SignalsViewController.h"
2015-12-26 17:27:27 +01:00
# import "TSOutgoingMessage.h"
2014-12-31 19:31:27 +01:00
# import "UIImage+normalizeImage.h"
2014-11-24 21:51:43 +01:00
# import "UIUtil.h"
2016-09-02 16:22:06 +02:00
# import < MobileCoreServices / UTCoreTypes . h >
# import < SignalServiceKit / MimeTypeUtil . h >
# import < SignalServiceKit / NSDate + millisecondTimeStamp . h >
2017-04-03 16:45:48 +02:00
# import < SignalServiceKit / OWSBlockingManager . h >
2016-10-14 22:59:58 +02:00
# import < SignalServiceKit / OWSMessageSender . h >
2016-09-02 16:22:06 +02:00
# import < SignalServiceKit / TSAccountManager . h >
2014-10-29 21:58:58 +01:00
2015-12-22 12:45:09 +01:00
static NSString * const kUnwindToMessagesViewSegue = @ "UnwindToMessagesViewSegue" ;
2014-12-24 02:25:10 +01:00
2014-10-29 21:58:58 +01:00
@ interface NewGroupViewController ( ) {
2015-12-22 12:45:09 +01:00
NSArray * contacts ;
2014-10-29 21:58:58 +01:00
}
2016-10-14 22:59:58 +02:00
2015-12-22 12:45:09 +01:00
@ property TSGroupThread * thread ;
2016-12-05 04:51:31 +01:00
@ property ( nonatomic , readonly , strong ) OWSMessageSender * messageSender ;
@ property ( nonatomic , readonly , strong ) OWSContactsManager * contactsManager ;
2014-10-29 21:58:58 +01:00
2017-04-03 16:45:48 +02:00
@ property ( nonatomic , readonly ) OWSBlockingManager * blockingManager ;
@ property ( nonatomic , readonly ) NSArray < NSString * > * blockedPhoneNumbers ;
2014-10-29 21:58:58 +01:00
@ end
2016-10-14 22:59:58 +02:00
2014-10-29 21:58:58 +01:00
@ implementation NewGroupViewController
2016-10-14 22:59:58 +02:00
- ( instancetype ) init
{
self = [ super init ] ;
if ( ! self ) {
return self ;
}
2016-12-05 04:51:31 +01:00
[ self commonInit ] ;
2016-10-14 22:59:58 +02:00
return self ;
}
- ( instancetype ) initWithCoder : ( NSCoder * ) aDecoder
{
self = [ super initWithCoder : aDecoder ] ;
if ( ! self ) {
return self ;
}
2016-12-05 04:51:31 +01:00
[ self commonInit ] ;
return self ;
}
- ( void ) commonInit
{
2017-03-30 18:51:48 +02:00
_messageSender = [ Environment getCurrent ] . messageSender ;
2016-12-05 04:51:31 +01:00
_contactsManager = [ Environment getCurrent ] . contactsManager ;
2017-02-08 17:59:02 +01:00
2017-04-03 16:45:48 +02:00
_blockingManager = [ OWSBlockingManager sharedManager ] ;
_blockedPhoneNumbers = [ _blockingManager blockedPhoneNumbers ] ;
2017-02-08 17:59:02 +01:00
[ self observeNotifications ] ;
}
- ( void ) observeNotifications
{
[ [ NSNotificationCenter defaultCenter ] addObserver : self
2017-02-08 20:25:31 +01:00
selector : @ selector ( signalRecipientsDidChange : )
name : OWSContactsManagerSignalRecipientsDidChangeNotification
2017-02-08 17:59:02 +01:00
object : nil ] ;
2017-04-03 16:45:48 +02:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( blockedPhoneNumbersDidChange : )
name : kNSNotificationName_BlockedPhoneNumbersDidChange
object : nil ] ;
2017-02-08 17:59:02 +01:00
}
- ( void ) dealloc
{
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
}
2017-02-08 20:25:31 +01:00
- ( void ) signalRecipientsDidChange : ( NSNotification * ) notification {
2017-04-03 16:45:48 +02:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self updateContacts ] ;
} ) ;
}
- ( void ) blockedPhoneNumbersDidChange : ( id ) notification
{
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
_blockedPhoneNumbers = [ _blockingManager blockedPhoneNumbers ] ;
[ self updateContacts ] ;
} ) ;
2017-02-08 17:59:02 +01:00
}
- ( void ) updateContacts {
AssertIsOnMainThread ( ) ;
2017-04-06 17:44:03 +02:00
// Snapshot selection state .
NSMutableSet * selectedContacts = [ NSMutableSet set ] ;
for ( NSIndexPath * indexPath in [ self . tableView indexPathsForSelectedRows ] ) {
Contact * contact = contacts [ ( NSUInteger ) indexPath . row ] ;
[ selectedContacts addObject : contact ] ;
}
2017-04-03 16:45:48 +02:00
contacts = [ self filteredContacts ] ;
2017-02-08 17:59:02 +01:00
[ self . tableView reloadData ] ;
2017-04-06 17:44:03 +02:00
// Restore selection state .
for ( Contact * contact in selectedContacts ) {
if ( [ contacts containsObject : contact ] ) {
NSInteger row = ( NSInteger ) [ contacts indexOfObject : contact ] ;
[ self . tableView selectRowAtIndexPath : [ NSIndexPath indexPathForRow : row inSection : 0 ]
animated : NO
scrollPosition : UITableViewScrollPositionNone ] ;
}
}
2016-10-14 22:59:58 +02:00
}
2017-04-06 17:44:03 +02:00
- ( BOOL ) isContactHidden : ( Contact * ) contact
2017-04-03 16:45:48 +02:00
{
if ( contact . parsedPhoneNumbers . count < 1 ) {
2017-04-05 18:22:35 +02:00
// Hide contacts without any valid phone numbers .
2017-04-03 16:45:48 +02:00
return YES ;
}
2017-04-06 17:44:03 +02:00
if ( [ self isCurrentUserContact : contact ] ) {
// We never want to add ourselves to a group .
return YES ;
}
return NO ;
}
- ( BOOL ) isContactBlocked : ( Contact * ) contact
{
if ( contact . parsedPhoneNumbers . count < 1 ) {
// Hide contacts without any valid phone numbers .
return NO ;
}
2017-04-03 16:45:48 +02:00
for ( PhoneNumber * phoneNumber in contact . parsedPhoneNumbers ) {
if ( [ _blockedPhoneNumbers containsObject : phoneNumber . toE164 ] ) {
return YES ;
}
}
return NO ;
}
- ( BOOL ) isCurrentUserContact : ( Contact * ) contact
{
for ( PhoneNumber * phoneNumber in contact . parsedPhoneNumbers ) {
if ( [ [ phoneNumber toE164 ] isEqualToString : [ TSAccountManager localNumber ] ] ) {
return YES ;
}
}
return NO ;
}
2017-04-06 17:44:03 +02:00
- ( NSArray < Contact * > * _Nonnull ) filteredContacts
{
NSMutableArray < Contact * > * result = [ NSMutableArray new ] ;
for ( Contact * contact in self . contactsManager . signalContacts ) {
if ( ! [ self isContactHidden : contact ] ) {
[ result addObject : contact ] ;
}
}
return [ result copy ] ;
}
2017-04-03 16:45:48 +02:00
- ( BOOL ) isContactInGroup : ( Contact * ) contact
{
for ( PhoneNumber * phoneNumber in contact . parsedPhoneNumbers ) {
if ( _thread ! = nil && _thread . groupModel . groupMemberIds ) {
// TODO : What if a contact has two phone numbers that
// correspond to signal account and one has been added
// to the group but not the other ?
if ( [ _thread . groupModel . groupMemberIds containsObject : [ phoneNumber toE164 ] ] ) {
return YES ;
}
}
}
return NO ;
}
2015-12-22 12:45:09 +01:00
- ( void ) configWithThread : ( TSGroupThread * ) gThread {
2014-12-17 06:44:36 +01:00
_thread = gThread ;
}
2014-10-29 21:58:58 +01:00
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
2015-01-14 22:30:01 +01:00
[ self . navigationController . navigationBar setTranslucent : NO ] ;
2014-12-24 02:25:10 +01:00
2017-04-03 16:45:48 +02:00
contacts = [ self filteredContacts ] ;
2015-12-22 12:45:09 +01:00
2015-01-27 02:20:11 +01:00
self . tableView . tableHeaderView . frame = CGRectMake ( 0 , 0 , 400 , 44 ) ;
2015-12-22 12:45:09 +01:00
self . tableView . tableHeaderView = self . tableView . tableHeaderView ;
2014-12-24 02:25:10 +01:00
[ self initializeDelegates ] ;
[ self initializeTableView ] ;
[ self initializeKeyboardHandlers ] ;
2015-12-22 12:45:09 +01:00
if ( _thread = = nil ) {
self . navigationItem . rightBarButtonItem =
[ [ UIBarButtonItem alloc ] initWithImage : [ [ UIImage imageNamed : @ "add-conversation" ]
imageWithRenderingMode : UIImageRenderingModeAlwaysOriginal ]
style : UIBarButtonItemStylePlain
target : self
action : @ selector ( createGroup ) ] ;
2015-02-19 07:00:05 +01:00
self . navigationItem . rightBarButtonItem . imageInsets = UIEdgeInsetsMake ( 0 , -10 , 0 , 10 ) ;
2015-12-22 12:45:09 +01:00
self . navigationItem . title = NSLocalizedString ( @ "NEW_GROUP_DEFAULT_TITLE" , @ "" ) ;
2016-12-07 03:27:07 +01:00
self . navigationItem . rightBarButtonItem . accessibilityLabel = NSLocalizedString ( @ "FINISH_GROUP_CREATION_LABEL" , @ "Accessibilty label for finishing new group" ) ;
2015-12-22 12:45:09 +01:00
} else {
self . navigationItem . rightBarButtonItem =
[ [ UIBarButtonItem alloc ] initWithTitle : NSLocalizedString ( @ "UPDATE_BUTTON_TITLE" , @ "" )
style : UIBarButtonItemStylePlain
target : self
action : @ selector ( updateGroup ) ] ;
self . navigationItem . title = _thread . groupModel . groupName ;
2014-12-17 06:44:36 +01:00
self . nameGroupTextField . text = _thread . groupModel . groupName ;
2015-12-22 12:45:09 +01:00
if ( _thread . groupModel . groupImage ! = nil ) {
2015-01-30 04:31:35 +01:00
_groupImage = _thread . groupModel . groupImage ;
2015-01-04 20:48:43 +01:00
[ self setupGroupImageButton : _thread . groupModel . groupImage ] ;
}
2014-12-17 06:44:36 +01:00
}
2015-02-18 23:21:03 +01:00
_nameGroupTextField . placeholder = NSLocalizedString ( @ "NEW_GROUP_NAMEGROUP_REQUEST_DEFAULT" , @ "" ) ;
2015-12-22 12:45:09 +01:00
_addPeopleLabel . text = NSLocalizedString ( @ "NEW_GROUP_REQUEST_ADDPEOPLE" , @ "" ) ;
2014-10-29 21:58:58 +01:00
}
# pragma mark - Initializers
2015-12-22 12:45:09 +01:00
- ( void ) initializeDelegates {
2014-10-29 21:58:58 +01:00
self . nameGroupTextField . delegate = self ;
}
2015-12-22 12:45:09 +01:00
- ( void ) initializeTableView {
self . tableView . tableFooterView = [ [ UIView alloc ] initWithFrame : CGRectZero ] ;
2014-10-29 21:58:58 +01:00
}
# pragma mark - Keyboard notifications
2015-12-22 12:45:09 +01:00
- ( void ) initializeKeyboardHandlers {
UITapGestureRecognizer * outsideTabRecognizer =
[ [ UITapGestureRecognizer alloc ] initWithTarget : self action : @ selector ( dismissKeyboardFromAppropriateSubView ) ] ;
2014-10-29 21:58:58 +01:00
[ self . tapToDismissView addGestureRecognizer : outsideTabRecognizer ] ;
}
2015-12-22 12:45:09 +01:00
- ( void ) dismissKeyboardFromAppropriateSubView {
2014-10-29 21:58:58 +01:00
[ self . nameGroupTextField resignFirstResponder ] ;
}
# pragma mark - Actions
2016-08-01 00:25:07 +02:00
- ( void ) createGroup
{
2015-12-22 12:45:09 +01:00
TSGroupModel * model = [ self makeGroup ] ;
2015-12-26 17:27:27 +01:00
[ [ TSStorageManager sharedManager ]
. dbConnection readWriteWithBlock : ^ ( YapDatabaseReadWriteTransaction * _Nonnull transaction ) {
self . thread = [ TSGroupThread getOrCreateThreadWithGroupModel : model transaction : transaction ] ;
} ] ;
2016-10-14 22:59:58 +02:00
void ( ^ popToThread ) ( ) = ^ {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self dismissViewControllerAnimated : YES
completion : ^ {
[ Environment messageGroup : self . thread ] ;
} ] ;
} ) ;
} ;
void ( ^ removeThreadWithError ) ( NSError * error ) = ^ ( NSError * error ) {
[ self . thread remove ] ;
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self dismissViewControllerAnimated : YES
completion : ^ {
SignalAlertView ( NSLocalizedString ( @ "GROUP_CREATING_FAILED" , nil ) ,
error . localizedDescription ) ;
} ] ;
} ) ;
} ;
2015-12-26 17:27:27 +01:00
UIAlertController * alertController =
[ UIAlertController alertControllerWithTitle : NSLocalizedString ( @ "GROUP_CREATING" , nil )
message : nil
preferredStyle : UIAlertControllerStyleAlert ] ;
2016-10-14 22:59:58 +02:00
[ self presentViewController : alertController
animated : YES
completion : ^ {
TSOutgoingMessage * message =
[ [ TSOutgoingMessage alloc ] initWithTimestamp : [ NSDate ows_millisecondTimeStamp ]
inThread : self . thread
messageBody : @ ""
attachmentIds : [ NSMutableArray new ] ] ;
message . groupMetaMessage = TSGroupMessageNew ;
message . customMessage = NSLocalizedString ( @ "GROUP_CREATED" , nil ) ;
if ( model . groupImage ) {
[ self . messageSender sendAttachmentData : UIImagePNGRepresentation ( model . groupImage )
contentType : OWSMimeTypeImagePng
inMessage : message
success : popToThread
failure : removeThreadWithError ] ;
} else {
[ self . messageSender sendMessage : message success : popToThread failure : removeThreadWithError ] ;
}
} ] ;
2014-12-17 06:44:36 +01:00
}
2016-08-01 00:25:07 +02:00
- ( void ) updateGroup
{
2015-12-22 12:45:09 +01:00
NSMutableArray * mut = [ [ NSMutableArray alloc ] init ] ;
for ( NSIndexPath * idx in _tableView . indexPathsForSelectedRows ) {
2015-01-27 02:20:11 +01:00
[ mut addObjectsFromArray : [ [ contacts objectAtIndex : ( NSUInteger ) idx . row ] textSecureIdentifiers ] ] ;
2014-12-24 02:25:10 +01:00
}
2015-01-30 04:31:35 +01:00
[ mut addObjectsFromArray : _thread . groupModel . groupMemberIds ] ;
2015-12-22 12:45:09 +01:00
2015-02-28 17:49:46 +01:00
_groupModel = [ [ TSGroupModel alloc ] initWithTitle : _nameGroupTextField . text
memberIds : [ [ [ NSSet setWithArray : mut ] allObjects ] mutableCopy ]
image : _thread . groupModel . groupImage
2016-08-01 00:25:07 +02:00
groupId : _thread . groupModel . groupId ] ;
2015-12-22 12:45:09 +01:00
2015-02-28 17:49:46 +01:00
[ self . nameGroupTextField resignFirstResponder ] ;
2015-12-22 12:45:09 +01:00
2014-12-24 02:25:10 +01:00
[ self performSegueWithIdentifier : kUnwindToMessagesViewSegue sender : self ] ;
2014-10-29 21:58:58 +01:00
}
2014-12-17 06:44:36 +01:00
2016-08-01 00:25:07 +02:00
- ( TSGroupModel * ) makeGroup
{
2015-12-22 12:45:09 +01:00
NSString * title = _nameGroupTextField . text ;
NSMutableArray * mut = [ [ NSMutableArray alloc ] init ] ;
for ( NSIndexPath * idx in _tableView . indexPathsForSelectedRows ) {
2015-01-27 02:20:11 +01:00
[ mut addObjectsFromArray : [ [ contacts objectAtIndex : ( NSUInteger ) idx . row ] textSecureIdentifiers ] ] ;
2014-10-29 21:58:58 +01:00
}
2015-12-22 12:45:09 +01:00
[ mut addObject : [ TSAccountManager localNumber ] ] ;
NSData * groupId = [ SecurityUtils generateRandomBytes : 16 ] ;
2016-08-01 00:25:07 +02:00
return [ [ TSGroupModel alloc ] initWithTitle : title memberIds : mut image : _groupImage groupId : groupId ] ;
2014-10-29 21:58:58 +01:00
}
2015-12-22 12:45:09 +01:00
- ( IBAction ) addGroupPhoto : ( id ) sender {
2016-11-26 00:12:00 +01:00
UIAlertController * actionSheetController = [ UIAlertController alertControllerWithTitle : NSLocalizedString ( @ "NEW_GROUP_ADD_PHOTO_ACTION" , @ "Action Sheet title prompting the user for a group avatar" )
message : nil
preferredStyle : UIAlertControllerStyleActionSheet ] ;
UIAlertAction * dismissAction = [ UIAlertAction actionWithTitle : NSLocalizedString ( @ "TXT_CANCEL_TITLE" , @ "" )
style : UIAlertActionStyleCancel
handler : nil ] ;
[ actionSheetController addAction : dismissAction ] ;
2016-11-29 22:54:01 +01:00
UIAlertAction * takePictureAction = [ UIAlertAction actionWithTitle : NSLocalizedString ( @ "MEDIA_FROM_CAMERA_BUTTON" , @ "media picker option to take photo or video" )
2016-11-26 00:12:00 +01:00
style : UIAlertActionStyleDefault
handler : ^ ( UIAlertAction * _Nonnull action ) {
[ self takePicture ] ;
} ] ;
[ actionSheetController addAction : takePictureAction ] ;
2016-11-29 22:54:01 +01:00
UIAlertAction * choosePictureAction = [ UIAlertAction actionWithTitle : NSLocalizedString ( @ "MEDIA_FROM_LIBRARY_BUTTON" , @ "media picker option to choose from library" )
2016-11-26 00:12:00 +01:00
style : UIAlertActionStyleDefault
handler : ^ ( UIAlertAction * _Nonnull action ) {
[ self chooseFromLibrary ] ;
} ] ;
[ actionSheetController addAction : choosePictureAction ] ;
[ self presentViewController : actionSheetController animated : true completion : nil ] ;
2014-10-29 21:58:58 +01:00
}
# pragma mark - Group Image
2015-12-22 12:45:09 +01:00
- ( void ) takePicture {
2014-10-29 21:58:58 +01:00
UIImagePickerController * picker = [ [ UIImagePickerController alloc ] init ] ;
2015-12-22 12:45:09 +01:00
picker . delegate = self ;
picker . allowsEditing = NO ;
picker . sourceType = UIImagePickerControllerSourceTypeCamera ;
if ( [ UIImagePickerController isSourceTypeAvailable : UIImagePickerControllerSourceTypeCamera ] ) {
picker . mediaTypes = [ [ NSArray alloc ] initWithObjects : ( NSString * ) kUTTypeImage , nil ] ;
2015-01-30 09:49:40 +01:00
[ self presentViewController : picker animated : YES completion : [ UIUtil modalCompletionBlock ] ] ;
2014-10-29 21:58:58 +01:00
}
}
2015-12-22 12:45:09 +01:00
- ( void ) chooseFromLibrary {
2014-10-29 21:58:58 +01:00
UIImagePickerController * picker = [ [ UIImagePickerController alloc ] init ] ;
2015-12-22 12:45:09 +01:00
picker . delegate = self ;
picker . sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum ;
if ( [ UIImagePickerController isSourceTypeAvailable : UIImagePickerControllerSourceTypeSavedPhotosAlbum ] ) {
2014-10-29 21:58:58 +01:00
picker . mediaTypes = [ [ NSArray alloc ] initWithObjects : ( NSString * ) kUTTypeImage , nil ] ;
2015-01-30 09:49:40 +01:00
[ self presentViewController : picker animated : YES completion : [ UIUtil modalCompletionBlock ] ] ;
2014-10-29 21:58:58 +01:00
}
}
/ *
* Dismissing UIImagePickerController
* /
- ( void ) imagePickerControllerDidCancel : ( UIImagePickerController * ) picker {
[ self dismissViewControllerAnimated : YES completion : nil ] ;
}
/ *
* Fetch data from UIImagePickerController
* /
2015-12-22 12:45:09 +01:00
- ( void ) imagePickerController : ( UIImagePickerController * ) picker didFinishPickingMediaWithInfo : ( NSDictionary * ) info {
2014-10-29 21:58:58 +01:00
UIImage * picture_camera = [ info objectForKey : UIImagePickerControllerOriginalImage ] ;
2015-12-22 12:45:09 +01:00
2014-10-29 21:58:58 +01:00
if ( picture_camera ) {
2015-12-22 12:45:09 +01:00
UIImage * small = [ picture_camera resizedImageToFitInSize : CGSizeMake ( 100.00 , 100.00 ) scaleIfSmaller : NO ] ;
2015-01-04 20:48:43 +01:00
_thread . groupModel . groupImage = small ;
2015-12-22 12:45:09 +01:00
_groupImage = small ;
2015-01-04 20:48:43 +01:00
[ self setupGroupImageButton : small ] ;
2014-10-29 21:58:58 +01:00
}
[ self dismissViewControllerAnimated : YES completion : nil ] ;
}
2015-12-22 12:45:09 +01:00
- ( void ) setupGroupImageButton : ( UIImage * ) image {
2015-01-30 04:31:35 +01:00
[ _groupImageButton setImage : image forState : UIControlStateNormal ] ;
2015-12-22 12:45:09 +01:00
_groupImageButton . imageView . layer . cornerRadius = CGRectGetWidth ( [ _groupImageButton . imageView frame ] ) / 2.0 f ;
2015-01-30 04:31:35 +01:00
_groupImageButton . imageView . layer . masksToBounds = YES ;
2015-12-22 12:45:09 +01:00
_groupImageButton . imageView . layer . borderColor = [ [ UIColor lightGrayColor ] CGColor ] ;
_groupImageButton . imageView . layer . borderWidth = 0.5 f ;
2016-04-22 21:34:09 +02:00
_groupImageButton . imageView . contentMode = UIViewContentModeScaleAspectFill ;
2014-12-24 02:25:10 +01:00
}
2014-10-29 21:58:58 +01:00
# pragma mark - Table view data source
- ( NSInteger ) numberOfSectionsInTableView : ( UITableView * ) tableView {
return 1 ;
}
- ( NSInteger ) tableView : ( UITableView * ) tableView numberOfRowsInSection : ( NSInteger ) section {
2015-01-27 02:20:11 +01:00
return ( NSInteger ) [ contacts count ] ;
2014-10-29 21:58:58 +01:00
}
- ( UITableViewCell * ) tableView : ( UITableView * ) tableView cellForRowAtIndexPath : ( NSIndexPath * ) indexPath {
2017-04-06 17:44:03 +02:00
ContactTableViewCell * cell
= ( ContactTableViewCell * ) [ tableView dequeueReusableCellWithIdentifier : [ ContactTableViewCell reuseIdentifier ] ] ;
if ( ! cell ) {
cell = [ ContactTableViewCell new ] ;
2014-10-29 21:58:58 +01:00
}
2015-12-22 12:45:09 +01:00
2017-04-06 17:44:03 +02:00
[ self updateContentsOfCell : cell indexPath : indexPath ] ;
2015-12-22 12:45:09 +01:00
2017-04-06 17:44:03 +02:00
return cell ;
}
2015-12-22 12:45:09 +01:00
2017-04-06 17:44:03 +02:00
- ( void ) updateContentsOfCell : ( ContactTableViewCell * ) cell indexPath : ( NSIndexPath * ) indexPath
{
OWSAssert ( cell ) ;
OWSAssert ( indexPath ) ;
Contact * contact = contacts [ ( NSUInteger ) indexPath . row ] ;
2017-04-07 02:58:42 +02:00
OWSAssert ( contact ! = nil ) ;
2017-04-06 17:44:03 +02:00
BOOL isBlocked = [ self isContactBlocked : contact ] ;
BOOL isInGroup = [ self isContactInGroup : contact ] ;
BOOL isSelected = [ [ self . tableView indexPathsForSelectedRows ] containsObject : indexPath ] ;
// More than one of these conditions might be true .
// In order of priority . . .
cell . accessoryMessage = nil ;
cell . accessoryView = nil ;
cell . accessoryType = UITableViewCellAccessoryNone ;
if ( isInGroup ) {
OWSAssert ( ! isSelected ) ;
// . . . if the user is already in the group , indicate that .
cell . accessoryMessage = NSLocalizedString (
@ "CONTACT_CELL_IS_IN_GROUP" , @ "An indicator that a contact is a member of the current group." ) ;
} else if ( isSelected ) {
// . . . if the user is being added to the group , indicate that .
cell . accessoryType = UITableViewCellAccessoryCheckmark ;
} else if ( isBlocked ) {
// . . . if the user is blocked , indicate that .
cell . accessoryMessage
= NSLocalizedString ( @ "CONTACT_CELL_IS_BLOCKED" , @ "An indicator that a contact has been blocked." ) ;
2015-02-17 00:14:50 +01:00
}
2017-04-06 17:44:03 +02:00
[ cell configureWithContact : contact contactsManager : self . contactsManager ] ;
}
2015-12-22 12:45:09 +01:00
2017-04-06 17:44:03 +02:00
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForRowAtIndexPath : ( NSIndexPath * ) indexPath
{
return [ ContactTableViewCell rowHeight ] ;
2014-10-29 21:58:58 +01:00
}
# pragma mark - Table View delegate
2017-04-06 17:44:03 +02:00
2015-12-22 12:45:09 +01:00
- ( void ) tableView : ( UITableView * ) tableView didSelectRowAtIndexPath : ( NSIndexPath * ) indexPath {
2017-04-06 17:44:03 +02:00
Contact * contact = contacts [ ( NSUInteger ) indexPath . row ] ;
BOOL isBlocked = [ self isContactBlocked : contact ] ;
BOOL isInGroup = [ self isContactInGroup : contact ] ;
if ( isInGroup ) {
// Deselect .
[ tableView deselectRowAtIndexPath : indexPath animated : YES ] ;
NSString * displayName = [ _contactsManager displayNameForContact : contact ] ;
UIAlertController * controller = [ UIAlertController
alertControllerWithTitle :
NSLocalizedString ( @ "EDIT_GROUP_VIEW_ALREADY_IN_GROUP_ALERT_TITLE" ,
@ "A title of the alert if user tries to add a user to a group who is already in the group." )
message : [ NSString
stringWithFormat :
NSLocalizedString ( @ "EDIT_GROUP_VIEW_ALREADY_IN_GROUP_ALERT_MESSAGE_FORMAT" ,
@ "A format for the message of the alert if user tries to "
@ "add a user to a group who is already in the group. Embeds {{the "
@ "blocked user's name or phone number}}." ) ,
displayName ]
preferredStyle : UIAlertControllerStyleAlert ] ;
[ controller addAction : [ UIAlertAction actionWithTitle : NSLocalizedString ( @ "OK" , nil )
style : UIAlertActionStyleDefault
handler : nil ] ] ;
[ self presentViewController : controller animated : YES completion : nil ] ;
return ;
} else if ( isBlocked ) {
// Deselect .
[ self . tableView deselectRowAtIndexPath : indexPath animated : YES ] ;
__weak NewGroupViewController * weakSelf = self ;
[ BlockListUIUtils showUnblockContactActionSheet : contact
fromViewController : self
blockingManager : _blockingManager
contactsManager : _contactsManager
completionBlock : ^ ( BOOL isStillBlocked ) {
if ( ! isStillBlocked ) {
// Re - select .
[ weakSelf . tableView selectRowAtIndexPath : indexPath
animated : YES
scrollPosition : UITableViewScrollPositionNone ] ;
ContactTableViewCell * cell = ( ContactTableViewCell * ) [ weakSelf . tableView
cellForRowAtIndexPath : indexPath ] ;
[ weakSelf updateContentsOfCell : cell indexPath : indexPath ] ;
}
} ] ;
return ;
}
2014-10-29 21:58:58 +01:00
2017-04-06 17:44:03 +02:00
ContactTableViewCell * cell = ( ContactTableViewCell * ) [ self . tableView cellForRowAtIndexPath : indexPath ] ;
[ self updateContentsOfCell : cell indexPath : indexPath ] ;
2015-02-17 00:14:50 +01:00
}
2014-10-29 21:58:58 +01:00
2015-12-22 12:45:09 +01:00
- ( void ) tableView : ( UITableView * ) tableView didDeselectRowAtIndexPath : ( NSIndexPath * ) indexPath {
2017-04-06 17:44:03 +02:00
ContactTableViewCell * cell = ( ContactTableViewCell * ) [ self . tableView cellForRowAtIndexPath : indexPath ] ;
[ self updateContentsOfCell : cell indexPath : indexPath ] ;
2014-10-29 21:58:58 +01:00
}
# pragma mark - Text Field Delegate
2015-12-22 12:45:09 +01:00
- ( BOOL ) textFieldShouldReturn : ( UITextField * ) textField {
2014-10-29 21:58:58 +01:00
[ self . nameGroupTextField resignFirstResponder ] ;
return NO ;
}
2017-03-28 22:05:21 +02:00
# pragma mark - UIScrollViewDelegate
- ( void ) scrollViewDidScroll : ( UIScrollView * ) scrollView {
[ self . nameGroupTextField resignFirstResponder ] ;
}
2014-10-29 21:58:58 +01:00
@ end