mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-18 01:14:22 +02:00
fix nested playlist folder drag behavior
This commit is contained in:
@@ -372,9 +372,25 @@ export const PlaylistFolderDragExpandProvider = ({
|
|||||||
expandedSet,
|
expandedSet,
|
||||||
setMany,
|
setMany,
|
||||||
}: PlaylistFolderDragExpandProviderProps) => {
|
}: PlaylistFolderDragExpandProviderProps) => {
|
||||||
|
const separator = useSidebarPlaylistFolderSeparator();
|
||||||
const autoExpandedRef = useRef<Set<string>>(new Set());
|
const autoExpandedRef = useRef<Set<string>>(new Set());
|
||||||
const activeHoveredRef = useRef<null | string>(null);
|
const activeHoveredRef = useRef<null | string>(null);
|
||||||
|
|
||||||
|
const getOpenChain = useCallback(
|
||||||
|
(folderPath: string) => {
|
||||||
|
const segments = folderPath.split(separator).filter((segment) => segment.length > 0);
|
||||||
|
const chain: string[] = [];
|
||||||
|
|
||||||
|
for (let index = 1; index < segments.length; index++) {
|
||||||
|
chain.push(segments.slice(0, index).join(separator));
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.push(folderPath);
|
||||||
|
return chain;
|
||||||
|
},
|
||||||
|
[separator],
|
||||||
|
);
|
||||||
|
|
||||||
const collapseAutoExpanded = useCallback(
|
const collapseAutoExpanded = useCallback(
|
||||||
(paths: string[]) => {
|
(paths: string[]) => {
|
||||||
const toCollapse = paths.filter((path) => autoExpandedRef.current.has(path));
|
const toCollapse = paths.filter((path) => autoExpandedRef.current.has(path));
|
||||||
@@ -388,35 +404,60 @@ export const PlaylistFolderDragExpandProvider = ({
|
|||||||
|
|
||||||
const onFolderDragHover = useCallback(
|
const onFolderDragHover = useCallback(
|
||||||
(folderPath: string) => {
|
(folderPath: string) => {
|
||||||
const previous = activeHoveredRef.current;
|
const current = activeHoveredRef.current;
|
||||||
if (previous && previous !== folderPath) {
|
if (
|
||||||
collapseAutoExpanded([previous]);
|
current &&
|
||||||
|
current !== folderPath &&
|
||||||
|
current.startsWith(`${folderPath}${separator}`)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openChain = getOpenChain(folderPath);
|
||||||
activeHoveredRef.current = folderPath;
|
activeHoveredRef.current = folderPath;
|
||||||
|
|
||||||
if (expandedSet.has(folderPath) || autoExpandedRef.current.has(folderPath)) return;
|
const toCollapse = [...autoExpandedRef.current].filter(
|
||||||
autoExpandedRef.current.add(folderPath);
|
(path) => !openChain.includes(path),
|
||||||
setMany([folderPath], true);
|
);
|
||||||
|
if (toCollapse.length > 0) {
|
||||||
|
collapseAutoExpanded(toCollapse);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toExpand = openChain.filter(
|
||||||
|
(path) => !expandedSet.has(path) && !autoExpandedRef.current.has(path),
|
||||||
|
);
|
||||||
|
if (toExpand.length === 0) return;
|
||||||
|
|
||||||
|
for (const path of toExpand) autoExpandedRef.current.add(path);
|
||||||
|
setMany(toExpand, true);
|
||||||
},
|
},
|
||||||
[collapseAutoExpanded, expandedSet, setMany],
|
[collapseAutoExpanded, expandedSet, getOpenChain, separator, setMany],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onFolderDragLeave = useCallback(
|
const onFolderDragLeave = useCallback(
|
||||||
(folderPath: string) => {
|
(folderPath: string) => {
|
||||||
if (activeHoveredRef.current === folderPath) {
|
const active = activeHoveredRef.current;
|
||||||
|
if (active && active !== folderPath && active.startsWith(`${folderPath}${separator}`)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active === folderPath) {
|
||||||
activeHoveredRef.current = null;
|
activeHoveredRef.current = null;
|
||||||
}
|
}
|
||||||
collapseAutoExpanded([folderPath]);
|
collapseAutoExpanded([folderPath]);
|
||||||
},
|
},
|
||||||
[collapseAutoExpanded],
|
[collapseAutoExpanded, separator],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onFolderDrop = useCallback((folderPath: string) => {
|
const onFolderDrop = useCallback(
|
||||||
autoExpandedRef.current.delete(folderPath);
|
(folderPath: string) => {
|
||||||
if (activeHoveredRef.current === folderPath) {
|
for (const path of getOpenChain(folderPath)) autoExpandedRef.current.delete(path);
|
||||||
activeHoveredRef.current = null;
|
if (activeHoveredRef.current === folderPath) {
|
||||||
}
|
activeHoveredRef.current = null;
|
||||||
}, []);
|
}
|
||||||
|
},
|
||||||
|
[getOpenChain],
|
||||||
|
);
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({ onFolderDragHover, onFolderDragLeave, onFolderDrop }),
|
() => ({ onFolderDragHover, onFolderDragLeave, onFolderDrop }),
|
||||||
|
|||||||
Reference in New Issue
Block a user