Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / applications / drive / src / app / store / _views / useLinkPath.tsx
bloba4d2af6aed345dd3b237c4beb743bdca950cf720
1 import { useCallback } from 'react';
3 import { useDevicesListing } from '../_devices';
4 import type { DecryptedLink } from '../_links';
5 import { useLink } from '../_links';
6 import useLinksState from '../_links/useLinksState';
7 import { ShareType, useShare } from '../_shares';
8 import { isLinkReadOnly } from './utils/useIsActiveLinkReadOnly';
10 type PathItem = {
11     linkId: string;
12     name: string;
13     isRoot: boolean;
14     link: DecryptedLink;
15     isReadOnly?: boolean;
18 const generateLinkPath = async (
19     abortSignal: AbortSignal,
20     shareId: string,
21     linkId: string,
22     getLink: (abortSignal: AbortSignal, shareId: string, linkId: string) => Promise<DecryptedLink>
23 ) => {
24     const currentLinkMeta = await getLink(abortSignal, shareId, linkId);
25     const path = [currentLinkMeta];
27     let nextLinkId = currentLinkMeta.parentLinkId;
28     while (nextLinkId) {
29         const linkMeta = await getLink(abortSignal, shareId, nextLinkId);
30         path.unshift(linkMeta);
31         nextLinkId = linkMeta.parentLinkId;
32     }
34     return path;
37 /**
38  * useLinkPath provides paths to links.
39  * Ideally, this should not be used directly, but be part of useFolderView
40  * (for breadcrumb), for example.
41  */
42 export default function useLinkPath() {
43     const { getLink } = useLink();
44     const { getShare } = useShare();
45     const { getDeviceByShareId } = useDevicesListing();
47     // This is hack. Do not keep it around when moved properly to the state.
48     // When name of some parent changes, we need to update the location as
49     // well, but thats not part of the child link. Therefore, this function
50     // needs to be called any time the state changes. To not do too much
51     // work when its not needed, we cache the callbacks, for which we need
52     // the state. Once the location is part of the state, this whole hook
53     // will not be needed. The problem might be, that updating location for
54     // every link in the store might not be good as well, so that needs more
55     // thoughts.
56     const { getLink: getCachedLink } = useLinksState();
58     const traverseLinksToRoot = useCallback(
59         async (abortSignal: AbortSignal, shareId: string, linkId: string): Promise<PathItem[]> => {
60             const path = await generateLinkPath(abortSignal, shareId, linkId, getLink);
61             const rootShare = await getShare(abortSignal, shareId);
63             const rootLinkName = rootShare.type === ShareType.device && getDeviceByShareId(shareId)?.name;
65             return path.map((link) => ({
66                 linkId: link.linkId,
67                 name: !link.parentLinkId && rootLinkName ? rootLinkName : link.name,
68                 isRoot: !link.parentLinkId,
69                 isReadOnly: isLinkReadOnly(link, rootShare.type),
70                 link,
71             }));
72         },
73         [getCachedLink]
74     );
76     const getPath = useCallback(
77         async (abortSignal: AbortSignal, shareId: string, linkId: string): Promise<string> => {
78             return traverseLinksToRoot(abortSignal, shareId, linkId)
79                 .then((path) => {
80                     return `/${path.map(({ name }) => name).join('/')}`;
81                 })
82                 .catch((err) => {
83                     return err.message || '';
84                 });
85         },
86         [traverseLinksToRoot]
87     );
89     return {
90         traverseLinksToRoot,
91         getPath,
92     };
95 export function useLinkPathPublic() {
96     const { getLink } = useLink();
97     // This is hack. Do not keep it around when moved properly to the state.
98     // When name of some parent changes, we need to update the location as
99     // well, but thats not part of the child link. Therefore, this function
100     // needs to be called any time the state changes. To not do too much
101     // work when its not needed, we cache the callbacks, for which we need
102     // the state. Once the location is part of the state, this whole hook
103     // will not be needed. The problem might be, that updating location for
104     // every link in the store might not be good as well, so that needs more
105     // thoughts.
106     const { getLink: getCachedLink } = useLinksState();
108     const traverseLinksToRoot = useCallback(
109         async (abortSignal: AbortSignal, shareId: string, linkId: string): Promise<PathItem[]> => {
110             const path = await generateLinkPath(abortSignal, shareId, linkId, getLink);
112             return path.map((link) => ({
113                 linkId: link.linkId,
114                 name: link.name,
115                 isRoot: !!link.parentLinkId,
116                 link,
117             }));
118         },
119         [getCachedLink]
120     );
122     return {
123         traverseLinksToRoot,
124     };