react-native-contacts 7.0.0 → 7.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -10
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/rt2zz/reactnativecontacts/ContactsManager.java +31 -4
- package/android/src/main/java/com/rt2zz/reactnativecontacts/ContactsProvider.java +3 -0
- package/foo.js +1 -0
- package/index.d.ts +2 -1
- package/ios/RCTContacts/RCTContacts.m +60 -33
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,10 +29,14 @@ PermissionsAndroid.request(
|
|
|
29
29
|
'buttonPositive': 'Please accept bare mortal'
|
|
30
30
|
}
|
|
31
31
|
)
|
|
32
|
-
.then(Contacts.getAll)
|
|
33
|
-
.then(contacts => {
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
.then(Contacts.getAll()
|
|
33
|
+
.then((contacts) => {
|
|
34
|
+
// work with contacts
|
|
35
|
+
console.log(contacts)
|
|
36
|
+
})
|
|
37
|
+
.catch((e) => {
|
|
38
|
+
console.log(e)
|
|
39
|
+
}))
|
|
36
40
|
```
|
|
37
41
|
|
|
38
42
|
## Installation
|
|
@@ -49,8 +53,14 @@ npm install react-native-contacts --save
|
|
|
49
53
|
```
|
|
50
54
|
yarn add react-native-contacts
|
|
51
55
|
```
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
## You no longer need to include the pod line in the PodFile since V7.0.0+, we now support autolinking!
|
|
57
|
+
If you were previously using manually linking follow these steps to upgrade
|
|
58
|
+
```
|
|
59
|
+
react-native unlink react-native-contacts
|
|
60
|
+
npm install latest version of react-native-contacts
|
|
61
|
+
Your good to go!
|
|
62
|
+
```
|
|
63
|
+
### react native version 60 and above
|
|
54
64
|
|
|
55
65
|
If you are using react native version 0.60 or above you do not have to link this library.
|
|
56
66
|
|
|
@@ -134,10 +144,10 @@ The `READ_CONTACTS` permission must be added to your main application's `Android
|
|
|
134
144
|
```
|
|
135
145
|
|
|
136
146
|
##### API 22 and below
|
|
137
|
-
Add `
|
|
147
|
+
Add `READ_PROFILE` and/or `WRITE_PROFILE` permissions to `AndroidManifest.xml`
|
|
138
148
|
```xml
|
|
139
149
|
...
|
|
140
|
-
<uses-permission android:name="android.permission.
|
|
150
|
+
<uses-permission android:name="android.permission.READ_PROFILE" />
|
|
141
151
|
...
|
|
142
152
|
```
|
|
143
153
|
|
|
@@ -169,7 +179,8 @@ If you'd like to read/write the contact's notes, call the `iosEnableNotesUsage(t
|
|
|
169
179
|
* `getPhotoForId(contactId)`: Promise<string> - returns a URI (or null) for a contacts photo
|
|
170
180
|
* `addContact(contact)`: Promise<Contact> - adds a contact to the AddressBook.
|
|
171
181
|
* `openContactForm(contact)` - create a new contact and display in contactsUI.
|
|
172
|
-
* `openExistingContact(contact)` - where contact is an object with a valid recordID
|
|
182
|
+
* `openExistingContact(contact)` - open existing contact (edit mode), where contact is an object with a valid recordID
|
|
183
|
+
* `viewExistingContact(contact)` - open existing contact (view mode), where contact is an object with a valid recordID
|
|
173
184
|
* `editExistingContact(contact)`: Promise<Contact> - add numbers to the contact, where the contact is an object with a valid recordID and an array of phoneNumbers
|
|
174
185
|
* `updateContact(contact)`: Promise<Contact> - where contact is an object with a valid recordID
|
|
175
186
|
* `deleteContact(contact)` - where contact is an object with a valid recordID
|
|
@@ -215,7 +226,7 @@ If you'd like to read/write the contact's notes, call the `iosEnableNotesUsage(t
|
|
|
215
226
|
prefix: 'MR',
|
|
216
227
|
suffix: '',
|
|
217
228
|
department: '',
|
|
218
|
-
birthday: {'year': 1988, 'month':
|
|
229
|
+
birthday: {'year': 1988, 'month': 1, 'day': 1 },
|
|
219
230
|
imAddresses: [
|
|
220
231
|
{ username: '0123456789', service: 'ICQ'},
|
|
221
232
|
{ username: 'johndoe123', service: 'Facebook'}
|
package/android/build.gradle
CHANGED
|
@@ -308,15 +308,18 @@ public class ContactsManager extends ReactContextBaseJavaModule implements Activ
|
|
|
308
308
|
ReadableArray phoneNumbers = contact.hasKey("phoneNumbers") ? contact.getArray("phoneNumbers") : null;
|
|
309
309
|
int numOfPhones = 0;
|
|
310
310
|
String[] phones = null;
|
|
311
|
-
|
|
311
|
+
String[] phonesLabels = null;
|
|
312
|
+
Integer[] phonesLabelsTypes = null;
|
|
312
313
|
if (phoneNumbers != null) {
|
|
313
314
|
numOfPhones = phoneNumbers.size();
|
|
314
315
|
phones = new String[numOfPhones];
|
|
315
|
-
phonesLabels = new
|
|
316
|
+
phonesLabels = new String[numOfPhones];
|
|
317
|
+
phonesLabelsTypes = new Integer[numOfPhones];
|
|
316
318
|
for (int i = 0; i < numOfPhones; i++) {
|
|
317
319
|
phones[i] = phoneNumbers.getMap(i).getString("number");
|
|
318
320
|
String label = phoneNumbers.getMap(i).getString("label");
|
|
319
|
-
phonesLabels[i] =
|
|
321
|
+
phonesLabels[i] = label;
|
|
322
|
+
phonesLabelsTypes[i] = mapStringToPhoneType(label);
|
|
320
323
|
}
|
|
321
324
|
}
|
|
322
325
|
|
|
@@ -432,8 +435,10 @@ public class ContactsManager extends ReactContextBaseJavaModule implements Activ
|
|
|
432
435
|
for (int i = 0; i < numOfPhones; i++) {
|
|
433
436
|
ContentValues phone = new ContentValues();
|
|
434
437
|
phone.put(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
|
|
435
|
-
phone.put(CommonDataKinds.Phone.TYPE,
|
|
438
|
+
phone.put(CommonDataKinds.Phone.TYPE, phonesLabelsTypes[i]);
|
|
439
|
+
phone.put(CommonDataKinds.Phone.LABEL, phonesLabels[i]);
|
|
436
440
|
phone.put(CommonDataKinds.Phone.NUMBER, phones[i]);
|
|
441
|
+
|
|
437
442
|
contactData.add(phone);
|
|
438
443
|
}
|
|
439
444
|
|
|
@@ -514,6 +519,28 @@ public class ContactsManager extends ReactContextBaseJavaModule implements Activ
|
|
|
514
519
|
promise.reject(e.toString());
|
|
515
520
|
}
|
|
516
521
|
}
|
|
522
|
+
|
|
523
|
+
/*
|
|
524
|
+
* View contact in native app
|
|
525
|
+
*/
|
|
526
|
+
@ReactMethod
|
|
527
|
+
public void viewExistingContact(ReadableMap contact, Promise promise) {
|
|
528
|
+
|
|
529
|
+
String recordID = contact.hasKey("recordID") ? contact.getString("recordID") : null;
|
|
530
|
+
|
|
531
|
+
try {
|
|
532
|
+
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, recordID);
|
|
533
|
+
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
534
|
+
intent.setDataAndType(uri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);
|
|
535
|
+
intent.putExtra("finishActivityOnSaveCompleted", true);
|
|
536
|
+
|
|
537
|
+
updateContactPromise = promise;
|
|
538
|
+
getReactApplicationContext().startActivityForResult(intent, REQUEST_OPEN_EXISTING_CONTACT, Bundle.EMPTY);
|
|
539
|
+
|
|
540
|
+
} catch (Exception e) {
|
|
541
|
+
promise.reject(e.toString());
|
|
542
|
+
}
|
|
543
|
+
}
|
|
517
544
|
|
|
518
545
|
/*
|
|
519
546
|
* Edit contact in native app
|
package/foo.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('hello')
|
package/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export function getPhotoForId(contactId: string): Promise<string>;
|
|
|
6
6
|
export function addContact(contact: Contact): Promise<void>;
|
|
7
7
|
export function openContactForm(contact: Partial<Contact>): Promise<Contact>;
|
|
8
8
|
export function openExistingContact(contact: Contact): Promise<Contact>;
|
|
9
|
+
export function viewExistingContact(contact: { recordID: string }): Promise<Contact | void>
|
|
9
10
|
export function editExistingContact(contact: Contact): Promise<Contact>;
|
|
10
11
|
export function updateContact(contact: Contact): Promise<void>;
|
|
11
12
|
export function deleteContact(contact: Contact): Promise<void>;
|
|
@@ -54,7 +55,7 @@ export interface Birthday {
|
|
|
54
55
|
export interface Contact {
|
|
55
56
|
recordID: string;
|
|
56
57
|
backTitle: string;
|
|
57
|
-
company: string;
|
|
58
|
+
company: string|null;
|
|
58
59
|
emailAddresses: EmailAddress[];
|
|
59
60
|
displayName: string;
|
|
60
61
|
familyName: string;
|
|
@@ -347,9 +347,9 @@ RCT_EXPORT_METHOD(getCount:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromise
|
|
|
347
347
|
if (birthday.month != NSDateComponentUndefined && birthday.day != NSDateComponentUndefined) {
|
|
348
348
|
//months are indexed to 0 in JavaScript (0 = January) so we subtract 1 from NSDateComponents.month
|
|
349
349
|
if (birthday.year != NSDateComponentUndefined) {
|
|
350
|
-
[output setObject:@{@"year": @(birthday.year), @"month": @(birthday.month
|
|
350
|
+
[output setObject:@{@"year": @(birthday.year), @"month": @(birthday.month), @"day": @(birthday.day)} forKey:@"birthday"];
|
|
351
351
|
} else {
|
|
352
|
-
[output setObject:@{@"month": @(birthday.month
|
|
352
|
+
[output setObject:@{@"month": @(birthday.month), @"day":@(birthday.day)} forKey:@"birthday"];
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
355
|
}
|
|
@@ -676,18 +676,8 @@ RCT_EXPORT_METHOD(openContactForm:(NSDictionary *)contactData
|
|
|
676
676
|
viewController = viewController.presentedViewController;
|
|
677
677
|
}
|
|
678
678
|
[viewController presentViewController:navigation animated:YES completion:nil];
|
|
679
|
-
|
|
680
|
-
if (@available(iOS 13, *)) {
|
|
681
|
-
viewController.view.window.backgroundColor=[UIColor blackColor];
|
|
682
|
-
navigation.navigationBar.topItem.title = @"";
|
|
683
|
-
UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame];
|
|
684
|
-
statusBar.backgroundColor = [UIColor blackColor];
|
|
685
|
-
statusBar.tag=1;
|
|
686
|
-
controller.navigationController.navigationBar.tintColor = [UIColor blackColor];
|
|
687
|
-
[[UIApplication sharedApplication].keyWindow addSubview:statusBar];
|
|
688
|
-
}
|
|
689
679
|
|
|
690
|
-
updateContactPromise = resolve;
|
|
680
|
+
self->updateContactPromise = resolve;
|
|
691
681
|
});
|
|
692
682
|
}
|
|
693
683
|
|
|
@@ -716,7 +706,7 @@ RCT_EXPORT_METHOD(openExistingContact:(NSDictionary *)contactData resolver:(RCTP
|
|
|
716
706
|
CNContactViewController *contactViewController = [CNContactViewController viewControllerForContact:contact];
|
|
717
707
|
|
|
718
708
|
// Add a cancel button which will close the view
|
|
719
|
-
contactViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:backTitle == nil ? @"Cancel" : backTitle style:
|
|
709
|
+
contactViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:backTitle == nil ? @"Cancel" : backTitle style:UIBarButtonItemStyleDone target:self action:@selector(cancelContactForm)];
|
|
720
710
|
contactViewController.delegate = self;
|
|
721
711
|
|
|
722
712
|
|
|
@@ -777,6 +767,56 @@ RCT_EXPORT_METHOD(openExistingContact:(NSDictionary *)contactData resolver:(RCTP
|
|
|
777
767
|
}
|
|
778
768
|
}
|
|
779
769
|
|
|
770
|
+
RCT_EXPORT_METHOD(viewExistingContact:(NSDictionary *)contactData resolver:(RCTPromiseResolveBlock) resolve
|
|
771
|
+
rejecter:(RCTPromiseRejectBlock) reject)
|
|
772
|
+
{
|
|
773
|
+
if(!contactStore) {
|
|
774
|
+
contactStore = [[CNContactStore alloc] init];
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
NSString* recordID = [contactData valueForKey:@"recordID"];
|
|
778
|
+
NSString* backTitle = [contactData valueForKey:@"backTitle"];
|
|
779
|
+
|
|
780
|
+
NSArray *keys = @[CNContactIdentifierKey,
|
|
781
|
+
CNContactEmailAddressesKey,
|
|
782
|
+
CNContactBirthdayKey,
|
|
783
|
+
CNContactImageDataKey,
|
|
784
|
+
CNContactPhoneNumbersKey,
|
|
785
|
+
[CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName],
|
|
786
|
+
[CNContactViewController descriptorForRequiredKeys]];
|
|
787
|
+
|
|
788
|
+
@try {
|
|
789
|
+
|
|
790
|
+
CNContact *contact = [contactStore unifiedContactWithIdentifier:recordID keysToFetch:keys error:nil];
|
|
791
|
+
|
|
792
|
+
CNContactViewController *contactViewController = [CNContactViewController viewControllerForContact:contact];
|
|
793
|
+
|
|
794
|
+
// Add a cancel button which will close the view
|
|
795
|
+
contactViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:backTitle == nil ? @"Cancel" : backTitle style:UIBarButtonSystemItemCancel target:self action:@selector(cancelContactForm)];
|
|
796
|
+
contactViewController.delegate = self;
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
800
|
+
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:contactViewController];
|
|
801
|
+
|
|
802
|
+
UIViewController *currentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
|
|
803
|
+
|
|
804
|
+
while (currentViewController.presentedViewController)
|
|
805
|
+
{
|
|
806
|
+
currentViewController = currentViewController.presentedViewController;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
[currentViewController presentViewController:navigation animated:YES completion:nil];
|
|
810
|
+
|
|
811
|
+
updateContactPromise = resolve;
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
}
|
|
815
|
+
@catch (NSException *exception) {
|
|
816
|
+
reject(@"Error", [exception reason], nil);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
780
820
|
RCT_EXPORT_METHOD(editExistingContact:(NSDictionary *)contactData resolver:(RCTPromiseResolveBlock) resolve
|
|
781
821
|
rejecter:(RCTPromiseRejectBlock) reject)
|
|
782
822
|
{
|
|
@@ -860,17 +900,7 @@ RCT_EXPORT_METHOD(editExistingContact:(NSDictionary *)contactData resolver:(RCTP
|
|
|
860
900
|
[viewController presentViewController:navigation animated:YES completion:nil];
|
|
861
901
|
[controller presentViewController:alert animated:YES completion:nil];
|
|
862
902
|
|
|
863
|
-
|
|
864
|
-
viewController.view.window.backgroundColor=[UIColor blackColor];
|
|
865
|
-
navigation.navigationBar.topItem.title = @"";
|
|
866
|
-
UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame];
|
|
867
|
-
statusBar.backgroundColor = [UIColor blackColor];
|
|
868
|
-
statusBar.tag=1;
|
|
869
|
-
controller.navigationController.navigationBar.tintColor = [UIColor blackColor];
|
|
870
|
-
[[UIApplication sharedApplication].keyWindow addSubview:statusBar];
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
updateContactPromise = resolve;
|
|
903
|
+
self->updateContactPromise = resolve;
|
|
874
904
|
});
|
|
875
905
|
|
|
876
906
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
@@ -903,6 +933,10 @@ RCT_EXPORT_METHOD(editExistingContact:(NSDictionary *)contactData resolver:(RCTP
|
|
|
903
933
|
{
|
|
904
934
|
if (updateContactPromise != nil) {
|
|
905
935
|
UIViewController *rootViewController = (UIViewController*)[[[[UIApplication sharedApplication] delegate] window] rootViewController];
|
|
936
|
+
while (rootViewController.presentedViewController)
|
|
937
|
+
{
|
|
938
|
+
rootViewController = rootViewController.presentedViewController;
|
|
939
|
+
}
|
|
906
940
|
[rootViewController dismissViewControllerAnimated:YES completion:nil];
|
|
907
941
|
|
|
908
942
|
updateContactPromise(nil);
|
|
@@ -925,12 +959,6 @@ RCT_EXPORT_METHOD(editExistingContact:(NSDictionary *)contactData resolver:(RCTP
|
|
|
925
959
|
|
|
926
960
|
updateContactPromise = nil;
|
|
927
961
|
}
|
|
928
|
-
|
|
929
|
-
UIView *statusBar = [[UIApplication sharedApplication].keyWindow viewWithTag:1];
|
|
930
|
-
|
|
931
|
-
if(statusBar) {
|
|
932
|
-
[statusBar removeFromSuperview];
|
|
933
|
-
}
|
|
934
962
|
}
|
|
935
963
|
|
|
936
964
|
RCT_EXPORT_METHOD(updateContact:(NSDictionary *)contactData resolver:(RCTPromiseResolveBlock) resolve
|
|
@@ -1011,8 +1039,7 @@ RCT_EXPORT_METHOD(updateContact:(NSDictionary *)contactData resolver:(RCTPromise
|
|
|
1011
1039
|
if (birthday[@"year"]) {
|
|
1012
1040
|
components.year = [birthday[@"year"] intValue];
|
|
1013
1041
|
}
|
|
1014
|
-
|
|
1015
|
-
components.month = [birthday[@"month"] intValue] + 1;
|
|
1042
|
+
components.month = [birthday[@"month"] intValue];
|
|
1016
1043
|
components.day = [birthday[@"day"] intValue];
|
|
1017
1044
|
}
|
|
1018
1045
|
|