diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 272b2ee..bbe0125 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -22,6 +22,7 @@ "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", "@tanstack/react-query": "^5.52.1", + "@types/react-window": "^1.8.8", "axios": "^1.7.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -35,6 +36,8 @@ "react-resizable-panels": "^2.1.1", "react-router-dom": "^6.26.1", "react-slick": "^0.30.2", + "react-virtualized-auto-sizer": "^1.0.24", + "react-window": "^1.8.10", "recharts": "^2.12.7", "slick-carousel": "^1.8.1", "sweetalert2": "^11.14.1", @@ -6950,6 +6953,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-window": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", + "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", @@ -11032,6 +11044,12 @@ "node": ">= 0.6" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, "node_modules/memoizerific": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", @@ -12696,6 +12714,33 @@ "react-dom": ">=16.6.0" } }, + "node_modules/react-virtualized-auto-sizer": { + "version": "1.0.24", + "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.24.tgz", + "integrity": "sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==", + "license": "MIT", + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-window": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.10.tgz", + "integrity": "sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "memoize-one": ">=3.1.1 <6" + }, + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index a4bb4ac..71d2985 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,6 +28,7 @@ "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", "@tanstack/react-query": "^5.52.1", + "@types/react-window": "^1.8.8", "axios": "^1.7.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -41,6 +42,8 @@ "react-resizable-panels": "^2.1.1", "react-router-dom": "^6.26.1", "react-slick": "^0.30.2", + "react-virtualized-auto-sizer": "^1.0.24", + "react-window": "^1.8.10", "recharts": "^2.12.7", "slick-carousel": "^1.8.1", "sweetalert2": "^11.14.1", diff --git a/frontend/src/components/ImageUploadFileModal/ImageUploadFileForm.tsx b/frontend/src/components/ImageUploadFileModal/ImageUploadFileForm.tsx index e93b577..52be1c4 100644 --- a/frontend/src/components/ImageUploadFileModal/ImageUploadFileForm.tsx +++ b/frontend/src/components/ImageUploadFileModal/ImageUploadFileForm.tsx @@ -4,6 +4,7 @@ import { cn } from '@/lib/utils'; import useAuthStore from '@/stores/useAuthStore'; import { CircleCheckBig, CircleDashed, CircleX, X } from 'lucide-react'; import useUploadImageFileQuery from '@/queries/projects/useUploadImageFileQuery'; +import { FixedSizeList } from 'react-window'; export default function ImageUploadFileForm({ onClose, @@ -135,48 +136,56 @@ export default function ImageUploadFileForm({ )} {files.length > 0 && ( )} {isUploading ? ( diff --git a/frontend/src/components/WorkspaceSidebar/ProjectDirectoryItem.tsx b/frontend/src/components/WorkspaceSidebar/ProjectDirectoryItem.tsx index c590308..d3dd73b 100644 --- a/frontend/src/components/WorkspaceSidebar/ProjectDirectoryItem.tsx +++ b/frontend/src/components/WorkspaceSidebar/ProjectDirectoryItem.tsx @@ -56,7 +56,6 @@ export default function ProjectDirectoryItem({ key={`${projectId}-${item.imageTitle}`} item={item} depth={depth + 1} - folderId={folderData.id} selected={image?.id === item.id} /> ))} diff --git a/frontend/src/components/WorkspaceSidebar/ProjectFileItem.tsx b/frontend/src/components/WorkspaceSidebar/ProjectFileItem.tsx index eb5c2b5..12d4090 100644 --- a/frontend/src/components/WorkspaceSidebar/ProjectFileItem.tsx +++ b/frontend/src/components/WorkspaceSidebar/ProjectFileItem.tsx @@ -2,12 +2,10 @@ import { cn } from '@/lib/utils'; import { ImageResponse } from '@/types'; import { ArrowDownToLine, Check, CircleSlash, Image, Loader, Minus, Send } from 'lucide-react'; import useCanvasStore from '@/stores/useCanvasStore'; -import useProjectStore from '@/stores/useProjectStore'; export default function ProjectFileItem({ className = '', item, - folderId = 0, depth = 0, selected, }: { @@ -19,11 +17,9 @@ export default function ProjectFileItem({ }) { const paddingLeft = depth * 12; const setImage = useCanvasStore((state) => state.setImage); - const setFolderId = useProjectStore((state) => state.setFolderId); const handleClick = () => { setImage(item); - setFolderId(folderId); }; return (