1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 09:27:55 +01:00
Telegram/Telegraph/TGCreateContactController.m
2015-10-01 19:19:52 +03:00

495 lines
19 KiB
Objective-C

/*
* This is the source code of Telegram for iOS v. 1.1
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Peter Iakovlev, 2013.
*/
#import "TGCreateContactController.h"
#import "ActionStage.h"
#import "TGPhoneUtils.h"
#import "TGStringUtils.h"
#import "TGDatabase.h"
#import "TGUserInfoCollectionItem.h"
#import "TGUserInfoEditingPhoneCollectionItem.h"
#import "TGUserInfoAddPhoneCollectionItem.h"
#import "TGNavigationController.h"
#import "TGPhoneLabelPickerController.h"
#import "TGSynchronizeContactsActor.h"
#import "TGAlertView.h"
@interface TGCreateContactController () <TGUserInfoEditingPhoneCollectionItemDelegate, TGPhoneLabelPickerControllerDelegate>
{
int32_t _uid;
TGUser *_user;
TGPhonebookContact *_phonebookInfo;
int32_t _uidToAdd;
NSString *_phoneNumberToAdd;
bool _activateNameEditingOnReset;
NSIndexPath *_currentLabelPickerIndexPath;
}
@end
@implementation TGCreateContactController
- (instancetype)init
{
self = [super init];
if (self != nil)
{
[self _commonInit:true];
_activateNameEditingOnReset = true;
}
return self;
}
- (instancetype)initWithUid:(int32_t)uid firstName:(NSString *)firstName lastName:(NSString *)lastName phoneNumber:(NSString *)phoneNumber
{
self = [super init];
if (self != nil)
{
[self _commonInit:true];
_uid = uid;
_user = [[TGDatabaseInstance() loadUser:_uid] copy];
_user.firstName = firstName;
_user.lastName = lastName;
_user.phoneNumber = phoneNumber;
[self.userInfoItem setUser:_user animated:false];
self.navigationItem.rightBarButtonItem.enabled = firstName.length != 0 || lastName.length != 0;
if (phoneNumber.length != 0)
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = [[TGSynchronizeContactsManager phoneLabels] firstObject];
phoneItem.phone = phoneNumber;
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
}
return self;
}
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName phoneNumber:(NSString *)phoneNumber
{
self = [super init];
if (self != nil)
{
[self _commonInit:true];
_user = [[TGUser alloc] init];
_user.firstName = firstName;
_user.lastName = lastName;
_user.phoneNumber = phoneNumber;
[self.userInfoItem setUser:_user animated:false];
self.navigationItem.rightBarButtonItem.enabled = firstName.length != 0 || lastName.length != 0;
if (phoneNumber.length != 0)
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = [[TGSynchronizeContactsManager phoneLabels] firstObject];
phoneItem.phone = phoneNumber;
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
}
return self;
}
- (instancetype)initWithUid:(int32_t)uid phoneNumber:(NSString *)phoneNumber existingUid:(int32_t)existingUid
{
self = [super init];
if (self != nil)
{
[self _commonInit:false];
_uid = existingUid;
_user = [[TGDatabaseInstance() loadUser:existingUid] copy];
_phonebookInfo = [TGDatabaseInstance() phonebookContactByPhoneId:phoneMatchHash(_user.phoneNumber)];
_uidToAdd = uid;
_phoneNumberToAdd = phoneNumber;
[self.userInfoItem setUser:_user animated:false];
self.navigationItem.rightBarButtonItem.enabled = _user.firstName.length != 0 || _user.lastName.length != 0;
NSMutableArray *existingLabels = [[NSMutableArray alloc] initWithArray:[TGSynchronizeContactsManager phoneLabels]];
for (TGPhoneNumber *number in _phonebookInfo.phoneNumbers)
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = number.label;
phoneItem.phone = number.number;
if (number.label != nil)
[existingLabels removeObject:number.label];
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
if (phoneNumber.length != 0)
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = existingLabels.count != 0 ? [existingLabels firstObject] : [[TGSynchronizeContactsManager phoneLabels] lastObject];
phoneItem.phone = phoneNumber;
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
}
return self;
}
- (instancetype)initWithUid:(int32_t)uid phoneNumber:(NSString *)phoneNumber existingNativeContactId:(int)existingNativeContactId
{
self = [super init];
if (self != nil)
{
[self _commonInit:false];
_phonebookInfo = [TGDatabaseInstance() phonebookContactByNativeId:existingNativeContactId];
_user = [[TGUser alloc] init];
_user.firstName = _phonebookInfo.firstName;
_user.lastName = _phonebookInfo.lastName;
_uidToAdd = uid;
_phoneNumberToAdd = phoneNumber;
self.userInfoItem.disableAvatar = true;
[self.userInfoItem setUser:_user animated:false];
self.navigationItem.rightBarButtonItem.enabled = _user.firstName.length != 0 || _user.lastName.length != 0;
NSMutableArray *existingLabels = [[NSMutableArray alloc] initWithArray:[TGSynchronizeContactsManager phoneLabels]];
for (TGPhoneNumber *number in _phonebookInfo.phoneNumbers)
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = number.label;
phoneItem.phone = number.number;
if (number.label != nil)
[existingLabels removeObject:number.label];
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
if (phoneNumber.length != 0)
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = existingLabels.count != 0 ? [existingLabels firstObject] : [[TGSynchronizeContactsManager phoneLabels] lastObject];
phoneItem.phone = phoneNumber;
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
}
return self;
}
- (void)_commonInit:(bool)isModal
{
[self setTitleText:TGLocalized(@"NewContact.Title")];
if (isModal)
[self setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Cancel") style:UIBarButtonItemStylePlain target:self action:@selector(cancelPressed)]];
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Done") style:UIBarButtonItemStyleDone target:self action:@selector(donePressed)]];
self.navigationItem.rightBarButtonItem.enabled = false;
UIEdgeInsets phonesSectionInsets = self.phonesSection.insets;
phonesSectionInsets.top += 32.0f;
self.phonesSection.insets = phonesSectionInsets;
[self.userInfoItem setEditing:true animated:false];
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections insertItem:[[TGUserInfoAddPhoneCollectionItem alloc] initWithAction:@selector(addPhonePressed)] toSection:phonesSectionIndex atIndex:0];
}
}
- (void)_resetCollectionView
{
[super _resetCollectionView];
if ([self.collectionView respondsToSelector:@selector(setKeyboardDismissMode:)])
self.collectionView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
if (_activateNameEditingOnReset)
{
_activateNameEditingOnReset = false;
[self.collectionView layoutSubviews];
[self.userInfoItem makeNameFieldFirstResponder];
}
[self enterEditingMode:false];
}
- (void)cancelPressed
{
[self.presentingViewController dismissViewControllerAnimated:true completion:nil];
}
- (void)donePressed
{
if (!self.view.userInteractionEnabled)
return;
self.view.userInteractionEnabled = false;
int matchHash = phoneMatchHash(_user.phoneNumber);
bool hasCurrentNumber = false;
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
for (id item in self.phonesSection.items)
{
if ([item isKindOfClass:[TGUserInfoEditingPhoneCollectionItem class]])
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = item;
if (phoneItem.phone.length != 0)
{
[phoneNumbers addObject:[[TGPhoneNumber alloc] initWithLabel:phoneItem.label number:phoneItem.phone]];
if (!hasCurrentNumber && phoneMatchHash(phoneItem.phone) == matchHash)
hasCurrentNumber = true;
}
}
}
if (_phonebookInfo != nil)
[self changePhoneNumbers:phoneNumbers removedMainPhone:false];
else
{
TGPhonebookContact *phonebookContact = [[TGPhonebookContact alloc] init];
phonebookContact.firstName = self.userInfoItem.editingFirstName == nil ? @"" : self.userInfoItem.editingFirstName;
phonebookContact.lastName = self.userInfoItem.editingLastName == nil ? @"" : self.userInfoItem.editingLastName;
phonebookContact.phoneNumbers = phoneNumbers;
static int actionId = 0;
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/synchronizeContacts/(%d,%d,addContactLocal)", _uid, actionId++] options:[NSDictionary dictionaryWithObjectsAndKeys:phonebookContact, @"contact", [[NSNumber alloc] initWithInt:hasCurrentNumber ? _uid : 0], @"uid", nil] watcher:self];
}
}
- (void)addPhonePressed
{
NSMutableArray *possibleLabels = [[NSMutableArray alloc] initWithArray:[TGSynchronizeContactsManager phoneLabels]];
for (id item in self.phonesSection.items)
{
if ([item isKindOfClass:[TGUserInfoEditingPhoneCollectionItem class]])
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = item;
if (phoneItem.label != nil)
[possibleLabels removeObject:phoneItem.label];
}
}
TGUserInfoEditingPhoneCollectionItem *phoneItem = [[TGUserInfoEditingPhoneCollectionItem alloc] init];
phoneItem.delegate = self;
phoneItem.label = possibleLabels.count != 0 ? [possibleLabels firstObject] : [[TGSynchronizeContactsManager phoneLabels] lastObject];
NSUInteger phonesSectionIndex = [self indexForSection:self.phonesSection];
if (phonesSectionIndex != NSNotFound)
{
[self.menuSections beginRecordingChanges];
[self.menuSections insertItem:phoneItem toSection:phonesSectionIndex atIndex:MAX(0, (NSInteger)self.phonesSection.items.count - 1)];
[self.menuSections commitRecordedChanges:self.collectionView];
[phoneItem makePhoneFieldFirstResponder];
}
}
- (void)editingPhoneItemRequestedDelete:(TGUserInfoEditingPhoneCollectionItem *)editingPhoneItem
{
NSIndexPath *indexPath = [self indexPathForItem:editingPhoneItem];
if (indexPath != nil)
{
[self.menuSections beginRecordingChanges];
[self.menuSections deleteItemFromSection:indexPath.section atIndex:indexPath.item];
[self.menuSections commitRecordedChanges:self.collectionView];
}
}
- (void)editingPhoneItemRequestedLabelSelection:(TGUserInfoEditingPhoneCollectionItem *)editingPhoneItem
{
NSIndexPath *indexPath = [self indexPathForItem:editingPhoneItem];
if (indexPath != nil)
{
_currentLabelPickerIndexPath = indexPath;
TGPhoneLabelPickerController *labelController = [[TGPhoneLabelPickerController alloc] initWithSelectedLabel:editingPhoneItem.label];
labelController.delegate = self;
TGNavigationController *navigationController = [TGNavigationController navigationControllerWithControllers:@[labelController]];
if ([self inPopover])
{
navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
navigationController.presentationStyle = TGNavigationControllerPresentationStyleChildInPopover;
}
else if ([self inFormSheet])
{
navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
navigationController.presentationStyle = TGNavigationControllerPresentationStyleInFormSheet;
}
[self presentViewController:navigationController animated:true completion:nil];
}
}
- (void)phoneLabelPickerController:(TGPhoneLabelPickerController *)__unused phoneLabelPickerController didFinishWithLabel:(NSString *)label
{
TGUserInfoEditingPhoneCollectionItem *phoneItem = self.phonesSection.items[_currentLabelPickerIndexPath.item];
phoneItem.label = label;
_currentLabelPickerIndexPath = nil;
}
- (void)changePhoneNumbers:(NSArray *)phoneNumbers removedMainPhone:(bool)removedMainPhone
{
self.view.userInteractionEnabled = false;
[ActionStageInstance() dispatchOnStageQueue:^
{
if ([TGSynchronizeContactsManager instance].phonebookAccessStatus != TGPhonebookAccessStatusEnabled)
{
TGDispatchOnMainThread(^
{
self.view.userInteractionEnabled = true;
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"Profile.PhonebookAccessDisabled") delegate:nil cancelButtonTitle:TGLocalized(@"Common.OK") otherButtonTitles:nil] show];
});
}
else
{
TGDispatchOnMainThread(^
{
self.view.userInteractionEnabled = true;
});
static int actionId = 0;
NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
[options setObject:[[NSNumber alloc] initWithInt:_uid] forKey:@"uid"];
[options setObject:[[NSNumber alloc] initWithInt:_phonebookInfo.nativeId] forKey:@"nativeId"];
if (phoneNumbers != nil)
[options setObject:phoneNumbers forKey:@"phones"];
if (removedMainPhone)
[options setObject:[[NSNumber alloc] initWithBool:true] forKey:@"removedMainPhone"];
bool found = false;
NSString *phoneNumberToAdd = [TGPhoneUtils cleanInternationalPhone:_phoneNumberToAdd forceInternational:false];
for (TGPhoneNumber *phoneNumber in phoneNumbers)
{
if ([[TGPhoneUtils cleanInternationalPhone:phoneNumber.number forceInternational:false] isEqualToString:phoneNumberToAdd])
{
found = true;
break;
}
}
if (found)
[options setObject:@(_uidToAdd) forKey:@"addingUid"];
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/synchronizeContacts/(%s,%d,changePhonesLocal)", removedMainPhone ? "removedMainPhone" : "", actionId++] options:options watcher:self];
}
}];
}
#pragma mark -
- (void)actionStageActionRequested:(NSString *)action options:(id)options
{
if ([action isEqualToString:@"editingNameChanged"])
{
self.navigationItem.rightBarButtonItem.enabled = self.userInfoItem.editingFirstName.length != 0 || self.userInfoItem.editingLastName.length != 0;
}
[super actionStageActionRequested:action options:options];
}
- (void)actorCompleted:(int)status path:(NSString *)path result:(id)result
{
if ([path hasSuffix:@"addContactLocal)"] || [path hasSuffix:@"changePhonesLocal)"])
{
TGDispatchOnMainThread(^
{
self.view.userInteractionEnabled = true;
id<TGCreateContactControllerDelegate> delegate = _delegate;
if ([delegate respondsToSelector:@selector(createContactControllerDidFinish:)])
[delegate createContactControllerDidFinish:self];
else
[self.presentingViewController dismissViewControllerAnimated:true completion:nil];
});
}
[super actorCompleted:status path:path result:result];
}
@end