diff --git a/Classes/Base.lproj/ChatConversationCreateView.xib b/Classes/Base.lproj/ChatConversationCreateView.xib index c2ac45000..48ba99239 100644 --- a/Classes/Base.lproj/ChatConversationCreateView.xib +++ b/Classes/Base.lproj/ChatConversationCreateView.xib @@ -1,7 +1,10 @@ - + + - + + + @@ -29,23 +32,23 @@ - + - + - + - + - + - + - + - + - + - + @@ -179,7 +182,7 @@ - + @@ -187,19 +190,37 @@ + - + @@ -209,6 +230,7 @@ + @@ -233,5 +255,11 @@ + + + + + + diff --git a/Classes/Base.lproj/ContactsListView.xib b/Classes/Base.lproj/ContactsListView.xib index 3b350e211..17f2c9c9d 100644 --- a/Classes/Base.lproj/ContactsListView.xib +++ b/Classes/Base.lproj/ContactsListView.xib @@ -1,7 +1,10 @@ - + + - + + + @@ -10,6 +13,8 @@ + + @@ -153,7 +158,7 @@ - + @@ -166,7 +171,7 @@ - + @@ -177,11 +182,29 @@ + @@ -218,5 +241,11 @@ + + + + + + diff --git a/Classes/ChatConversationCreateTableView.h b/Classes/ChatConversationCreateTableView.h index 450ab1d4a..640af50d9 100644 --- a/Classes/ChatConversationCreateTableView.h +++ b/Classes/ChatConversationCreateTableView.h @@ -22,13 +22,14 @@ @interface ChatConversationCreateTableView : UITableViewController @property(nonatomic) Boolean allFilter; @property(nonatomic) Boolean notFirstTime; +@property(nonatomic) Boolean reloadMagicSearch; @property(nonatomic, strong) NSMutableArray *contactsGroup; -@property(nonatomic) LinphoneMagicSearch *magicSearch; @property(weak, nonatomic) IBOutlet UISearchBar *searchBar; @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; @property (weak, nonatomic) IBOutlet UIButton *controllerNextButton; @property (weak, nonatomic) IBOutlet UIView *waitView; +@property (weak, nonatomic) IBOutlet UIView *loadingView; @property(nonatomic) Boolean isForEditing; @property(nonatomic) Boolean isGroupChat; diff --git a/Classes/ChatConversationCreateTableView.m b/Classes/ChatConversationCreateTableView.m index fbf20e17c..efc6a2bd5 100644 --- a/Classes/ChatConversationCreateTableView.m +++ b/Classes/ChatConversationCreateTableView.m @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#import "linphoneapp-Swift.h" #import "ChatConversationCreateTableView.h" #import "UIChatCreateCell.h" #import "LinphoneManager.h" @@ -28,14 +29,18 @@ @property(nonatomic, strong) NSMutableArray *addresses; @property(nonatomic, strong) NSMutableArray *phoneOrAddr; @property(nonatomic, strong) NSMutableArray *addressesCached; +@property(readonly, nonatomic) NSMutableDictionary *ldapContactAddressBookMap; + @end @implementation ChatConversationCreateTableView - (void)viewWillAppear:(BOOL)animated { + if (!_ldapContactAddressBookMap) { + _ldapContactAddressBookMap = [NSMutableDictionary dictionary]; + } [super viewWillAppear:animated]; - _magicSearch = linphone_core_create_magic_search(LC); int y = _contactsGroup.count > 0 ? _collectionView.frame.origin.y + _collectionView.frame.size.height : _searchBar.frame.origin.y + _searchBar.frame.size.height; @@ -53,6 +58,18 @@ _addresses = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count]; _phoneOrAddr = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count]; _addressesCached = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onChatMagicSearchStarted:) + name:kLinphoneMagicSearchStarted + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onChatMagicSearchFinished:) + name:kLinphoneMagicSearchFinished + object:nil]; + if(_notFirstTime) { for(NSString *addr in _contactsGroup) { [_collectionView registerClass:UIChatCreateCollectionViewCell.class forCellWithReuseIdentifier:addr]; @@ -64,32 +81,31 @@ [_searchBar setText:@""]; [self searchBar:_searchBar textDidChange:_searchBar.text]; self.tableView.accessibilityIdentifier = @"Suggested addresses"; + } - (void) viewWillDisappear:(BOOL)animated { + [[NSNotificationCenter defaultCenter] removeObserver:self]; _notFirstTime = FALSE; - linphone_magic_search_unref(_magicSearch); - _magicSearch = NULL; } -- (void) loadData { - [self reloadDataWithFilter:_searchBar.text]; +- (void)onChatMagicSearchStarted:(NSNotification *)k { + _loadingView.hidden = FALSE; +} +- (void)onChatMagicSearchFinished:(NSNotification *)k { + [self buildChatContactTable]; + _loadingView.hidden = TRUE; } -- (void)reloadDataWithFilter:(NSString *)filter { - [_addresses removeAllObjects]; - [_phoneOrAddr removeAllObjects]; - [_addressesCached removeAllObjects]; - - if (!_magicSearch) - return; - - bctbx_list_t *results = linphone_magic_search_get_contact_list_from_filter(_magicSearch, filter.UTF8String, _allFilter ? "" : "*"); +- (void) buildChatContactTable { + [_ldapContactAddressBookMap removeAllObjects]; + bctbx_list_t *results = [MagicSearchSingleton.instance getLastSearchResults]; while (results) { + LinphoneSearchResult *result = results->data; const LinphoneAddress *addr = linphone_search_result_get_address(result); + const char *phoneNumber = NULL; - Contact *contact = nil; char *uri = nil; NSString *address = nil; @@ -99,10 +115,10 @@ contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:address]]; } - if (!addr || (!contact && linphone_search_result_get_friend(result))) { + const LinphoneFriend* friend = linphone_search_result_get_friend(result); + if (!addr || (!contact && friend)) { phoneNumber = linphone_search_result_get_phone_number(result); if (!phoneNumber) { - results = results->next; continue; } @@ -111,13 +127,17 @@ const char *normalizedPhoneNumber = linphone_account_normalize_phone_number(account, phoneNumber); if (!normalizedPhoneNumber) { // get invalid phone number, continue - results = results->next; continue; } addr = linphone_account_normalize_sip_uri(account, normalizedPhoneNumber); uri = linphone_address_as_string_uri_only(addr); address = [NSString stringWithUTF8String:uri]; + + contact = [[Contact alloc] initWithFriend:friend]; + [contact setCreatedFromLdap:TRUE]; + [_ldapContactAddressBookMap setObject:contact forKey:address]; } + } if (!addr) { @@ -125,18 +145,36 @@ continue; } - ms_free(uri); - + ms_free(uri); + [_addresses addObject:address]; [_phoneOrAddr addObject:phoneNumber ? [NSString stringWithUTF8String:phoneNumber] : address]; - [_addressesCached addObject:[NSString stringWithFormat:@"%d",linphone_search_result_get_capabilities(result)]]; - + [_addressesCached addObject:[NSString stringWithFormat:@"%d",linphone_search_result_get_capabilities(result)]]; + results = results->next; } - + _reloadMagicSearch = FALSE; [self.tableView reloadData]; } +- (void) loadData { + [self reloadDataWithFilter:_searchBar.text]; +} + +- (void)reloadDataWithFilter:(NSString *)filter { + [_addresses removeAllObjects]; + [_phoneOrAddr removeAllObjects]; + [_addressesCached removeAllObjects]; + _reloadMagicSearch = _reloadMagicSearch || [filter length]==0 || ![[MagicSearchSingleton.instance currentFilter] isEqualToString:filter]; + [MagicSearchSingleton.instance setCurrentFilter:filter]; + + if (_reloadMagicSearch) { + [MagicSearchSingleton.instance searchForContactsWithDomain:_allFilter ? @"" : @"*" sourceFlags:LinphoneMagicSearchSourceAll clearCache:FALSE]; + } else { + [self buildChatContactTable]; + } +} + #pragma mark - TableView methods - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { @@ -160,6 +198,10 @@ NSString *key = [_addresses objectAtIndex:indexPath.row]; NSString *phoneOrAddr = [_phoneOrAddr objectAtIndex:indexPath.row]; Contact *contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:key]]; + if (!contact) { + contact = [_ldapContactAddressBookMap objectForKey:key]; + } + const LinphonePresenceModel *model = contact.friend ? linphone_friend_get_presence_model(contact.friend) : NULL; Boolean linphoneContact = [FastAddressBook contactHasValidSipDomain:contact] || (model && linphone_presence_model_get_basic_status(model) == LinphonePresenceBasicStatusOpen); @@ -173,7 +215,7 @@ BOOL greyCellForEncryptedChat = _isEncrypted ? capabilities > 1 : TRUE; BOOL greyCellForGroupChat = _isGroupChat ? capabilities > 0 : TRUE; cell.userInteractionEnabled = cell.greyView.hidden = greyCellForEncryptedChat && greyCellForGroupChat; - cell.displayNameLabel.text = [FastAddressBook displayNameForAddress:addr]; + cell.displayNameLabel.text = [contact createdFromLdap] ? [contact displayName] : [FastAddressBook displayNameForAddress:addr]; char *str = linphone_address_as_string(addr); cell.addressLabel.text = linphoneContact ? [NSString stringWithUTF8String:str] : phoneOrAddr; ms_free(str); @@ -275,17 +317,11 @@ searchBar.showsCancelButton = (searchText.length > 0); [self reloadDataWithFilter:searchText]; if ([searchText isEqualToString:@""]) { - if (_magicSearch) - linphone_magic_search_reset_search_cache(_magicSearch); - [_searchBar resignFirstResponder]; } } - (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(nonnull NSString *)text { - if (text.length < _searchBar.text.length && _magicSearch) - linphone_magic_search_reset_search_cache(_magicSearch); - return TRUE; } @@ -302,9 +338,6 @@ } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { - if (_magicSearch) - linphone_magic_search_reset_search_cache(_magicSearch); - [searchBar resignFirstResponder]; } diff --git a/Classes/ChatConversationCreateView.m b/Classes/ChatConversationCreateView.m index 9f81e8a41..04e99b5df 100644 --- a/Classes/ChatConversationCreateView.m +++ b/Classes/ChatConversationCreateView.m @@ -188,20 +188,20 @@ typedef enum { ContactsAll, ContactsLinphone, ContactsMAX } ContactsCategory; - (void)changeView:(ContactsCategory)view { CGRect frame = _selectedButtonImage.frame; - if (_tableController.magicSearch) - linphone_magic_search_reset_search_cache(_tableController.magicSearch); if (view == ContactsAll && !_allButton.selected) { frame.origin.x = _allButton.frame.origin.x; _allButton.selected = TRUE; _linphoneButton.selected = FALSE; _tableController.allFilter = TRUE; + _tableController.reloadMagicSearch = TRUE; [_tableController loadData]; } else if (view == ContactsLinphone && !_linphoneButton.selected) { frame.origin.x = _linphoneButton.frame.origin.x; _linphoneButton.selected = TRUE; _allButton.selected = FALSE; _tableController.allFilter = FALSE; + _tableController.reloadMagicSearch = TRUE; [_tableController loadData]; } _selectedButtonImage.frame = frame; diff --git a/Classes/Contact.h b/Classes/Contact.h index 984d11346..603e66014 100644 --- a/Classes/Contact.h +++ b/Classes/Contact.h @@ -35,6 +35,7 @@ @property(nonatomic, strong) NSMutableArray *sipAddresses; @property(nonatomic, strong) NSMutableArray *emails; @property(nonatomic, strong) NSMutableArray *phones; +@property BOOL createdFromLdap; @property BOOL added; - (void)setAvatar:(UIImage *)avatar; diff --git a/Classes/Contact.m b/Classes/Contact.m index fd27e9078..1a47d0672 100644 --- a/Classes/Contact.m +++ b/Classes/Contact.m @@ -36,6 +36,7 @@ _person = acncontact; _friend = afriend ? linphone_friend_ref(afriend) : NULL; _added = FALSE; + _createdFromLdap = FALSE; _phones = [[NSMutableArray alloc] init]; _sipAddresses = [[NSMutableArray alloc] init]; _emails = [[NSMutableArray alloc] init]; diff --git a/Classes/ContactDetailsTableView.m b/Classes/ContactDetailsTableView.m index 642c71e1a..d12321175 100644 --- a/Classes/ContactDetailsTableView.m +++ b/Classes/ContactDetailsTableView.m @@ -160,7 +160,7 @@ /*first and last name only when editting */ return (self.tableView.isEditing) ? 1 : 0; } else if (section == ContactSections_Sip) { - return _contact.sipAddresses.count; + return _contact.createdFromLdap ? 0 : _contact.sipAddresses.count; } else if (section == ContactSections_Number) { return _contact.phones.count; } else if (section == ContactSections_Email) { @@ -193,30 +193,30 @@ value = _contact.lastName; [cell hideDeleteButton:YES]; } else if ([indexPath section] == ContactSections_Number) { - value = _contact.phones[indexPath.row]; - [cell.editTextfield setKeyboardType:UIKeyboardTypePhonePad]; - } else if ([indexPath section] == ContactSections_Sip) { - value = _contact.sipAddresses[indexPath.row]; - LinphoneAddress *addr = NULL; - if ([LinphoneManager.instance - lpConfigBoolForKey:@"contact_display_username_only"] && - (addr = linphone_core_interpret_url(LC, [value UTF8String]))) { - value = - [NSString stringWithCString:linphone_address_get_username(addr) - encoding:[NSString defaultCStringEncoding]]; - linphone_address_destroy(addr); - } - [cell.editTextfield setKeyboardType:UIKeyboardTypeASCIICapable]; - } else if ([indexPath section] == ContactSections_Email) { - value = _contact.emails[indexPath.row]; - [cell.editTextfield setKeyboardType:UIKeyboardTypeEmailAddress]; - } - if ([value hasPrefix:@" "]) - value = [value substringFromIndex:1]; - [cell setAddress:value]; + value = _contact.phones[indexPath.row]; + [cell.editTextfield setKeyboardType:UIKeyboardTypePhonePad]; + } else if ([indexPath section] == ContactSections_Sip) { + value = _contact.sipAddresses[indexPath.row]; + LinphoneAddress *addr = NULL; + if ([LinphoneManager.instance + lpConfigBoolForKey:@"contact_display_username_only"] && + (addr = linphone_core_interpret_url(LC, [value UTF8String]))) { + value = + [NSString stringWithCString:linphone_address_get_username(addr) + encoding:[NSString defaultCStringEncoding]]; + linphone_address_destroy(addr); + } + [cell.editTextfield setKeyboardType:UIKeyboardTypeASCIICapable]; + } else if ([indexPath section] == ContactSections_Email) { + value = _contact.emails[indexPath.row]; + [cell.editTextfield setKeyboardType:UIKeyboardTypeEmailAddress]; + } + if ([value hasPrefix:@" "]) + value = [value substringFromIndex:1]; + [cell setAddress:value]; cell.contentView.userInteractionEnabled = false; - - return cell; + + return cell; } - (void)tableView:(UITableView *)tableView @@ -283,7 +283,7 @@ if (section == ContactSections_Number) { text = NSLocalizedString(@"Phone numbers", nil); addEntryName = NSLocalizedString(@"Add new phone number", nil); - } else if (section == ContactSections_Sip) { + } else if (section == ContactSections_Sip && !_contact.createdFromLdap) { text = NSLocalizedString(@"SIP addresses", nil); addEntryName = NSLocalizedString(@"Add new SIP address", nil); } else if (section == ContactSections_Email && diff --git a/Classes/ContactDetailsView.m b/Classes/ContactDetailsView.m index 22a98fa24..0031ab8f5 100644 --- a/Classes/ContactDetailsView.m +++ b/Classes/ContactDetailsView.m @@ -119,8 +119,8 @@ _contact = acontact; _emptyLabel.hidden = (_contact != NULL); _avatarImage.hidden = !_emptyLabel.hidden; - _deleteButton.hidden = !_emptyLabel.hidden; - _editButton.hidden = !_emptyLabel.hidden; + _deleteButton.hidden = !_emptyLabel.hidden || [_contact createdFromLdap]; + _editButton.hidden = !_emptyLabel.hidden || [_contact createdFromLdap]; [_avatarImage setImage:[FastAddressBook imageForContact:_contact] bordered:NO withRoundedRadius:YES]; [ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact]; diff --git a/Classes/ContactsListTableView.h b/Classes/ContactsListTableView.h index 958bae2c2..adf5a87b6 100644 --- a/Classes/ContactsListTableView.h +++ b/Classes/ContactsListTableView.h @@ -28,9 +28,9 @@ @private OrderedDictionary *addressBookMap; } -@property(nonatomic) BOOL ongoing; +@property(atomic) BOOL reloadMagicSearch; - (void)loadData; -- (void)loadSearchedData; +- (void)loadDataWithFilter:(NSString *)filter; - (void)removeAllContacts; @end diff --git a/Classes/ContactsListTableView.m b/Classes/ContactsListTableView.m index 9de6000c3..c32d92a7b 100644 --- a/Classes/ContactsListTableView.m +++ b/Classes/ContactsListTableView.m @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#import "linphoneapp-Swift.h" #import "ContactsListTableView.h" #import "UIContactCell.h" #import "LinphoneManager.h" @@ -24,31 +25,33 @@ #import "Utils.h" @implementation ContactsListTableView -NSArray *sortedAddresses; #pragma mark - Lifecycle Functions - (void)initContactsTableViewController { addressBookMap = [[OrderedDictionary alloc] init]; - sortedAddresses = [[NSArray alloc] init]; - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(onAddressBookUpdate:) - name:kLinphoneAddressBookUpdate - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(onAddressBookUpdate:) - name:CNContactStoreDidChangeNotification - object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onAddressBookUpdate:) + name:CNContactStoreDidChangeNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onMagicSearchFinished:) + name:kLinphoneMagicSearchFinished + object:nil]; } - (void)onAddressBookUpdate:(NSNotification *)k { - if ((!_ongoing && (PhoneMainView.instance.currentView == ContactsListView.compositeViewDescription)) || (IPAD && PhoneMainView.instance.currentView == ContactDetailsView.compositeViewDescription)) { + if ((![MagicSearchSingleton.instance isSearchOngoing] && (PhoneMainView.instance.currentView == ContactsListView.compositeViewDescription)) || (IPAD && PhoneMainView.instance.currentView == ContactDetailsView.compositeViewDescription)) { [self loadData]; } } +- (void)onMagicSearchFinished:(NSNotification *)k { + [self buildContactTable]; +} + - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (IPAD) { @@ -64,7 +67,7 @@ NSArray *sortedAddresses; if (self) { [self initContactsTableViewController]; } - _ongoing = FALSE; + _reloadMagicSearch = TRUE; return self; } @@ -114,118 +117,17 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) { - (NSString *)displayNameForContact:(Contact *)person { NSString *name = person.displayName; if (name != nil && [name length] > 0 && ![name isEqualToString:NSLocalizedString(@"Unknown", nil)]) { - // 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; - } + + // 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 NSLocalizedString(@"Unknown", nil); } -- (void)loadData { - _ongoing = TRUE; - LOGI(@"====>>>> Load contact list - Start"); - NSString* previous = [PhoneMainView.instance getPreviousViewName]; - addressBookMap = [LinphoneManager.instance getLinphoneManagerAddressBookMap]; - BOOL updated = [LinphoneManager.instance getContactsUpdated]; - if(([previous isEqualToString:@"ContactsDetailsView"] && updated) || updated || [addressBookMap count] == 0){ - [LinphoneManager.instance setContactsUpdated:FALSE]; - @synchronized(addressBookMap) { - NSDictionary *allContacts = [[NSMutableDictionary alloc] initWithDictionary:LinphoneManager.instance.fastAddressBook.addressBookMap]; - sortedAddresses = [[LinphoneManager.instance.fastAddressBook.addressBookMap allKeys] sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { - Contact* first = [allContacts objectForKey:a]; - Contact* second = [allContacts objectForKey:b]; - if([[first.firstName lowercaseString] compare:[second.firstName lowercaseString]] == NSOrderedSame) - return [[first.lastName lowercaseString] compare:[second.lastName lowercaseString]]; - else - return [[first.firstName lowercaseString] compare:[second.firstName lowercaseString]]; - }]; - - - LOGI(@"====>>>> Load contact list - Start 2 !!"); - //Set all contacts from ContactCell to nil - for (NSInteger j = 0; j < [self.tableView numberOfSections]; ++j){ - for (NSInteger i = 0; i < [self.tableView numberOfRowsInSection:j]; ++i) - { - [[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]] setContact:nil]; - } - } - - // Reset Address book - [addressBookMap removeAllObjects]; - for (NSString *addr in sortedAddresses) { - Contact *contact = nil; - @synchronized(LinphoneManager.instance.fastAddressBook.addressBookMap) { - contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:addr]; - } - BOOL add = true; - // Do not add the contact directly if we set some filter - if ([ContactSelection getSipFilter] || - [ContactSelection emailFilterEnabled]) { - add = false; - } - if ([FastAddressBook contactHasValidSipDomain:contact]) { - add = true; - }else if (contact.friend && - linphone_presence_model_get_basic_status( - linphone_friend_get_presence_model( - contact.friend)) == - LinphonePresenceBasicStatusOpen) { - add = true; - } - - if (!add && [ContactSelection emailFilterEnabled]) { - // Add this contact if it has an email - add = (contact.emails.count > 0); - } - - NSMutableString *name = [[NSMutableString alloc] initWithString: [self displayNameForContact:contact]]; - if (add && name != nil) { - NSString *firstChar = [[name substringToIndex:1] uppercaseString]; - // Put in correct subAr - if ([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') { - firstChar = @"#"; - } - NSMutableArray *subAr = [addressBookMap objectForKey:firstChar]; - if (subAr == nil) { - subAr = [[NSMutableArray alloc] init]; - [addressBookMap insertObject:subAr forKey:firstChar selector:@selector(caseInsensitiveCompare:)]; - } - NSUInteger idx = [subAr indexOfObject:contact inSortedRange:(NSRange){0, subAr.count} options:NSBinarySearchingInsertionIndex usingComparator:^NSComparisonResult( Contact *_Nonnull obj1, Contact *_Nonnull obj2) { - return [[self displayNameForContact:obj1] compare:[self displayNameForContact:obj2] options:NSCaseInsensitiveSearch]; - }]; - if (![subAr containsObject:contact]) { - [subAr insertObject:contact atIndex:idx]; - } - } - } - // since we refresh the tableview, we must perform this on main - // thread - dispatch_async(dispatch_get_main_queue(), ^(void) { - if (IPAD) { - if (!([self totalNumberOfItems] > 0)) { - ContactDetailsView *view = VIEW(ContactDetailsView); - [view setContact:nil]; - } - } - }); - } - [LinphoneManager.instance setLinphoneManagerAddressBookMap:addressBookMap]; - } - LOGI(@"====>>>> Load contact list - End"); - [super loadData]; - _ongoing = FALSE; -} - -- (void)loadSearchedData { - LOGI(@"Load search contact list"); +- (void)buildContactTable { @synchronized(addressBookMap) { //Set all contacts from ContactCell to nil for (NSInteger j = 0; j < [self.tableView numberOfSections]; ++j) @@ -237,101 +139,72 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) { } // Reset Address book [addressBookMap removeAllObjects]; + NSMutableArray *subAr = [NSMutableArray new]; - NSMutableArray *subArBegin = [NSMutableArray new]; - NSMutableArray *subArContain = [NSMutableArray new]; [addressBookMap insertObject:subAr forKey:@"" selector:@selector(caseInsensitiveCompare:)]; - for (NSString *addr in sortedAddresses) { - @synchronized( - LinphoneManager.instance.fastAddressBook.addressBookMap) { - Contact *contact = - [LinphoneManager.instance.fastAddressBook.addressBookMap - objectForKey:addr]; - - BOOL add = true; - // Do not add the contact directly if we set some filter - if ([ContactSelection getSipFilter] || - [ContactSelection emailFilterEnabled]) { - add = false; - } - NSString *filter = [ContactSelection getNameOrEmailFilter]; - if ([FastAddressBook contactHasValidSipDomain:contact]) { - add = true; - } - if (contact.friend && - linphone_presence_model_get_basic_status( - linphone_friend_get_presence_model( - contact.friend)) == - LinphonePresenceBasicStatusOpen) { - add = true; - } - - if (!add && [ContactSelection emailFilterEnabled]) { - // Add this contact if it has an email - add = (contact.emails.count > 0); - } - NSInteger idx_begin = -1; - NSInteger idx_sort = -1; - NSMutableString *name = - [self displayNameForContact:contact] - ? [[NSMutableString alloc] - initWithString: - [self displayNameForContact:contact]] - : nil; - if (add && name != nil) { - if ([[contact displayName] - rangeOfString:filter - options:NSCaseInsensitiveSearch] - .location == 0) { - if (![subArBegin containsObject:contact]) { - idx_begin = idx_begin + 1; - [subArBegin insertObject:contact atIndex:idx_begin]; - } - } else if ([[contact displayName] - rangeOfString:filter - options:NSCaseInsensitiveSearch] - .location != NSNotFound) { - if (![subArContain containsObject:contact]) { - idx_sort = idx_sort + 1; - [subArContain insertObject:contact atIndex:idx_sort]; - } - } - } - } - } - [subArBegin - sortUsingComparator:^NSComparisonResult( - Contact *_Nonnull obj1, Contact *_Nonnull obj2) { - return [[self displayNameForContact:obj1] - compare:[self displayNameForContact:obj2] - options:NSCaseInsensitiveSearch]; - }]; - - [subArContain - sortUsingComparator:^NSComparisonResult( - Contact *_Nonnull obj1, Contact *_Nonnull obj2) { - return [[self displayNameForContact:obj1] - compare:[self displayNameForContact:obj2] - options:NSCaseInsensitiveSearch]; - }]; - - [subAr addObjectsFromArray:subArBegin]; - [subAr addObjectsFromArray:subArContain]; - [super loadData]; - - // since we refresh the tableview, we must perform this on main - // thread - dispatch_async(dispatch_get_main_queue(), ^(void) { - if (IPAD) { - if (!([self totalNumberOfItems] > 0)) { - ContactDetailsView *view = VIEW(ContactDetailsView); - [view setContact:nil]; - } - } - }); - } + // + + NSArray *searchResults = [MagicSearchSingleton.instance getLastSearchContacts]; + + for (Contact *contact in searchResults) { + NSMutableString *name = [[NSMutableString alloc] initWithString: [self displayNameForContact:contact]]; + if (name != nil) { + NSString *firstChar = [[name substringToIndex:1] uppercaseString]; + // Put in correct subAr + if ([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') { + firstChar = @"#"; + } + NSMutableArray *subAr = [addressBookMap objectForKey:firstChar]; + if (subAr == nil) { + subAr = [[NSMutableArray alloc] init]; + [addressBookMap insertObject:subAr forKey:firstChar selector:@selector(caseInsensitiveCompare:)]; + } + NSUInteger idx = [subAr indexOfObject:contact inSortedRange:(NSRange){0, subAr.count} options:NSBinarySearchingInsertionIndex usingComparator:^NSComparisonResult( Contact *_Nonnull obj1, Contact *_Nonnull obj2) { + return [[self displayNameForContact:obj1] compare:[self displayNameForContact:obj2] options:NSCaseInsensitiveSearch]; + }]; + if (![subAr containsObject:contact]) { + [subAr insertObject:contact atIndex:idx]; + } + } + } + [super loadData]; + } + // since we refresh the tableview, we must perform this on main + // thread + dispatch_async(dispatch_get_main_queue(), ^(void) { + if (IPAD) { + if (!([self totalNumberOfItems] > 0)) { + ContactDetailsView *view = VIEW(ContactDetailsView); + [view setContact:nil]; + } + } + }); + _reloadMagicSearch = FALSE; } +- (void)loadData { + if (_reloadMagicSearch) { + NSString *domain = @""; + if ([ContactSelection getSipFilterEnabled]) { + LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC); + if (defaultAccount) { + domain = [NSString stringWithUTF8String:linphone_account_params_get_domain(linphone_account_get_params(defaultAccount))]; + } + } + int sourceFlags = LinphoneMagicSearchSourceFriends | LinphoneMagicSearchSourceLdapServers; + [MagicSearchSingleton.instance searchForContactsWithDomain:domain sourceFlags:sourceFlags clearCache:[LinphoneManager.instance getContactsUpdated]]; + [LinphoneManager.instance setContactsUpdated:FALSE]; + } else { + [self buildContactTable]; + } +} + +- (void)loadDataWithFilter: (NSString *)filter { + LOGI(@"Load search contact list"); + _reloadMagicSearch = _reloadMagicSearch || [filter length]==0 || ![[MagicSearchSingleton.instance currentFilter] isEqualToString:filter]; + [MagicSearchSingleton.instance setCurrentFilter:filter]; + [self loadData]; +} #pragma mark - UITableViewDataSource Functions diff --git a/Classes/ContactsListView.h b/Classes/ContactsListView.h index 6045ed074..d3577d819 100644 --- a/Classes/ContactsListView.h +++ b/Classes/ContactsListView.h @@ -34,39 +34,15 @@ typedef enum _ContactSelectionMode { ContactSelectionModeNone, ContactSelectionM + (NSString *)getAddAddress; /*! * Filters contacts by SIP domain. - * @param domain SIP domain to filter. Use @"*" or nil to disable it. + * @param enabled Wether SIP domain filter is enabled */ -+ (void)setSipFilter:(NSString *)domain; ++ (void)enableSipFilter:(BOOL)enabled; /*! - * Weither contacts are filtered by SIP domain or not. + * Wether SIP domain filter is enabled * @return the filter used, or nil if none. */ -+ (NSString *)getSipFilter; - -/*! - * Weither always keep contacts with an email address or not. - * @param enable TRUE if you want to always keep contacts with an email. - */ -+ (void)enableEmailFilter:(BOOL)enable; - -/*! - * Weither always keep contacts with an email address or not. - * @return TRUE if this behaviour is enabled. - */ -+ (BOOL)emailFilterEnabled; - -/*! - * Filters contacts by name and/or email fuzzy matching pattern. - * @param fuzzyName fuzzy word to match. Use nil to disable it. - */ -+ (void)setNameOrEmailFilter:(NSString *)fuzzyName; - -/*! - * Weither contacts are filtered by name and/or email. - * @return the filter used, or nil if none. - */ -+ (NSString *)getNameOrEmailFilter; ++ (BOOL)getSipFilterEnabled; @end @@ -80,6 +56,8 @@ typedef enum _ContactSelectionMode { ContactSelectionModeNone, ContactSelectionM @property(strong, nonatomic) IBOutlet UISearchBar *searchBar; @property(weak, nonatomic) IBOutlet UIImageView *selectedButtonImage; @property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *toggleSelectionButton; +@property (weak, nonatomic) IBOutlet UILabel *loadingLabel; +@property (weak, nonatomic) IBOutlet UIView *loadingView; - (IBAction)onAllClick:(id)event; - (IBAction)onLinphoneClick:(id)event; diff --git a/Classes/ContactsListView.m b/Classes/ContactsListView.m index 8ac94238f..158714f8a 100644 --- a/Classes/ContactsListView.m +++ b/Classes/ContactsListView.m @@ -17,15 +17,14 @@ * along with this program. If not, see . */ +#import "linphoneapp-Swift.h" #import "PhoneMainView.h" @implementation ContactSelection static ContactSelectionMode sSelectionMode = ContactSelectionModeNone; static NSString *sAddAddress = nil; -static NSString *sSipFilter = nil; -static BOOL sEnableEmailFilter = FALSE; -static NSString *sNameOrEmailFilter; +static BOOL bSipFilterEnabled = FALSE; static BOOL addAddressFromOthers = FALSE; + (void)setSelectionMode:(ContactSelectionMode)selectionMode { @@ -45,28 +44,12 @@ static BOOL addAddressFromOthers = FALSE; return sAddAddress; } -+ (void)setSipFilter:(NSString *)domain { - sSipFilter = domain; ++ (void)enableSipFilter:(BOOL)enabled { + bSipFilterEnabled = enabled; } -+ (NSString *)getSipFilter { - return sSipFilter; -} - -+ (void)enableEmailFilter:(BOOL)enable { - sEnableEmailFilter = enable; -} - -+ (BOOL)emailFilterEnabled { - return sEnableEmailFilter; -} - -+ (void)setNameOrEmailFilter:(NSString *)fuzzyName { - sNameOrEmailFilter = fuzzyName; -} - -+ (NSString *)getNameOrEmailFilter { - return sNameOrEmailFilter; ++ (BOOL)getSipFilterEnabled { + return bSipFilterEnabled; } @end @@ -105,12 +88,16 @@ static UICompositeViewDescription *compositeDescription = nil; #pragma mark - ViewController Functions - (void)viewDidLoad { + NSLog(@"Debuglog viewDidLoad"); [super viewDidLoad]; + _searchBar.text = [MagicSearchSingleton.instance currentFilter]; tableController.tableView.accessibilityIdentifier = @"Contacts table"; + + if (![[PhoneMainView.instance getPreviousViewName] isEqualToString:@"ContactDetailsView"]) { + _searchBar.text = @""; + } [self changeView:ContactsAll]; - /*if ([tableController totalNumberOfItems] == 0) { - [self changeView:ContactsAll]; - }*/ + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboards)]; @@ -120,8 +107,9 @@ static UICompositeViewDescription *compositeDescription = nil; } - (void)viewWillAppear:(BOOL)animated { + + NSLog(@"Debuglog viewWillAppear"); [super viewWillAppear:animated]; - [ContactSelection setNameOrEmailFilter:@""]; _searchBar.showsCancelButton = (_searchBar.text.length > 0); int y = _searchBar.frame.origin.y + _searchBar.frame.size.height; @@ -143,9 +131,28 @@ static UICompositeViewDescription *compositeDescription = nil; self.linphoneButton.hidden = TRUE; self.selectedButtonImage.hidden = TRUE; } + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onMagicSearchStarted:) + name:kLinphoneMagicSearchStarted + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onMagicSearchFinished:) + name:kLinphoneMagicSearchFinished + object:nil]; +} + +- (void)onMagicSearchStarted:(NSNotification *)k { + _loadingView.hidden = FALSE; +} +- (void)onMagicSearchFinished:(NSNotification *)k { + _loadingView.hidden = TRUE; } - (void)viewDidAppear:(BOOL)animated { + NSLog(@"Debuglog viewDidAppear"); [super viewDidAppear:animated]; if (![FastAddressBook isAuthorized]) { UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Address book", nil) @@ -182,6 +189,7 @@ static UICompositeViewDescription *compositeDescription = nil; } - (void) viewWillDisappear:(BOOL)animated { + [[NSNotificationCenter defaultCenter] removeObserver:self]; self.view = NULL; [self.tableController removeAllContacts]; } @@ -189,25 +197,26 @@ static UICompositeViewDescription *compositeDescription = nil; #pragma mark - - (void)changeView:(ContactsCategory)view { + NSLog(@"Debuglog changeView"); CGRect frame = _selectedButtonImage.frame; if (view == ContactsAll && !allButton.selected) { //REQUIRED TO RELOAD WITH FILTER [LinphoneManager.instance setContactsUpdated:TRUE]; frame.origin.x = allButton.frame.origin.x; - [ContactSelection setSipFilter:nil]; - [ContactSelection enableEmailFilter:FALSE]; + [ContactSelection enableSipFilter:FALSE]; allButton.selected = TRUE; linphoneButton.selected = FALSE; - [tableController loadData]; + [tableController setReloadMagicSearch:TRUE]; + [tableController loadDataWithFilter: _searchBar.text]; } else if (view == ContactsLinphone && !linphoneButton.selected) { //REQUIRED TO RELOAD WITH FILTER [LinphoneManager.instance setContactsUpdated:TRUE]; frame.origin.x = linphoneButton.frame.origin.x; - [ContactSelection setSipFilter:LinphoneManager.instance.contactFilter]; - [ContactSelection enableEmailFilter:FALSE]; + [ContactSelection enableSipFilter:TRUE]; linphoneButton.selected = TRUE; allButton.selected = FALSE; - [tableController loadData]; + [tableController setReloadMagicSearch:TRUE]; + [tableController loadDataWithFilter: _searchBar.text]; } _selectedButtonImage.frame = frame; if ([LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"]) { @@ -217,7 +226,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)refreshButtons { [addButton setHidden:FALSE]; - [self changeView:[ContactSelection getSipFilter] ? ContactsLinphone : ContactsAll]; + [self changeView:[ContactSelection getSipFilterEnabled] ? ContactsLinphone : ContactsAll]; } #pragma mark - Action Functions @@ -263,9 +272,9 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { searchBar.text = @""; - [self searchBar:searchBar textDidChange:@""]; [LinphoneManager.instance setContactsUpdated:TRUE]; - [tableController loadData]; + [self searchBar:searchBar textDidChange:@""]; + [searchBar resignFirstResponder]; } @@ -278,14 +287,12 @@ static UICompositeViewDescription *compositeDescription = nil; #pragma mark - searchBar delegate - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { - // display searchtext in UPPERCASE - // searchBar.text = [searchText uppercaseString]; - [ContactSelection setNameOrEmailFilter:searchText]; - if (searchText.length == 0) { - [LinphoneManager.instance setContactsUpdated:TRUE]; - [tableController loadData]; - } else { - [tableController loadSearchedData]; + NSLog(@"Debuglog textdidchange"); + if (![searchText isEqualToString:[MagicSearchSingleton.instance currentFilter]]) { + if (searchText.length == 0) { + [LinphoneManager.instance setContactsUpdated:TRUE]; + } + [tableController loadDataWithFilter:searchText]; } } diff --git a/Classes/DialerView.m b/Classes/DialerView.m index df1a5d70f..9bbde008d 100644 --- a/Classes/DialerView.m +++ b/Classes/DialerView.m @@ -390,9 +390,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (IBAction)onAddContactClick:(id)event { [ContactSelection setSelectionMode:ContactSelectionModeEdit]; [ContactSelection setAddAddress:[_addressField text]]; - [ContactSelection setSipFilter:nil]; - [ContactSelection setNameOrEmailFilter:nil]; - [ContactSelection enableEmailFilter:FALSE]; + [ContactSelection enableSipFilter:FALSE]; [PhoneMainView.instance changeCurrentView:ContactsListView.compositeViewDescription]; } diff --git a/Classes/HistoryDetailsView.m b/Classes/HistoryDetailsView.m index 3dda8aa54..5b676ec25 100644 --- a/Classes/HistoryDetailsView.m +++ b/Classes/HistoryDetailsView.m @@ -194,10 +194,7 @@ static UICompositeViewDescription *compositeDescription = nil; normSip = [normSip hasPrefix:@"sip:"] ? [normSip substringFromIndex:4] : normSip; [ContactSelection setAddAddress:normSip]; [ContactSelection setSelectionMode:ContactSelectionModeEdit]; - - [ContactSelection setSipFilter:nil]; - [ContactSelection enableEmailFilter:FALSE]; - [ContactSelection setNameOrEmailFilter:nil]; + [ContactSelection enableSipFilter:FALSE]; [PhoneMainView.instance changeCurrentView:ContactsListView.compositeViewDescription]; ms_free(lAddress); } diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index d544354be..2ee225e9b 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -63,6 +63,8 @@ extern NSString *const kLinphoneVoiceMessagePlayerEOF; extern NSString *const kLinphoneVoiceMessagePlayerLostFocus; extern NSString *const kLinphoneConfStateParticipantListChanged; extern NSString *const kLinphoneConfStateChanged; +extern NSString *const kLinphoneMagicSearchStarted; +extern NSString *const kLinphoneMagicSearchFinished; extern NSString *const kLinphoneMsgNotificationAppGroupId; @@ -178,9 +180,6 @@ typedef struct _LinphoneManagerSounds { - (void)shouldPresentLinkPopup; -- (void) setLinphoneManagerAddressBookMap:(OrderedDictionary*) addressBook; -- (OrderedDictionary*) getLinphoneManagerAddressBookMap; - - (void) setContactsUpdated:(BOOL) updated; - (BOOL) getContactsUpdated; diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 64788c350..17fcdacb9 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -80,6 +80,8 @@ NSString *const kLinphoneVoiceMessagePlayerEOF = @"LinphoneVoiceMessagePlayerEOF NSString *const kLinphoneVoiceMessagePlayerLostFocus = @"LinphoneVoiceMessagePlayerLostFocus"; NSString *const kLinphoneConfStateChanged = @"kLinphoneConfStateChanged"; NSString *const kLinphoneConfStateParticipantListChanged = @"kLinphoneConfStateParticipantListChanged"; +NSString *const kLinphoneMagicSearchStarted = @"LinphoneMagicSearchStarted"; +NSString *const kLinphoneMagicSearchFinished = @"LinphoneMagicSearchFinished"; NSString *const kLinphoneMsgNotificationAppGroupId = @"group.org.linphone.phone.msgNotification"; @@ -286,15 +288,7 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre [NSNotificationCenter.defaultCenter removeObserver:self]; } -#pragma mark - AddressBookMap - -- (void) setLinphoneManagerAddressBookMap:(OrderedDictionary*) addressBook{ - _linphoneManagerAddressBookMap = addressBook; -} - -- (OrderedDictionary*) getLinphoneManagerAddressBookMap{ - return _linphoneManagerAddressBookMap; -} +#pragma mark - Contacts Updated - (void) setContactsUpdated:(BOOL) updated{ _contactsUpdated = updated; diff --git a/Classes/LinphoneUI/TabBarView.m b/Classes/LinphoneUI/TabBarView.m index ec171fbf9..6048f1a39 100644 --- a/Classes/LinphoneUI/TabBarView.m +++ b/Classes/LinphoneUI/TabBarView.m @@ -152,8 +152,6 @@ - (IBAction)onContactsClick:(id)event { [ContactSelection setAddAddress:nil]; - [ContactSelection enableEmailFilter:FALSE]; - [ContactSelection setNameOrEmailFilter:nil]; [PhoneMainView.instance changeCurrentView:ContactsListView.compositeViewDescription]; } diff --git a/Classes/MagicSearch.swift b/Classes/MagicSearch.swift new file mode 100644 index 000000000..8ce270f30 --- /dev/null +++ b/Classes/MagicSearch.swift @@ -0,0 +1,141 @@ +// +// ContactListMagicSearch.swift +// linphone +// +// Created by QuentinArguillere on 25/03/2022. +// + +import Foundation +import linphonesw + +@objc class MagicSearchSingleton : NSObject { + static var theMagicSearchSingleton: MagicSearchSingleton? + + var lc = CallManager.instance().lc + var ongoingSearch = false + var needUpdateLastSearchContacts = false + var lastSearchContacts : [Contact] = [] + + @objc var currentFilter : String = "" + var previousFilter : String? + var magicSearch : MagicSearch + var magicSearchDelegate : MagicSearchDelegate? + + + override init() { + magicSearch = try! lc!.createMagicSearch() + magicSearch.limitedSearch = false + super.init() + + magicSearchDelegate = MagicSearchDelegateStub(onSearchResultsReceived: { (magicSearch: MagicSearch) in + self.needUpdateLastSearchContacts = true + self.ongoingSearch = false + Log.directLog(BCTBX_LOG_MESSAGE, text: "Contact magic search -- filter = \(String(describing: self.previousFilter)) -- \(magicSearch.lastSearch.count) contact founds") + NotificationCenter.default.post(name: Notification.Name(kLinphoneMagicSearchFinished), object: self) + }, onLdapHaveMoreResults: { (magicSearch: MagicSearch, ldap: Ldap) in + Log.directLog(BCTBX_LOG_MESSAGE, text: "Ldap have more result") + }) + + magicSearch.addDelegate(delegate: magicSearchDelegate!) + } + + + @objc static func instance() -> MagicSearchSingleton { + if (theMagicSearchSingleton == nil) { + theMagicSearchSingleton = MagicSearchSingleton() + } + return theMagicSearchSingleton! + } + + + func getContactFromAddr(addr: Address) -> Contact? { + return LinphoneManager.instance().fastAddressBook.addressBookMap.object(forKey: addr.asStringUriOnly() as Any) as? Contact + } + func getContactFromPhoneNb(phoneNb: String) -> Contact? { + let contactKey = FastAddressBook.localizedLabel(FastAddressBook.normalizeSipURI( lc?.defaultAccount?.normalizePhoneNumber(username: phoneNb) ?? phoneNb)) + return LinphoneManager.instance().fastAddressBook.addressBookMap.object(forKey: contactKey as Any) as? Contact + } + + func searchAndAddMatchingContact(searchResult: SearchResult) -> Contact? { + if let friend = searchResult.friend { + if let addr = friend.address, let foundContact = getContactFromAddr(addr: addr) { + return foundContact + } + for phoneNb in friend.phoneNumbers { + if let foundContact = getContactFromPhoneNb(phoneNb: phoneNb) { + return foundContact + } + } + // No contacts found (searchResult likely comes from LDAP), creating a new one + if let newContact = Contact(friend: friend.getCobject) { + newContact.createdFromLdap = true + return newContact + } + } + + if let addr = searchResult.address, let foundContact = getContactFromAddr(addr: addr) { + return foundContact + } + + if let foundContact = getContactFromPhoneNb(phoneNb: searchResult.phoneNumber) { + return foundContact + } + + return nil + } + + @objc func isSearchOngoing() -> Bool { + return ongoingSearch + } + + @objc func getLastSearchResults() -> UnsafeMutablePointer? { + + var cList: UnsafeMutablePointer? = nil + for data in magicSearch.lastSearch { + cList = bctbx_list_append(cList, UnsafeMutableRawPointer(data.getCobject)) + } + return cList + } + + @objc func getLastSearchContacts() -> [Contact] { + if (needUpdateLastSearchContacts) { + lastSearchContacts = [] + var addedContactNames : [String] = [] + for res in magicSearch.lastSearch { + if let contact = searchAndAddMatchingContact(searchResult: res) { + if (!addedContactNames.contains(contact.displayName)) { + addedContactNames.append(contact.displayName) + lastSearchContacts.append(contact) + } + } + } + needUpdateLastSearchContacts = false + } + + return lastSearchContacts + } + + @objc func searchForContacts(domain: String, sourceFlags: Int, clearCache: Bool) { + if (clearCache) { + magicSearch.resetSearchCache() + } + if let oldFilter = previousFilter { + if (oldFilter.count > currentFilter.count || oldFilter != currentFilter) { + magicSearch.resetSearchCache() + } + } + previousFilter = currentFilter + + ongoingSearch = true + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + if (self.ongoingSearch) { + NotificationCenter.default.post(name: Notification.Name(kLinphoneMagicSearchStarted), object: self) + } + } + magicSearch.getContactsListAsync(filter: currentFilter, domain: domain, sourceFlags: sourceFlags, aggregation: MagicSearchAggregation.Friend) + } + + + func setupLDAPTestSettings() { + } +} diff --git a/Classes/linphone-Bridging-Header.h b/Classes/linphone-Bridging-Header.h index 3e52d89b6..5eaded494 100644 --- a/Classes/linphone-Bridging-Header.h +++ b/Classes/linphone-Bridging-Header.h @@ -5,7 +5,7 @@ #import -#import "FastAddressBook.h" +#import "LinphoneManager.h" #import "Log.h" #import "AudioHelper.h" #import "ChatConversationTableView.h" diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj index e19b7645c..94513df76 100644 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -628,6 +628,7 @@ 63F1DF4F1BCE985F00EDED90 /* UICallConferenceCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F1DF4D1BCE985F00EDED90 /* UICallConferenceCell.m */; }; 63F1DF511BCE986A00EDED90 /* UICallConferenceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 63F1DF531BCE986A00EDED90 /* UICallConferenceCell.xib */; }; 63FB30351A680E73008CA393 /* UIRoundedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FB30341A680E73008CA393 /* UIRoundedImageView.m */; }; + 662553B427EDFB35007F67D8 /* MagicSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 662553B327EDFB35007F67D8 /* MagicSearch.swift */; }; 669B140827A1821F0012220A /* scroll_to_bottom_default.png in Resources */ = {isa = PBXBuildFile; fileRef = 669B140727A1821F0012220A /* scroll_to_bottom_default.png */; }; 669B140C27A29D140012220A /* FloatingScrollDownButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669B140B27A29D140012220A /* FloatingScrollDownButton.swift */; }; 6F3A2542B1FC7C128439D37C /* Pods_linphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFCC14A580A05DEC78090273 /* Pods_linphone.framework */; }; @@ -1619,6 +1620,7 @@ 63F1DF521BCE986A00EDED90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UICallConferenceCell.xib; sourceTree = ""; }; 63FB30331A680E73008CA393 /* UIRoundedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIRoundedImageView.h; sourceTree = ""; }; 63FB30341A680E73008CA393 /* UIRoundedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIRoundedImageView.m; sourceTree = ""; }; + 662553B327EDFB35007F67D8 /* MagicSearch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagicSearch.swift; sourceTree = ""; }; 669B140727A1821F0012220A /* scroll_to_bottom_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = scroll_to_bottom_default.png; sourceTree = ""; }; 669B140B27A29D140012220A /* FloatingScrollDownButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingScrollDownButton.swift; sourceTree = ""; }; 70E542F213E147E3002BA2C0 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; @@ -2098,6 +2100,7 @@ D3549815158761D0000081D8 /* ContactsListTableView.m */, D35497FB15875372000081D8 /* ContactsListView.h */, D35497FC15875372000081D8 /* ContactsListView.m */, + 662553B327EDFB35007F67D8 /* MagicSearch.swift */, D38187C015FE342800C3EDCA /* ContactsListView.xib */, 631098471D4660580041F2B3 /* CountryListView.h */, 631098481D4660580041F2B3 /* CountryListView.m */, @@ -4379,6 +4382,7 @@ D3807FFC15C2894A005BE9BC /* IASKPSTitleValueSpecifierViewCell.m in Sources */, D3807FFE15C2894A005BE9BC /* IASKSlider.m in Sources */, D380800015C2894A005BE9BC /* IASKSwitch.m in Sources */, + 662553B427EDFB35007F67D8 /* MagicSearch.swift in Sources */, D380800215C2894A005BE9BC /* IASKTextField.m in Sources */, D380801315C299D0005BE9BC /* ColorSpaceUtilites.m in Sources */, C64A854E2667B67200252AD2 /* EphemeralSettingsView.m in Sources */,