diff --git a/Classes/Base.lproj/ContactsListView.xib b/Classes/Base.lproj/ContactsListView.xib index f859dc067..95b5effd4 100644 --- a/Classes/Base.lproj/ContactsListView.xib +++ b/Classes/Base.lproj/ContactsListView.xib @@ -1,8 +1,8 @@ - + - + @@ -10,10 +10,10 @@ + - @@ -127,10 +127,13 @@ + + + - + @@ -176,4 +179,9 @@ + + + + + diff --git a/Classes/ContactDetailsView.m b/Classes/ContactDetailsView.m index 4d5384b3a..583fd83f2 100644 --- a/Classes/ContactDetailsView.m +++ b/Classes/ContactDetailsView.m @@ -75,34 +75,12 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info } - (void)removeContact { - if (contact == NULL) { - [PhoneMainView.instance popCurrentView]; - return; - } - - // Remove contact from book - if (ABRecordGetRecordID(contact) != kABRecordInvalidID) { - CFErrorRef error = NULL; - ABAddressBookRemoveRecord(addressBook, contact, (CFErrorRef *)&error); - if (error != NULL) { - LOGE(@"Remove contact %p: Fail(%@)", contact, [(__bridge NSError *)error localizedDescription]); - } else { - LOGI(@"Remove contact %p: Success!", contact); - } - contact = NULL; - - // Save address book - error = NULL; + if (contact != NULL) { inhibUpdate = TRUE; - ABAddressBookSave(addressBook, (CFErrorRef *)&error); + [[[LinphoneManager instance] fastAddressBook] removeContact:contact]; inhibUpdate = FALSE; - if (error != NULL) { - LOGE(@"Save AddressBook: Fail(%@)", [(__bridge NSError *)error localizedDescription]); - } else { - LOGI(@"Save AddressBook: Success!"); - } - [[LinphoneManager instance].fastAddressBook reload]; } + [PhoneMainView.instance popCurrentView]; } - (void)saveData { diff --git a/Classes/ContactsListTableView.h b/Classes/ContactsListTableView.h index 43b993a8b..5f03946bc 100644 --- a/Classes/ContactsListTableView.h +++ b/Classes/ContactsListTableView.h @@ -20,9 +20,11 @@ #import #import +#import "UICheckBoxTVTableViewController.h" + #import "OrderedDictionary.h" -@interface ContactsListTableView : UITableViewController { +@interface ContactsListTableView : UICheckBoxTVTableViewController { @private OrderedDictionary *addressBookMap; NSMutableDictionary *avatarMap; diff --git a/Classes/ContactsListTableView.m b/Classes/ContactsListTableView.m index 9fe75a3b0..45329c247 100644 --- a/Classes/ContactsListTableView.m +++ b/Classes/ContactsListTableView.m @@ -82,6 +82,41 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) { return (int)(within_sentence != NULL ? 0 : fuzzy_word + strlen(fuzzy_word) - c); } +- (NSString *)displayNameForContact:(ABRecordRef)person { + NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty)); + NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName]; + NSString *lLastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty)); + NSString *lLocalizedLastName = [FastAddressBook localizedLabel:lLastName]; + NSString *lOrganization = CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty)); + NSString *lLocalizedlOrganization = [FastAddressBook localizedLabel:lOrganization]; + + NSString *name = nil; + if (lLocalizedFirstName.length && lLocalizedLastName.length) { + name = [NSString stringWithFormat:@"%@ %@", lLocalizedFirstName, lLocalizedLastName]; + } else if (lLocalizedLastName.length) { + name = [NSString stringWithFormat:@"%@", lLocalizedLastName]; + } else if (lLocalizedFirstName.length) { + name = [NSString stringWithFormat:@"%@", lLocalizedFirstName]; + } else if (lLocalizedlOrganization.length) { + name = [NSString stringWithFormat:@"%@", lLocalizedlOrganization]; + } + + if (name != nil && [name length] > 0) { + // Add the contact only if it fuzzy match filter too (if any) + if ([ContactSelection getNameOrEmailFilter] == nil || + (ms_strcmpfuz([[[ContactSelection getNameOrEmailFilter] lowercaseString] UTF8String], + [[name lowercaseString] UTF8String]) == 0)) { + + // Sort contacts by first letter. We need to translate the name to ASCII first, because of UTF-8 + // issues. For instance expected order would be: Alberta(A tilde) before ASylvano. + NSData *name2ASCIIdata = [name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; + NSString *name2ASCII = [[NSString alloc] initWithData:name2ASCIIdata encoding:NSASCIIStringEncoding]; + return name2ASCII; + } + } + return nil; +} + - (void)loadData { LOGI(@"Load contact list"); @synchronized(addressBookMap) { @@ -109,57 +144,24 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) { CFRelease(personEmailAddresses); } - if (add) { - NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty)); - NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName]; - NSString *lLastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty)); - NSString *lLocalizedLastName = [FastAddressBook localizedLabel:lLastName]; - NSString *lOrganization = CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty)); - NSString *lLocalizedlOrganization = [FastAddressBook localizedLabel:lOrganization]; + NSString *name = [self displayNameForContact:person]; + if (add && name != nil) { + NSString *firstChar = [[name substringToIndex:1] uppercaseString]; - NSString *name = nil; - if (lLocalizedFirstName.length && lLocalizedLastName.length) { - name = [NSString stringWithFormat:@"%@ %@", lLocalizedFirstName, lLocalizedLastName]; - } else if (lLocalizedLastName.length) { - name = [NSString stringWithFormat:@"%@", lLocalizedLastName]; - } else if (lLocalizedFirstName.length) { - name = [NSString stringWithFormat:@"%@", lLocalizedFirstName]; - } else if (lLocalizedlOrganization.length) { - name = [NSString stringWithFormat:@"%@", lLocalizedlOrganization]; + // Put in correct subDic + if ([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') { + firstChar = @"#"; } - - if (name != nil && [name length] > 0) { - // Add the contact only if it fuzzy match filter too (if any) - if ([ContactSelection getNameOrEmailFilter] == nil || - (ms_strcmpfuz([[[ContactSelection getNameOrEmailFilter] lowercaseString] UTF8String], - [[name lowercaseString] UTF8String]) == 0)) { - - // Sort contacts by first letter. We need to translate the name to ASCII first, because of UTF-8 - // issues. For instance expected order would be: Alberta(A tilde) before ASylvano. - NSData *name2ASCIIdata = - [name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; - NSString *name2ASCII = - [[NSString alloc] initWithData:name2ASCIIdata encoding:NSASCIIStringEncoding]; - NSString *firstChar = [[name2ASCII substringToIndex:1] uppercaseString]; - - // Put in correct subDic - if ([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') { - firstChar = @"#"; - } - OrderedDictionary *subDic = [addressBookMap objectForKey:firstChar]; - if (subDic == nil) { - subDic = [[OrderedDictionary alloc] init]; - [addressBookMap insertObject:subDic - forKey:firstChar - selector:@selector(caseInsensitiveCompare:)]; - } - [subDic insertObject:lPerson forKey:name2ASCII selector:@selector(caseInsensitiveCompare:)]; - } + OrderedDictionary *subDic = [addressBookMap objectForKey:firstChar]; + if (subDic == nil) { + subDic = [[OrderedDictionary alloc] init]; + [addressBookMap insertObject:subDic forKey:firstChar selector:@selector(caseInsensitiveCompare:)]; } + [subDic insertObject:lPerson forKey:name selector:@selector(caseInsensitiveCompare:)]; } } } - [self.tableView reloadData]; + [super loadData]; } static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) { @@ -184,7 +186,7 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *kCellId = @"UIContactCell"; + NSString *kCellId = NSStringFromClass(UIContactCell.class); UIContactCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId]; if (cell == nil) { cell = [[UIContactCell alloc] initWithIdentifier:kCellId]; @@ -195,24 +197,15 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info ABRecordRef contact = (__bridge ABRecordRef)([subDic objectForKey:key]); // Cached avatar - UIImage *image = nil; - id data = [avatarMap objectForKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]]; - if (data == nil) { - image = [FastAddressBook getContactImage:contact thumbnail:true]; - if (image != nil) { - [avatarMap setObject:image forKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]]; - } else { - [avatarMap setObject:[NSNull null] forKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]]; - } - } else if (data != [NSNull null]) { - image = data; - } + UIImage *image = [avatarMap objectForKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]]; if (image == nil) { - image = [UIImage imageNamed:@"avatar_unknown_small.png"]; + image = [FastAddressBook getContactImage:contact thumbnail:true]; + [avatarMap setObject:image forKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]]; } - [[cell avatarImage] setImage:image]; - + [cell.avatarImage setImage:image]; [cell setContact:contact]; + [super accessoryForCell:cell atPath:indexPath]; + return cell; } @@ -221,28 +214,43 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - OrderedDictionary *subDic = [addressBookMap objectForKey:[addressBookMap keyAtIndex:[indexPath section]]]; - ABRecordRef lPerson = (__bridge ABRecordRef)([subDic objectForKey:[subDic keyAtIndex:[indexPath row]]]); + [super tableView:tableView didSelectRowAtIndexPath:indexPath]; + if (![self isEditing]) { + OrderedDictionary *subDic = [addressBookMap objectForKey:[addressBookMap keyAtIndex:[indexPath section]]]; + ABRecordRef lPerson = (__bridge ABRecordRef)([subDic objectForKey:[subDic keyAtIndex:[indexPath row]]]); - // Go to Contact details view - ContactDetailsView *view = VIEW(ContactDetailsView); - [PhoneMainView.instance changeCurrentView:view.compositeViewDescription push:TRUE]; - if ([ContactSelection getSelectionMode] != ContactSelectionModeEdit) { - [view setContact:lPerson]; - } else { - [view editContact:lPerson address:[ContactSelection getAddAddress]]; + // Go to Contact details view + ContactDetailsView *view = VIEW(ContactDetailsView); + [PhoneMainView.instance changeCurrentView:view.compositeViewDescription push:TRUE]; + if ([ContactSelection getSelectionMode] != ContactSelectionModeEdit) { + [view setContact:lPerson]; + } else { + [view editContact:lPerson address:[ContactSelection getAddAddress]]; + } } } -#pragma mark - UITableViewDelegate Functions - -- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView - editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { - // Detemine if it's in editing mode - if (self.editing) { - return UITableViewCellEditingStyleDelete; +- (void)tableView:(UITableView *)tableView + commitEditingStyle:(UITableViewCellEditingStyle)editingStyle + forRowAtIndexPath:(NSIndexPath *)indexPath { + if (editingStyle == UITableViewCellEditingStyleDelete) { + ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self)); + [tableView beginUpdates]; + OrderedDictionary *subDic = [addressBookMap objectForKey:[addressBookMap keyAtIndex:[indexPath section]]]; + NSString *key = [[subDic allKeys] objectAtIndex:[indexPath row]]; + ABRecordRef contact = (__bridge ABRecordRef)([subDic objectForKey:key]); + NSString *firstChar = [[self displayNameForContact:contact] substringToIndex:1]; + [[addressBookMap objectForKey:firstChar] removeObjectForKey:[self displayNameForContact:contact]]; + if ([tableView numberOfRowsInSection:indexPath.section] == 1) { + [addressBookMap removeObjectForKey:firstChar]; + [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] + withRowAnimation:UITableViewRowAnimationFade]; + } + [[[LinphoneManager instance] fastAddressBook] removeContact:contact]; + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] + withRowAnimation:UITableViewRowAnimationFade]; + [tableView endUpdates]; + ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self)); } - return UITableViewCellEditingStyleNone; } - @end diff --git a/Classes/ContactsListView.h b/Classes/ContactsListView.h index b41706e52..5af2cf370 100644 --- a/Classes/ContactsListView.h +++ b/Classes/ContactsListView.h @@ -22,6 +22,7 @@ #import "UICompositeView.h" #import "ContactsListTableView.h" +#import "UIIconButton.h" typedef enum _ContactSelectionMode { ContactSelectionModeNone, @@ -79,19 +80,19 @@ typedef enum _ContactSelectionMode { : UIViewController @property(strong, nonatomic) IBOutlet ContactsListTableView *tableController; -@property(nonatomic, strong) IBOutlet UINavigationController *sysViewController; @property(strong, nonatomic) IBOutlet UIView *topBar; @property(nonatomic, strong) IBOutlet UIButton *allButton; @property(nonatomic, strong) IBOutlet UIButton *linphoneButton; @property(nonatomic, strong) IBOutlet UIButton *backButton; @property(nonatomic, strong) IBOutlet UIButton *addButton; @property(strong, nonatomic) IBOutlet UISearchBar *searchBar; -@property(weak, nonatomic) IBOutlet UITableView *tableView; +@property(weak, nonatomic) IBOutlet UIIconButton *deleteButton; - (IBAction)onAllClick:(id)event; - (IBAction)onLinphoneClick:(id)event; - (IBAction)onAddContactClick:(id)event; - (IBAction)onBackClick:(id)event; - (IBAction)onEditClick:(id)sender; +- (IBAction)onDeleteClick:(id)sender; @end diff --git a/Classes/ContactsListView.m b/Classes/ContactsListView.m index 6c9cee329..238aa4ced 100644 --- a/Classes/ContactsListView.m +++ b/Classes/ContactsListView.m @@ -78,10 +78,6 @@ static NSString *sNameOrEmailFilter; @implementation ContactsListView @synthesize tableController; -@synthesize tableView; - -@synthesize sysViewController; - @synthesize allButton; @synthesize linphoneButton; @synthesize backButton; @@ -129,7 +125,7 @@ static UICompositeViewDescription *compositeDescription = nil; subViewFrame.size.height -= self.topBar.frame.size.height; [UIView animateWithDuration:0.2 animations:^{ - self.tableView.frame = subViewFrame; + self.tableController.tableView.frame = subViewFrame; }]; } @@ -239,6 +235,21 @@ static UICompositeViewDescription *compositeDescription = nil; } - (IBAction)onEditClick:(id)sender { + [tableController setEditing:!tableController.isEditing animated:TRUE]; + _deleteButton.hidden = !tableController.isEditing; + addButton.hidden = !_deleteButton.hidden; +} + +- (IBAction)onDeleteClick:(id)sender { + NSString *msg = + [NSString stringWithFormat:NSLocalizedString(@"Are you sure that you want to delete %d contacts?", nil), + tableController.selectedItems.count]; + [UIConfirmationDialog ShowWithMessage:msg + onCancelClick:nil + onConfirmationClick:^() { + [tableController removeSelection]; + [tableController loadData]; + }]; } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { diff --git a/Classes/HistoryListTableView.m b/Classes/HistoryListTableView.m index 7a1c193c1..0e64a0c86 100644 --- a/Classes/HistoryListTableView.m +++ b/Classes/HistoryListTableView.m @@ -137,7 +137,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [super tableView:tableView didSelectRowAtIndexPath:indexPath]; - if ([self isEditing]) { + if (![self isEditing]) { LinphoneCallLog *callLog = [[_callLogs objectAtIndex:[indexPath row]] pointerValue]; if (callLog != NULL && linphone_call_log_get_call_id(callLog) != NULL) { LinphoneAddress *addr = linphone_call_log_get_remote_address(callLog); @@ -150,15 +150,6 @@ } } -- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView - editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { - // Detemine if it's in editing mode - if (self.editing) { - return UITableViewCellEditingStyleDelete; - } - return UITableViewCellEditingStyleNone; -} - - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { diff --git a/Classes/HistoryListView.m b/Classes/HistoryListView.m index 32a8c6811..a950a36b5 100644 --- a/Classes/HistoryListView.m +++ b/Classes/HistoryListView.m @@ -22,13 +22,6 @@ @implementation HistoryListView -@synthesize tableController; - -@synthesize allButton; -@synthesize missedButton; -@synthesize editButton; -@synthesize deleteButton; - typedef enum _HistoryView { History_All, History_Missed, History_MAX } HistoryView; #pragma mark - Lifecycle Functions @@ -62,11 +55,11 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - if ([tableController isEditing]) { - [tableController setEditing:FALSE animated:FALSE]; + if ([_tableController isEditing]) { + [_tableController setEditing:FALSE animated:FALSE]; } - [deleteButton setHidden:TRUE]; - [editButton setOff]; + [_deleteButton setHidden:TRUE]; + [_editButton setOff]; [self changeView:History_All]; // Reset missed call @@ -88,26 +81,26 @@ static UICompositeViewDescription *compositeDescription = nil; #pragma mark - - (void)hideEditIfNeeded { - editButton.hidden = ([tableController tableView:tableController.tableView numberOfRowsInSection:0] == 0); - if ([editButton isSelected]) { - [editButton toggle]; + _editButton.hidden = ([_tableController tableView:_tableController.tableView numberOfRowsInSection:0] == 0); + if ([_editButton isSelected]) { + [_editButton toggle]; [self onEditClick:nil]; } } - (void)changeView:(HistoryView)view { if (view == History_All) { - allButton.selected = TRUE; - [tableController setMissedFilter:FALSE]; + _allButton.selected = TRUE; + [_tableController setMissedFilter:FALSE]; } else { - allButton.selected = FALSE; + _allButton.selected = FALSE; } if (view == History_Missed) { - missedButton.selected = TRUE; - [tableController setMissedFilter:TRUE]; + _missedButton.selected = TRUE; + [_tableController setMissedFilter:TRUE]; } else { - missedButton.selected = FALSE; + _missedButton.selected = FALSE; } [self hideEditIfNeeded]; } @@ -123,19 +116,19 @@ static UICompositeViewDescription *compositeDescription = nil; } - (IBAction)onEditClick:(id)event { - [tableController setEditing:![tableController isEditing] animated:TRUE]; - [deleteButton setHidden:![tableController isEditing]]; + [_tableController setEditing:!_tableController.isEditing animated:TRUE]; + _deleteButton.hidden = !_tableController.isEditing; } - (IBAction)onDeleteClick:(id)event { NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Are you sure that you want to delete %d history?", nil), - tableController.selectedItems.count]; + _tableController.selectedItems.count]; [UIConfirmationDialog ShowWithMessage:msg onCancelClick:nil onConfirmationClick:^() { - [tableController removeSelection]; - [tableController loadData]; + [_tableController removeSelection]; + [_tableController loadData]; [self hideEditIfNeeded]; }]; } diff --git a/Classes/LinphoneUI/UICheckBoxTVTableViewController.m b/Classes/LinphoneUI/UICheckBoxTVTableViewController.m index 602f1a5e1..8e953fef1 100644 --- a/Classes/LinphoneUI/UICheckBoxTVTableViewController.m +++ b/Classes/LinphoneUI/UICheckBoxTVTableViewController.m @@ -43,7 +43,19 @@ [self accessoryForCell:cell atPath:indexPath]; } +- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView + editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { + // Detemine if it's in editing mode + if (self.editing) { + return UITableViewCellEditingStyleDelete; + } + return UITableViewCellEditingStyleNone; +} + +#pragma mark - + - (void)accessoryForCell:(UITableViewCell *)cell atPath:(NSIndexPath *)indexPath { + cell.selectionStyle = UITableViewCellSelectionStyleNone; if ([self isEditing]) { UIImage *image = nil; if (cell.accessoryType == UITableViewCellAccessoryCheckmark) { @@ -80,7 +92,7 @@ - (void)removeSelection { // we must iterate through selected items in reverse order [_selectedItems sortUsingComparator:^(NSIndexPath *obj1, NSIndexPath *obj2) { - return [obj1 compare:obj2]; + return [obj2 compare:obj1]; }]; for (NSIndexPath *indexPath in _selectedItems) { [self tableView:self.tableView diff --git a/Classes/LinphoneUI/UIContactCell.m b/Classes/LinphoneUI/UIContactCell.m index c5a03deac..a5de1bdd4 100644 --- a/Classes/LinphoneUI/UIContactCell.m +++ b/Classes/LinphoneUI/UIContactCell.m @@ -35,9 +35,11 @@ NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil]; - if ([arrayOfViews count] >= 1) { - [self.contentView addSubview:[arrayOfViews objectAtIndex:0]]; - } + // resize cell to match .nib size. It is needed when resized the cell to + // correctly adapt its height too + UIView *sub = ((UIView *)[arrayOfViews objectAtIndex:0]); + [self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)]; + [self addSubview:sub]; } return self; } @@ -77,4 +79,18 @@ } } +- (void)setEditing:(BOOL)editing { + [self setEditing:editing animated:FALSE]; +} + +- (void)setEditing:(BOOL)editing animated:(BOOL)animated { + if (animated) { + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.3]; + } + if (animated) { + [UIView commitAnimations]; + } +} + @end diff --git a/Classes/LinphoneUI/UIHistoryCell.m b/Classes/LinphoneUI/UIHistoryCell.m index e379e01a4..19216bc3c 100644 --- a/Classes/LinphoneUI/UIHistoryCell.m +++ b/Classes/LinphoneUI/UIHistoryCell.m @@ -39,7 +39,6 @@ UIView *sub = ((UIView *)[arrayOfViews objectAtIndex:0]); [self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)]; [self addSubview:sub]; - self.selectionStyle = UITableViewCellSelectionStyleNone; callLog = NULL; } return self; diff --git a/Classes/Utils/FastAddressBook.h b/Classes/Utils/FastAddressBook.h index 89771ba06..e9e3688ac 100644 --- a/Classes/Utils/FastAddressBook.h +++ b/Classes/Utils/FastAddressBook.h @@ -29,6 +29,7 @@ - (void)reload; - (void)saveAddressBook; +- (int)removeContact:(ABRecordRef)contact; + (BOOL)isAuthorized; diff --git a/Classes/Utils/FastAddressBook.m b/Classes/Utils/FastAddressBook.m index 65618211e..ec99d1a1d 100644 --- a/Classes/Utils/FastAddressBook.m +++ b/Classes/Utils/FastAddressBook.m @@ -341,4 +341,28 @@ void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void return ret; } +- (int)removeContact:(ABRecordRef)contact { + // Remove contact from book + if (contact && ABRecordGetRecordID(contact) != kABRecordInvalidID) { + CFErrorRef error = NULL; + ABAddressBookRemoveRecord(addressBook, contact, (CFErrorRef *)&error); + if (error != NULL) { + LOGE(@"Remove contact %p: Fail(%@)", contact, [(__bridge NSError *)error localizedDescription]); + } else { + LOGI(@"Remove contact %p: Success!", contact); + } + contact = NULL; + + // Save address book + error = NULL; + ABAddressBookSave(addressBook, (CFErrorRef *)&error); + if (error != NULL) { + LOGE(@"Save AddressBook: Fail(%@)", [(__bridge NSError *)error localizedDescription]); + } else { + LOGI(@"Save AddressBook: Success!"); + } + return error ? -1 : 0; + } + return -2; +} @end