Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / containers / contacts / ContactEmailsProvider.tsx
blob927aed400b04d2c6e3424ff4b54d77823675ba23
1 import type { ReactNode } from 'react';
2 import { createContext, useContext, useMemo } from 'react';
4 import { useContactGroups } from '@proton/mail';
5 import { useContactEmails } from '@proton/mail/contactEmails/hooks';
6 import { canonicalizeEmail } from '@proton/shared/lib/helpers/email';
7 import type { ContactEmail, ContactGroup } from '@proton/shared/lib/interfaces/contacts';
8 import type { SimpleMap } from '@proton/shared/lib/interfaces/utils';
10 export type GroupWithContacts = { group: ContactGroup; contacts: ContactEmail[] };
11 export type GroupsWithContactsMap = SimpleMap<GroupWithContacts>;
13 export type ContactEmailsCache = {
14     contactEmails: ContactEmail[];
15     contactGroups: ContactGroup[];
16     contactEmailsMap: SimpleMap<ContactEmail>;
17     contactEmailsMapWithDuplicates: SimpleMap<ContactEmail[]>;
18     groupsWithContactsMap: GroupsWithContactsMap;
21 const ContactEmailsContext = createContext<ContactEmailsCache | null>(null);
23 const computeGroupsMap = (contacts: ContactEmail[], contactGroups: ContactGroup[]) =>
24     contacts.reduce<GroupsWithContactsMap>((acc, contact) => {
25         contact.LabelIDs?.forEach((labelID) => {
26             if (acc[labelID]) {
27                 acc[labelID]?.contacts.push(contact);
28             } else {
29                 const group = contactGroups.find((group) => group.ID === labelID);
30                 if (group) {
31                     acc[labelID] = { group, contacts: [contact] };
32                 }
33             }
34         });
35         return acc;
36     }, {});
38 export const useContactEmailsCache = () => {
39     const state = useContext(ContactEmailsContext);
40     if (!state) {
41         throw new Error('Trying to use uninitialized ContactEmailsProvider');
42     }
43     return state;
46 const toMapWithDuplicates = (contacts: ContactEmail[]) => {
47     const contactEmailsMapWithDuplicates = contacts.reduce<SimpleMap<ContactEmail[]>>((acc, contact) => {
48         const email = canonicalizeEmail(contact.Email);
49         const contacts = acc[email];
50         if (!contacts) {
51             acc[email] = [contact];
52         } else {
53             contacts.push(contact);
54             contacts.sort((a, b) => a.Order - b.Order);
55         }
56         return acc;
57     }, {});
59     const contactEmailsMap = Object.keys(contactEmailsMapWithDuplicates).reduce<SimpleMap<ContactEmail>>((acc, key) => {
60         acc[key] = contactEmailsMapWithDuplicates[key]?.[0];
61         return acc;
62     }, {});
64     return { contactEmailsMap, contactEmailsMapWithDuplicates };
67 interface Props {
68     children?: ReactNode;
70 const ContactEmailsProvider = ({ children }: Props) => {
71     const [contactEmails = []] = useContactEmails();
72     const [contactGroups = []] = useContactGroups();
73     const cache = useMemo(() => {
74         return {
75             contactEmails,
76             contactGroups,
77             ...toMapWithDuplicates(contactEmails),
78             groupsWithContactsMap: computeGroupsMap(contactEmails, contactGroups),
79         };
80     }, [contactEmails, contactGroups]);
82     return <ContactEmailsContext.Provider value={cache}>{children}</ContactEmailsContext.Provider>;
85 export default ContactEmailsProvider;