diff --git a/Classes/Base.lproj/ContactDetailsView.xib b/Classes/Base.lproj/ContactDetailsView.xib
index 513c57641..f58448469 100644
--- a/Classes/Base.lproj/ContactDetailsView.xib
+++ b/Classes/Base.lproj/ContactDetailsView.xib
@@ -72,7 +72,7 @@
-
+
@@ -126,7 +126,7 @@
-
+
diff --git a/Classes/ContactDetailsTableView.m b/Classes/ContactDetailsTableView.m
index 352652f25..ee376a013 100644
--- a/Classes/ContactDetailsTableView.m
+++ b/Classes/ContactDetailsTableView.m
@@ -572,13 +572,12 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
[cell setAddress:value];
if (contactSections[[indexPath section]] == ContactSections_Number) {
[cell.editTextfield setKeyboardType:UIKeyboardTypePhonePad];
- [cell.editTextfield setPlaceholder:NSLocalizedString(@"Phone number", nil)];
} else if (contactSections[[indexPath section]] == ContactSections_Sip) {
[cell.editTextfield setKeyboardType:UIKeyboardTypeASCIICapable];
- [cell.editTextfield setPlaceholder:NSLocalizedString(@"SIP address", nil)];
} else if (contactSections[[indexPath section]] == ContactSections_Email) {
[cell.editTextfield setKeyboardType:UIKeyboardTypeASCIICapable];
- [cell.editTextfield setPlaceholder:NSLocalizedString(@"Email address", nil)];
+ } else {
+ [cell.editTextfield setKeyboardType:UIKeyboardTypeDefault];
}
return cell;
}
@@ -591,7 +590,8 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
NSString *key = nil;
ABPropertyID property = [self propertyIDForSection:contactSections[indexPath.section]];
- if (property != kABInvalidPropertyType) {
+ if (property != kABInvalidPropertyType && property != kABPersonFirstNameProperty &&
+ property != kABPersonLastNameProperty) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, property);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
NSString *labelRef = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(lMap, index));
@@ -625,8 +625,30 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
- if (!editing) {
+ BOOL showEmails = [[LinphoneManager instance] lpConfigBoolForKey:@"show_contacts_emails_preference"];
+ if (editing) {
+ // add phone/SIP/email entries so that the user can add new data
+ for (int section = 0; section < [self numberOfSectionsInTableView:[self tableView]]; ++section) {
+ if (contactSections[section] == ContactSections_Number || contactSections[section] == ContactSections_Sip ||
+ (showEmails && contactSections[section] == ContactSections_Email)) {
+ [self addEntry:self.tableView section:section animated:animated];
+ }
+ }
+ } else {
[LinphoneUtils findAndResignFirstResponder:[self tableView]];
+ // remove empty phone numbers
+ for (int section = 0; section < [self numberOfSectionsInTableView:[self tableView]]; ++section) {
+ // remove phony entries that were not filled by the user
+ if (contactSections[section] == ContactSections_Number || contactSections[section] == ContactSections_Sip ||
+ (showEmails && contactSections[section] == ContactSections_Email)) {
+
+ [self removeEmptyEntry:self.tableView section:section animated:animated];
+ if ([[self getSectionData:section] count] == 0 && animated) { // the section is empty -> remove titles
+ [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section]
+ withRowAnimation:UITableViewRowAnimationFade];
+ }
+ }
+ }
}
[self loadData];
if (contactDetailsDelegate != nil) {
@@ -642,6 +664,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
NSString *text = nil;
BOOL canAddEntry = self.tableView.isEditing;
+ NSString *addEntryName = nil;
if (contactSections[section] == ContactSections_First_Name && self.tableView.isEditing) {
text = NSLocalizedString(@"First name", nil);
canAddEntry = NO;
@@ -651,11 +674,14 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
} else if ([self getSectionData:section].count > 0 || self.tableView.isEditing) {
if (contactSections[section] == ContactSections_Number) {
text = NSLocalizedString(@"Phone numbers", nil);
+ addEntryName = NSLocalizedString(@"Add new phone number", nil);
} else if (contactSections[section] == ContactSections_Sip) {
text = NSLocalizedString(@"SIP addresses", nil);
+ addEntryName = NSLocalizedString(@"Add new SIP address", nil);
} else if (contactSections[section] == ContactSections_Email &&
[LinphoneManager.instance lpConfigBoolForKey:@"show_contacts_emails_preference"]) {
text = NSLocalizedString(@"Email addresses", nil);
+ addEntryName = NSLocalizedString(@"Add new email", nil);
}
}
@@ -683,6 +709,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
[tempAddButton setImage:[UIImage imageNamed:@"add_field_over.png"] forState:UIControlStateSelected];
[tempAddButton addTarget:self action:@selector(onAddClick:) forControlEvents:UIControlEventTouchUpInside];
tempAddButton.tag = section;
+ tempAddButton.accessibilityLabel = addEntryName;
[tempView addSubview:tempAddButton];
}
@@ -744,6 +771,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
UIView *view = [textField superview];
+
// Find TableViewCell
while (view != nil && ![view isKindOfClass:[UIContactDetailsCell class]])
view = [view superview];
@@ -757,18 +785,36 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
ABPropertyID property = [self propertyIDForSection:sect];
NSString *value = [textField text];
- if (sect == ContactSections_Sip) {
- [self setSipContactEntry:entry withValue:value];
- } else if (property != kABInvalidPropertyType) {
- ABMultiValueRef lcMap = ABRecordCopyValue(contact, property);
- ABMutableMultiValueRef lMap = ABMultiValueCreateMutableCopy(lcMap);
- CFRelease(lcMap);
- NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
- ABMultiValueReplaceValueAtIndex(lMap, (__bridge CFStringRef)value, index);
- ABRecordSetValue(contact, property, lMap, nil);
- CFRelease(lMap);
+ switch (sect) {
+ case ContactSections_First_Name:
+ case ContactSections_Last_Name: {
+ // [cell.detailTextLabel setText:[textField text]];
+ CFErrorRef error = NULL;
+ ABRecordSetValue(contact, property, (__bridge CFTypeRef)([textField text]), (CFErrorRef *)&error);
+ if (error != NULL) {
+ LOGE(@"Error when saving property %i in contact %p: Fail(%@)", property, contact,
+ [(__bridge NSError *)error localizedDescription]);
+ }
+ break;
+ }
+ case ContactSections_Sip:
+ [self setSipContactEntry:entry withValue:value];
+ break;
+ case ContactSections_Email:
+ case ContactSections_Number: {
+ ABMultiValueRef lcMap = ABRecordCopyValue(contact, property);
+ ABMutableMultiValueRef lMap = ABMultiValueCreateMutableCopy(lcMap);
+ CFRelease(lcMap);
+ NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
+ ABMultiValueReplaceValueAtIndex(lMap, (__bridge CFStringRef)value, index);
+ ABRecordSetValue(contact, property, lMap, nil);
+ CFRelease(lMap);
+ break;
+ }
+ case ContactSections_MAX:
+ case ContactSections_None:
+ break;
}
-
cell.editTextfield.text = value;
} else {
LOGE(@"Not valid UIEditableTableViewCell");
@@ -779,7 +825,11 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
return TRUE;
}
- (BOOL)isValid {
- return true;
+ NSString *firstName =
+ (__bridge NSString *)(ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_First_Name]));
+ NSString *lastName =
+ (__bridge NSString *)(ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_Last_Name]));
+ return firstName.length > 0 || lastName.length > 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
diff --git a/Classes/ContactDetailsView.m b/Classes/ContactDetailsView.m
index fe2d410f4..e0816193a 100644
--- a/Classes/ContactDetailsView.m
+++ b/Classes/ContactDetailsView.m
@@ -119,7 +119,7 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info
[_tableController setContact:_contact];
if (reload) {
- [self setEditing:FALSE];
+ [self setEditing:TRUE animated:FALSE];
[[_tableController tableView] reloadData];
}
}
@@ -141,7 +141,7 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info
if (linphoneAddress) {
linphone_address_destroy(linphoneAddress);
}
- [self setEditing:FALSE];
+ [self setEditing:TRUE];
[[_tableController tableView] reloadData];
}
@@ -172,8 +172,10 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
- [_editButton setBackgroundImage:[UIImage imageNamed:@"valid_disabled.png"]
- forState:(UIControlStateDisabled | UIControlStateSelected)];
+ _tableController.tableView.accessibilityIdentifier = @"Contact table";
+
+ [_editButton setImage:[UIImage imageNamed:@"valid_disabled.png"]
+ forState:(UIControlStateDisabled | UIControlStateSelected)];
if ([ContactSelection getSelectionMode] == ContactSelectionModeEdit ||
[ContactSelection getSelectionMode] == ContactSelectionModeNone) {
@@ -226,6 +228,7 @@ static UICompositeViewDescription *compositeDescription = nil;
_cancelButton.hidden = !editing;
_backButton.hidden = editing;
_nameLabel.hidden = editing;
+ [ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
CGRect frame = self.contentView.frame;
frame.size.height -= _avatarImage.frame.origin.y + _avatarImage.frame.size.height;
diff --git a/Classes/ContactsListView.m b/Classes/ContactsListView.m
index ff11b1a8b..9fbb1c4a4 100644
--- a/Classes/ContactsListView.m
+++ b/Classes/ContactsListView.m
@@ -108,22 +108,14 @@ static UICompositeViewDescription *compositeDescription = nil;
#pragma mark - ViewController Functions
-//- (void)relayoutTableView {
-// CGRect subViewFrame = self.view.frame;
-// // let the top bar be visible
-// subViewFrame.origin.y += self.topBar.frame.size.height + self.searchBar.frame.size.height;
-// subViewFrame.size.height -= self.topBar.frame.size.height + self.searchBar.frame.size.height;
-// [UIView animateWithDuration:0.2
-// animations:^{
-// self.tableController.tableView.frame = subViewFrame;
-// }];
-//}
-
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_searchBar.showsCancelButton = (_searchBar.text.length > 0);
+ if (tableController.isEditing) {
+ tableController.editing = NO;
+ }
[self update];
}
diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m
index dc26ca5c4..d964a6006 100644
--- a/Classes/LinphoneManager.m
+++ b/Classes/LinphoneManager.m
@@ -2336,7 +2336,7 @@ static void audioRouteChangeListenerCallback(void *inUserData, // 1
const MSList *it = linphone_core_get_proxy_config_list([LinphoneManager getLc]);
while (it) {
- if (linphone_address_equal(addr, linphone_proxy_config_get_identity_address(it->data))) {
+ if (linphone_address_weak_equal(addr, linphone_proxy_config_get_identity_address(it->data))) {
return YES;
}
it = it->next;
diff --git a/TestsUI/ContactsTester.m b/TestsUI/ContactsTester.m
index 7d07fcdb7..70706942d 100644
--- a/TestsUI/ContactsTester.m
+++ b/TestsUI/ContactsTester.m
@@ -14,6 +14,10 @@
#pragma mark - Setup
+- (void)beforeAll {
+ [self switchToValidAccountIfNeeded];
+}
+
- (void)beforeEach {
[super beforeEach];
if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Back" error:nil]) {
@@ -24,15 +28,9 @@
#pragma mark - Utils
-- (void)setText:(NSString *)text forContactHeaderIndex:(NSInteger)idx {
- [tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:0]
- inTableViewWithAccessibilityIdentifier:@"Contact Name Table"];
- [tester enterTextIntoCurrentFirstResponder:text];
-}
-
-- (void)setText:(NSString *)text forContactNumbersIndex:(NSInteger)idx inSection:(NSInteger)section {
+- (void)setText:(NSString *)text forIndex:(NSInteger)idx inSection:(NSInteger)section {
[tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:section]
- inTableViewWithAccessibilityIdentifier:@"Contact numbers table"];
+ inTableViewWithAccessibilityIdentifier:@"Contact table"];
[tester enterTextIntoCurrentFirstResponder:text];
}
@@ -49,30 +47,31 @@
traits:UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled |
UIAccessibilityTraitSelected];
- [self setText:firstName forContactHeaderIndex:0];
+ [self setText:firstName forIndex:0 inSection:ContactSections_First_Name];
// entering text should enable the "edit" button
[tester waitForViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton | UIAccessibilityTraitSelected];
- if (lastName)
- [self setText:lastName forContactHeaderIndex:1];
+ if (lastName) {
+ [self setText:lastName forIndex:0 inSection:ContactSections_Last_Name];
+ }
if (phone) {
- [self setText:phone forContactNumbersIndex:0 inSection:ContactSections_Number];
+ [self setText:phone forIndex:0 inSection:ContactSections_Number];
}
if (sip) {
- [self setText:sip forContactNumbersIndex:0 inSection:ContactSections_Sip];
+ [self setText:sip forIndex:0 inSection:ContactSections_Sip];
}
[tester tapViewWithAccessibilityLabel:@"Edit"];
}
- (void)tapCellForRowAtIndexPath:(NSInteger)idx inSection:(NSInteger)section atX:(CGFloat)x {
- UITableView *tv = [self findTableView:@"Contact numbers table"];
+ UITableView *tv = [self findTableView:@"Contact table"];
NSIndexPath *path = [NSIndexPath indexPathForRow:idx inSection:section];
UITableViewCell *last =
- [tester waitForCellAtIndexPath:path inTableViewWithAccessibilityIdentifier:@"Contact numbers table"];
+ [tester waitForCellAtIndexPath:path inTableViewWithAccessibilityIdentifier:@"Contact table"];
XCTAssertNotNil(last);
CGRect cellFrame = [last.contentView convertRect:last.contentView.frame toView:tv];
@@ -84,25 +83,19 @@
[self tapCellForRowAtIndexPath:idx inSection:section atX:-10];
}
-- (void)tapEditButtonForRowAtIndexPath:(NSInteger)idx inSection:(NSInteger)section {
- // tap the "+" to add a new item (or "-" to delete it).... WOW, this code is ugly!
- // the thing is: we don't handle the "+" button ourself (system stuff)
- // so it is not present in the tableview cell... so we tap on a fixed position of screen :)
- [self tapCellForRowAtIndexPath:idx inSection:section atX:10];
-}
-
- (void)addEntries:(NSArray *)numbers inSection:(NSInteger)section {
[tester tapViewWithAccessibilityLabel:@"Edit"];
- [self setText:[numbers objectAtIndex:0] forContactNumbersIndex:0 inSection:section];
+ NSString *name = (section == ContactSections_Sip) ? @"Add new SIP address" : @"Add new phone number";
+ [self setText:[numbers objectAtIndex:0] forIndex:0 inSection:section];
for (NSInteger i = 1; i < numbers.count; i++) {
- [self tapEditButtonForRowAtIndexPath:i - 1 inSection:section];
- [self setText:[numbers objectAtIndex:i] forContactNumbersIndex:i inSection:section];
+ [tester tapViewWithAccessibilityLabel:name traits:UIAccessibilityTraitButton];
+ [self setText:[numbers objectAtIndex:i] forIndex:i inSection:section];
}
[tester tapViewWithAccessibilityLabel:@"Edit"];
for (NSInteger i = 0; i < numbers.count; i++) {
- [tester waitForViewWithAccessibilityLabel:[@"Linphone, " stringByAppendingString:[numbers objectAtIndex:i]]
- traits:UIAccessibilityTraitStaticText];
+ [tester waitForViewWithAccessibilityLabel:[@"Call " stringByAppendingString:[numbers objectAtIndex:i]]
+ traits:UIAccessibilityTraitButton];
}
}
@@ -121,7 +114,7 @@
NSString *contactName = [self getUUID];
NSString *phone = @"+5 15 #0664;447*46";
[self createContact:contactName lastName:@"dummy" phoneNumber:phone SIPAddress:nil];
- [tester tapViewWithAccessibilityLabel:[@"Linphone, " stringByAppendingString:phone]];
+ [tester tapViewWithAccessibilityLabel:[@"Call " stringByAppendingString:phone]];
[tester waitForViewWithAccessibilityLabel:[phone stringByAppendingString:@" is not registered."]];
[tester tapViewWithAccessibilityLabel:@"Cancel"];
}
@@ -136,18 +129,14 @@
[tester tapViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
[tester tapViewWithAccessibilityLabel:@"Edit"];
- [tester scrollViewWithAccessibilityIdentifier:@"Contact numbers table" byFractionOfSizeHorizontal:0 vertical:-0.9];
+ [tester scrollViewWithAccessibilityIdentifier:@"Contact table" byFractionOfSizeHorizontal:0 vertical:-0.9];
- [tester tapViewWithAccessibilityLabel:@"Remove"];
-
- [tester waitForAbsenceOfViewWithAccessibilityLabel:@"Firstname, Lastname"
- value:fullName
- traits:UIAccessibilityTraitStaticText];
+ [tester tapViewWithAccessibilityLabel:@"Delete"];
+ [tester tapViewWithAccessibilityLabel:@"DELETE"];
}
- (void)testEditContact {
NSString *contactName = [self getUUID];
- NSString *fullName = [contactName stringByAppendingString:@" dummy"];
[self createContact:contactName lastName:@"dummy" phoneNumber:nil SIPAddress:nil];
/* Phone number */
@@ -159,24 +148,21 @@
[tester tapViewWithAccessibilityLabel:@"Edit"];
// remove all numbers
for (NSInteger i = 0; i < phones.count; i++) {
- [self tapEditButtonForRowAtIndexPath:0 inSection:ContactSections_Number];
- [self deleteContactEntryForRowAtIndexPath:0 inSection:ContactSections_Number];
+ [self tapRemoveButtonForRowAtIndexPath:0 inSection:ContactSections_Number];
}
// remove all SIPs
for (NSInteger i = 0; i < SIPs.count; i++) {
- [self tapEditButtonForRowAtIndexPath:0 inSection:ContactSections_Sip];
- [self deleteContactEntryForRowAtIndexPath:0 inSection:ContactSections_Sip];
+ [self tapRemoveButtonForRowAtIndexPath:0 inSection:ContactSections_Sip];
}
[tester tapViewWithAccessibilityLabel:@"Edit"];
// then remove the contact
[tester tapViewWithAccessibilityLabel:@"Edit"];
- [tester scrollViewWithAccessibilityIdentifier:@"Contact numbers table" byFractionOfSizeHorizontal:0 vertical:-0.9];
+ [tester scrollViewWithAccessibilityIdentifier:@"Contact table" byFractionOfSizeHorizontal:0 vertical:-0.9];
- [tester tapViewWithAccessibilityLabel:@"Remove"];
-
- [tester waitForAbsenceOfViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
+ [tester tapViewWithAccessibilityLabel:@"Delete"];
+ [tester tapViewWithAccessibilityLabel:@"DELETE"];
}
@end