1import * as Contacts from 'expo-contacts';
2
3export function parseDate({ year, month, day }: { year: number; month: number; day: number }) {
4  const nYear = year || new Date().getFullYear();
5  // TODO: Evan: add support for calendars: https://github.com/moment/moment/issues/1454
6  const date = new Date(nYear, month, day, 0, 0);
7  return date;
8}
9
10export function parseAddress({
11  city,
12  country,
13  postalCode,
14  region,
15  street,
16}: {
17  city: string;
18  country: string;
19  postalCode: string;
20  region: string;
21  street: string;
22}) {
23  const address = [street, city, region, postalCode, country]
24    .filter((item) => item !== '')
25    .join(', ');
26  return address;
27}
28
29export function parseKey(key: string) {
30  return {
31    [Contacts.Fields.ID]: 'ID',
32    [Contacts.Fields.ContactType]: 'Contact Type',
33    [Contacts.Fields.Name]: 'Name',
34    [Contacts.Fields.FirstName]: 'First Name',
35    [Contacts.Fields.MiddleName]: 'Middle Name',
36    [Contacts.Fields.LastName]: 'Last Name',
37    [Contacts.Fields.MaidenName]: 'Maiden Name',
38    [Contacts.Fields.NamePrefix]: 'Prefix',
39    [Contacts.Fields.NameSuffix]: 'Suffix',
40    [Contacts.Fields.Nickname]: 'Nickname',
41    [Contacts.Fields.PhoneticFirstName]: 'Phonetic First Name',
42    [Contacts.Fields.PhoneticMiddleName]: 'Phonetic Middle Name',
43    [Contacts.Fields.PhoneticLastName]: 'Phonetic Last Name',
44    [Contacts.Fields.Birthday]: 'Birthday',
45    [Contacts.Fields.NonGregorianBirthday]: 'Non-Gregorian Birthday',
46    [Contacts.Fields.Emails]: 'Email Addresses',
47    [Contacts.Fields.PhoneNumbers]: 'Phone Numbers',
48    [Contacts.Fields.Addresses]: 'Addresses',
49    [Contacts.Fields.SocialProfiles]: 'Social Profiles',
50    [Contacts.Fields.InstantMessageAddresses]: 'Instant Message Addresses',
51    [Contacts.Fields.UrlAddresses]: 'URL Addresses',
52    [Contacts.Fields.Company]: 'Company',
53    [Contacts.Fields.JobTitle]: 'Job Title',
54    [Contacts.Fields.Department]: 'Department',
55    [Contacts.Fields.ImageAvailable]: 'Image Available',
56    [Contacts.Fields.Image]: 'Image',
57    [Contacts.Fields.RawImage]: 'Raw Image',
58    [Contacts.Fields.Note]: 'Note',
59    [Contacts.Fields.Dates]: 'Dates',
60    [Contacts.Fields.Relationships]: 'Relationships',
61  }[key];
62}
63
64export function getPrimary<T extends { isPrimary?: boolean }>(items: T[]) {
65  if (items) {
66    const primary = items.filter(({ isPrimary }) => isPrimary);
67    if (primary.length > 0) {
68      return primary[0];
69    }
70    return items[0];
71  }
72  return null;
73}
74
75export async function getGroupWithNameAsync(
76  groupName: string
77): Promise<Contacts.Group | undefined> {
78  const groups = await Contacts.getGroupsAsync({ groupName });
79  if (groups && groups.length > 0) {
80    return groups[0];
81  }
82  return undefined;
83}
84
85export async function cloneAsync(contactId: string) {
86  const contact = await Contacts.getContactByIdAsync(contactId);
87  if (contact) {
88    await Contacts.addContactAsync(contact);
89  }
90}
91
92export async function ensureGroupAsync(groupName: string) {
93  const group = await getGroupWithNameAsync(groupName);
94  if (!group) {
95    return await Contacts.createGroupAsync(groupName);
96  }
97  return group.id;
98}
99
100export async function deleteGroupWithNameAsync(groupName: string) {
101  try {
102    const group = await getGroupWithNameAsync(groupName);
103    if (group) {
104      await Contacts.removeGroupAsync(group.id!);
105    }
106  } catch ({ message }) {
107    console.error(message);
108  }
109}
110
111export async function removeAllChildrenFromGroupWithNameAsync(groupName: string) {
112  try {
113    const groupId = await ensureGroupAsync(groupName);
114
115    const { data: contacts } = await Contacts.getContactsAsync({ groupId });
116    await Promise.all(
117      contacts.map((contact) => Contacts.removeContactFromGroupAsync(contact.id!, groupId!))
118    );
119  } catch ({ message }) {
120    console.error(message);
121  }
122}
123
124export async function debugAddFirstContactToGroupAsync() {
125  const groupId = await ensureGroupAsync('Expo Contacts');
126  const { data: contacts } = await Contacts.getContactsAsync({ pageSize: 1 });
127  const contact = contacts[0];
128  await Contacts.addExistingContactToGroupAsync(contact.id!, groupId!);
129}
130
131export function presentNewContactFormAsync({
132  contact,
133  options,
134}: { contact?: Contacts.Contact; options?: Contacts.FormOptions } = {}) {
135  return Contacts.presentFormAsync(null, contact, { ...options, isNew: true });
136}
137
138export function presentUnknownContactFormAsync({
139  contact,
140  options,
141}: { contact?: Contacts.Contact; options?: Contacts.FormOptions } = {}) {
142  return Contacts.presentFormAsync(null, contact, { ...options, isNew: false });
143}
144
145export function presentContactInfoFormAsync({
146  contact,
147  options,
148}: { contact?: Contacts.Contact; options?: Contacts.FormOptions } = {}) {
149  return Contacts.presentFormAsync(contact!.id, null, { ...options, isNew: false });
150}
151