//
// SPDX-License-Identifier: AGPL-3.0
-import { CollectionPanelFilesState, CollectionPanelFile, CollectionPanelDirectory, mapCollectionFileToCollectionPanelFile, mergeCollectionPanelFilesStates } from "./collection-panel-files-state";
+import { CollectionPanelFilesState, CollectionPanelFile, CollectionPanelDirectory, mapCollectionFileToCollectionPanelFile, mergeCollectionPanelFilesStates } from './collection-panel-files-state';
import { CollectionPanelFilesAction, collectionPanelFilesAction } from "./collection-panel-files-actions";
-import { createTree, mapTreeValues, getNode, setNode, getNodeAncestors, getNodeDescendants, setNodeValueWith, mapTree } from "~/models/tree";
+import { createTree, mapTreeValues, getNode, setNode, getNodeAncestorsIds, getNodeDescendantsIds, setNodeValueWith, mapTree } from "~/models/tree";
import { CollectionFileType } from "~/models/collection-file";
export const collectionPanelFilesReducer = (state: CollectionPanelFilesState = createTree(), action: CollectionPanelFilesAction) => {
+ // Low-level tree handling setNode() func does in-place data modifications
+ // for performance reasons, so we pass a copy of 'state' to avoid side effects.
return collectionPanelFilesAction.match(action, {
SET_COLLECTION_FILES: files =>
- mergeCollectionPanelFilesStates(state, mapTree(mapCollectionFileToCollectionPanelFile)(files)),
+ mergeCollectionPanelFilesStates({...state}, mapTree(mapCollectionFileToCollectionPanelFile)(files)),
TOGGLE_COLLECTION_FILE_COLLAPSE: data =>
- toggleCollapse(data.id)(state),
+ toggleCollapse(data.id)({...state}),
- TOGGLE_COLLECTION_FILE_SELECTION: data => [state]
+ TOGGLE_COLLECTION_FILE_SELECTION: data => [{...state}]
.map(toggleSelected(data.id))
.map(toggleAncestors(data.id))
.map(toggleDescendants(data.id))[0],
SELECT_ALL_COLLECTION_FILES: () =>
- mapTreeValues(v => ({ ...v, selected: true }))(state),
+ mapTreeValues(v => ({ ...v, selected: true }))({...state}),
UNSELECT_ALL_COLLECTION_FILES: () =>
- mapTreeValues(v => ({ ...v, selected: false }))(state),
+ mapTreeValues(v => ({ ...v, selected: false }))({...state}),
default: () => state
}) as CollectionPanelFilesState;
const toggleDescendants = (id: string) => (tree: CollectionPanelFilesState) => {
const node = getNode(id)(tree);
if (node && node.value.type === CollectionFileType.DIRECTORY) {
- return getNodeDescendants(id)(tree)
+ return getNodeDescendantsIds(id)(tree)
.reduce((newTree, id) =>
setNodeValueWith(v => ({ ...v, selected: node.value.selected }))(id)(newTree), tree);
}
};
const toggleAncestors = (id: string) => (tree: CollectionPanelFilesState) => {
- const ancestors = getNodeAncestors(id)(tree).reverse();
+ const ancestors = getNodeAncestorsIds(id)(tree).reverse();
return ancestors.reduce((newTree, parent) => parent ? toggleParentNode(parent)(newTree) : newTree, tree);
};