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: Contacts.FieldType) {
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    // @ts-ignore
89    await Contacts.addContactAsync(contact);
90  }
91}
92
93export async function ensureGroupAsync(groupName: string) {
94  const group = await getGroupWithNameAsync(groupName);
95  if (!group) {
96    const groupId = await Contacts.createGroupAsync(groupName);
97    return groupId;
98  }
99  return group.id;
100}
101
102export async function deleteGroupWithNameAsync(groupName: string) {
103  try {
104    const group = await getGroupWithNameAsync(groupName);
105    if (group) {
106      Contacts.removeGroupAsync(group.id!);
107    }
108  } catch ({ message }) {
109    // tslint:disable-next-line no-console
110    console.error(message);
111  }
112}
113
114export async function removeAllChildrenFromGroupWithNameAsync(groupName: string) {
115  try {
116    const groupId = await ensureGroupAsync(groupName);
117
118    const { data: contacts } = await Contacts.getContactsAsync({ groupId });
119    await Promise.all(
120      contacts.map(contact => Contacts.removeContactFromGroupAsync(contact.id, groupId!))
121    );
122  } catch ({ message }) {
123    // tslint:disable-next-line no-console
124    console.error(message);
125  }
126}
127
128export async function debugAddFirstContactToGroupAsync() {
129  const groupId = await ensureGroupAsync('Expo Contacts');
130  const { data: contacts } = await Contacts.getContactsAsync({ pageSize: 1 });
131  const contact = contacts[0];
132  Contacts.addExistingContactToGroupAsync(contact.id, groupId!);
133}
134
135export function presentNewContactFormAsync({
136  contact,
137  options,
138}: { contact?: Contacts.Contact; options?: Contacts.FormOptions } = {}) {
139  return Contacts.presentFormAsync(null, contact, { ...options, isNew: true });
140}
141
142export function presentUnknownContactFormAsync({
143  contact,
144  options,
145}: { contact?: Contacts.Contact; options?: Contacts.FormOptions } = {}) {
146  return Contacts.presentFormAsync(null, contact, { ...options, isNew: false });
147}
148
149export function presentContactInfoFormAsync({
150  contact,
151  options,
152}: { contact?: Contacts.Contact; options?: Contacts.FormOptions } = {}) {
153  return Contacts.presentFormAsync(contact!.id, null, { ...options, isNew: false });
154}
155