143 lines
3.5 KiB
TypeScript
143 lines
3.5 KiB
TypeScript
//@ts-nocheck
|
|
import {
|
|
addIndex,
|
|
append,
|
|
compose,
|
|
equals,
|
|
filter,
|
|
find,
|
|
includes,
|
|
isNil,
|
|
map,
|
|
mergeLeft,
|
|
not,
|
|
propEq,
|
|
reduce,
|
|
uniq
|
|
} from 'ramda';
|
|
import { DirItem } from '../models';
|
|
import { SyncAction, SyncObjectCallback, SyncParamAction } from '../types';
|
|
import { createStoreHook } from '../utils/store_creator';
|
|
|
|
interface DirsStates {
|
|
drives: DirItem[];
|
|
directories: DirItem[];
|
|
focused?: DirItem;
|
|
selected?: string;
|
|
expanded: string[];
|
|
}
|
|
|
|
type DirsActions = {
|
|
updateDrives: (dirs: Omit<DirItem, 'sort' | 'parent'>[]) => void;
|
|
saveDirectories: (dirs: Omit<DirItem, 'sort' | 'parent'>[], parent: string) => void;
|
|
focus: SyncParamAction<string>;
|
|
unfocus: SyncAction;
|
|
selectDirectory: SyncParamAction<string>;
|
|
unselectDirectory: SyncAction;
|
|
expandDir: SyncParamAction<string>;
|
|
foldDir: SyncParamAction<string>;
|
|
};
|
|
|
|
const initialState: DirsStates = {
|
|
drives: [],
|
|
directories: [],
|
|
focused: undefined,
|
|
selected: undefined,
|
|
expanded: []
|
|
};
|
|
|
|
export const useDirTreeStore = createStoreHook<DirsStates & DirsActions>((set, get) => ({
|
|
...initialState,
|
|
updateDrives(dirs) {
|
|
set(df => {
|
|
df.drives = addIndex<Omit<DirItem, 'sort' | 'paraent'>, DirItem>(map)(
|
|
(item, index) => mergeLeft({ sort: index * 10, path: item.path, parent: undefined }, item),
|
|
dirs
|
|
);
|
|
});
|
|
},
|
|
saveDirectories(dirs, parent) {
|
|
const convertedDirs = addIndex<Omit<DirItem, 'sort' | 'parent'>, DirItem>(map)(
|
|
(item, index) => mergeLeft({ sort: index * 10, path: item.path, parent }, item),
|
|
dirs
|
|
);
|
|
const premerged = reduce(
|
|
(acc, elem) => {
|
|
const dir = find(propEq('id', elem.id), convertedDirs);
|
|
if (not(isNil(dir))) {
|
|
acc = append(mergeLeft(dir, elem), acc);
|
|
} else {
|
|
acc = append(elem, acc);
|
|
}
|
|
return acc;
|
|
},
|
|
[],
|
|
get().directories
|
|
);
|
|
const afterMerged = reduce(
|
|
(acc, elem) => {
|
|
const dir = find(propEq('id', elem.id), acc);
|
|
if (isNil(dir)) {
|
|
return append(elem, acc);
|
|
} else {
|
|
return acc;
|
|
}
|
|
},
|
|
premerged,
|
|
convertedDirs
|
|
);
|
|
set(df => {
|
|
df.directories = afterMerged;
|
|
});
|
|
},
|
|
focus(specifiedDirId) {
|
|
const requestedDir = find(propEq('id', specifiedDirId), get().directories);
|
|
if (not(isNil(requestedDir))) {
|
|
set(df => {
|
|
df.focused = requestedDir;
|
|
});
|
|
}
|
|
},
|
|
unfocus() {
|
|
set(df => {
|
|
df.focused = undefined;
|
|
});
|
|
},
|
|
selectDirectory(dirId) {
|
|
set(df => {
|
|
df.selected = dirId;
|
|
});
|
|
},
|
|
unselectDirectory() {
|
|
set(df => {
|
|
df.selected = undefined;
|
|
});
|
|
},
|
|
expandDir(dirId) {
|
|
set(df => {
|
|
df.expanded = uniq(append(dirId, df.expanded));
|
|
});
|
|
},
|
|
foldDir(dirId) {
|
|
set(df => {
|
|
df.expanded = filter(compose(not, equals(dirId)), df.expanded);
|
|
});
|
|
}
|
|
}));
|
|
|
|
export function currentRootsSelector(): SyncObjectCallback<DirsStates, DirItem[]> {
|
|
return state => (isNil(state.focused) ? state.drives : [state.focused]);
|
|
}
|
|
|
|
export function selectDirectories(parent: string): SyncObjectCallback<DirItem[], DirItem[]> {
|
|
return dirs => filter(propEq('parent', parent), dirs) ?? [];
|
|
}
|
|
|
|
export function subDirectoriesSelector(parent: string): SyncObjectCallback<DirsStates, DirItem[]> {
|
|
return state => filter(propEq('parent', parent), state.directories) ?? [];
|
|
}
|
|
|
|
export function isExpandedSelector(dirId: string): SyncObjectCallback<DirsStates, bool> {
|
|
return state => includes(dirId, state.expanded);
|
|
}
|