Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-26032] iOS/Android: Fix Ti.Contacts parity, deprecate old API's properly #10038

Merged
merged 15 commits into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ public void save(Object people)

@Kroll.method
public PersonProxy getPersonByID(long id)
{
Log.w(TAG, "Ti.Contacts.getPersonByID() has been deprecated in favor of Ti.Contacts.getPersonByIdentifier() for cross-platform parity", Log.DEBUG_MODE);
return contactsApi.getPersonById(id);
}

@Kroll.method
public PersonProxy getPersonByIdentifier(long id)
{
return contactsApi.getPersonById(id);
}
Expand Down
13 changes: 8 additions & 5 deletions apidoc/Titanium/Contacts/Contacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,17 @@ methods:
type: Number

- name: getGroupByID
summary: Gets the group with the specified identifier. Deprecated for >= iOS9. Use <Titanium.Contacts.getGroupByIdentifier> instead.
summary: Gets the group with the specified identifier.
returns:
type: Titanium.Contacts.Group
platforms: [iphone, ipad]
parameters:
- name: id
summary: Group identifier.
type: Number
osver: {ios: {max: "8.0"}}
deprecated:
since: "5.0.0"
notes: Use <Titanium.Contacts.getGroupByIdentifier> instead.

- name: getGroupByIdentifier
summary: Gets the group with the specified identifier.
Expand All @@ -105,7 +107,6 @@ methods:
summary: Group identifier.
type: String
since: "5.0.0"
osver: {ios: {min: "9.0"}}

- name: getPeopleWithName
summary: |
Expand All @@ -120,14 +121,16 @@ methods:
type: String

- name: getPersonByID
summary: Gets the person with the specified identifier. Deprecated for >= iOS9. Use <Titanium.Contacts.getPersonByIdentifier> instead.
summary: Gets the person with the specified identifier.
returns:
type: Titanium.Contacts.Person
parameters:
- name: id
summary: Contact identifier.
type: Number
osver: {ios: {max: "8.0"}}
deprecated:
since: "5.0.0"
notes: Use <Titanium.Contacts.getPersonByIdentifier> instead.

- name: getPersonByIdentifier
summary: Gets the person with the specified identifier.
Expand Down
10 changes: 5 additions & 5 deletions iphone/Classes/ContactsModule.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2014 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2018 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
Expand All @@ -17,8 +17,8 @@

