1 import type { FC, PropsWithChildren } from 'react';
2 import { useEffect, useMemo, useState } from 'react';
3 import { useSelector } from 'react-redux';
5 import { useNavigation } from '@proton/pass/components/Navigation/NavigationProvider';
6 import { selectMostRecentInvite } from '@proton/pass/store/selectors/invites';
7 import type { MaybeNull } from '@proton/pass/types';
8 import type { Invite } from '@proton/pass/types/data/invites';
10 import { InviteContext, type InviteContextValue } from './InviteContext';
11 import { VaultAccessManager } from './VaultAccessManager';
12 import { VaultInviteCreate, type VaultInviteCreateValues } from './VaultInviteCreate';
13 import { VaultInviteRespond } from './VaultInviteRespond';
15 type InviteContextState =
16 | ({ view: 'invite' } & VaultInviteCreateValues<false>)
17 | ({ view: 'invite-new' } & VaultInviteCreateValues<true>)
18 | { view: 'manage'; shareId: string };
20 export const InviteProvider: FC<PropsWithChildren> = ({ children }) => {
21 const { setFilters } = useNavigation();
23 const [state, setState] = useState<MaybeNull<InviteContextState>>(null);
24 const [invite, setInvite] = useState<MaybeNull<Invite>>(null);
25 const latestInvite = useSelector(selectMostRecentInvite);
27 const handles = useMemo(
29 close: () => setState(null),
30 createInvite: (props: VaultInviteCreateValues<false>) => setState({ view: 'invite', ...props }),
31 createSharedVault: (props: VaultInviteCreateValues<true>) => setState({ view: 'invite-new', ...props }),
32 manageAccess: (shareId: string) => setState({ view: 'manage', shareId }),
33 onInviteResponse: () => setInvite(null),
38 const contextValue = useMemo<InviteContextValue>(
42 onShareDisabled: (disabledShareId: string) => {
43 const shareId = (() => {
44 switch (state?.view) {
46 return state.vault.shareId;
54 if (disabledShareId === shareId) {
59 respondToInvite: setInvite,
65 /* If the latest invite was promoted from a new user invite,
66 * auto prompt the "respond to invite" modal */
67 if (latestInvite?.fromNewUser) setInvite(latestInvite);
71 <InviteContext.Provider value={contextValue}>
73 switch (state?.view) {
75 return <VaultInviteCreate withVaultCreation={false} {...state} />;
81 onVaultCreated={(selectedShareId) => setFilters({ selectedShareId })}
85 return <VaultAccessManager shareId={state.shareId} />;
91 {invite && <VaultInviteRespond {...invite} />}
93 </InviteContext.Provider>