Files
comic_viewer/src/states/dirs.ts

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);
}