expo-contacts 15.0.6 → 15.0.8
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/CHANGELOG.md +16 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/contacts/ContactsModule.kt +71 -0
- package/build/Contacts.d.ts +48 -10
- package/build/Contacts.d.ts.map +1 -1
- package/expo-module.config.json +1 -1
- package/ios/ContactsModule.swift +44 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/{15.0.6/expo.modules.contacts-15.0.6-sources.jar → 15.0.8/expo.modules.contacts-15.0.8-sources.jar} +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8-sources.jar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8-sources.jar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8-sources.jar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8-sources.jar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.aar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.aar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.aar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.aar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/{15.0.6/expo.modules.contacts-15.0.6.module → 15.0.8/expo.modules.contacts-15.0.8.module} +22 -22
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.module.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.module.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.module.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.module.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/{15.0.6/expo.modules.contacts-15.0.6.pom → 15.0.8/expo.modules.contacts-15.0.8.pom} +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.pom.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.pom.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.pom.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.8/expo.modules.contacts-15.0.8.pom.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/maven-metadata.xml +4 -4
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/maven-metadata.xml.sha512 +1 -1
- package/package.json +3 -3
- package/src/Contacts.ts +60 -36
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6-sources.jar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6-sources.jar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6-sources.jar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6-sources.jar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.aar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.aar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.aar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.aar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.module.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.module.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.module.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.module.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.pom.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.pom.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.pom.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.contacts/15.0.6/expo.modules.contacts-15.0.6.pom.sha512 +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,22 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 15.0.8 — 2025-09-10
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Added `addContactsChangeListener()` to detect contact changes with platform-specific behavior. . ([#39434](https://github.com/expo/expo/pull/39434) by [@hryhoriiK97](https://github.com/hryhoriiK97))
|
|
18
|
+
|
|
19
|
+
### 💡 Others
|
|
20
|
+
|
|
21
|
+
- Extracted the read permission check from `FileSystemUtilities` ([#39210](https://github.com/expo/expo/pull/39210) by [@kosmydel](https://github.com/kosmydel))
|
|
22
|
+
|
|
23
|
+
## 15.0.7 — 2025-09-02
|
|
24
|
+
|
|
25
|
+
### 💡 Others
|
|
26
|
+
|
|
27
|
+
- Improved type safety with NewContact and ExistingContact types. ([#39269](https://github.com/expo/expo/pull/39269) by [@hryhoriiK97](https://github.com/hryhoriiK97))
|
|
28
|
+
|
|
13
29
|
## 15.0.6 — 2025-08-31
|
|
14
30
|
|
|
15
31
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -4,9 +4,12 @@ import android.Manifest
|
|
|
4
4
|
import android.app.Activity
|
|
5
5
|
import android.content.ContentResolver
|
|
6
6
|
import android.content.Intent
|
|
7
|
+
import android.database.ContentObserver
|
|
7
8
|
import android.database.Cursor
|
|
8
9
|
import android.net.Uri
|
|
9
10
|
import android.os.Bundle
|
|
11
|
+
import android.os.Handler
|
|
12
|
+
import android.os.HandlerThread
|
|
10
13
|
import android.provider.ContactsContract
|
|
11
14
|
import android.provider.ContactsContract.CommonDataKinds
|
|
12
15
|
import expo.modules.contacts.models.BaseModel
|
|
@@ -29,6 +32,8 @@ import expo.modules.kotlin.records.Record
|
|
|
29
32
|
import kotlinx.coroutines.launch
|
|
30
33
|
import java.util.UUID
|
|
31
34
|
|
|
35
|
+
const val onContactsChangeEventName = "onContactsChange"
|
|
36
|
+
|
|
32
37
|
data class ContactPage(
|
|
33
38
|
val data: List<Contact>,
|
|
34
39
|
val hasPreviousPage: Boolean = false,
|
|
@@ -123,6 +128,9 @@ class QueryArguments(
|
|
|
123
128
|
class ContactsModule : Module() {
|
|
124
129
|
private var contactPickingPromise: Promise? = null
|
|
125
130
|
private var contactManipulationPromise: Promise? = null
|
|
131
|
+
private var contactChangeObserver: ContentObserver? = null
|
|
132
|
+
private var contactsHandlerThread: HandlerThread? = null
|
|
133
|
+
private var contactsHandler: Handler? = null
|
|
126
134
|
|
|
127
135
|
private val permissionsManager: Permissions
|
|
128
136
|
get() = appContext.permissions ?: throw Exceptions.PermissionsModuleNotFound()
|
|
@@ -133,6 +141,21 @@ class ContactsModule : Module() {
|
|
|
133
141
|
override fun definition() = ModuleDefinition {
|
|
134
142
|
Name("ExpoContacts")
|
|
135
143
|
|
|
144
|
+
Events(onContactsChangeEventName)
|
|
145
|
+
|
|
146
|
+
OnDestroy {
|
|
147
|
+
stopObservingContactChanges()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
OnStartObserving(onContactsChangeEventName) {
|
|
151
|
+
ensureReadPermission()
|
|
152
|
+
startObservingContactChanges()
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
OnStopObserving(onContactsChangeEventName) {
|
|
156
|
+
stopObservingContactChanges()
|
|
157
|
+
}
|
|
158
|
+
|
|
136
159
|
AsyncFunction("requestPermissionsAsync") { promise: Promise ->
|
|
137
160
|
if (permissionsManager.isPermissionPresentInManifest(Manifest.permission.WRITE_CONTACTS)) {
|
|
138
161
|
Permissions.askForPermissionsWithPermissionsManager(permissionsManager, promise, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)
|
|
@@ -681,6 +704,54 @@ class ContactsModule : Module() {
|
|
|
681
704
|
ensureReadPermission()
|
|
682
705
|
ensureWritePermission()
|
|
683
706
|
}
|
|
707
|
+
|
|
708
|
+
private fun startObservingContactChanges() {
|
|
709
|
+
if (contactChangeObserver != null) {
|
|
710
|
+
return
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
contactsHandlerThread = HandlerThread("ContactsObserverThread")
|
|
714
|
+
contactsHandlerThread?.start()
|
|
715
|
+
contactsHandler = Handler(contactsHandlerThread!!.looper)
|
|
716
|
+
|
|
717
|
+
val observer = object : ContentObserver(contactsHandler) {
|
|
718
|
+
override fun onChange(selfChange: Boolean, uri: Uri?) {
|
|
719
|
+
super.onChange(selfChange, uri)
|
|
720
|
+
handleContactChange()
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
val urisToObserve = listOf(
|
|
725
|
+
ContactsContract.Contacts.CONTENT_URI,
|
|
726
|
+
ContactsContract.RawContacts.CONTENT_URI
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
urisToObserve.forEach { uri ->
|
|
730
|
+
resolver.registerContentObserver(uri, true, observer)
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
contactChangeObserver = observer
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
private fun stopObservingContactChanges() {
|
|
737
|
+
contactChangeObserver?.let { observer ->
|
|
738
|
+
resolver.unregisterContentObserver(observer)
|
|
739
|
+
contactChangeObserver = null
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
contactsHandler = null
|
|
743
|
+
contactsHandlerThread?.quitSafely()
|
|
744
|
+
contactsHandlerThread = null
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
private fun handleContactChange() {
|
|
748
|
+
sendEvent(
|
|
749
|
+
onContactsChangeEventName,
|
|
750
|
+
mapOf(
|
|
751
|
+
"body" to null
|
|
752
|
+
)
|
|
753
|
+
)
|
|
754
|
+
}
|
|
684
755
|
}
|
|
685
756
|
|
|
686
757
|
fun <T> Map<String, Any>.safeGet(key: String): T? {
|
package/build/Contacts.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { PermissionResponse, PermissionStatus, PermissionExpiration } from 'expo-modules-core';
|
|
1
|
+
import { PermissionResponse, PermissionStatus, PermissionExpiration, EventSubscription } from 'expo-modules-core';
|
|
2
2
|
import { type ShareOptions } from 'react-native';
|
|
3
|
+
export declare const onContactsChangeEventName = "onContactsChange";
|
|
3
4
|
export type ContactsPermissionResponse = PermissionResponse & {
|
|
4
5
|
/**
|
|
5
6
|
* Indicates if your app has access to the whole or only part of the contact library. Possible values are:
|
|
@@ -238,13 +239,11 @@ export type Image = {
|
|
|
238
239
|
base64?: string;
|
|
239
240
|
};
|
|
240
241
|
/**
|
|
241
|
-
*
|
|
242
|
+
* Base contact type without ID. For better type safety, consider using:
|
|
243
|
+
* - `Contact` when creating new contacts (no ID needed)
|
|
244
|
+
* - `ExistingContact` when working with contacts returned from the system (ID guaranteed)
|
|
242
245
|
*/
|
|
243
246
|
export type Contact = {
|
|
244
|
-
/**
|
|
245
|
-
* Immutable identifier used for querying and indexing. This value will be generated by the OS when the contact is created.
|
|
246
|
-
*/
|
|
247
|
-
id?: string;
|
|
248
247
|
/**
|
|
249
248
|
* Denoting a person or company.
|
|
250
249
|
*/
|
|
@@ -372,6 +371,15 @@ export type Contact = {
|
|
|
372
371
|
*/
|
|
373
372
|
isFavorite?: boolean;
|
|
374
373
|
};
|
|
374
|
+
/**
|
|
375
|
+
* Type for existing contacts returned from the system - guarantees the id field is present.
|
|
376
|
+
*/
|
|
377
|
+
export type ExistingContact = Contact & {
|
|
378
|
+
/**
|
|
379
|
+
* Immutable identifier used for querying and indexing. This value will be generated by the OS when the contact is created.
|
|
380
|
+
*/
|
|
381
|
+
id: string;
|
|
382
|
+
};
|
|
375
383
|
/**
|
|
376
384
|
* The return value for queried contact operations like `getContactsAsync`.
|
|
377
385
|
*/
|
|
@@ -379,7 +387,7 @@ export type ContactResponse = {
|
|
|
379
387
|
/**
|
|
380
388
|
* An array of contacts that match a particular query.
|
|
381
389
|
*/
|
|
382
|
-
data:
|
|
390
|
+
data: ExistingContact[];
|
|
383
391
|
/**
|
|
384
392
|
* This will be `true` if there are more contacts to retrieve beyond what is returned.
|
|
385
393
|
*/
|
|
@@ -577,7 +585,7 @@ export declare function getPagedContactsAsync(contactQuery?: ContactQuery): Prom
|
|
|
577
585
|
* }
|
|
578
586
|
* ```
|
|
579
587
|
*/
|
|
580
|
-
export declare function getContactByIdAsync(id: string, fields?: FieldType[]): Promise<
|
|
588
|
+
export declare function getContactByIdAsync(id: string, fields?: FieldType[]): Promise<ExistingContact | undefined>;
|
|
581
589
|
/**
|
|
582
590
|
* Creates a new contact and adds it to the system.
|
|
583
591
|
* > **Note**: For Android users, the Expo Go app does not have the required `WRITE_CONTACTS` permission to write to Contacts.
|
|
@@ -612,7 +620,7 @@ export declare function addContactAsync(contact: Contact, containerId?: string):
|
|
|
612
620
|
*/
|
|
613
621
|
export declare function updateContactAsync(contact: {
|
|
614
622
|
id: string;
|
|
615
|
-
} & Partial<
|
|
623
|
+
} & Partial<ExistingContact>): Promise<string>;
|
|
616
624
|
/**
|
|
617
625
|
* Delete a contact from the system.
|
|
618
626
|
* @param contactId ID of the contact you want to delete.
|
|
@@ -740,7 +748,7 @@ export declare function getGroupsAsync(groupQuery: GroupQuery): Promise<Group[]>
|
|
|
740
748
|
* required to use this method.
|
|
741
749
|
* @return A promise that fulfills with a single `Contact` object if a contact is selected or `null` if no contact is selected (when selection is canceled).
|
|
742
750
|
*/
|
|
743
|
-
export declare function presentContactPickerAsync(): Promise<
|
|
751
|
+
export declare function presentContactPickerAsync(): Promise<ExistingContact | null>;
|
|
744
752
|
/**
|
|
745
753
|
* Get the default container's ID.
|
|
746
754
|
* @return A promise that fulfills with default container ID.
|
|
@@ -782,6 +790,36 @@ export declare function requestPermissionsAsync(): Promise<ContactsPermissionRes
|
|
|
782
790
|
* @platform ios 18.0+
|
|
783
791
|
*/
|
|
784
792
|
export declare function presentAccessPickerAsync(): Promise<string[]>;
|
|
793
|
+
/**
|
|
794
|
+
* Adds a listener for contact changes. The listener will be called whenever contacts are added, updated, or deleted.
|
|
795
|
+
*
|
|
796
|
+
* **Platform differences:**
|
|
797
|
+
* - **Android**: 5-7 second delay - uses `ContentObserver` with inherent system delays
|
|
798
|
+
* - **iOS**: Immediate response - uses `CNContactStoreDidChangeNotification`
|
|
799
|
+
*
|
|
800
|
+
* The Android delay is a system limitation that affects all apps using `ContentObserver` for contacts.
|
|
801
|
+
* This delay is by design to batch notifications for better performance and battery life.
|
|
802
|
+
* For more immediate updates, you can also listen to app state changes and refresh
|
|
803
|
+
* contacts when the app comes to the foreground. This ensures users see the latest contacts when
|
|
804
|
+
* returning from the native Contacts app.
|
|
805
|
+
*
|
|
806
|
+
* @param listener The function that will be executed when contacts change.
|
|
807
|
+
* This function accepts no arguments.
|
|
808
|
+
*
|
|
809
|
+
* @returns A subscription object with a `remove` method to stop listening.
|
|
810
|
+
* @example
|
|
811
|
+
* ```jsx
|
|
812
|
+
* const subscription = Contacts.addContactChangeListener(() => {
|
|
813
|
+
* console.log('Contacts changed - refreshing contact list');
|
|
814
|
+
* // Refresh your contact list when changes are detected
|
|
815
|
+
* loadContacts();
|
|
816
|
+
* });
|
|
817
|
+
*
|
|
818
|
+
* // Later, remove the listener
|
|
819
|
+
* subscription.remove();
|
|
820
|
+
* ```
|
|
821
|
+
*/
|
|
822
|
+
export declare function addContactsChangeListener(listener: () => void): EventSubscription;
|
|
785
823
|
/**
|
|
786
824
|
* Possible fields to retrieve for a contact.
|
|
787
825
|
*/
|
package/build/Contacts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Contacts.d.ts","sourceRoot":"","sources":["../src/Contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"Contacts.d.ts","sourceRoot":"","sources":["../src/Contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EAGpB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAIlE,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAE5D,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,GAAG;IAC5D;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,GAAG,eAAe,EAAE,CAAC;AAExE,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,GAAG,cAAc,EAAE,CAAC;AAEjE,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,GAAG,YAAY,EAAE,CAAC;AAE3D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAE7C,MAAM,MAAM,IAAI,GAAG;IACjB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAGF;;;GAGG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB;;OAEG;IACH,WAAW,EAAE,WAAW,CAAC;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB;;OAEG;IACH,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IACtB;;OAEG;IACH,uBAAuB,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAClD;;OAEG;IACH,YAAY,CAAC,EAAE,UAAU,EAAE,CAAC;IAC5B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,IAAI,CAAC;IAC5B;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG;IACtC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,GAAG,SAAS,EAAE,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,qBAAqB,CAAC,EAAE,SAAS,EAAE,CAAC;IACpC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;CACrB,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,CAAC;AAEtE;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEzD;AAGD,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,YAAY,GAAE,YAAiB,GAC9B,OAAO,CAAC,GAAG,CAAC,CAgBd;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CAAC,YAAY,GAAE,YAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAKhG;AAED,wBAAsB,qBAAqB,CACzC,YAAY,GAAE,YAAiB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAW1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,SAAS,EAAE,GACnB,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAmBtC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,GACjD,OAAO,CAAC,MAAM,CAAC,CAKjB;AAGD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAKxE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,GAAE,YAAiB,GAC9B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK7B;AAGD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,EACxB,WAAW,GAAE,WAAgB,GAC5B,OAAO,CAAC,GAAG,CAAC,CAwBd;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,GAAG,CAAC,CAMd;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW3F;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAM3F;AAGD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAMpE;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,CAAC,CAMd;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,CAAC,CAMd;AAGD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAM7E;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAKjF;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,MAAM,CAAC,CAMlE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAM7F;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAM/E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAMnF;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAElE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,iBAAiB,CAYjF;AAED;;GAEG;AACH,oBAAY,MAAM;IAChB,EAAE,OAAO;IACT,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,iBAAiB,sBAAsB;IACvC,kBAAkB,uBAAuB;IACzC,gBAAgB,qBAAqB;IACrC,QAAQ,aAAa;IACrB;;OAEG;IACH,oBAAoB,yBAAyB;IAC7C,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,SAAS,cAAc;IACvB;;OAEG;IACH,cAAc,mBAAmB;IACjC,uBAAuB,4BAA4B;IACnD,YAAY,iBAAiB;IAC7B,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,cAAc,mBAAmB;IACjC,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,aAAa,kBAAkB;IAC/B;;OAEG;IACH,UAAU,eAAe;CAC1B;AAED;;GAEG;AACH,oBAAY,eAAe;IACzB,SAAS,cAAc;IACvB;;OAEG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,OAAO,YAAY;IACnB;;OAEG;IACH,MAAM,WAAW;IACjB;;OAEG;IACH,mBAAmB,wBAAwB;IAC3C;;OAEG;IACH,iBAAiB,sBAAsB;IACvC;;OAEG;IACH,MAAM,WAAW;IACjB;;OAEG;IACH,OAAO,YAAY;IACnB;;OAEG;IACH,MAAM,WAAW;IACjB;;OAEG;IACH,OAAO,YAAY;IACnB;;OAEG;IACH,YAAY,iBAAiB;IAC7B;;OAEG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,OAAO,YAAY;IACnB;;OAEG;IACH,eAAe,oBAAoB;IACnC;;OAEG;IACH,cAAc,mBAAmB;IACjC;;OAEG;IACH,gBAAgB,qBAAqB;CACtC;AAED;;GAEG;AACH,oBAAY,cAAc;IACxB;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,OAAO,YAAY;IACnB;;OAEG;IACH,UAAU,eAAe;CAC1B;AAED,oBAAY,SAAS;IACnB;;;OAGG;IACH,WAAW,gBAAgB;IAC3B;;OAEG;IACH,SAAS,cAAc;IACvB;;OAEG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,IAAI,SAAS;CACd;AAED,oBAAY,YAAY;IACtB;;OAEG;IACH,MAAM,WAAW;IACjB;;OAEG;IACH,OAAO,YAAY;CACpB"}
|
package/expo-module.config.json
CHANGED
package/ios/ContactsModule.swift
CHANGED
|
@@ -2,6 +2,8 @@ import ExpoModulesCore
|
|
|
2
2
|
import Contacts
|
|
3
3
|
import ContactsUI
|
|
4
4
|
|
|
5
|
+
let onContactsChangeEventName = "onContactsChange"
|
|
6
|
+
|
|
5
7
|
public class ContactsModule: Module, OnContactPickingResultHandler {
|
|
6
8
|
private let contactStore = CNContactStore()
|
|
7
9
|
private let delegate = ContactControllerDelegate()
|
|
@@ -9,9 +11,11 @@ public class ContactsModule: Module, OnContactPickingResultHandler {
|
|
|
9
11
|
private var contactPickerDelegate: ContactPickerControllerDelegate?
|
|
10
12
|
private var contactPickingPromise: Promise?
|
|
11
13
|
private var contactManipulationPromise: Promise?
|
|
14
|
+
private var contactChangeObserver: NSObjectProtocol?
|
|
12
15
|
|
|
13
16
|
public func definition() -> ModuleDefinition {
|
|
14
17
|
Name("ExpoContacts")
|
|
18
|
+
Events(onContactsChangeEventName)
|
|
15
19
|
|
|
16
20
|
OnCreate {
|
|
17
21
|
appContext?.permissions?.register([
|
|
@@ -19,6 +23,18 @@ public class ContactsModule: Module, OnContactPickingResultHandler {
|
|
|
19
23
|
])
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
OnDestroy {
|
|
27
|
+
stopObservingContactChanges()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
OnStartObserving(onContactsChangeEventName) {
|
|
31
|
+
startObservingContactChanges()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
OnStopObserving(onContactsChangeEventName) {
|
|
35
|
+
stopObservingContactChanges()
|
|
36
|
+
}
|
|
37
|
+
|
|
22
38
|
AsyncFunction("getDefaultContainerIdentifierAsync") {
|
|
23
39
|
return contactStore.defaultContainerIdentifier()
|
|
24
40
|
}
|
|
@@ -540,7 +556,7 @@ public class ContactsModule: Module, OnContactPickingResultHandler {
|
|
|
540
556
|
let path = url.path
|
|
541
557
|
let standardizedPath = NSString(string: path).standardizingPath
|
|
542
558
|
|
|
543
|
-
guard FileSystemUtilities.permissions(appContext, for: url).contains(.read) else {
|
|
559
|
+
guard FileSystemUtilities.permissions(appContext, for: url).contains(.read) && FileManager.default.isReadableFile(atPath: url.path) else {
|
|
544
560
|
return nil
|
|
545
561
|
}
|
|
546
562
|
|
|
@@ -638,4 +654,31 @@ public class ContactsModule: Module, OnContactPickingResultHandler {
|
|
|
638
654
|
|
|
639
655
|
return fetchRequest
|
|
640
656
|
}
|
|
657
|
+
|
|
658
|
+
private func startObservingContactChanges() {
|
|
659
|
+
guard contactChangeObserver == nil else { return }
|
|
660
|
+
|
|
661
|
+
contactChangeObserver = NotificationCenter.default.addObserver(
|
|
662
|
+
forName: .CNContactStoreDidChange,
|
|
663
|
+
object: nil,
|
|
664
|
+
queue: .main
|
|
665
|
+
) { [weak self] _ in
|
|
666
|
+
self?.handleContactStoreChange()
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
private func stopObservingContactChanges() {
|
|
671
|
+
if let observer = contactChangeObserver {
|
|
672
|
+
NotificationCenter.default.removeObserver(observer)
|
|
673
|
+
contactChangeObserver = nil
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
private func handleContactStoreChange() {
|
|
678
|
+
// Send event when contacts change - CNContactStoreDidChangeNotification
|
|
679
|
+
// only tells us that something changed, not what specifically changed
|
|
680
|
+
sendEvent(onContactsChangeEventName, [
|
|
681
|
+
"body": nil
|
|
682
|
+
])
|
|
683
|
+
}
|
|
641
684
|
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dbdb06070a7f1acfbe77c416cdda21c8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
325af909d1f86d6ed1b53bfc7ece14f6aac3bd89
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0004c5348c39a530f8d5f27aed83a350e5e9951ba5cbb3cef3d0084d0df6aa7d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fa6ce97a32d7797872255a7138021ac335f9932259ef778c8d72e8612f409eb1f75ca4e33c71d480ea27e8e88ad25b27b637b75a4b269c2dd2bc35c75310c93e
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
090541f37e9acd58aa7e32bd83e1b480
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
70a1418151d809587539343412d1b18c6050c714
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
87350fc991be2a1eef8a692cfb438d64fbabad25ad040530f0ffe732d347c09b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
adad029ba7b8c4664f084e88186d58d2b84ec686e93984353270b3599d0cd8ee102041fe89238b0fbe2e32db649081b23fa93ea52c873fc45d40d4dd82f381d3
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"component": {
|
|
4
4
|
"group": "host.exp.exponent",
|
|
5
5
|
"module": "expo.modules.contacts",
|
|
6
|
-
"version": "15.0.
|
|
6
|
+
"version": "15.0.8",
|
|
7
7
|
"attributes": {
|
|
8
8
|
"org.gradle.status": "release"
|
|
9
9
|
}
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
{
|
|
27
|
-
"name": "expo.modules.contacts-15.0.
|
|
28
|
-
"url": "expo.modules.contacts-15.0.
|
|
29
|
-
"size":
|
|
30
|
-
"sha512": "
|
|
31
|
-
"sha256": "
|
|
32
|
-
"sha1": "
|
|
33
|
-
"md5": "
|
|
27
|
+
"name": "expo.modules.contacts-15.0.8.aar",
|
|
28
|
+
"url": "expo.modules.contacts-15.0.8.aar",
|
|
29
|
+
"size": 114994,
|
|
30
|
+
"sha512": "adad029ba7b8c4664f084e88186d58d2b84ec686e93984353270b3599d0cd8ee102041fe89238b0fbe2e32db649081b23fa93ea52c873fc45d40d4dd82f381d3",
|
|
31
|
+
"sha256": "87350fc991be2a1eef8a692cfb438d64fbabad25ad040530f0ffe732d347c09b",
|
|
32
|
+
"sha1": "70a1418151d809587539343412d1b18c6050c714",
|
|
33
|
+
"md5": "090541f37e9acd58aa7e32bd83e1b480"
|
|
34
34
|
}
|
|
35
35
|
]
|
|
36
36
|
},
|
|
@@ -60,13 +60,13 @@
|
|
|
60
60
|
],
|
|
61
61
|
"files": [
|
|
62
62
|
{
|
|
63
|
-
"name": "expo.modules.contacts-15.0.
|
|
64
|
-
"url": "expo.modules.contacts-15.0.
|
|
65
|
-
"size":
|
|
66
|
-
"sha512": "
|
|
67
|
-
"sha256": "
|
|
68
|
-
"sha1": "
|
|
69
|
-
"md5": "
|
|
63
|
+
"name": "expo.modules.contacts-15.0.8.aar",
|
|
64
|
+
"url": "expo.modules.contacts-15.0.8.aar",
|
|
65
|
+
"size": 114994,
|
|
66
|
+
"sha512": "adad029ba7b8c4664f084e88186d58d2b84ec686e93984353270b3599d0cd8ee102041fe89238b0fbe2e32db649081b23fa93ea52c873fc45d40d4dd82f381d3",
|
|
67
|
+
"sha256": "87350fc991be2a1eef8a692cfb438d64fbabad25ad040530f0ffe732d347c09b",
|
|
68
|
+
"sha1": "70a1418151d809587539343412d1b18c6050c714",
|
|
69
|
+
"md5": "090541f37e9acd58aa7e32bd83e1b480"
|
|
70
70
|
}
|
|
71
71
|
]
|
|
72
72
|
},
|
|
@@ -80,13 +80,13 @@
|
|
|
80
80
|
},
|
|
81
81
|
"files": [
|
|
82
82
|
{
|
|
83
|
-
"name": "expo.modules.contacts-15.0.
|
|
84
|
-
"url": "expo.modules.contacts-15.0.
|
|
85
|
-
"size":
|
|
86
|
-
"sha512": "
|
|
87
|
-
"sha256": "
|
|
88
|
-
"sha1": "
|
|
89
|
-
"md5": "
|
|
83
|
+
"name": "expo.modules.contacts-15.0.8-sources.jar",
|
|
84
|
+
"url": "expo.modules.contacts-15.0.8-sources.jar",
|
|
85
|
+
"size": 20364,
|
|
86
|
+
"sha512": "fa6ce97a32d7797872255a7138021ac335f9932259ef778c8d72e8612f409eb1f75ca4e33c71d480ea27e8e88ad25b27b637b75a4b269c2dd2bc35c75310c93e",
|
|
87
|
+
"sha256": "0004c5348c39a530f8d5f27aed83a350e5e9951ba5cbb3cef3d0084d0df6aa7d",
|
|
88
|
+
"sha1": "325af909d1f86d6ed1b53bfc7ece14f6aac3bd89",
|
|
89
|
+
"md5": "dbdb06070a7f1acfbe77c416cdda21c8"
|
|
90
90
|
}
|
|
91
91
|
]
|
|
92
92
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c1c9272f344b19a39ec8c1f3531b7d64
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aab0e1cc2a1d8a6e8ca6d652d409036a0a2fcac0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6b5505615754fa4a3ad18dbdf2c574187e52e0131e4c8ded017f8ce1c27e1e4e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
5303d97a8167b9213f313388144937b4d50033ab333b316028b78a347f00f7b10917256d6937ae993a53be3cbf82e502dcf57017a1659f396eff0cee2726ff6d
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<modelVersion>4.0.0</modelVersion>
|
|
10
10
|
<groupId>host.exp.exponent</groupId>
|
|
11
11
|
<artifactId>expo.modules.contacts</artifactId>
|
|
12
|
-
<version>15.0.
|
|
12
|
+
<version>15.0.8</version>
|
|
13
13
|
<packaging>aar</packaging>
|
|
14
14
|
<name>expo.modules.contacts</name>
|
|
15
15
|
<url>https://github.com/expo/expo</url>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ee05c3d5bd7a540683b825c214134a6e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c649e07bd649ede948ab2ac35f05868e687a6343
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0cd3a3db36f2cac6fc9ce6298c1afad2e4dc72ce28d6f2e372564a10f5b25102
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6a2528ff39024c31f218327c29e6a4e66fdfb1b57bc510792181992e782ec372a2e0dce9315b3df218f55b53d5d9b942322bc658ac8210bf64a89cd77f5da8cb
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>host.exp.exponent</groupId>
|
|
4
4
|
<artifactId>expo.modules.contacts</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>15.0.
|
|
7
|
-
<release>15.0.
|
|
6
|
+
<latest>15.0.8</latest>
|
|
7
|
+
<release>15.0.8</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>15.0.
|
|
9
|
+
<version>15.0.8</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20250910183903</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
fdcc7d8ca088bcd87444520bcb34ca58
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2f052601c2e3227136413548f31519582baffd4f
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
761e75654df429d8537838d82c1cc421197ed580f479409f4d3ac6bf823b12aa
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
204d8dd2ad8dd8cc5764c757f724d3a0d4c3b5e907d246bba1c1cae4ad33466ad0682b175fbe442260489ff5e1d825dd2ab0d6c236c22b6ecd89381c0302b410
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-contacts",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.8",
|
|
4
4
|
"description": "Provides access to the phone's system contacts.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"preset": "expo-module-scripts"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"expo-module-scripts": "^5.0.
|
|
37
|
+
"expo-module-scripts": "^5.0.7"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"expo": "*",
|
|
41
41
|
"react": "*",
|
|
42
42
|
"react-native": "*"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "87186d10c8239c6469e055417e67bd4d0ed63efb"
|
|
45
45
|
}
|
package/src/Contacts.ts
CHANGED
|
@@ -4,11 +4,14 @@ import {
|
|
|
4
4
|
PermissionExpiration,
|
|
5
5
|
UnavailabilityError,
|
|
6
6
|
uuid,
|
|
7
|
+
EventSubscription,
|
|
7
8
|
} from 'expo-modules-core';
|
|
8
9
|
import { Platform, Share, type ShareOptions } from 'react-native';
|
|
9
10
|
|
|
10
11
|
import ExpoContacts from './ExpoContacts';
|
|
11
12
|
|
|
13
|
+
export const onContactsChangeEventName = 'onContactsChange';
|
|
14
|
+
|
|
12
15
|
export type ContactsPermissionResponse = PermissionResponse & {
|
|
13
16
|
/**
|
|
14
17
|
* Indicates if your app has access to the whole or only part of the contact library. Possible values are:
|
|
@@ -262,13 +265,11 @@ export type Image = {
|
|
|
262
265
|
};
|
|
263
266
|
|
|
264
267
|
/**
|
|
265
|
-
*
|
|
268
|
+
* Base contact type without ID. For better type safety, consider using:
|
|
269
|
+
* - `Contact` when creating new contacts (no ID needed)
|
|
270
|
+
* - `ExistingContact` when working with contacts returned from the system (ID guaranteed)
|
|
266
271
|
*/
|
|
267
272
|
export type Contact = {
|
|
268
|
-
/**
|
|
269
|
-
* Immutable identifier used for querying and indexing. This value will be generated by the OS when the contact is created.
|
|
270
|
-
*/
|
|
271
|
-
id?: string;
|
|
272
273
|
/**
|
|
273
274
|
* Denoting a person or company.
|
|
274
275
|
*/
|
|
@@ -397,6 +398,16 @@ export type Contact = {
|
|
|
397
398
|
isFavorite?: boolean;
|
|
398
399
|
};
|
|
399
400
|
|
|
401
|
+
/**
|
|
402
|
+
* Type for existing contacts returned from the system - guarantees the id field is present.
|
|
403
|
+
*/
|
|
404
|
+
export type ExistingContact = Contact & {
|
|
405
|
+
/**
|
|
406
|
+
* Immutable identifier used for querying and indexing. This value will be generated by the OS when the contact is created.
|
|
407
|
+
*/
|
|
408
|
+
id: string;
|
|
409
|
+
};
|
|
410
|
+
|
|
400
411
|
/**
|
|
401
412
|
* The return value for queried contact operations like `getContactsAsync`.
|
|
402
413
|
*/
|
|
@@ -404,7 +415,7 @@ export type ContactResponse = {
|
|
|
404
415
|
/**
|
|
405
416
|
* An array of contacts that match a particular query.
|
|
406
417
|
*/
|
|
407
|
-
data:
|
|
418
|
+
data: ExistingContact[];
|
|
408
419
|
/**
|
|
409
420
|
* This will be `true` if there are more contacts to retrieve beyond what is returned.
|
|
410
421
|
*/
|
|
@@ -659,7 +670,7 @@ export async function getPagedContactsAsync(
|
|
|
659
670
|
export async function getContactByIdAsync(
|
|
660
671
|
id: string,
|
|
661
672
|
fields?: FieldType[]
|
|
662
|
-
): Promise<
|
|
673
|
+
): Promise<ExistingContact | undefined> {
|
|
663
674
|
if (!ExpoContacts.getContactsAsync) {
|
|
664
675
|
throw new UnavailabilityError('Contacts', 'getContactsAsync');
|
|
665
676
|
}
|
|
@@ -702,8 +713,7 @@ export async function addContactAsync(contact: Contact, containerId?: string): P
|
|
|
702
713
|
throw new UnavailabilityError('Contacts', 'addContactAsync');
|
|
703
714
|
}
|
|
704
715
|
|
|
705
|
-
|
|
706
|
-
return await ExpoContacts.addContactAsync(noIdContact, containerId);
|
|
716
|
+
return await ExpoContacts.addContactAsync(contact, containerId);
|
|
707
717
|
}
|
|
708
718
|
|
|
709
719
|
/**
|
|
@@ -721,7 +731,7 @@ export async function addContactAsync(contact: Contact, containerId?: string): P
|
|
|
721
731
|
* ```
|
|
722
732
|
*/
|
|
723
733
|
export async function updateContactAsync(
|
|
724
|
-
contact: { id: string } & Partial<
|
|
734
|
+
contact: { id: string } & Partial<ExistingContact>
|
|
725
735
|
): Promise<string> {
|
|
726
736
|
if (!ExpoContacts.updateContactAsync) {
|
|
727
737
|
throw new UnavailabilityError('Contacts', 'updateContactAsync');
|
|
@@ -970,7 +980,7 @@ export async function getGroupsAsync(groupQuery: GroupQuery): Promise<Group[]> {
|
|
|
970
980
|
* required to use this method.
|
|
971
981
|
* @return A promise that fulfills with a single `Contact` object if a contact is selected or `null` if no contact is selected (when selection is canceled).
|
|
972
982
|
*/
|
|
973
|
-
export async function presentContactPickerAsync(): Promise<
|
|
983
|
+
export async function presentContactPickerAsync(): Promise<ExistingContact | null> {
|
|
974
984
|
if (!ExpoContacts.presentContactPickerAsync) {
|
|
975
985
|
throw new UnavailabilityError('Contacts', 'presentContactPickerAsync');
|
|
976
986
|
}
|
|
@@ -1049,33 +1059,47 @@ export async function presentAccessPickerAsync(): Promise<string[]> {
|
|
|
1049
1059
|
return await ExpoContacts.presentAccessPickerAsync();
|
|
1050
1060
|
}
|
|
1051
1061
|
|
|
1052
|
-
/**
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1062
|
+
/**
|
|
1063
|
+
* Adds a listener for contact changes. The listener will be called whenever contacts are added, updated, or deleted.
|
|
1064
|
+
*
|
|
1065
|
+
* **Platform differences:**
|
|
1066
|
+
* - **Android**: 5-7 second delay - uses `ContentObserver` with inherent system delays
|
|
1067
|
+
* - **iOS**: Immediate response - uses `CNContactStoreDidChangeNotification`
|
|
1068
|
+
*
|
|
1069
|
+
* The Android delay is a system limitation that affects all apps using `ContentObserver` for contacts.
|
|
1070
|
+
* This delay is by design to batch notifications for better performance and battery life.
|
|
1071
|
+
* For more immediate updates, you can also listen to app state changes and refresh
|
|
1072
|
+
* contacts when the app comes to the foreground. This ensures users see the latest contacts when
|
|
1073
|
+
* returning from the native Contacts app.
|
|
1074
|
+
*
|
|
1075
|
+
* @param listener The function that will be executed when contacts change.
|
|
1076
|
+
* This function accepts no arguments.
|
|
1077
|
+
*
|
|
1078
|
+
* @returns A subscription object with a `remove` method to stop listening.
|
|
1079
|
+
* @example
|
|
1080
|
+
* ```jsx
|
|
1081
|
+
* const subscription = Contacts.addContactChangeListener(() => {
|
|
1082
|
+
* console.log('Contacts changed - refreshing contact list');
|
|
1083
|
+
* // Refresh your contact list when changes are detected
|
|
1084
|
+
* loadContacts();
|
|
1085
|
+
* });
|
|
1086
|
+
*
|
|
1087
|
+
* // Later, remove the listener
|
|
1088
|
+
* subscription.remove();
|
|
1089
|
+
* ```
|
|
1090
|
+
*/
|
|
1091
|
+
export function addContactsChangeListener(listener: () => void): EventSubscription {
|
|
1092
|
+
if (!ExpoContacts.addListener) {
|
|
1093
|
+
throw new UnavailabilityError('Contacts', 'addContactChangeListener');
|
|
1060
1094
|
}
|
|
1061
1095
|
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
(
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
console.warn(
|
|
1070
|
-
`You have set an id "${item.id}" at index "${index}" for the key "${key}" of the contact. This value will be ignored, because the id will be generated by the OS`
|
|
1071
|
-
);
|
|
1072
|
-
return { ...item, id: null };
|
|
1073
|
-
}
|
|
1074
|
-
return item;
|
|
1075
|
-
});
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
return updatedContact;
|
|
1096
|
+
const eventSubscription = ExpoContacts.addListener(onContactsChangeEventName, listener);
|
|
1097
|
+
|
|
1098
|
+
return {
|
|
1099
|
+
remove: () => {
|
|
1100
|
+
eventSubscription?.remove();
|
|
1101
|
+
},
|
|
1102
|
+
};
|
|
1079
1103
|
}
|
|
1080
1104
|
|
|
1081
1105
|
/**
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
b03c91138ab3950fd241c862b7439b5f
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
b39c529ef7f2a0aa86fd98d627c8610b058f22c2
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
7805b5686f14c0034af179db4c28f3af823529d1f21fca8eac2355601cca4636
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
b56feb83e945a7b4df2ca5a71da12aa5d4dc939082da448ab8548bc4967bb24eb48062902db6f3bb234e47d2ad2e55647c3b39f344af2cecd6d87f5b2b5f6aaa
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
60da4805ae575641769712538ac47447
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3e3ada292984968f3b3a0efff627541e214505b6
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
bf95197f5375c51a051ea0a2fc1e9706b1e0ca53b27b6bafdc54f3d9180882c8
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
9b4eb25c6973464079f6217fb1636fc94afca78a2fe1b34c815491a6f424d4700dabcc1192afec7ce70bcb3426e9517cceeaa64e5e3fd9568eb4087e73a3872e
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
9fac9437f2c09a64527f85ddaef9ef43
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
6050751d847a4e88f0474330c9bc121efe40d21b
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
673c47e1c20ab2b1e69b0bd2bb52f5b7717b83ea7faaf3dabb88fc059cc2c40e
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
5846e7d6f8221a02d123f85242baa5a589ee0cf47b815fb269859edbcc885787f40adeea52cb0d3d9cdc84f4c790a08989fc881ad0498b5837f35ab7d2d491f7
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1aace678ec6b01f26247e93aff21e105
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
903b74c040cb682fa011a3be2be13ef4ec9ea936
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ad2ea6203058f8101afc0ae026ee958322b314d0109d63728249b0cc5a6e92aa
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
8f01a3ecee3e679c46964f4495bc926df415d84f8aefb2b4bfb93bea11fee479e48992e9fa076221a4c68b061ec386a06d634001e1240aeaa2ad12707fba3687
|