2014-10-29 21:58:58 +01:00
|
|
|
//
|
|
|
|
// NewGroupViewController.m
|
|
|
|
// Signal
|
|
|
|
//
|
|
|
|
// Created by Dylan Bourgeois on 13/11/14.
|
|
|
|
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "NewGroupViewController.h"
|
|
|
|
#import "SignalsViewController.h"
|
2014-11-21 14:38:37 +01:00
|
|
|
#import "ContactsManager.h"
|
|
|
|
#import "Environment.h"
|
2014-12-24 02:25:10 +01:00
|
|
|
#import "FunctionalUtil.h"
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2014-12-17 06:44:36 +01:00
|
|
|
#import "SecurityUtils.h"
|
|
|
|
#import "SignalKeyingStorage.h"
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2014-12-31 19:31:27 +01:00
|
|
|
#import "UIImage+normalizeImage.h"
|
|
|
|
|
2014-11-24 21:51:43 +01:00
|
|
|
#import "UIUtil.h"
|
2015-01-14 22:30:01 +01:00
|
|
|
#import "DJWActionSheet+OWS.h"
|
2014-10-29 21:58:58 +01:00
|
|
|
#import <MobileCoreServices/UTCoreTypes.h>
|
|
|
|
|
2014-12-24 02:25:10 +01:00
|
|
|
static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue";
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
@interface NewGroupViewController () {
|
|
|
|
NSArray* contacts;
|
|
|
|
}
|
2014-12-17 06:44:36 +01:00
|
|
|
@property TSGroupThread* thread;
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
@end
|
|
|
|
@implementation NewGroupViewController
|
|
|
|
|
2014-12-17 06:44:36 +01:00
|
|
|
- (void)configWithThread:(TSGroupThread *)gThread{
|
|
|
|
_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
|
|
|
contacts = [Environment getCurrent].contactsManager.textSecureContacts;
|
|
|
|
|
2015-01-27 02:20:11 +01:00
|
|
|
|
|
|
|
self.tableView.tableHeaderView.frame = CGRectMake(0, 0, 400, 44);
|
|
|
|
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
|
2015-02-17 00:14:50 +01:00
|
|
|
|
|
|
|
|
2014-12-24 02:25:10 +01:00
|
|
|
contacts = [contacts filter:^int(Contact* contact) {
|
|
|
|
for(PhoneNumber* number in [contact parsedPhoneNumbers]) {
|
|
|
|
if([[number toE164] isEqualToString:[SignalKeyingStorage.localNumber toE164]]) {
|
2015-01-30 04:31:35 +01:00
|
|
|
// remove local number
|
2014-12-24 02:25:10 +01:00
|
|
|
return NO;
|
|
|
|
}
|
2015-01-30 04:31:35 +01:00
|
|
|
else if(_thread!=nil && _thread.groupModel.groupMemberIds){
|
|
|
|
return ![_thread.groupModel.groupMemberIds containsObject:[number toE164]];
|
|
|
|
}
|
2014-12-24 02:25:10 +01:00
|
|
|
}
|
|
|
|
return YES;
|
|
|
|
}];
|
|
|
|
|
|
|
|
[self initializeDelegates];
|
|
|
|
[self initializeTableView];
|
|
|
|
[self initializeKeyboardHandlers];
|
|
|
|
|
2014-12-17 06:44:36 +01:00
|
|
|
if(_thread==nil) {
|
2015-01-27 02:20:11 +01:00
|
|
|
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-02-18 23:21:03 +01:00
|
|
|
self.navigationItem.title = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @"");
|
2014-12-17 06:44:36 +01:00
|
|
|
}
|
|
|
|
else {
|
2015-02-18 23:21:03 +01:00
|
|
|
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:NSLocalizedString(@"UPDATE_BUTTON_TITLE", @"") style:UIBarButtonItemStylePlain target:self action:@selector(updateGroup)];
|
2014-12-17 06:44:36 +01:00
|
|
|
self.navigationItem.title = _thread.groupModel.groupName;
|
|
|
|
self.nameGroupTextField.text = _thread.groupModel.groupName;
|
2015-01-04 20:48:43 +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", @"");
|
|
|
|
_addPeopleLabel.text = NSLocalizedString(@"NEW_GROUP_REQUEST_ADDPEOPLE", @"");
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)didReceiveMemoryWarning {
|
|
|
|
[super didReceiveMemoryWarning];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Initializers
|
|
|
|
|
|
|
|
-(void)initializeDelegates
|
|
|
|
{
|
|
|
|
self.nameGroupTextField.delegate = self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)initializeTableView
|
|
|
|
{
|
|
|
|
self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Keyboard notifications
|
|
|
|
|
|
|
|
- (void)initializeKeyboardHandlers{
|
|
|
|
UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)];
|
|
|
|
[self.tapToDismissView addGestureRecognizer:outsideTabRecognizer];
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void) dismissKeyboardFromAppropriateSubView {
|
|
|
|
[self.nameGroupTextField resignFirstResponder];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Actions
|
|
|
|
-(void)createGroup {
|
2015-01-16 15:28:41 +01:00
|
|
|
TSGroupModel* model = [self makeGroup];
|
2015-04-14 21:49:00 +02:00
|
|
|
[Environment messageGroupModel:model withCompose:YES];
|
2014-12-17 06:44:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)updateGroup {
|
2014-12-24 02:25:10 +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-02-28 17:49:46 +01:00
|
|
|
|
|
|
|
_groupModel = [[TSGroupModel alloc] initWithTitle:_nameGroupTextField.text
|
|
|
|
memberIds:[[[NSSet setWithArray:mut] allObjects] mutableCopy]
|
|
|
|
image:_thread.groupModel.groupImage
|
|
|
|
groupId:_thread.groupModel.groupId
|
|
|
|
associatedAttachmentId:nil];
|
|
|
|
|
|
|
|
[self.nameGroupTextField resignFirstResponder];
|
|
|
|
|
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
|
|
|
|
2015-01-16 15:28:41 +01:00
|
|
|
-(TSGroupModel*)makeGroup {
|
2014-10-29 21:58:58 +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
|
|
|
}
|
2014-12-17 06:44:36 +01:00
|
|
|
[mut addObject:[SignalKeyingStorage.localNumber toE164]];
|
|
|
|
NSData* groupId = [SecurityUtils generateRandomBytes:16];
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2015-01-31 12:37:36 +01:00
|
|
|
return [[TSGroupModel alloc] initWithTitle:title memberIds:mut image:_groupImage groupId:groupId associatedAttachmentId:nil];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
-(IBAction)addGroupPhoto:(id)sender
|
|
|
|
{
|
2014-12-24 02:25:10 +01:00
|
|
|
[self.nameGroupTextField resignFirstResponder];
|
2015-02-18 23:21:03 +01:00
|
|
|
[DJWActionSheet showInView:self.parentViewController.view withTitle:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
|
|
|
destructiveButtonTitle:nil otherButtonTitles:@[NSLocalizedString(@"TAKE_PICTURE_BUTTON", @""),NSLocalizedString(@"CHOOSE_MEDIA_BUTTON", @"")]
|
2014-10-29 21:58:58 +01:00
|
|
|
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
|
|
|
|
|
|
|
|
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
|
2015-08-14 00:19:29 +02:00
|
|
|
DDLogDebug(@"User Cancelled");
|
2014-10-29 21:58:58 +01:00
|
|
|
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
|
2015-08-14 00:19:29 +02:00
|
|
|
DDLogDebug(@"Destructive button tapped");
|
2014-10-29 21:58:58 +01:00
|
|
|
}else {
|
|
|
|
switch (tappedButtonIndex) {
|
|
|
|
case 0:
|
|
|
|
[self takePicture];
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
[self chooseFromLibrary];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Group Image
|
|
|
|
|
|
|
|
-(void)takePicture
|
|
|
|
{
|
|
|
|
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)chooseFromLibrary
|
|
|
|
{
|
|
|
|
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
|
|
|
picker.delegate = self;
|
|
|
|
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
|
|
|
|
|
|
|
|
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
|
|
|
|
{
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
|
|
|
|
{
|
|
|
|
UIImage *picture_camera = [info objectForKey:UIImagePickerControllerOriginalImage];
|
|
|
|
|
|
|
|
if (picture_camera) {
|
2015-01-04 20:48:43 +01:00
|
|
|
UIImage *small = [picture_camera resizedImageToFitInSize:CGSizeMake(100.00,100.00) scaleIfSmaller:NO];
|
|
|
|
_thread.groupModel.groupImage = small;
|
2015-01-30 04:31:35 +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];
|
|
|
|
}
|
|
|
|
|
2014-12-24 02:25:10 +01:00
|
|
|
-(void)setupGroupImageButton:(UIImage*)image {
|
2015-01-30 04:31:35 +01:00
|
|
|
[_groupImageButton setImage:image forState:UIControlStateNormal];
|
|
|
|
_groupImageButton.imageView.layer.cornerRadius = CGRectGetWidth([_groupImageButton.imageView frame])/2.0f;
|
|
|
|
_groupImageButton.imageView.layer.masksToBounds = YES;
|
|
|
|
_groupImageButton.imageView.layer.borderColor = [[UIColor lightGrayColor] CGColor];
|
|
|
|
_groupImageButton.imageView.layer.borderWidth = 0.5f;
|
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 {
|
|
|
|
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchCell"];
|
|
|
|
|
|
|
|
if (cell == nil) {
|
2015-01-27 02:20:11 +01:00
|
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GroupSearchCell"];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
2015-02-17 00:14:50 +01:00
|
|
|
|
2015-01-27 02:20:11 +01:00
|
|
|
NSUInteger row = (NSUInteger)indexPath.row;
|
|
|
|
Contact* contact = contacts[row];
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2015-01-27 02:20:11 +01:00
|
|
|
cell.textLabel.attributedText = [self attributedStringForContact:contact inCell:cell];
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
|
|
|
2015-02-17 00:14:50 +01:00
|
|
|
if ([[tableView indexPathsForSelectedRows] containsObject:indexPath]) {
|
|
|
|
[self adjustSelected:cell];
|
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Table View delegate
|
|
|
|
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
|
|
{
|
|
|
|
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
|
2015-02-17 00:14:50 +01:00
|
|
|
[self adjustSelected:cell];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-02-17 00:14:50 +01:00
|
|
|
- (void)adjustSelected:(UITableViewCell*)cell {
|
|
|
|
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
|
|
{
|
|
|
|
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
|
2015-01-27 02:20:11 +01:00
|
|
|
cell.accessoryType = UITableViewCellAccessoryNone;
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Text Field Delegate
|
|
|
|
|
|
|
|
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
|
|
|
|
[self.nameGroupTextField resignFirstResponder];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
#pragma mark - Cell Utility
|
|
|
|
|
|
|
|
- (NSAttributedString *)attributedStringForContact:(Contact *)contact inCell:(UITableViewCell*)cell {
|
|
|
|
NSMutableAttributedString *fullNameAttributedString = [[NSMutableAttributedString alloc] initWithString:contact.fullName];
|
|
|
|
|
|
|
|
UIFont *firstNameFont;
|
|
|
|
UIFont *lastNameFont;
|
|
|
|
|
|
|
|
if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) {
|
2015-01-14 22:30:01 +01:00
|
|
|
firstNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize];
|
|
|
|
lastNameFont = [UIFont ows_regularFontWithSize:cell.textLabel.font.pointSize];
|
2014-11-21 14:38:37 +01:00
|
|
|
} else{
|
2015-01-14 22:30:01 +01:00
|
|
|
firstNameFont = [UIFont ows_regularFontWithSize:cell.textLabel.font.pointSize];
|
|
|
|
lastNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize];
|
2014-11-21 14:38:37 +01:00
|
|
|
}
|
|
|
|
[fullNameAttributedString addAttribute:NSFontAttributeName value:firstNameFont range:NSMakeRange(0, contact.firstName.length)];
|
|
|
|
[fullNameAttributedString addAttribute:NSFontAttributeName value:lastNameFont range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)];
|
|
|
|
|
|
|
|
[fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, contact.fullName.length)];
|
2015-01-14 22:30:01 +01:00
|
|
|
|
|
|
|
if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) {
|
|
|
|
[fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
[fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(0, contact.firstName.length)];
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
return fullNameAttributedString;
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
@end
|