/* * PhoneGap is available under *either* the terms of the modified BSD license *or* the * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text. * * Copyright (c) 2005-2010, Nitobi Software Inc. * Copyright (c) 2010, IBM Corporation */ #import "Contacts.h" #import #import "PhoneGapDelegate.h" #import "Categories.h" #import "Notification.h" @implementation ContactsPicker @synthesize allowsEditing; @synthesize callbackId; @synthesize selectedId; @end @implementation NewContactsController @synthesize callbackId; @end @implementation DisplayContactsController @synthesize successCallback; @synthesize errorCallback; @end @implementation PGContacts // no longer used since code gets AddressBook for each operation. // If address book changes during save or remove operation, may get error but not much we can do about it // If address book changes during UI creation, display or edit, we don't control any saves so no need for callback /*void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void* context) { // note that this function is only called when another AddressBook instance modifies // the address book, not the current one. For example, through an OTA MobileMe sync Contacts* contacts = (Contacts*)context; [contacts addressBookDirty]; }*/ -(PGPlugin*) initWithWebView:(UIWebView*)theWebView { self = (PGContacts*)[super initWithWebView:(UIWebView*)theWebView]; /*if (self) { addressBook = ABAddressBookCreate(); ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, self); }*/ return self; } // overridden to clean up Contact statics -(void)onAppTerminate { //NSLog(@"Contacts::onAppTerminate"); [PGContact releaseDefaults]; } // iPhone only method to create a new contact through the GUI - (void) newContact:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options; { NSString* callbackId = [arguments objectAtIndex:0]; NewContactsController* npController = [[[NewContactsController alloc] init] autorelease]; npController.addressBook = ABAddressBookCreate(); npController.newPersonViewDelegate = self; npController.callbackId = callbackId; UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:npController] autorelease]; [[super appViewController] presentModalViewController:navController animated: YES]; } - (void) newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person { ABRecordID recordId = kABRecordInvalidID; NewContactsController* newCP = (NewContactsController*) newPersonViewController; NSString* callbackId = newCP.callbackId; if (person != NULL) { //return the contact id recordId = ABRecordGetRecordID(person); } [newPersonViewController dismissModalViewControllerAnimated:YES]; PluginResult* result = [PluginResult resultWithStatus: PGCommandStatus_OK messageAsInt: recordId]; //jsString = [NSString stringWithFormat: @"%@(%d);", newCP.jsCallback, recordId]; [self writeJavascript: [result toSuccessCallbackString:callbackId]]; } - (void) displayContact:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options { ABRecordID recordID = kABRecordInvalidID; NSString* callbackId = [arguments objectAtIndex:0]; recordID = [[arguments objectAtIndex:1] intValue]; bool bEdit = [options isKindOfClass:[NSNull class]] ? false : [options existsValue:@"true" forKey:@"allowsEditing"]; ABAddressBookRef addrBook = ABAddressBookCreate(); ABRecordRef rec = ABAddressBookGetPersonWithRecordID(addrBook, recordID); if (rec) { ABPersonViewController* personController = [[[ABPersonViewController alloc] init] autorelease]; personController.displayedPerson = rec; personController.personViewDelegate = self; personController.allowsEditing = NO; UIBarButtonItem* doneButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target: self action: @selector(dismissModalView:)] autorelease]; UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:personController] autorelease]; [self.appViewController presentModalViewController:navController animated: YES]; // this needs to be AFTER presentModal, if not it does not show up (iOS 4 regression: workaround) personController.navigationItem.rightBarButtonItem = doneButton; if (bEdit) { // create the editing controller and push it onto the stack ABPersonViewController* editPersonController = [[[ABPersonViewController alloc] init] autorelease]; editPersonController.displayedPerson = rec; editPersonController.personViewDelegate = self; editPersonController.allowsEditing = YES; [navController pushViewController:editPersonController animated:YES]; } } else { // no record, return error PluginResult* result = [PluginResult resultWithStatus: PGCommandStatus_OK messageAsInt: UNKNOWN_ERROR]; [self writeJavascript:[result toErrorCallbackString:callbackId]]; } CFRelease(addrBook); } - (void) dismissModalView:(id)sender { [self.appViewController dismissModalViewControllerAnimated:YES]; } - (BOOL) personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue { return YES; } - (void) chooseContact:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options { NSString* callbackId = [arguments objectAtIndex:0]; ContactsPicker* pickerController = [[[ContactsPicker alloc] init] autorelease]; pickerController.peoplePickerDelegate = self; pickerController.callbackId = callbackId; pickerController.selectedId = kABRecordInvalidID; pickerController.allowsEditing = (BOOL)[options existsValue:@"true" forKey:@"allowsEditing"]; [[super appViewController] presentModalViewController:pickerController animated: YES]; } - (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { ContactsPicker* picker = (ContactsPicker*)peoplePicker; ABRecordID contactId = ABRecordGetRecordID(person); picker.selectedId = contactId; // save so can return when dismiss if (picker.allowsEditing) { ABPersonViewController* personController = [[[ABPersonViewController alloc] init] autorelease]; personController.displayedPerson = person; personController.personViewDelegate = self; personController.allowsEditing = picker.allowsEditing; [peoplePicker pushViewController:personController animated:YES]; } else { // return the contact Id PluginResult* result = [PluginResult resultWithStatus: PGCommandStatus_OK messageAsInt: contactId]; [self writeJavascript:[result toSuccessCallbackString: picker.callbackId]]; [picker dismissModalViewControllerAnimated:YES]; } return NO; } - (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier { return YES; } - (void) peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker { // return contactId or invalid if none picked ContactsPicker* picker = (ContactsPicker*)peoplePicker; PluginResult* result = [PluginResult resultWithStatus:PGCommandStatus_OK messageAsInt: picker.selectedId]; [self writeJavascript:[result toSuccessCallbackString:picker.callbackId]]; [peoplePicker dismissModalViewControllerAnimated:YES]; } - (void) search:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options { NSString* jsString = nil; NSString* callbackId = [arguments objectAtIndex:0]; NSArray* fields = [options valueForKey:@"fields"]; NSDictionary* findOptions = [options valueForKey:@"findOptions"]; ABAddressBookRef addrBook = nil; NSArray* foundRecords = nil; addrBook = ABAddressBookCreate(); // get the findOptions values BOOL multiple = NO; // default is false NSString* filter = nil; if (![findOptions isKindOfClass:[NSNull class]]){ id value = nil; filter = (NSString*)[findOptions objectForKey:@"filter"]; value = [findOptions objectForKey:@"multiple"]; if ([value isKindOfClass:[NSNumber class]]){ // multiple is a boolean that will come through as an NSNumber multiple = [(NSNumber*)value boolValue]; //NSLog(@"multiple is: %d", multiple); } } NSDictionary* returnFields = [[PGContact class] calcReturnFields: fields]; NSMutableArray* matches = nil; if (!filter || [filter isEqualToString:@""]){ // get all records foundRecords = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook); if (foundRecords && [foundRecords count] > 0){ // create Contacts and put into matches array // doesn't make sense to ask for all records when multiple == NO but better check int xferCount = multiple == YES ? [foundRecords count] : 1; matches = [NSMutableArray arrayWithCapacity:xferCount]; for(int k = 0; k 0){ // convert to JS Contacts format and return in callback // - returnFields determines what properties to return NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; int count = multiple == YES ? [matches count] : 1; for(int i = 0; i