Merge branch 'feat/rbf-wording' into 'main'
[ProtonMail-WebClient.git] / packages / drive-store / lib / _nodes / useNode.ts
blobdfdeedb97da333fee0dc527ba4fc4eb7eb5f559b
1 import type { SHARE_MEMBER_PERMISSIONS } from '@proton/shared/lib/drive/permissions';
2 import mergeUint8Arrays from '@proton/utils/mergeUint8Arrays';
4 import { useLinkPath } from '../../store';
5 import { useDownload } from '../../store/_downloads';
6 import { useLink, validateLinkName } from '../../store/_links';
7 import { useDirectSharingInfo } from '../../store/_shares/useDirectSharingInfo';
8 import useUploadHelper from '../../store/_uploads/UploadProvider/useUploadHelper';
9 import { useAbortSignal } from '../../store/_views/utils';
10 import { ValidationError } from '../../utils/errorHandling/ValidationError';
11 import { streamToBuffer } from '../../utils/stream';
12 import type { LegacyNodeMeta } from '../interface';
13 import type { DecryptedNode } from './interface';
14 import { decryptedLinkToNode } from './utils';
16 export const useNode = () => {
17     const { getLink } = useLink();
18     const { getPath } = useLinkPath();
19     const { getSharePermissions } = useDirectSharingInfo();
20     const { downloadStream } = useDownload();
21     const { findAvailableName } = useUploadHelper();
22     const abortSignal = useAbortSignal([]);
24     const getNode = async ({ shareId, linkId, volumeId }: LegacyNodeMeta): Promise<DecryptedNode> => {
25         const link = await getLink(abortSignal, shareId, linkId);
27         return decryptedLinkToNode(link, volumeId);
28     };
30     const getNodeContents = async ({
31         shareId,
32         linkId,
33         volumeId,
34     }: LegacyNodeMeta): Promise<{
35         contents: Uint8Array;
36         node: DecryptedNode;
37     }> => {
38         const link = await getLink(abortSignal, shareId, linkId);
40         const { stream, controls } = downloadStream({
41             ...link,
42             shareId,
43         });
44         const cancelListener = () => {
45             controls.cancel();
46         };
47         abortSignal.addEventListener('abort', cancelListener);
48         const buffer = await streamToBuffer(stream);
49         abortSignal.removeEventListener('abort', cancelListener);
51         return {
52             contents: mergeUint8Arrays(buffer),
53             node: decryptedLinkToNode(link, volumeId),
54         };
55     };
57     const getNodePermissions = async ({ shareId }: LegacyNodeMeta): Promise<SHARE_MEMBER_PERMISSIONS> => {
58         return getSharePermissions(abortSignal, shareId);
59     };
61     const getNodePath = async ({ shareId, linkId }: LegacyNodeMeta): Promise<string> => {
62         return getPath(abortSignal, shareId, linkId);
63     };
65     const findAvailableNodeName = async (
66         { shareId, linkId: parentLinkId }: LegacyNodeMeta,
67         filename: string
68     ): Promise<string> => {
69         const error = validateLinkName(filename);
71         if (error) {
72             throw new ValidationError(error);
73         }
75         const name = await findAvailableName(abortSignal, { shareId, parentLinkId, filename });
77         return name.filename;
78     };
80     return {
81         getNode,
82         getNodePath,
83         getNodeContents,
84         getNodePermissions,
85         findAvailableNodeName,
86     };
89 export default useNode;