1import { PermissionStatus, UnavailabilityError, uuid } from 'expo-modules-core';
2import { Platform, Share } from 'react-native';
3import ExpoContacts from './ExpoContacts';
4export { PermissionStatus };
5/**
6 * Returns whether the Contacts API is enabled on the current device. This method does not check the app permissions.
7 * @returns A promise that fulfills with a `boolean`, indicating whether the Contacts API is available on the current device. It always resolves to `false` on web.
8 */
9export async function isAvailableAsync() {
10    return !!ExpoContacts.getContactsAsync;
11}
12export async function shareContactAsync(contactId, message, shareOptions = {}) {
13    if (Platform.OS === 'ios') {
14        const url = await writeContactToFileAsync({
15            id: contactId,
16        });
17        return await Share.share({
18            url,
19            message,
20        }, shareOptions);
21    }
22    else if (!ExpoContacts.shareContactAsync) {
23        throw new UnavailabilityError('Contacts', 'shareContactAsync');
24    }
25    return await ExpoContacts.shareContactAsync(contactId, message);
26}
27/**
28 * Return a list of contacts that fit a given criteria. You can get all of the contacts by passing no criteria.
29 * @param contactQuery Object used to query contacts.
30 * @return A promise that fulfills with `ContactResponse` object returned from the query.
31 * @example
32 * ```js
33 * const { data } = await Contacts.getContactsAsync({
34 *   fields: [Contacts.Fields.Emails],
35 * });
36 *
37 * if (data.length > 0) {
38 *   const contact = data[0];
39 *   console.log(contact);
40 * }
41 * ```
42 */
43export async function getContactsAsync(contactQuery = {}) {
44    if (!ExpoContacts.getContactsAsync) {
45        throw new UnavailabilityError('Contacts', 'getContactsAsync');
46    }
47    return await ExpoContacts.getContactsAsync(contactQuery);
48}
49export async function getPagedContactsAsync(contactQuery = {}) {
50    const { pageSize, ...nOptions } = contactQuery;
51    if (pageSize && pageSize <= 0) {
52        throw new Error('Error: Contacts.getPagedContactsAsync: `pageSize` must be greater than 0');
53    }
54    return await getContactsAsync({
55        ...nOptions,
56        pageSize,
57    });
58}
59/**
60 * Used for gathering precise data about a contact. Returns a contact matching the given `id`.
61 * @param id The ID of a system contact.
62 * @param fields If specified, the fields defined will be returned. When skipped, all fields will be returned.
63 * @return A promise that fulfills with `Contact` object with ID matching the input ID, or `undefined` if there is no match.
64 * @example
65 * ```js
66 * const contact = await Contacts.getContactByIdAsync('161A368D-D614-4A15-8DC6-665FDBCFAE55');
67 * if (contact) {
68 *   console.log(contact);
69 * }
70 * ```
71 */
72export async function getContactByIdAsync(id, fields) {
73    if (!ExpoContacts.getContactsAsync) {
74        throw new UnavailabilityError('Contacts', 'getContactsAsync');
75    }
76    if (id == null) {
77        throw new Error('Error: Contacts.getContactByIdAsync: Please pass an ID as a parameter');
78    }
79    else {
80        const results = await ExpoContacts.getContactsAsync({
81            pageSize: 1,
82            pageOffset: 0,
83            fields,
84            id,
85        });
86        if (results && results.data && results.data.length > 0) {
87            return results.data[0];
88        }
89    }
90    return undefined;
91}
92/**
93 * Creates a new contact and adds it to the system.
94 * > **Note**: For Android users, the Expo Go app does not have the required `WRITE_CONTACTS` permission to write to Contacts.
95 * > You will need to create a [development build](/develop/development-builds/create-a-build/) and add permission in there manually to use this method.
96 * @param contact A contact with the changes you wish to persist. The `id` parameter will not be used.
97 * @param containerId @tag-ios The container that will parent the contact.
98 * @return A promise that fulfills with ID of the new system contact.
99 * @example
100 * ```js
101 * const contact = {
102 *   [Contacts.Fields.FirstName]: 'Bird',
103 *   [Contacts.Fields.LastName]: 'Man',
104 *   [Contacts.Fields.Company]: 'Young Money',
105 * };
106 * const contactId = await Contacts.addContactAsync(contact);
107 * ```
108 */
109export async function addContactAsync(contact, containerId) {
110    if (!ExpoContacts.addContactAsync) {
111        throw new UnavailabilityError('Contacts', 'addContactAsync');
112    }
113    const noIdContact = removeIds(contact);
114    return await ExpoContacts.addContactAsync(noIdContact, containerId);
115}
116/**
117 * Mutate the information of an existing contact. Due to an iOS bug, `nonGregorianBirthday` field cannot be modified.
118 * > **info** On Android, you can use [`presentFormAsync`](#contactspresentformasynccontactid-contact-formoptions) to make edits to contacts.
119 * @param contact A contact object including the wanted changes.
120 * @return A promise that fulfills with ID of the updated system contact if mutation was successful.
121 * @example
122 * ```js
123 * const contact = {
124 *   id: '161A368D-D614-4A15-8DC6-665FDBCFAE55',
125 *   [Contacts.Fields.FirstName]: 'Drake',
126 *   [Contacts.Fields.Company]: 'Young Money',
127 * };
128 * await Contacts.updateContactAsync(contact);
129 * ```
130 * @platform ios
131 */
132export async function updateContactAsync(contact) {
133    if (!ExpoContacts.updateContactAsync) {
134        throw new UnavailabilityError('Contacts', 'updateContactAsync');
135    }
136    return await ExpoContacts.updateContactAsync(contact);
137}
138// @needs-audit
139/**
140 * Delete a contact from the system.
141 * @param contactId ID of the contact you want to delete.
142 * @example
143 * ```js
144 * await Contacts.removeContactAsync('161A368D-D614-4A15-8DC6-665FDBCFAE55');
145 * ```
146 * @platform ios
147 */
148export async function removeContactAsync(contactId) {
149    if (!ExpoContacts.removeContactAsync) {
150        throw new UnavailabilityError('Contacts', 'removeContactAsync');
151    }
152    return await ExpoContacts.removeContactAsync(contactId);
153}
154/**
155 * Query a set of contacts and write them to a local URI that can be used for sharing.
156 * @param contactQuery Used to query contact you want to write.
157 * @return A promise that fulfills with shareable local URI, or `undefined` if there was no match.
158 * @example
159 * ```js
160 * const localUri = await Contacts.writeContactToFileAsync({
161 *   id: '161A368D-D614-4A15-8DC6-665FDBCFAE55',
162 * });
163 * Share.share({ url: localUri, message: 'Call me!' });
164 * ```
165 */
166export async function writeContactToFileAsync(contactQuery = {}) {
167    if (!ExpoContacts.writeContactToFileAsync) {
168        throw new UnavailabilityError('Contacts', 'writeContactToFileAsync');
169    }
170    return await ExpoContacts.writeContactToFileAsync(contactQuery);
171}
172// @needs-audit
173/**
174 * Present a native form for manipulating contacts.
175 * @param contactId The ID of a system contact.
176 * @param contact A contact with the changes you want to persist.
177 * @param formOptions Options for the native editor.
178 * @example
179 * ```js
180 * await Contacts.presentFormAsync('161A368D-D614-4A15-8DC6-665FDBCFAE55');
181 * ```
182 */
183export async function presentFormAsync(contactId, contact, formOptions = {}) {
184    if (!ExpoContacts.presentFormAsync) {
185        throw new UnavailabilityError('Contacts', 'presentFormAsync');
186    }
187    if (Platform.OS === 'ios') {
188        const adjustedOptions = formOptions;
189        if (contactId) {
190            if (contact) {
191                contact = undefined;
192                console.log('Expo.Contacts.presentFormAsync: You should define either a `contact` or a `contactId` but not both.');
193            }
194            if (adjustedOptions.isNew !== undefined) {
195                console.log('Expo.Contacts.presentFormAsync: `formOptions.isNew` is not supported with `contactId`');
196            }
197        }
198        return await ExpoContacts.presentFormAsync(contactId, contact, adjustedOptions);
199    }
200    else {
201        return await ExpoContacts.presentFormAsync(contactId, contact, formOptions);
202    }
203}
204// iOS Only
205/**
206 * Add a group to a container.
207 * @param groupId The group you want to target.
208 * @param containerId The container you want to add membership to.
209 * @example
210 * ```js
211 * await Contacts.addExistingGroupToContainerAsync(
212 *   '161A368D-D614-4A15-8DC6-665FDBCFAE55',
213 *   '665FDBCFAE55-D614-4A15-8DC6-161A368D'
214 * );
215 * ```
216 * @platform ios
217 */
218export async function addExistingGroupToContainerAsync(groupId, containerId) {
219    if (!ExpoContacts.addExistingGroupToContainerAsync) {
220        throw new UnavailabilityError('Contacts', 'addExistingGroupToContainerAsync');
221    }
222    return await ExpoContacts.addExistingGroupToContainerAsync(groupId, containerId);
223}
224/**
225 * Create a group with a name, and add it to a container. If the container is undefined, the default container will be targeted.
226 * @param name Name of the new group.
227 * @param containerId The container you to add membership to.
228 * @return A promise that fulfills with ID of the new group.
229 * @example
230 * ```js
231 * const groupId = await Contacts.createGroupAsync('Sailor Moon');
232 * ```
233 * @platform ios
234 */
235export async function createGroupAsync(name, containerId) {
236    if (!ExpoContacts.createGroupAsync) {
237        throw new UnavailabilityError('Contacts', 'createGroupAsync');
238    }
239    name = name || uuid.v4();
240    if (!containerId) {
241        containerId = await getDefaultContainerIdAsync();
242    }
243    return await ExpoContacts.createGroupAsync(name, containerId);
244}
245/**
246 * Change the name of an existing group.
247 * @param groupName New name for an existing group.
248 * @param groupId ID of the group you want to edit.
249 * @example
250 * ```js
251 * await Contacts.updateGroupName('Expo Friends', '161A368D-D614-4A15-8DC6-665FDBCFAE55');
252 * ```
253 * @platform ios
254 */
255export async function updateGroupNameAsync(groupName, groupId) {
256    if (!ExpoContacts.updateGroupNameAsync) {
257        throw new UnavailabilityError('Contacts', 'updateGroupNameAsync');
258    }
259    return await ExpoContacts.updateGroupNameAsync(groupName, groupId);
260}
261// @needs-audit
262/**
263 * Delete a group from the device.
264 * @param groupId ID of the group you want to remove.
265 * @example
266 * ```js
267 * await Contacts.removeGroupAsync('161A368D-D614-4A15-8DC6-665FDBCFAE55');
268 * ```
269 * @platform ios
270 */
271export async function removeGroupAsync(groupId) {
272    if (!ExpoContacts.removeGroupAsync) {
273        throw new UnavailabilityError('Contacts', 'removeGroupAsync');
274    }
275    return await ExpoContacts.removeGroupAsync(groupId);
276}
277// @needs-audit
278/**
279 * Add a contact as a member to a group. A contact can be a member of multiple groups.
280 * @param contactId ID of the contact you want to edit.
281 * @param groupId ID for the group you want to add membership to.
282 * @example
283 * ```js
284 * await Contacts.addExistingContactToGroupAsync(
285 *   '665FDBCFAE55-D614-4A15-8DC6-161A368D',
286 *   '161A368D-D614-4A15-8DC6-665FDBCFAE55'
287 * );
288 * ```
289 * @platform ios
290 */
291export async function addExistingContactToGroupAsync(contactId, groupId) {
292    if (!ExpoContacts.addExistingContactToGroupAsync) {
293        throw new UnavailabilityError('Contacts', 'addExistingContactToGroupAsync');
294    }
295    return await ExpoContacts.addExistingContactToGroupAsync(contactId, groupId);
296}
297// @needs-audit
298/**
299 * Remove a contact's membership from a given group. This will not delete the contact.
300 * @param contactId ID of the contact you want to remove.
301 * @param groupId ID for the group you want to remove membership of.
302 * @example
303 * ```js
304 * await Contacts.removeContactFromGroupAsync(
305 *   '665FDBCFAE55-D614-4A15-8DC6-161A368D',
306 *   '161A368D-D614-4A15-8DC6-665FDBCFAE55'
307 * );
308 * ```
309 * @platform ios
310 */
311export async function removeContactFromGroupAsync(contactId, groupId) {
312    if (!ExpoContacts.removeContactFromGroupAsync) {
313        throw new UnavailabilityError('Contacts', 'removeContactFromGroupAsync');
314    }
315    return await ExpoContacts.removeContactFromGroupAsync(contactId, groupId);
316}
317// @needs-audit
318/**
319 * Query and return a list of system groups.
320 * @param groupQuery Information regarding which groups you want to get.
321 * @example
322 * ```js
323 * const groups = await Contacts.getGroupsAsync({ groupName: 'sailor moon' });
324 * const allGroups = await Contacts.getGroupsAsync({});
325 * ```
326 * @return A promise that fulfills with array of groups that fit the query.
327 * @platform ios
328 */
329export async function getGroupsAsync(groupQuery) {
330    if (!ExpoContacts.getGroupsAsync) {
331        throw new UnavailabilityError('Contacts', 'getGroupsAsync');
332    }
333    return await ExpoContacts.getGroupsAsync(groupQuery);
334}
335/**
336 * Get the default container's ID.
337 * @return A promise that fulfills with default container ID.
338 * @example
339 * ```js
340 * const containerId = await Contacts.getDefaultContainerIdAsync();
341 * ```
342 * @platform ios
343 */
344export async function getDefaultContainerIdAsync() {
345    if (!ExpoContacts.getDefaultContainerIdentifierAsync) {
346        throw new UnavailabilityError('Contacts', 'getDefaultContainerIdentifierAsync');
347    }
348    return await ExpoContacts.getDefaultContainerIdentifierAsync();
349}
350/**
351 * Query a list of system containers.
352 * @param containerQuery Information used to gather containers.
353 * @return A promise that fulfills with array of containers that fit the query.
354 * @example
355 * ```js
356 * const allContainers = await Contacts.getContainersAsync({
357 *   contactId: '665FDBCFAE55-D614-4A15-8DC6-161A368D',
358 * });
359 * ```
360 * @platform ios
361 */
362export async function getContainersAsync(containerQuery) {
363    if (!ExpoContacts.getContainersAsync) {
364        throw new UnavailabilityError('Contacts', 'getContainersAsync');
365    }
366    return await ExpoContacts.getContainersAsync(containerQuery);
367}
368/**
369 * Checks user's permissions for accessing contacts data.
370 * @return A promise that resolves to a [PermissionResponse](#permissionresponse) object.
371 */
372export async function getPermissionsAsync() {
373    if (!ExpoContacts.getPermissionsAsync) {
374        throw new UnavailabilityError('Contacts', 'getPermissionsAsync');
375    }
376    return await ExpoContacts.getPermissionsAsync();
377}
378/**
379 * Asks the user to grant permissions for accessing contacts data.
380 * @return A promise that resolves to a [PermissionResponse](#permissionresponse) object.
381 */
382export async function requestPermissionsAsync() {
383    if (!ExpoContacts.requestPermissionsAsync) {
384        throw new UnavailabilityError('Contacts', 'requestPermissionsAsync');
385    }
386    return await ExpoContacts.requestPermissionsAsync();
387}
388/** @private */
389function removeIds(contact) {
390    const updatedContact = { ...contact };
391    if (contact.id && __DEV__) {
392        console.warn(`You have set an id = ${contact.id} for the contact. This value will be ignored, because the id will be generated by the OS`);
393        delete updatedContact.id;
394    }
395    for (const key of Object.keys(contact)) {
396        if (Array.isArray(contact[key])) {
397            updatedContact[key] = contact[key].map((item, index) => {
398                if (item.id) {
399                    __DEV__ &&
400                        console.warn(`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`);
401                    return { ...item, id: null };
402                }
403                return item;
404            });
405        }
406    }
407    return updatedContact;
408}
409/**
410 * Possible fields to retrieve for a contact.
411 */
412export var Fields;
413(function (Fields) {
414    Fields["ID"] = "id";
415    Fields["ContactType"] = "contactType";
416    Fields["Name"] = "name";
417    Fields["FirstName"] = "firstName";
418    Fields["MiddleName"] = "middleName";
419    Fields["LastName"] = "lastName";
420    Fields["MaidenName"] = "maidenName";
421    Fields["NamePrefix"] = "namePrefix";
422    Fields["NameSuffix"] = "nameSuffix";
423    Fields["Nickname"] = "nickname";
424    Fields["PhoneticFirstName"] = "phoneticFirstName";
425    Fields["PhoneticMiddleName"] = "phoneticMiddleName";
426    Fields["PhoneticLastName"] = "phoneticLastName";
427    Fields["Birthday"] = "birthday";
428    /**
429     * @platform ios
430     */
431    Fields["NonGregorianBirthday"] = "nonGregorianBirthday";
432    Fields["Emails"] = "emails";
433    Fields["PhoneNumbers"] = "phoneNumbers";
434    Fields["Addresses"] = "addresses";
435    /**
436     * @platform ios
437     */
438    Fields["SocialProfiles"] = "socialProfiles";
439    Fields["InstantMessageAddresses"] = "instantMessageAddresses";
440    Fields["UrlAddresses"] = "urlAddresses";
441    Fields["Company"] = "company";
442    Fields["JobTitle"] = "jobTitle";
443    Fields["Department"] = "department";
444    Fields["ImageAvailable"] = "imageAvailable";
445    Fields["Image"] = "image";
446    Fields["RawImage"] = "rawImage";
447    Fields["ExtraNames"] = "extraNames";
448    Fields["Note"] = "note";
449    Fields["Dates"] = "dates";
450    Fields["Relationships"] = "relationships";
451})(Fields || (Fields = {}));
452/**
453 * This format denotes the common calendar format used to specify how a date is calculated in `nonGregorianBirthday` fields.
454 */
455export var CalendarFormats;
456(function (CalendarFormats) {
457    CalendarFormats["Gregorian"] = "gregorian";
458    /**
459     * @platform ios
460     */
461    CalendarFormats["Buddhist"] = "buddhist";
462    /**
463     * @platform ios
464     */
465    CalendarFormats["Chinese"] = "chinese";
466    /**
467     * @platform ios
468     */
469    CalendarFormats["Coptic"] = "coptic";
470    /**
471     * @platform ios
472     */
473    CalendarFormats["EthiopicAmeteMihret"] = "ethiopicAmeteMihret";
474    /**
475     * @platform ios
476     */
477    CalendarFormats["EthiopicAmeteAlem"] = "ethiopicAmeteAlem";
478    /**
479     * @platform ios
480     */
481    CalendarFormats["Hebrew"] = "hebrew";
482    /**
483     * @platform ios
484     */
485    CalendarFormats["ISO8601"] = "iso8601";
486    /**
487     * @platform ios
488     */
489    CalendarFormats["Indian"] = "indian";
490    /**
491     * @platform ios
492     */
493    CalendarFormats["Islamic"] = "islamic";
494    /**
495     * @platform ios
496     */
497    CalendarFormats["IslamicCivil"] = "islamicCivil";
498    /**
499     * @platform ios
500     */
501    CalendarFormats["Japanese"] = "japanese";
502    /**
503     * @platform ios
504     */
505    CalendarFormats["Persian"] = "persian";
506    /**
507     * @platform ios
508     */
509    CalendarFormats["RepublicOfChina"] = "republicOfChina";
510    /**
511     * @platform ios
512     */
513    CalendarFormats["IslamicTabular"] = "islamicTabular";
514    /**
515     * @platform ios
516     */
517    CalendarFormats["IslamicUmmAlQura"] = "islamicUmmAlQura";
518})(CalendarFormats || (CalendarFormats = {}));
519/**
520 * @platform ios
521 */
522export var ContainerTypes;
523(function (ContainerTypes) {
524    /**
525     * A local non-iCloud container.
526     */
527    ContainerTypes["Local"] = "local";
528    /**
529     * In association with email server.
530     */
531    ContainerTypes["Exchange"] = "exchange";
532    /**
533     * With cardDAV protocol used for sharing.
534     */
535    ContainerTypes["CardDAV"] = "cardDAV";
536    /**
537     * Unknown container.
538     */
539    ContainerTypes["Unassigned"] = "unassigned";
540})(ContainerTypes || (ContainerTypes = {}));
541export var SortTypes;
542(function (SortTypes) {
543    /**
544     * The user default method of sorting.
545     * @platform android
546     */
547    SortTypes["UserDefault"] = "userDefault";
548    /**
549     * Sort by first name in ascending order.
550     */
551    SortTypes["FirstName"] = "firstName";
552    /**
553     * Sort by last name in ascending order.
554     */
555    SortTypes["LastName"] = "lastName";
556    /**
557     * No sorting should be applied.
558     */
559    SortTypes["None"] = "none";
560})(SortTypes || (SortTypes = {}));
561export var ContactTypes;
562(function (ContactTypes) {
563    /**
564     * Contact is a human.
565     */
566    ContactTypes["Person"] = "person";
567    /**
568     * Contact is group or company.
569     */
570    ContactTypes["Company"] = "company";
571})(ContactTypes || (ContactTypes = {}));
572//# sourceMappingURL=Contacts.js.map