Files
11cafe-comfyui-workspace-ma…/ui/src/RecentFilesDrawer/FilesListFolderItem.tsx
T

142 lines
4.2 KiB
TypeScript

import { HStack, useColorMode, Text, Stack } from "@chakra-ui/react";
import {
foldersTable,
isFolder,
workflowsTable,
} from "../db-tables/WorkspaceDB";
import {
useState,
memo,
useContext,
useEffect,
MouseEvent,
DragEvent,
} from "react";
import { IconChevronDown, IconChevronRight } from "@tabler/icons-react";
import { RecentFilesContext } from "../WorkspaceContext";
import FilesListFolderItemRightClickMenu from "./FilesListFolderItemRightClickMenu";
import { ESortTypes, sortTypeLocalStorageKey } from "./types";
import { Folder, Workflow } from "../types/dbTypes";
import ItemsList from "./ItemsList";
type Props = {
folder: Folder;
};
export default memo(function FilesListFolderItem({ folder }: Props) {
const [isActive, setIsActive] = useState(false);
const [isCollapsed, setIsCollapsed] = useState(folder.isCollapse ?? true);
const [children, setChildren] = useState<Array<Folder | Workflow>>([]);
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
const [isMenuOpen, setIsMenuOpen] = useState(false);
const { colorMode } = useColorMode();
const {
draggingFile,
setDraggingFile,
refreshFolderStamp,
onRefreshFilesList,
} = useContext(RecentFilesContext);
const activeStyle =
colorMode === "light"
? { backgroundColor: "#E2E8F0" }
: { backgroundColor: "#4A5568" };
useEffect(() => {
workflowsTable
?.listFolderContent(
folder.id,
window.localStorage.getItem(sortTypeLocalStorageKey) as ESortTypes,
)
.then((child) => {
setChildren(child);
});
}, [folder.id, refreshFolderStamp]);
const handleContextMenu = (event: MouseEvent<HTMLDivElement>) => {
event.preventDefault();
setMenuPosition({ x: event.clientX, y: event.clientY });
setIsMenuOpen(true);
};
const handleDrop = async (e: DragEvent) => {
e.preventDefault();
e.stopPropagation();
if (!draggingFile) return setIsActive(false);
if (isFolder(draggingFile)) {
if (draggingFile.id === folder.id) return setIsActive(false);
await foldersTable?.update({
id: draggingFile.id,
parentFolderID: folder.id,
});
} else if (!isFolder(draggingFile)) {
await workflowsTable?.updateFlow(draggingFile.id, {
parentFolderID: folder.id,
});
}
await onRefreshFilesList?.();
setIsActive(false);
};
useEffect(() => {
if (!!folder.isCollapse === isCollapsed) return;
foldersTable?.update({
id: folder.id,
isCollapse: isCollapsed,
});
}, [isCollapsed]);
return (
<Stack>
<HStack
w={"100%"}
as={"button"}
py={1}
onClick={() => {
setIsCollapsed(!isCollapsed);
}}
onContextMenu={handleContextMenu}
draggable="true"
onDragOver={(e) => {
e.preventDefault();
e.stopPropagation();
setIsActive(true);
}}
onDragLeave={(e) => {
e.preventDefault();
e.stopPropagation();
setIsActive(false);
}}
onDragStart={() => setDraggingFile?.(folder)}
onDrop={handleDrop}
_hover={activeStyle}
style={isActive || isMenuOpen ? activeStyle : undefined}
className="droppable"
>
<HStack gap={1}>
{isCollapsed ? (
<IconChevronRight size={20} />
) : (
<IconChevronDown size={20} />
)}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="#EFC54D"
style={{ width: "1.2rem", height: "1.2rem" }}
>
<path d="M19.5 21a3 3 0 0 0 3-3v-4.5a3 3 0 0 0-3-3h-15a3 3 0 0 0-3 3V18a3 3 0 0 0 3 3h15ZM1.5 10.146V6a3 3 0 0 1 3-3h5.379a2.25 2.25 0 0 1 1.59.659l2.122 2.121c.14.141.331.22.53.22H19.5a3 3 0 0 1 3 3v1.146A4.483 4.483 0 0 0 19.5 9h-15a4.483 4.483 0 0 0-3 1.146Z" />
</svg>
</HStack>
<Text>{folder.name}</Text>
</HStack>
<FilesListFolderItemRightClickMenu
isopen={isMenuOpen}
menuPosition={menuPosition}
onClose={() => setIsMenuOpen(false)}
folder={folder}
/>
{!isCollapsed && (
<Stack ml={4} gap={0}>
<ItemsList items={children} />
</Stack>
)}
</Stack>
);
});