react-native-contacts 6.0.5 → 7.0.3

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 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
- ### react native version 60 and above
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 `READ_CONTACTS` and/or `WRITE_PROFILE` permissions to `AndroidManifest.xml`
147
+ Add `READ_PROFILE` and/or `WRITE_PROFILE` permissions to `AndroidManifest.xml`
138
148
  ```xml
139
149
  ...
140
- <uses-permission android:name="android.permission.READ_CONTACTS" />
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': 0, 'day': 1 },
229
+ birthday: {'year': 1988, 'month': 1, 'day': 1 },
219
230
  imAddresses: [
220
231
  { username: '0123456789', service: 'ICQ'},
221
232
  { username: 'johndoe123', service: 'Facebook'}
@@ -1,26 +1,27 @@
1
1
  buildscript {
2
2
  repositories {
3
+ mavenCentral()
3
4
  google()
4
- jcenter()
5
5
  }
6
6
 
7
7
  dependencies {
8
- classpath 'com.android.tools.build:gradle:3.1.4'
8
+ classpath 'com.android.tools.build:gradle:4.1.0'
9
9
  }
10
10
  }
11
11
 
12
12
  apply plugin: 'com.android.library'
13
13
 
14
- def DEFAULT_COMPILE_SDK_VERSION = 28
15
- def DEFAULT_TARGET_SDK_VERSION = 28
16
- def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3'
14
+ def DEFAULT_MIN_SDK_VERSION = 21
15
+ def DEFAULT_COMPILE_SDK_VERSION = 29
16
+ def DEFAULT_TARGET_SDK_VERSION = 29
17
+ def DEFAULT_BUILD_TOOLS_VERSION = '29.0.3'
17
18
 
18
19
  android {
19
20
  compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION
20
21
  buildToolsVersion rootProject.hasProperty('buildToolsVersion') ? rootProject.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION
21
22
 
22
23
  defaultConfig {
23
- minSdkVersion 16
24
+ minSdkVersion rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : DEFAULT_MIN_SDK_VERSION
24
25
  targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION
25
26
  versionCode 1
26
27
  versionName "1.0"
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
3
3
  distributionPath=wrapper/dists
4
4
  zipStoreBase=GRADLE_USER_HOME
5
5
  zipStorePath=wrapper/dists
6
- distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
@@ -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
- Integer[] phonesLabels = null;
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 Integer[numOfPhones];
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] = mapStringToPhoneType(label);
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, phonesLabels[i]);
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
@@ -551,6 +551,9 @@ public class ContactsProvider {
551
551
  }
552
552
  }
553
553
  break;
554
+ case Note.CONTENT_ITEM_TYPE:
555
+ contact.note = cursor.getString(cursor.getColumnIndex(Note.NOTE));
556
+ break;
554
557
  }
555
558
  }
556
559
 
package/index.d.ts CHANGED
@@ -54,7 +54,7 @@ export interface Birthday {
54
54
  export interface Contact {
55
55
  recordID: string;
56
56
  backTitle: string;
57
- company: string;
57
+ company: string|null;
58
58
  emailAddresses: EmailAddress[];
59
59
  displayName: string;
60
60
  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 - 1), @"day": @(birthday.day)} forKey:@"birthday"];
350
+ [output setObject:@{@"year": @(birthday.year), @"month": @(birthday.month), @"day": @(birthday.day)} forKey:@"birthday"];
351
351
  } else {
352
- [output setObject:@{@"month": @(birthday.month - 1), @"day":@(birthday.day)} forKey:@"birthday"];
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
 
@@ -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
- if (@available(iOS 13, *)) {
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(), ^{
@@ -925,12 +955,6 @@ RCT_EXPORT_METHOD(editExistingContact:(NSDictionary *)contactData resolver:(RCTP
925
955
 
926
956
  updateContactPromise = nil;
927
957
  }
928
-
929
- UIView *statusBar = [[UIApplication sharedApplication].keyWindow viewWithTag:1];
930
-
931
- if(statusBar) {
932
- [statusBar removeFromSuperview];
933
- }
934
958
  }
935
959
 
936
960
  RCT_EXPORT_METHOD(updateContact:(NSDictionary *)contactData resolver:(RCTPromiseResolveBlock) resolve
@@ -1011,8 +1035,7 @@ RCT_EXPORT_METHOD(updateContact:(NSDictionary *)contactData resolver:(RCTPromise
1011
1035
  if (birthday[@"year"]) {
1012
1036
  components.year = [birthday[@"year"] intValue];
1013
1037
  }
1014
- //months are indexed to 0 in JavaScript so we add 1 when assigning the month to DateComponent
1015
- components.month = [birthday[@"month"] intValue] + 1;
1038
+ components.month = [birthday[@"month"] intValue];
1016
1039
  components.day = [birthday[@"day"] intValue];
1017
1040
  }
1018
1041
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/rt2zz/react-native-contacts.git"
6
6
  },
7
- "version": "6.0.5",
7
+ "version": "7.0.3",
8
8
  "description": "React Native Contacts (android & ios)",
9
9
  "nativePackage": true,
10
10
  "keywords": [
@@ -44,7 +44,6 @@
44
44
  "react-native-cli": "^2.0.1"
45
45
  },
46
46
  "peerDependencies": {
47
- "react": "*",
48
- "react-native": "*"
47
+ "react-native": ">=0.64.0"
49
48
  }
50
49
  }