@interface ContactsModule : TiModule <ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate, CNContactViewControllerDelegate, TiContactsPersonUpdateObserver> {
@private
ABAddressBookRef addressBook;
ABPeoplePickerNavigationController *picker;
ABAddressBookRef addressBook; // Deprecated
ABPeoplePickerNavigationController *picker; // Deprecated
BOOL reloadAddressBook;
BOOL animated;
KrollCallback *cancelCallback;
Expand All @@ -41,11 +41,11 @@
- (NSArray *)getAllPeople:(id)unused;
- (TiContactsPerson *)createPerson:(id)arg;
- (void)removePerson:(id)arg;

@property (nonatomic, readonly) NSNumber *contactsAuthorization;
- (void)requestAuthorization:(id)args;
- (void)requestContactsPermissions:(id)args;

@property (nonatomic, readonly) NSNumber *contactsAuthorization;

@property (nonatomic, readonly) NSNumber *CONTACTS_KIND_PERSON;
@property (nonatomic, readonly) NSNumber *CONTACTS_KIND_ORGANIZATION;

Expand Down
91 changes: 43 additions & 48 deletions iphone/Classes/ContactsModule.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2018 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
Expand All @@ -27,7 +27,6 @@ @implementation ContactsModule

void CMExternalChangeCallback(ABAddressBookRef notifyAddressBook, CFDictionaryRef info, void *context)
{
DebugLog(@"Got External Change Callback");
ContactsModule *theModule = (ContactsModule *)context;
theModule->reloadAddressBook = YES;
[theModule fireEvent:@"reload" withObject:nil];
Expand Down Expand Up @@ -57,7 +56,7 @@ - (ABAddressBookRef)addressBook
if (addressBook == NULL) {
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
if (addressBook == NULL) {
DebugLog(@"[WARN] Could not create an address book. Make sure you have gotten permission first.");
DebugLog(@"[ERROR] Could not create an address book. Make sure you have gotten permission first.");
} else {
ABAddressBookRegisterExternalChangeCallback(addressBook, CMExternalChangeCallback, self);
}
Expand Down Expand Up @@ -203,11 +202,11 @@ - (void)requestContactsPermissions:(id)args
break;
case CNAuthorizationStatusDenied:
code = CNAuthorizationStatusDenied;
error = @"The user has denied access to the address book";
error = NSLocalizedString(@"The user has denied access to the address book", nil);
break;
case CNAuthorizationStatusRestricted:
code = CNAuthorizationStatusRestricted;
error = @"The user is unable to allow access to the address book";
error = NSLocalizedString(@"The user is unable to allow access to the address book", nil);
break;
default:
break;
Expand All @@ -224,7 +223,7 @@ - (void)requestContactsPermissions:(id)args
CNContactStore *ourContactStore = [self contactStore];
[ourContactStore requestAccessForEntityType:CNEntityTypeContacts
completionHandler:^(BOOL granted, NSError *error) {
NSString *errorMessage = granted ? nil : @"The user has denied access to the address book";
NSString *errorMessage = granted ? nil : NSLocalizedString(@"The user has denied access to the address book", nil);
NSDictionary *propertiesDict = [TiUtils dictionaryWithCode:[error code] message:errorMessage];
KrollEvent *invocationEvent = [[KrollEvent alloc] initWithCallback:callback eventObject:propertiesDict thisObject:self];
[[callback context] enqueue:invocationEvent];
Expand All @@ -244,11 +243,11 @@ - (void)requestContactsPermissions:(id)args
break;
case kABAuthorizationStatusDenied:
code = kABAuthorizationStatusDenied;
error = @"The user has denied access to the address book";
error = NSLocalizedString(@"The user has denied access to the address book", nil);
break;
case kABAuthorizationStatusRestricted:
code = kABAuthorizationStatusRestricted;
error = @"The user is unable to allow access to the address book";
error = NSLocalizedString(@"The user is unable to allow access to the address book", nil);
default:
break;
}
Expand Down Expand Up @@ -406,33 +405,35 @@ - (void)showContacts:(id)args
[[TiApp app] showModalController:picker animated:animated];
}

// OK to do outside main thread
- (TiContactsPerson *)getPersonByID:(id)arg
{
ENSURE_SINGLE_ARG(arg, NSObject)

if ([TiUtils isIOS9OrGreater]) {
DebugLog(@"This method is removed for iOS9 and greater.");
DEPRECATED_REPLACED(@"Contacts.getPersonByID", @"5.0.0", @"Contacts.getPersonByIdentifier");
return nil;
}
ENSURE_SINGLE_ARG(arg, NSObject)
__block int idNum = [TiUtils intValue:arg];
__block BOOL validId = NO;

__block ABRecordID recordId = [TiUtils intValue:arg];
__block BOOL isValidId = NO;

TiThreadPerformOnMainThread(^{
ABAddressBookRef ourAddressBook = [self addressBook];
if (ourAddressBook == NULL) {
return;
}
ABRecordRef record = NULL;
record = ABAddressBookGetPersonWithRecordID(ourAddressBook, idNum);
record = ABAddressBookGetPersonWithRecordID(ourAddressBook, recordId);
if (record != NULL) {
validId = YES;
isValidId = YES;
}
},
YES);
if (validId == YES) {
return [[[TiContactsPerson alloc] _initWithPageContext:[self executionContext] recordId:idNum module:self] autorelease];

if (isValidId) {
return [[[TiContactsPerson alloc] _initWithPageContext:[self executionContext] recordId:recordId module:self] autorelease];
}

return NULL;
}

Expand All @@ -441,40 +442,40 @@ - (TiContactsGroup *)getGroupByID:(id)arg
ENSURE_SINGLE_ARG(arg, NSObject)

if ([TiUtils isIOS9OrGreater]) {
DebugLog(@"This method is removed for iOS9 and greater.");
DEPRECATED_REPLACED(@"Contacts.getGroupByID", @"5.0.0", @"Contacts.getGroupByIdentifier");
return nil;
}

__block int idNum = [TiUtils intValue:arg];
__block BOOL validId = NO;
__block ABRecordID recordId = [TiUtils intValue:arg];
__block BOOL isValidId = NO;

TiThreadPerformOnMainThread(^{
ABAddressBookRef ourAddressBook = [self addressBook];
if (ourAddressBook == NULL) {
return;
}
ABRecordRef record = NULL;
record = ABAddressBookGetGroupWithRecordID(ourAddressBook, idNum);
record = ABAddressBookGetGroupWithRecordID(ourAddressBook, recordId);
if (record != NULL) {
validId = YES;
isValidId = YES;
}
},
YES);

if (validId == YES) {
return [[[TiContactsGroup alloc] _initWithPageContext:[self executionContext] recordId:idNum module:self] autorelease];
if (isValidId) {
return [[[TiContactsGroup alloc] _initWithPageContext:[self executionContext] recordId:recordId module:self] autorelease];
}

return NULL;
}

//New in iOS9
- (TiContactsPerson *)getPersonByIdentifier:(id)arg
{
// Backwards support for iOS 8: Use the deprecated API
if (![TiUtils isIOS9OrGreater]) {
DebugLog(@"This method is only for iOS9 and greater.");
return nil;
return [self getPersonByID:arg];
}

if (![NSThread isMainThread]) {
__block id result;
TiThreadPerformOnMainThread(^{
Expand All @@ -500,13 +501,13 @@ - (TiContactsPerson *)getPersonByIdentifier:(id)arg
observer:self] autorelease];
}

// New in iOS9
- (TiContactsGroup *)getGroupByIdentifier:(id)arg
{
// Backwards support for iOS 8: Use the deprecated API
if (![TiUtils isIOS9OrGreater]) {
DebugLog(@"This method is only for iOS9 and greater.");
return nil;
return [self getGroupByID:arg];
}

if (![NSThread isMainThread]) {
__block id result;
TiThreadPerformOnMainThread(^{
Expand Down Expand Up @@ -627,7 +628,7 @@ - (NSArray *)getAllPeople:(id)unused
RELEASE_TO_NIL(peopleRefs)
return people;
} else {
DebugLog(@"%@", [TiUtils messageFromError:error]);
DebugLog(@"[ERROR] %@", [TiUtils messageFromError:error]);
RELEASE_TO_NIL(peopleRefs)
return nil;
}
Expand Down Expand Up @@ -904,7 +905,7 @@ - (void)removeGroup:(id)arg
MAKE_SYSTEM_PROP(AUTHORIZATION_DENIED, kABAuthorizationStatusDenied);
MAKE_SYSTEM_PROP(AUTHORIZATION_AUTHORIZED, kABAuthorizationStatusAuthorized);

#pragma mark Picker delegate functions
#pragma mark ABPeoplePickerNavigationControllerDelegate (iOS < 9)

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
Expand All @@ -914,13 +915,13 @@ - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationContr
}
}

// Called after a person has been selected by the user. New in iOS 8
// Called after a person has been selected by the user
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person
{
if (selectedPersonCallback) {
TiContactsPerson *personObject = nil;
if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) {
// In iOS 8 selected contact is returned without requiring user permission. But we cannot query metadata like recordid.
// In iOS 8 selected contact is returned without requiring user permission. But we cannot query metadata like recordId.
personObject = [[[TiContactsPerson alloc] _initWithPageContext:[self executionContext] person:person module:self] autorelease];
} else {
// iOS7 and below or iOS8 with permission granted.
Expand All @@ -935,7 +936,7 @@ - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)p
}
}

// Called after a property has been selected by the user. New in iOS 8
// Called after a property has been selected by the user
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
if (selectedPropertyCallback) {
Expand Down Expand Up @@ -1024,7 +1025,8 @@ - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)p
}
}

//iOS9 delegates
#pragma mark CNContactPickerDelegate (iOS 9+)

- (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectContact:(nonnull CNContact *)contact
{
if (selectedPersonCallback) {
Expand All @@ -1036,11 +1038,6 @@ - (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectC
[[TiApp app] hideModalController:contactPicker animated:animated];
}
}
/*
- (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectContactProperties:(nonnull NSArray<CNContactProperty *> *)contactProperties
{

}*/

- (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectContactProperty:(nonnull CNContactProperty *)contactProperty
{
Expand Down Expand Up @@ -1101,7 +1098,7 @@ - (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectC
result = phoneNumber.stringValue;
}

//unfortunately, iOS9 Beta doesn't valuate birthdays. Watch this in case of changes.
// iOS 9+ doesn't valuate birthdays. Watch this in case of changes.
// Also contactProperty.identifier has an undocumented string "_systemCalendar" for gregorian calender.
if ([contactProperty.key isEqualToString:@"birthdays"]) {
if ([contactProperty.identifier isEqualToString:@"gregorian"] ||
Expand All @@ -1121,11 +1118,6 @@ - (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectC
}
return YES;
}
/*
- (void)contactPicker:(nonnull CNContactPickerViewController *)picker didSelectContacts:(nonnull NSArray<CNContact *> *)contacts
{

}*/

- (void)contactPickerDidCancel:(nonnull CNContactPickerViewController *)picker
{
Expand All @@ -1137,14 +1129,17 @@ - (void)contactPickerDidCancel:(nonnull CNContactPickerViewController *)picker

- (void)contactViewController:(nonnull CNContactViewController *)viewController didCompleteWithContact:(nullable CNContact *)contact
{
// Unused for nwo
}

#pragma mark - TiContactsPersonUpdateObserver
#pragma mark - Ti.Contacts.PersonUpdateObserver

- (void)didUpdatePerson:(TiContactsPerson *)person
{
saveRequest = saveRequest ? saveRequest : [CNSaveRequest new];
[saveRequest updateContact:person.nativePerson];
}

@end

#endif
8 changes: 4 additions & 4 deletions iphone/Classes/TiContactsPerson.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2018 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
Expand All @@ -11,14 +11,14 @@
#import <AddressBook/AddressBook.h>
#import <Contacts/Contacts.h>

@class TiContactsPerson;
@class TiContactsPerson, ContactsModule;

@protocol TiContactsPersonUpdateObserver <NSObject>

@optional
- (void)didUpdatePerson:(TiContactsPerson *)person;
@end

@class ContactsModule;

@interface TiContactsPerson : TiProxy {
@private
ABRecordRef record;
Expand Down