diff --git a/Classes/Base.lproj/ChatViewController.xib b/Classes/Base.lproj/ChatViewController.xib index 878b38caf..4f30247c4 100644 --- a/Classes/Base.lproj/ChatViewController.xib +++ b/Classes/Base.lproj/ChatViewController.xib @@ -1,8 +1,7 @@ - + - - + @@ -91,14 +90,11 @@ + + - - - - - @@ -113,4 +109,9 @@ - \ No newline at end of file + + + + + + diff --git a/Classes/Base.lproj/ContactsViewController.xib b/Classes/Base.lproj/ContactsViewController.xib index d16430f4d..ab36f8c0b 100644 --- a/Classes/Base.lproj/ContactsViewController.xib +++ b/Classes/Base.lproj/ContactsViewController.xib @@ -1,8 +1,8 @@ - + - - + + @@ -11,6 +11,7 @@ + @@ -21,7 +22,7 @@ - + @@ -109,11 +110,21 @@ + + + + + + + + + + @@ -127,4 +138,9 @@ - \ No newline at end of file + + + + + + diff --git a/Classes/ChatViewController.m b/Classes/ChatViewController.m index 73e3878bd..61b3cdbba 100644 --- a/Classes/ChatViewController.m +++ b/Classes/ChatViewController.m @@ -123,7 +123,8 @@ static UICompositeViewDescription *compositeDescription = nil; [ContactSelection setSelectionMode:ContactSelectionModeMessage]; [ContactSelection setAddAddress:nil]; [ContactSelection setSipFilter: [LinphoneManager instance].contactFilter]; - [ContactSelection setEmailFilter:FALSE]; + [ContactSelection enableEmailFilter:FALSE]; + [ContactSelection setNameOrEmailFilter:nil]; [[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE]; } else { [self startChatRoom]; diff --git a/Classes/ContactDetailsTableViewController.m b/Classes/ContactDetailsTableViewController.m index de95d9679..ee3ebf4f8 100644 --- a/Classes/ContactDetailsTableViewController.m +++ b/Classes/ContactDetailsTableViewController.m @@ -207,7 +207,8 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {ContactSe if(CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey), kCFCompareCaseInsensitive) == 0) { add = true; } - } else { //check domain + } else { + //check domain LinphoneAddress* address = linphone_address_new([(NSString*)CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey) UTF8String]); if (address) { if ([[ContactSelection getSipFilter] compare:@"*" options:NSCaseInsensitiveSearch] == NSOrderedSame) { diff --git a/Classes/ContactsTableViewController.m b/Classes/ContactsTableViewController.m index 459f86e4e..c591b5dbc 100644 --- a/Classes/ContactsTableViewController.m +++ b/Classes/ContactsTableViewController.m @@ -4,18 +4,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #import "ContactsTableViewController.h" #import "UIContactCell.h" @@ -33,237 +33,273 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf #pragma mark - Lifecycle Functions - (void)initContactsTableViewController { - addressBookMap = [[OrderedDictionary alloc] init]; - avatarMap = [[NSMutableDictionary alloc] init]; - - addressBook = ABAddressBookCreateWithOptions(nil, nil); - - ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, self); + addressBookMap = [[OrderedDictionary alloc] init]; + avatarMap = [[NSMutableDictionary alloc] init]; + + addressBook = ABAddressBookCreateWithOptions(nil, nil); + + ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, self); } - (id)init { - self = [super init]; - if (self) { + self = [super init]; + if (self) { [self initContactsTableViewController]; - } - return self; + } + return self; } - (id)initWithCoder:(NSCoder *)decoder { - self = [super initWithCoder:decoder]; - if (self) { + self = [super initWithCoder:decoder]; + if (self) { [self initContactsTableViewController]; } - return self; -} + return self; +} - (void)dealloc { - ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self); - CFRelease(addressBook); - [addressBookMap release]; - [avatarMap release]; - [super dealloc]; + ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self); + CFRelease(addressBook); + [addressBookMap release]; + [avatarMap release]; + [super dealloc]; } -#pragma mark - +#pragma mark - + +- (BOOL)contactHasValidSipDomain:(ABRecordRef)person { + // Check if one of the contact' sip URI matches the expected SIP filter + ABMultiValueRef personSipAddresses = ABRecordCopyValue(person, kABPersonInstantMessageProperty); + BOOL match = false; + NSString * filter = [ContactSelection getSipFilter]; + + for(int i = 0; i < ABMultiValueGetCount(personSipAddresses) && !match; ++i) { + CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(personSipAddresses, i); + if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) { + CFStringRef serviceKey = CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey); + + if (CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, serviceKey, kCFCompareCaseInsensitive) == 0) { + match = true; + } + } else { + //check domain + LinphoneAddress* address = linphone_address_new([(NSString*)CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey) UTF8String]); + + if (address) { + NSString* domain = [NSString stringWithCString:linphone_address_get_domain(address) + encoding:[NSString defaultCStringEncoding]]; + + if (([filter compare:@"*" options:NSCaseInsensitiveSearch] == NSOrderedSame) + || ([filter compare:domain options:NSCaseInsensitiveSearch] == NSOrderedSame)) { + match = true; + } + linphone_address_destroy(address); + } + } + CFRelease(lDict); + } + return match; +} + +static int ms_strcmpfuz(const char * fuzzy_word, const char * sentence) { + if (! fuzzy_word || !sentence) { + return fuzzy_word == sentence; + } + const char * c = fuzzy_word; + const char * within_sentence = sentence; + for (; c != NULL && *c != '\0' && within_sentence != NULL; ++c) { + within_sentence = strchr(within_sentence, *c); + // Could not find c character in sentence. Abort. + if (within_sentence == NULL) { + break; + } + // since strchr returns the index of the matched char, move forward + within_sentence++; + } + + // If the whole fuzzy was found, returns 0. Otherwise returns number of characters left. + return (within_sentence != NULL ? 0 : fuzzy_word + strlen(fuzzy_word) - c); +} - (void)loadData { - [LinphoneLogger logc:LinphoneLoggerLog format:"Load contact list"]; - @synchronized (addressBookMap) { - - // Reset Address book - [addressBookMap removeAllObjects]; - - NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); - for (id lPerson in lContacts) { - BOOL add = true; - if([ContactSelection getSipFilter] || [ContactSelection getEmailFilter]) { - add = false; - } - if([ContactSelection getSipFilter]) { - ABMultiValueRef lMap = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonInstantMessageProperty); - for(int i = 0; i < ABMultiValueGetCount(lMap); ++i) { - CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i); - if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) { - CFStringRef serviceKey = CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey); - CFStringRef username = username=CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey); - if(CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, serviceKey, kCFCompareCaseInsensitive) == 0) { - add = true; - } else { - add=false; + [LinphoneLogger logc:LinphoneLoggerLog format:"Load contact list"]; + @synchronized (addressBookMap) { + + // Reset Address book + [addressBookMap removeAllObjects]; + + NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); + for (id lPerson in lContacts) { + BOOL add = true; + ABRecordRef person = (ABRecordRef)lPerson; + + // Do not add the contact directly if we set some filter + if([ContactSelection getSipFilter] || [ContactSelection emailFilterEnabled]) { + add = false; + } + if([ContactSelection getSipFilter] && [self contactHasValidSipDomain:person]) { + add = true; + } + if (!add && [ContactSelection emailFilterEnabled]) { + ABMultiValueRef personEmailAddresses = ABRecordCopyValue(person, kABPersonEmailProperty); + // Add this contact if it has an email + add = (ABMultiValueGetCount(personEmailAddresses) > 0); + + CFRelease(personEmailAddresses); + } + + if(add) { + CFStringRef lFirstName = ABRecordCopyValue(person, kABPersonFirstNameProperty); + CFStringRef lLocalizedFirstName = (lFirstName != nil)? ABAddressBookCopyLocalizedLabel(lFirstName): nil; + CFStringRef lLastName = ABRecordCopyValue(person, kABPersonLastNameProperty); + CFStringRef lLocalizedLastName = (lLastName != nil)? ABAddressBookCopyLocalizedLabel(lLastName): nil; + CFStringRef lOrganization = ABRecordCopyValue(person, kABPersonOrganizationProperty); + CFStringRef lLocalizedlOrganization = (lOrganization != nil)? ABAddressBookCopyLocalizedLabel(lOrganization): nil; + NSString *name = nil; + if(lLocalizedFirstName != nil && lLocalizedLastName != nil) { + name=[NSString stringWithFormat:@"%@ %@", [(NSString *)lLocalizedFirstName retain], [(NSString *)lLocalizedLastName retain]]; + } else if(lLocalizedLastName != nil) { + name=[NSString stringWithFormat:@"%@",[(NSString *)lLocalizedLastName retain]]; + } else if(lLocalizedFirstName != nil) { + name=[NSString stringWithFormat:@"%@",[(NSString *)lLocalizedFirstName retain]]; + } else if(lLocalizedlOrganization != nil) { + name=[NSString stringWithFormat:@"%@",[(NSString *)lLocalizedlOrganization retain]]; + } + + 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)) { + + // Put in correct subDic + NSString *firstChar = [[name substringToIndex:1] uppercaseString]; + if([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') { + firstChar = @"#"; } - } else { - //check domain - LinphoneAddress* address = linphone_address_new([(NSString*)CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey) UTF8String]); - if (address) { - if ([[ContactSelection getSipFilter] compare:@"*" options:NSCaseInsensitiveSearch] == NSOrderedSame) { - add = true; - } else { - NSString* domain = [NSString stringWithCString:linphone_address_get_domain(address) - encoding:[NSString defaultCStringEncoding]]; - add = [domain compare:[ContactSelection getSipFilter] options:NSCaseInsensitiveSearch] == NSOrderedSame; - } - linphone_address_destroy(address); - } else { - add = false; - } - } - CFRelease(lDict); - } - CFRelease(lMap); - } - if ((add == false) && [ContactSelection getEmailFilter]) { - ABMultiValueRef lMap = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonEmailProperty); - if (ABMultiValueGetCount(lMap) > 0) { - add = true; - } - CFRelease(lMap); - } - if(add) { - CFStringRef lFirstName = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonFirstNameProperty); - CFStringRef lLocalizedFirstName = (lFirstName != nil)? ABAddressBookCopyLocalizedLabel(lFirstName): nil; - CFStringRef lLastName = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonLastNameProperty); - CFStringRef lLocalizedLastName = (lLastName != nil)? ABAddressBookCopyLocalizedLabel(lLastName): nil; - CFStringRef lOrganization = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonOrganizationProperty); - CFStringRef lLocalizedlOrganization = (lOrganization != nil)? ABAddressBookCopyLocalizedLabel(lOrganization): nil; - NSString *name = nil; - if(lLocalizedFirstName != nil && lLocalizedLastName != nil) { - name=[NSString stringWithFormat:@"%@%@", [(NSString *)lLocalizedFirstName retain], [(NSString *)lLocalizedLastName retain]]; - } else if(lLocalizedLastName != nil) { - name=[NSString stringWithFormat:@"%@",[(NSString *)lLocalizedLastName retain]]; - } else if(lLocalizedFirstName != nil) { - name=[NSString stringWithFormat:@"%@",[(NSString *)lLocalizedFirstName retain]]; - } else if(lLocalizedlOrganization != nil) { - name=[NSString stringWithFormat:@"%@",[(NSString *)lLocalizedlOrganization retain]]; - } - if(name != nil && [name length] > 0) { - // Put in correct subDic - NSString *firstChar = [[name substringToIndex:1] uppercaseString]; - if([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') { - firstChar = @"#"; - } - OrderedDictionary *subDic =[addressBookMap objectForKey: firstChar]; - if(subDic == nil) { - subDic = [[[OrderedDictionary alloc] init] autorelease]; - [addressBookMap insertObject:subDic forKey:firstChar selector:@selector(caseInsensitiveCompare:)]; - } - [subDic insertObject:lPerson forKey:name selector:@selector(caseInsensitiveCompare:)]; - } - if(lLocalizedlOrganization != nil) - CFRelease(lLocalizedlOrganization); - if(lOrganization != nil) - CFRelease(lOrganization); - if(lLocalizedLastName != nil) - CFRelease(lLocalizedLastName); - if(lLastName != nil) - CFRelease(lLastName); - if(lLocalizedFirstName != nil) - CFRelease(lLocalizedFirstName); - if(lFirstName != nil) - CFRelease(lFirstName); - } - } - if (lContacts) CFRelease(lContacts); - } - [self.tableView reloadData]; + OrderedDictionary *subDic =[addressBookMap objectForKey: firstChar]; + if(subDic == nil) { + subDic = [[[OrderedDictionary alloc] init] autorelease]; + [addressBookMap insertObject:subDic forKey:firstChar selector:@selector(caseInsensitiveCompare:)]; + } + [subDic insertObject:lPerson forKey:name selector:@selector(caseInsensitiveCompare:)]; + } + } + if(lLocalizedlOrganization != nil) + CFRelease(lLocalizedlOrganization); + if(lOrganization != nil) + CFRelease(lOrganization); + if(lLocalizedLastName != nil) + CFRelease(lLocalizedLastName); + if(lLastName != nil) + CFRelease(lLastName); + if(lLocalizedFirstName != nil) + CFRelease(lLocalizedFirstName); + if(lFirstName != nil) + CFRelease(lFirstName); + } + } + if (lContacts) + CFRelease(lContacts); + } + [self.tableView reloadData]; } static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context) { - ContactsTableViewController* controller = (ContactsTableViewController*)context; - ABAddressBookRevert(addressBook); - [controller->avatarMap removeAllObjects]; - [controller loadData]; + ContactsTableViewController* controller = (ContactsTableViewController*)context; + ABAddressBookRevert(addressBook); + [controller->avatarMap removeAllObjects]; + [controller loadData]; } #pragma mark - ViewController Functions - (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; + [super viewWillDisappear:animated]; } #pragma mark - UITableViewDataSource Functions - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { - return [addressBookMap allKeys]; + return [addressBookMap allKeys]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [addressBookMap count]; + return [addressBookMap count]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [(OrderedDictionary *)[addressBookMap objectForKey: [addressBookMap keyAtIndex: section]] count]; + return [(OrderedDictionary *)[addressBookMap objectForKey: [addressBookMap keyAtIndex: section]] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *kCellId = @"UIContactCell"; - UIContactCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId]; - if (cell == nil) { - cell = [[[UIContactCell alloc] initWithIdentifier:kCellId] autorelease]; - - // Background View - UACellBackgroundView *selectedBackgroundView = [[[UACellBackgroundView alloc] initWithFrame:CGRectZero] autorelease]; - cell.selectedBackgroundView = selectedBackgroundView; - [selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR]; - } - OrderedDictionary *subDic = [addressBookMap objectForKey: [addressBookMap keyAtIndex: [indexPath section]]]; - - NSString *key = [[subDic allKeys] objectAtIndex:[indexPath row]]; - ABRecordRef contact = [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; - } - if(image == nil) { - image = [UIImage imageNamed:@"avatar_unknown_small.png"]; - } - [[cell avatarImage] setImage:image]; - - [cell setContact: contact]; - return cell; + static NSString *kCellId = @"UIContactCell"; + UIContactCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId]; + if (cell == nil) { + cell = [[[UIContactCell alloc] initWithIdentifier:kCellId] autorelease]; + + // Background View + UACellBackgroundView *selectedBackgroundView = [[[UACellBackgroundView alloc] initWithFrame:CGRectZero] autorelease]; + cell.selectedBackgroundView = selectedBackgroundView; + [selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR]; + } + OrderedDictionary *subDic = [addressBookMap objectForKey: [addressBookMap keyAtIndex: [indexPath section]]]; + + NSString *key = [[subDic allKeys] objectAtIndex:[indexPath row]]; + ABRecordRef contact = [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; + } + if(image == nil) { + image = [UIImage imageNamed:@"avatar_unknown_small.png"]; + } + [[cell avatarImage] setImage:image]; + + [cell setContact: contact]; + return cell; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return [addressBookMap keyAtIndex: section]; + return [addressBookMap keyAtIndex: section]; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - OrderedDictionary *subDic = [addressBookMap objectForKey: [addressBookMap keyAtIndex: [indexPath section]]]; - ABRecordRef lPerson = [subDic objectForKey: [subDic keyAtIndex:[indexPath row]]]; - - // Go to Contact details view - ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController); - if(controller != nil) { - if([ContactSelection getSelectionMode] != ContactSelectionModeEdit) { - [controller setContact:lPerson]; - } else { - [controller editContact:lPerson address:[ContactSelection getAddAddress]]; - } - } + OrderedDictionary *subDic = [addressBookMap objectForKey: [addressBookMap keyAtIndex: [indexPath section]]]; + ABRecordRef lPerson = [subDic objectForKey: [subDic keyAtIndex:[indexPath row]]]; + + // Go to Contact details view + ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController); + if(controller != nil) { + if([ContactSelection getSelectionMode] != ContactSelectionModeEdit) { + [controller setContact:lPerson]; + } else { + [controller 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; - } - return UITableViewCellEditingStyleNone; + // Detemine if it's in editing mode + if (self.editing) { + return UITableViewCellEditingStyleDelete; + } + return UITableViewCellEditingStyleNone; } @end diff --git a/Classes/ContactsViewController.h b/Classes/ContactsViewController.h index c580d82bf..a7a91c866 100644 --- a/Classes/ContactsViewController.h +++ b/Classes/ContactsViewController.h @@ -4,18 +4,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #import #import @@ -30,18 +30,48 @@ typedef enum _ContactSelectionMode { ContactSelectionModeMessage } ContactSelectionMode; -@interface ContactSelection : NSObject { +@interface ContactSelection : NSObject { } + (void)setSelectionMode:(ContactSelectionMode)selectionMode; + (ContactSelectionMode)getSelectionMode; + (void)setAddAddress:(NSString*)address; + (NSString*)getAddAddress; -/* define sip filter, can be * or sip domain*/ +/*! + * Filters contacts by SIP domain. + * @param domain SIP domain to filter. Use @"*" or nil to disable it. + */ + (void)setSipFilter:(NSString*) domain; + +/*! + * Weither contacts are filtered by SIP domain or not. + * @return the filter used, or nil if none. + */ + (NSString*)getSipFilter; -+ (void)setEmailFilter:(BOOL)enable; -+ (BOOL)getEmailFilter; + +/*! + * 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; @end @@ -57,10 +87,12 @@ typedef enum _ContactSelectionMode { @property (nonatomic, retain) IBOutlet UIButton* linphoneButton; @property (nonatomic, retain) IBOutlet UIButton *backButton; @property (nonatomic, retain) IBOutlet UIButton *addButton; +@property (retain, nonatomic) IBOutlet UISearchBar *searchBar; - (IBAction)onAllClick:(id)event; - (IBAction)onLinphoneClick:(id)event; - (IBAction)onAddContactClick:(id)event; - (IBAction)onBackClick:(id)event; +- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText; @end diff --git a/Classes/ContactsViewController.m b/Classes/ContactsViewController.m index 621f3c13f..b2a898eba 100644 --- a/Classes/ContactsViewController.m +++ b/Classes/ContactsViewController.m @@ -4,18 +4,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #import "ContactsViewController.h" #import "PhoneMainView.h" @@ -28,47 +28,58 @@ static ContactSelectionMode sSelectionMode = ContactSelectionModeNone; static NSString* sAddAddress = nil; static NSString* sSipFilter = nil; -static BOOL sEmailFilter = FALSE; +static BOOL sEnableEmailFilter = FALSE; +static NSString* sNameOrEmailFilter; + (void)setSelectionMode:(ContactSelectionMode)selectionMode { - sSelectionMode = selectionMode; + sSelectionMode = selectionMode; } + (ContactSelectionMode)getSelectionMode { - return sSelectionMode; + return sSelectionMode; } + (void)setAddAddress:(NSString*)address { - if(sAddAddress != nil) { - [sAddAddress release]; - sAddAddress= nil; - } - if(address != nil) { - sAddAddress = [address retain]; - } + if(sAddAddress != nil) { + [sAddAddress release]; + sAddAddress= nil; + } + if(address != nil) { + sAddAddress = [address retain]; + } } + (NSString*)getAddAddress { - return sAddAddress; + return sAddAddress; } + (void)setSipFilter:(NSString*)domain { - [sSipFilter release]; + [sSipFilter release]; sSipFilter = [domain retain]; } + (NSString*)getSipFilter { - return sSipFilter; + return sSipFilter; } -+ (void)setEmailFilter:(BOOL)enable { - sEmailFilter = enable; ++ (void)enableEmailFilter:(BOOL)enable { + sEnableEmailFilter = enable; } -+ (BOOL)getEmailFilter { - return sEmailFilter; ++ (BOOL)emailFilterEnabled { + return sEnableEmailFilter; } ++ (void)setNameOrEmailFilter:(NSString*)fuzzyName { + [sNameOrEmailFilter release]; + sNameOrEmailFilter = [fuzzyName retain]; +} + ++ (NSString*)getNameOrEmailFilter { + return sNameOrEmailFilter; +} + + @end @implementation ContactsViewController @@ -85,28 +96,30 @@ static BOOL sEmailFilter = FALSE; @synthesize toolBar; typedef enum _HistoryView { - History_All, - History_Linphone, - History_MAX + History_All, + History_Linphone, + History_Search, + History_MAX } HistoryView; #pragma mark - Lifecycle Functions - (id)init { - return [super initWithNibName:@"ContactsViewController" bundle:[NSBundle mainBundle]]; + return [super initWithNibName:@"ContactsViewController" bundle:[NSBundle mainBundle]]; } - (void)dealloc { - [tableController release]; - [tableView release]; - - [allButton release]; - [linphoneButton release]; - [backButton release]; - [addButton release]; - - [super dealloc]; + [tableController release]; + [tableView release]; + + [allButton release]; + [linphoneButton release]; + [backButton release]; + [addButton release]; + + [_searchBar release]; + [super dealloc]; } #pragma mark - UICompositeViewDelegate Functions @@ -114,181 +127,181 @@ typedef enum _HistoryView { static UICompositeViewDescription *compositeDescription = nil; + (UICompositeViewDescription *)compositeViewDescription { - if(compositeDescription == nil) { - compositeDescription = [[UICompositeViewDescription alloc] init:@"Contacts" - content:@"ContactsViewController" - stateBar:nil - stateBarEnabled:false - tabBar:@"UIMainBar" - tabBarEnabled:true - fullscreen:false - landscapeMode:[LinphoneManager runningOnIpad] - portraitMode:true]; - } - return compositeDescription; + if(compositeDescription == nil) { + compositeDescription = [[UICompositeViewDescription alloc] init:@"Contacts" + content:@"ContactsViewController" + stateBar:nil + stateBarEnabled:false + tabBar:@"UIMainBar" + tabBarEnabled:true + fullscreen:false + landscapeMode:[LinphoneManager runningOnIpad] + portraitMode:true]; + } + return compositeDescription; } #pragma mark - ViewController Functions - (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; + [super viewWillDisappear:animated]; } - (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"]; - if( use_system && !self.sysViewController){// use system contacts - ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init]; - picker.peoplePickerDelegate = self; - picker.view.frame = self.view.frame; + [super viewWillAppear:animated]; - [self.view addSubview:picker.view]; + BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"]; + if( use_system && !self.sysViewController){// use system contacts + ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init]; + picker.peoplePickerDelegate = self; + picker.view.frame = self.view.frame; - self.sysViewController = picker; + [self.view addSubview:picker.view]; - } else if( !use_system && !self.tableController ){ + self.sysViewController = picker; - CGRect subViewFrame= self.view.frame; - // let the toolBar be visible - subViewFrame.origin.y += self.toolBar.frame.size.height; - subViewFrame.size.height -= self.toolBar.frame.size.height; + } else if( !use_system && !self.tableController ){ - self.tableController = [[[ContactsTableViewController alloc] init] autorelease]; - self.tableView = [[[UITableView alloc] init] autorelease]; + CGRect subViewFrame= self.view.frame; + // let the toolBar be visible + subViewFrame.origin.y += self.toolBar.frame.size.height; + subViewFrame.size.height -= self.toolBar.frame.size.height; - self.tableController.view = self.tableView; - self.tableView.frame = subViewFrame; + self.tableController = [[[ContactsTableViewController alloc] init] autorelease]; + self.tableView = [[[UITableView alloc] init] autorelease]; - self.tableView.dataSource = self.tableController; - self.tableView.delegate = self.tableController; + self.tableController.view = self.tableView; + self.tableView.frame = subViewFrame; - self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | - UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleTopMargin | - UIViewAutoresizingFlexibleBottomMargin | - UIViewAutoresizingFlexibleLeftMargin | - UIViewAutoresizingFlexibleRightMargin; + self.tableView.dataSource = self.tableController; + self.tableView.delegate = self.tableController; - [self.view addSubview:tableView]; - [self update]; - } + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | + UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleTopMargin | + UIViewAutoresizingFlexibleBottomMargin | + UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleRightMargin; + + [self.view addSubview:tableView]; + [self update]; + } } - (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - if(![FastAddressBook isAuthorized]) { - UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Address book",nil) + [super viewDidAppear:animated]; + if(![FastAddressBook isAuthorized]) { + UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Address book",nil) message:NSLocalizedString(@"You must authorize the application to have access to address book.\n" - "Toggle the application in Settings > Privacy > Contacts",nil) + "Toggle the application in Settings > Privacy > Contacts",nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"Continue",nil) otherButtonTitles:nil]; [error show]; [error release]; - [[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]]; - } + [[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]]; + } } - (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; + [super viewDidDisappear:animated]; } - (void)viewDidLoad { - [super viewDidLoad]; - - [self changeView:History_All]; - - // Set selected+over background: IB lack ! - [linphoneButton setBackgroundImage:[UIImage imageNamed:@"contacts_linphone_selected.png"] - forState:(UIControlStateHighlighted | UIControlStateSelected)]; - - [linphoneButton setTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] + [super viewDidLoad]; + + [self changeView:History_All]; + + // Set selected+over background: IB lack ! + [linphoneButton setBackgroundImage:[UIImage imageNamed:@"contacts_linphone_selected.png"] + forState:(UIControlStateHighlighted | UIControlStateSelected)]; + + [linphoneButton setTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] forState:UIControlStateNormal]; - + [LinphoneUtils buttonFixStates:linphoneButton]; - - // Set selected+over background: IB lack ! - [allButton setBackgroundImage:[UIImage imageNamed:@"contacts_all_selected.png"] - forState:(UIControlStateHighlighted | UIControlStateSelected)]; - - [LinphoneUtils buttonFixStates:allButton]; - - [tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4 - [tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4 + + // Set selected+over background: IB lack ! + [allButton setBackgroundImage:[UIImage imageNamed:@"contacts_all_selected.png"] + forState:(UIControlStateHighlighted | UIControlStateSelected)]; + + [LinphoneUtils buttonFixStates:allButton]; + + [tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4 + [tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4 } #pragma mark - - (void)changeView:(HistoryView)view { - if(view == History_All) { - [ContactSelection setSipFilter:nil]; - [ContactSelection setEmailFilter:FALSE]; - [tableController loadData]; - allButton.selected = TRUE; - } else { - allButton.selected = FALSE; - } + if(view == History_All) { + [ContactSelection setSipFilter:nil]; + [ContactSelection enableEmailFilter:FALSE]; + [tableController loadData]; + allButton.selected = TRUE; + } else { + allButton.selected = FALSE; + } - if(view == History_Linphone) { - [ContactSelection setSipFilter:[LinphoneManager instance].contactFilter]; - [ContactSelection setEmailFilter:FALSE]; - [tableController loadData]; - linphoneButton.selected = TRUE; - } else { - linphoneButton.selected = FALSE; - } + if(view == History_Linphone) { + [ContactSelection setSipFilter:[LinphoneManager instance].contactFilter]; + [ContactSelection enableEmailFilter:FALSE]; + [tableController loadData]; + linphoneButton.selected = TRUE; + } else { + linphoneButton.selected = FALSE; + } } - (void)update { - switch ([ContactSelection getSelectionMode]) { - case ContactSelectionModePhone: - case ContactSelectionModeMessage: - [addButton setHidden:TRUE]; - [backButton setHidden:FALSE]; - break; - default: - [addButton setHidden:FALSE]; - [backButton setHidden:TRUE]; - break; - } - if([ContactSelection getSipFilter]) { - allButton.selected = FALSE; - linphoneButton.selected = TRUE; - } else { - allButton.selected = TRUE; - linphoneButton.selected = FALSE; - } - [tableController loadData]; + switch ([ContactSelection getSelectionMode]) { + case ContactSelectionModePhone: + case ContactSelectionModeMessage: + [addButton setHidden:TRUE]; + [backButton setHidden:FALSE]; + break; + default: + [addButton setHidden:FALSE]; + [backButton setHidden:TRUE]; + break; + } + if([ContactSelection getSipFilter]) { + allButton.selected = FALSE; + linphoneButton.selected = TRUE; + } else { + allButton.selected = TRUE; + linphoneButton.selected = FALSE; + } + [tableController loadData]; } #pragma mark - Action Functions - (IBAction)onAllClick:(id)event { - [self changeView: History_All]; + [self changeView: History_All]; } - (IBAction)onLinphoneClick:(id)event { - [self changeView: History_Linphone]; + [self changeView: History_Linphone]; } - (IBAction)onAddContactClick:(id)event { - // Go to Contact details view - ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController); - if(controller != nil) { - if([ContactSelection getAddAddress] == nil) { - [controller newContact]; - } else { - [controller newContact:[ContactSelection getAddAddress]]; - } - } + // Go to Contact details view + ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController); + if(controller != nil) { + if([ContactSelection getAddAddress] == nil) { + [controller newContact]; + } else { + [controller newContact:[ContactSelection getAddAddress]]; + } + } } - (IBAction)onBackClick:(id)event { - [[PhoneMainView instance] popCurrentView]; + [[PhoneMainView instance] popCurrentView]; } @@ -296,8 +309,8 @@ static UICompositeViewDescription *compositeDescription = nil; -(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker { - [[PhoneMainView instance] popCurrentView]; - return; + [[PhoneMainView instance] popCurrentView]; + return; } - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker @@ -314,19 +327,23 @@ static UICompositeViewDescription *compositeDescription = nil; CFTypeRef multiValue = ABRecordCopyValue(person, property); CFIndex valueIdx = ABMultiValueGetIndexForIdentifier(multiValue,identifier); NSString *phoneNumber = (NSString *)ABMultiValueCopyValueAtIndex(multiValue, valueIdx); - // Go to dialer view - DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController); - if(controller != nil) { - [controller call:phoneNumber displayName:[(NSString*)ABRecordCopyCompositeName(person) autorelease]]; - } - [phoneNumber release]; - CFRelease(multiValue); + // Go to dialer view + DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController); + if(controller != nil) { + [controller call:phoneNumber displayName:[(NSString*)ABRecordCopyCompositeName(person) autorelease]]; + } + [phoneNumber release]; + CFRelease(multiValue); return false; } +- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { + [ContactSelection setNameOrEmailFilter:searchText]; + [tableController loadData]; +} - (void)viewDidUnload { - [self setToolBar:nil]; - [super viewDidUnload]; + [self setToolBar:nil]; + [super viewDidUnload]; } @end diff --git a/Classes/DialerViewController.m b/Classes/DialerViewController.m index 7a0a37efe..2f809a90f 100644 --- a/Classes/DialerViewController.m +++ b/Classes/DialerViewController.m @@ -4,18 +4,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #import #import @@ -76,7 +76,7 @@ [callButton release]; [addCallButton release]; [transferButton release]; - + [oneButton release]; [twoButton release]; [threeButton release]; @@ -89,13 +89,13 @@ [starButton release]; [zeroButton release]; [sharpButton release]; - + [videoPreview release]; [videoCameraSwitch release]; - + // Remove all observers [[NSNotificationCenter defaultCenter] removeObserver:self]; - + [super dealloc]; } @@ -106,12 +106,12 @@ static UICompositeViewDescription *compositeDescription = nil; + (UICompositeViewDescription *)compositeViewDescription { if(compositeDescription == nil) { - compositeDescription = [[UICompositeViewDescription alloc] init:@"Dialer" - content:@"DialerViewController" - stateBar:@"UIStateBar" - stateBarEnabled:true - tabBar:@"UIMainBar" - tabBarEnabled:true + compositeDescription = [[UICompositeViewDescription alloc] init:@"Dialer" + content:@"DialerViewController" + stateBar:@"UIStateBar" + stateBarEnabled:true + tabBar:@"UIMainBar" + tabBarEnabled:true fullscreen:false landscapeMode:[LinphoneManager runningOnIpad] portraitMode:true]; @@ -124,13 +124,13 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - + // Set observer - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(callUpdateEvent:) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(callUpdateEvent:) name:kLinphoneCallUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(coreUpdateEvent:) name:kLinphoneCoreUpdate @@ -178,16 +178,16 @@ static UICompositeViewDescription *compositeDescription = nil; #endif } -} +} - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - + // Remove observer - [[NSNotificationCenter defaultCenter] removeObserver:self + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCoreUpdate object:nil]; @@ -195,7 +195,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)viewDidLoad { [super viewDidLoad]; - + [zeroButton setDigit:'0']; [oneButton setDigit:'1']; [twoButton setDigit:'2']; @@ -208,9 +208,9 @@ static UICompositeViewDescription *compositeDescription = nil; [nineButton setDigit:'9']; [starButton setDigit:'*']; [sharpButton setDigit:'#']; - + [addressField setAdjustsFontSizeToFitWidth:TRUE]; // Not put it in IB: issue with placeholder size - + if([LinphoneManager runningOnIpad]) { if ([LinphoneManager instance].frontCamId != nil) { // only show camera switch button if we have more than 1 camera @@ -248,7 +248,7 @@ static UICompositeViewDescription *compositeDescription = nil; #pragma mark - Event Functions -- (void)callUpdateEvent:(NSNotification*)notif { +- (void)callUpdateEvent:(NSNotification*)notif { LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue]; LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue]; [self callUpdate:call state:state]; @@ -283,7 +283,7 @@ static UICompositeViewDescription *compositeDescription = nil; [transferButton setHidden:true]; } [callButton setHidden:true]; - [backButton setHidden:false]; + [backButton setHidden:false]; [addContactButton setHidden:true]; } else { [addCallButton setHidden:true]; @@ -330,7 +330,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (BOOL)textFieldShouldReturn:(UITextField *)textField { if (textField == addressField) { [addressField resignFirstResponder]; - } + } return YES; } @@ -341,10 +341,11 @@ static UICompositeViewDescription *compositeDescription = nil; [ContactSelection setSelectionMode:ContactSelectionModeEdit]; [ContactSelection setAddAddress:[addressField text]]; [ContactSelection setSipFilter:nil]; - [ContactSelection setEmailFilter:FALSE]; + [ContactSelection setNameOrEmailFilter:nil]; + [ContactSelection enableEmailFilter:FALSE]; ContactsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE], ContactsViewController); if(controller != nil) { - + } } diff --git a/Classes/HistoryDetailsViewController.m b/Classes/HistoryDetailsViewController.m index dfaf43580..e327e4040 100644 --- a/Classes/HistoryDetailsViewController.m +++ b/Classes/HistoryDetailsViewController.m @@ -4,18 +4,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #import "HistoryDetailsViewController.h" #import "PhoneMainView.h" @@ -55,10 +55,10 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - + [dateFormatter release]; [callLogId release]; - + [avatarImage release]; [addressLabel release]; [dateLabel release]; @@ -72,7 +72,7 @@ [callButton release]; [messageButton release]; [addContactButton release]; - + [super dealloc]; } @@ -83,12 +83,12 @@ static UICompositeViewDescription *compositeDescription = nil; + (UICompositeViewDescription *)compositeViewDescription { if(compositeDescription == nil) { - compositeDescription = [[UICompositeViewDescription alloc] init:@"HistoryDetails" - content:@"HistoryDetailsViewController" - stateBar:nil - stateBarEnabled:false - tabBar:@"UIMainBar" - tabBarEnabled:true + compositeDescription = [[UICompositeViewDescription alloc] init:@"HistoryDetails" + content:@"HistoryDetailsViewController" + stateBar:nil + stateBarEnabled:false + tabBar:@"UIMainBar" + tabBarEnabled:true fullscreen:false landscapeMode:[LinphoneManager runningOnIpad] portraitMode:true]; @@ -124,12 +124,12 @@ static UICompositeViewDescription *compositeDescription = nil; if( use_system ){ [addContactButton setHidden:TRUE]; } - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(update) + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(update) name:kLinphoneAddressBookUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(coreUpdateEvent:) name:kLinphoneCoreUpdate @@ -138,11 +138,11 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - - [[NSNotificationCenter defaultCenter] removeObserver:self + + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneAddressBookUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCoreUpdate object:nil]; @@ -156,7 +156,7 @@ static UICompositeViewDescription *compositeDescription = nil; } -#pragma mark - +#pragma mark - + (void)adaptSize:(UILabel*)label field:(UIView*)field { // @@ -164,20 +164,20 @@ static UICompositeViewDescription *compositeDescription = nil; // CGRect labelFrame = [label frame]; CGRect fieldFrame = [field frame]; - + fieldFrame.origin.x -= labelFrame.size.width; - + // Compute firstName size CGSize contraints; contraints.height = [label frame].size.height; contraints.width = ([field frame].size.width + [field frame].origin.x) - [label frame].origin.x; CGSize firstNameSize = [[label text] sizeWithFont:[label font] constrainedToSize: contraints]; labelFrame.size.width = firstNameSize.width; - + // Compute lastName size & position fieldFrame.origin.x += labelFrame.size.width; fieldFrame.size.width = (contraints.width + [label frame].origin.x) - fieldFrame.origin.x; - + [label setFrame: labelFrame]; [field setFrame: fieldFrame]; } @@ -186,7 +186,7 @@ static UICompositeViewDescription *compositeDescription = nil; if(![LinphoneManager isLcReady]) { return; } - + // Look for the call log callLog = NULL; const MSList *list = linphone_core_get_call_logs([LinphoneManager getLc]); @@ -199,20 +199,20 @@ static UICompositeViewDescription *compositeDescription = nil; } list = list->next; } - + // Pop if callLog is null if(callLog == NULL) { [[PhoneMainView instance] popCurrentView]; return; } - + LinphoneAddress* addr =linphone_call_log_get_remote_address(callLog); - + UIImage *image = nil; NSString* address = nil; if(addr != NULL) { BOOL useLinphoneAddress = true; - // contact name + // contact name char* lAddress = linphone_address_as_string_uri_only(addr); if(lAddress) { NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]]; @@ -227,25 +227,25 @@ static UICompositeViewDescription *compositeDescription = nil; if(useLinphoneAddress) { const char* lDisplayName = linphone_address_get_display_name(addr); const char* lUserName = linphone_address_get_username(addr); - if (lDisplayName) + if (lDisplayName) address = [NSString stringWithUTF8String:lDisplayName]; - else if(lUserName) + else if(lUserName) address = [NSString stringWithUTF8String:lUserName]; } } - + // Set Image if(image == nil) { image = [UIImage imageNamed:@"avatar_unknown.png"]; } [avatarImage setImage:image]; - + // Set Address if(address == nil) { address = NSLocalizedString(@"Unknown", nil); } [addressLabel setText:address]; - + // Hide/Show add button BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"]; if(contact) { @@ -253,7 +253,7 @@ static UICompositeViewDescription *compositeDescription = nil; } else if (!use_system) { [addContactButton setHidden:FALSE]; } - + // State NSMutableString *state = [NSMutableString string]; if (linphone_call_log_get_dir(callLog) == LinphoneCallIncoming) { @@ -283,7 +283,7 @@ static UICompositeViewDescription *compositeDescription = nil; // Duration int duration = linphone_call_log_get_duration(callLog); [durationLabel setText:[NSString stringWithFormat:@"%02i:%02i", (duration/60), duration - 60 * (duration / 60), nil]]; - + // contact name [plainAddressLabel setText:@""]; if (addr != NULL) { @@ -297,7 +297,7 @@ static UICompositeViewDescription *compositeDescription = nil; } } } - + if (addr != NULL) { [callButton setHidden:FALSE]; [messageButton setHidden:FALSE]; @@ -305,7 +305,7 @@ static UICompositeViewDescription *compositeDescription = nil; [callButton setHidden:TRUE]; [messageButton setHidden:TRUE]; } - + } @@ -327,16 +327,17 @@ static UICompositeViewDescription *compositeDescription = nil; - (IBAction)onAddContactClick:(id)event { LinphoneAddress* addr; - + addr=linphone_call_log_get_remote_address(callLog); if (addr != NULL) { char* lAddress = linphone_address_as_string_uri_only(addr); if(lAddress != NULL) { [ContactSelection setAddAddress:[NSString stringWithUTF8String:lAddress]]; [ContactSelection setSelectionMode:ContactSelectionModeEdit]; - + [ContactSelection setSipFilter:nil]; - [ContactSelection setEmailFilter:FALSE]; + [ContactSelection enableEmailFilter:FALSE]; + [ContactSelection setNameOrEmailFilter:nil]; ContactsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE], ContactsViewController); if(controller != nil) { } @@ -346,26 +347,26 @@ static UICompositeViewDescription *compositeDescription = nil; } - (IBAction)onCallClick:(id)event { - LinphoneAddress* addr; + LinphoneAddress* addr; addr=linphone_call_log_get_remote_address(callLog); - + char* lAddress = linphone_address_as_string_uri_only(addr); - if(lAddress == NULL) + if(lAddress == NULL) return; - + NSString *displayName = nil; if(contact != nil) { - displayName = [FastAddressBook getContactDisplayName:contact]; + displayName = [FastAddressBook getContactDisplayName:contact]; } else { const char* lDisplayName = linphone_address_get_display_name(addr); const char* lUserName = linphone_address_get_username(addr); - if (lDisplayName) + if (lDisplayName) displayName = [NSString stringWithUTF8String:lDisplayName]; - else if(lUserName) + else if(lUserName) displayName = [NSString stringWithUTF8String:lUserName]; } - - + + DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController); if(controller != nil) { if(displayName != nil) { @@ -380,11 +381,11 @@ static UICompositeViewDescription *compositeDescription = nil; - (IBAction)onMessageClick:(id)event { LinphoneAddress* addr; addr=linphone_call_log_get_remote_address(callLog); - + char* lAddress = linphone_address_as_string_uri_only(addr); if(lAddress == NULL) return; - + NSString *displayName = nil; if(contact != nil) { displayName = [FastAddressBook getContactDisplayName:contact]; @@ -396,7 +397,7 @@ static UICompositeViewDescription *compositeDescription = nil; else if(lUserName) displayName = [NSString stringWithUTF8String:lUserName]; } - + // Go to ChatRoom view [[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]]; ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController); diff --git a/Classes/LinphoneUI/UIMainBar.m b/Classes/LinphoneUI/UIMainBar.m index 899435fab..dbacbeb29 100644 --- a/Classes/LinphoneUI/UIMainBar.m +++ b/Classes/LinphoneUI/UIMainBar.m @@ -4,16 +4,16 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -46,7 +46,7 @@ static NSString * const kDisappearAnimation = @"disappear"; - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - + [historyButton release]; [contactsButton release]; [dialerButton release]; @@ -56,7 +56,7 @@ static NSString * const kDisappearAnimation = @"disappear"; [historyNotificationLabel release]; [chatNotificationView release]; [chatNotificationLabel release]; - + [super dealloc]; } @@ -65,17 +65,17 @@ static NSString * const kDisappearAnimation = @"disappear"; - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(changeViewEvent:) + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(changeViewEvent:) name:kLinphoneMainViewChange object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(callUpdate:) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(callUpdate:) name:kLinphoneCallUpdate object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(textReceived:) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(textReceived:) name:kLinphoneTextReceived object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -87,14 +87,14 @@ static NSString * const kDisappearAnimation = @"disappear"; - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - - [[NSNotificationCenter defaultCenter] removeObserver:self + + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneMainViewChange object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneTextReceived object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self @@ -103,35 +103,35 @@ static NSString * const kDisappearAnimation = @"disappear"; } - (void)viewDidLoad { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationWillEnterForeground:) - name:UIApplicationWillEnterForegroundNotification + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification object:nil]; - + { UIButton *historyButtonLandscape = (UIButton*) [landscapeView viewWithTag:[historyButton tag]]; // Set selected+over background: IB lack ! [historyButton setBackgroundImage:[UIImage imageNamed:@"history_selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + // Set selected+over background: IB lack ! [historyButtonLandscape setBackgroundImage:[UIImage imageNamed:@"history_selected_landscape.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + [LinphoneUtils buttonFixStatesForTabs:historyButton]; [LinphoneUtils buttonFixStatesForTabs:historyButtonLandscape]; } - + { UIButton *contactsButtonLandscape = (UIButton*) [landscapeView viewWithTag:[contactsButton tag]]; // Set selected+over background: IB lack ! [contactsButton setBackgroundImage:[UIImage imageNamed:@"contacts_selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + // Set selected+over background: IB lack ! [contactsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"contacts_selected_landscape.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + [LinphoneUtils buttonFixStatesForTabs:contactsButton]; [LinphoneUtils buttonFixStatesForTabs:contactsButtonLandscape]; } @@ -140,11 +140,11 @@ static NSString * const kDisappearAnimation = @"disappear"; // Set selected+over background: IB lack ! [dialerButton setBackgroundImage:[UIImage imageNamed:@"dialer_selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + // Set selected+over background: IB lack ! [dialerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"dialer_selected_landscape.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + [LinphoneUtils buttonFixStatesForTabs:dialerButton]; [LinphoneUtils buttonFixStatesForTabs:dialerButtonLandscape]; } @@ -153,37 +153,37 @@ static NSString * const kDisappearAnimation = @"disappear"; // Set selected+over background: IB lack ! [settingsButton setBackgroundImage:[UIImage imageNamed:@"settings_selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + // Set selected+over background: IB lack ! [settingsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"settings_selected_landscape.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + [LinphoneUtils buttonFixStatesForTabs:settingsButton]; [LinphoneUtils buttonFixStatesForTabs:settingsButtonLandscape]; } - + { UIButton *chatButtonLandscape = (UIButton*) [landscapeView viewWithTag:[chatButton tag]]; // Set selected+over background: IB lack ! [chatButton setBackgroundImage:[UIImage imageNamed:@"chat_selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + // Set selected+over background: IB lack ! [chatButtonLandscape setBackgroundImage:[UIImage imageNamed:@"chat_selected_landscape.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)]; - + [LinphoneUtils buttonFixStatesForTabs:chatButton]; [LinphoneUtils buttonFixStatesForTabs:chatButtonLandscape]; } - + [super viewDidLoad]; // Have to be after due to TPMultiLayoutViewController } - (void)viewDidUnload { [super viewDidUnload]; - - [[NSNotificationCenter defaultCenter] removeObserver:self - name:UIApplicationWillEnterForegroundNotification + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIApplicationWillEnterForegroundNotification object:nil]; } @@ -203,8 +203,8 @@ static NSString * const kDisappearAnimation = @"disappear"; #pragma mark - Event Functions -- (void)applicationWillEnterForeground:(NSNotification*)notif { - // Force the animations +- (void)applicationWillEnterForeground:(NSNotification*)notif { + // Force the animations [[self.view layer] removeAllAnimations]; [historyNotificationView.layer setTransform:CATransform3DIdentity]; [chatNotificationView.layer setTransform:CATransform3DIdentity]; @@ -219,7 +219,7 @@ static NSString * const kDisappearAnimation = @"disappear"; [self updateMissedCall:linphone_core_get_missed_calls_count([LinphoneManager getLc]) appear:TRUE]; } -- (void)changeViewEvent:(NSNotification*)notif { +- (void)changeViewEvent:(NSNotification*)notif { //UICompositeViewDescription *view = [notif.userInfo objectForKey: @"view"]; //if(view != nil) [self updateView:[[PhoneMainView instance] firstView]]; @@ -246,7 +246,7 @@ static NSString * const kDisappearAnimation = @"disappear"; } -#pragma mark - +#pragma mark - - (void)update:(BOOL)appear{ [self updateView:[[PhoneMainView instance] firstView]]; @@ -354,14 +354,14 @@ static NSString * const kDisappearAnimation = @"disappear"; bounce.autoreverses = TRUE; bounce.repeatCount = HUGE_VALF; [target.layer addAnimation:bounce forKey:animationID]; - + } - (void)stopBounceAnimation:(NSString *)animationID target:(UIView *)target { [target.layer removeAnimationForKey:animationID]; } - -- (void)updateView:(UICompositeViewDescription*) view { + +- (void)updateView:(UICompositeViewDescription*) view { // Update buttons if([view equal:[HistoryViewController compositeViewDescription]]) { historyButton.selected = TRUE; @@ -401,7 +401,8 @@ static NSString * const kDisappearAnimation = @"disappear"; [ContactSelection setSelectionMode:ContactSelectionModeNone]; [ContactSelection setAddAddress:nil]; [ContactSelection setSipFilter:nil]; - [ContactSelection setEmailFilter:FALSE]; + [ContactSelection enableEmailFilter:FALSE]; + [ContactSelection setNameOrEmailFilter:nil]; [[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription]]; } @@ -422,7 +423,7 @@ static NSString * const kDisappearAnimation = @"disappear"; - (NSDictionary*)attributesForView:(UIView*)view { NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; - + [attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"]; [attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"]; if([view isKindOfClass:[UIButton class]]) { @@ -430,7 +431,7 @@ static NSString * const kDisappearAnimation = @"disappear"; [LinphoneUtils buttonMultiViewAddAttributes:attributes button:button]; } [attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"]; - + return attributes; }