Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / applications / drive / src / app / components / sections / Photos / hooks / usePhotosSelection.ts
blob6f9d8351c28e623c4a9285e8789e95b1b95601bf
1 import { useCallback, useMemo, useState } from 'react';
3 import { isPhotoGroup } from '../../../../store/_photos';
4 import type { PhotoGroup } from '../../../../store/_photos/interface';
6 type SelectionItem = { linkId: string };
7 type SelectionGroup = PhotoGroup;
9 export const getGroupLinkIds = <T extends SelectionItem>(data: (T | SelectionGroup)[], groupIndex: number) => {
10     if (!isPhotoGroup(data[groupIndex])) {
11         return [];
12     }
14     const items: string[] = [];
16     for (let i = groupIndex + 1; i < data.length; i++) {
17         const current = data[i];
19         if (isPhotoGroup(current)) {
20             break;
21         }
23         items.push(current.linkId);
24     }
26     return items;
29 type HandleSelectionArgs = {
30     isSelected: boolean;
31     isMultiSelect?: boolean;
34 export const usePhotosSelection = <T extends SelectionItem>(
35     data: (T | SelectionGroup)[],
36     photoLinkIdToIndexMap: Record<string, number>
37 ) => {
38     const [selection, setSelection] = useState<Record<string, boolean>>({});
39     const [lastIndex, setLastIndex] = useState<number | undefined>();
41     const setSelected = useCallback(
42         (isSelected: boolean, ...linkIds: string[]) => {
43             setSelection((state) => {
44                 let newState = { ...state };
46                 linkIds.forEach((linkId) => {
47                     if (isSelected) {
48                         newState[linkId] = true;
49                     } else {
50                         delete newState[linkId];
51                     }
52                 });
54                 return newState;
55             });
56         },
57         [setSelection]
58     );
60     const clearSelection = useCallback(() => {
61         setSelection({});
62         setLastIndex(undefined);
63     }, [setSelection]);
65     const handleSelection = useCallback(
66         (index: number, { isSelected, isMultiSelect }: HandleSelectionArgs) => {
67             const item = data[index];
69             if (isPhotoGroup(item)) {
70                 const groupLinkIds = getGroupLinkIds(data, index);
71                 setSelected(isSelected, ...groupLinkIds);
72                 const lastIndexLinkId = groupLinkIds.shift();
73                 setLastIndex(lastIndexLinkId ? photoLinkIdToIndexMap[lastIndexLinkId] : undefined);
74             } else {
75                 if (isMultiSelect && lastIndex !== undefined) {
76                     const startIndex = lastIndex < index ? lastIndex : index;
77                     const endIndex = lastIndex < index ? index : lastIndex;
79                     const items = (
80                         data.slice(startIndex, endIndex + 1).filter((item) => !isPhotoGroup(item)) as T[]
81                     ).map((item) => item.linkId);
83                     setSelection({});
84                     setSelected(true, ...items);
85                     return;
86                 }
88                 setLastIndex(index);
89                 setSelected(isSelected, item.linkId);
90             }
91         },
92         [data, setSelected, photoLinkIdToIndexMap, lastIndex]
93     );
95     const selectedItems = useMemo(
96         () =>
97             Object.keys(selection).reduce<T[]>((acc, linkId) => {
98                 const item = data[photoLinkIdToIndexMap[linkId]];
99                 if (item && !isPhotoGroup(item)) {
100                     acc.push(item);
101                 }
103                 return acc;
104             }, []),
105         [selection, data, photoLinkIdToIndexMap]
106     );
108     const isGroupSelected = useCallback(
109         (groupIndex: number) => {
110             let linkIds = getGroupLinkIds(data, groupIndex);
111             let selectedCount = 0;
113             for (let linkId of linkIds) {
114                 if (selection[linkId]) {
115                     selectedCount++;
116                 } else if (selectedCount > 0) {
117                     break;
118                 }
119             }
121             if (selectedCount === 0) {
122                 return false;
123             }
125             return selectedCount === linkIds.length || 'some';
126         },
127         [data, selection]
128     );
130     const isItemSelected = useCallback((linkId: string) => !!selection[linkId], [selection]);
132     return {
133         selectedItems,
134         setSelected,
135         clearSelection,
136         handleSelection,
137         isGroupSelected,
138         isItemSelected,
139     };