feat: refine frontend folder management and display by merging folder tree data.

This commit is contained in:
2025-12-09 12:37:27 +01:00
parent 463046c970
commit 8a16293f0e
7 changed files with 155 additions and 190 deletions
@@ -2,7 +2,7 @@ import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import type { DragEvent } from 'react';
import { useStatusToast } from '../../../lib/context/StatusToastContext';
import { DEFAULT_FOLDER_NAME, hasFiles } from '../../../app/workspaceUtils';
import { hasFiles } from '../../../app/workspaceUtils';
import {
createFolder,
deleteFolder,
@@ -35,11 +35,12 @@ import useNotifyApiError from '../../../hooks/useNotifyApiError';
import type {
FolderState,
DragState,
FolderNode,
} from '../../types/workspaceTypes';
import type FoldersManager from '../../FoldersManager';
interface UseFolderTreeActionsOptions {
folderState: Pick<FolderState, 'folderNodes' | 'setFolderNodes' | 'selectedFolder' | 'setSelectedFolder' | 'setCreatingFolder'>;
folderState: Pick<FolderState, 'folderNodes' | 'selectedFolder' | 'setSelectedFolder' | 'setCreatingFolder'> & { foldersManager?: FoldersManager };
dragState: DragState;
actions: {
handleFileDrop: (dataTransfer: DataTransfer, folderId: FolderKey) => Promise<void> | void;
@@ -58,10 +59,10 @@ const useFolderTreeActions = ({
}: UseFolderTreeActionsOptions) => {
const {
folderNodes,
setFolderNodes,
selectedFolder,
setSelectedFolder,
setCreatingFolder,
foldersManager,
} = folderState;
const {
@@ -101,50 +102,9 @@ const useFolderTreeActions = ({
try {
await moveFolderRequest(folderId, parent_id);
setFolderNodes((prev: Map<FolderKey, FolderNode>) => {
const next = new Map(prev);
const currentNode = next.get(folderId);
if (!currentNode) {
return prev;
}
next.set(folderId, { ...currentNode, parentId: parent_id ?? null });
const previousParent = next.get(previousParentKey);
if (previousParent) {
const remainingChildren = (previousParent.children || []).filter(
(childId) => childId !== folderId,
);
next.set(previousParentKey, {
...previousParent,
children: remainingChildren,
hasChildren: remainingChildren.length > 0,
});
}
if (!next.has(targetKey)) {
next.set(targetKey, {
id: targetKey,
name: targetKey === 'root' ? DEFAULT_FOLDER_NAME : 'Folder',
parentId: targetKey === 'root' ? null : null,
children: [],
expanded: targetKey === 'root',
loaded: false,
hasChildren: false,
});
}
const targetNode = next.get(targetKey);
if (targetNode && !targetNode.children.includes(folderId)) {
next.set(targetKey, {
...targetNode,
children: [...targetNode.children, folderId],
hasChildren: true,
});
}
return next;
});
if (foldersManager) {
foldersManager.invalidateTree();
}
if (selectedFolder === folderId) {
setSelectedFolder(folderId);
@@ -160,7 +120,7 @@ const useFolderTreeActions = ({
folderNodes,
notifyApiError,
selectedFolder,
setFolderNodes,
foldersManager,
setSelectedFolder,
showToast,
],
@@ -202,14 +162,9 @@ const useFolderTreeActions = ({
try {
await renameFolderRequest(folderId, trimmed);
setFolderNodes((prev: Map<FolderKey, FolderNode>) => {
const next = new Map(prev);
const node = next.get(folderId);
if (node) {
next.set(folderId, { ...node, name: trimmed });
}
return next;
});
if (foldersManager) {
foldersManager.ingest([{ id: folderId, name: trimmed }]);
}
showToast('Folder renamed.', 'success');
return true;
@@ -221,7 +176,7 @@ const useFolderTreeActions = ({
},
[
notifyApiError,
setFolderNodes,
foldersManager,
showToast,
],
);
@@ -250,29 +205,13 @@ const useFolderTreeActions = ({
throw new Error('Folder creation failed.');
}
showToast('Folder created.', 'success');
setFolderNodes((prev: Map<FolderKey, FolderNode>) => {
const next = new Map(prev);
const parentId = folderData.parent_id ?? payload.parent_id ?? 'root';
const parentNode = next.get(parentId);
if (parentNode) {
next.set(parentId, {
...parentNode,
children: parentNode.children.concat([folderData.id]),
loaded: true,
hasChildren: true,
});
}
next.set(folderData.id, {
id: folderData.id,
name: folderData.name ?? payload.name,
parentId: parentId,
children: folderData.children || [],
expanded: false,
loaded: false,
hasChildren: Array.isArray(folderData.children) ? folderData.children.length > 0 : false,
});
return next;
});
if (foldersManager) {
// Ingest the new folder data immediately so it's available
foldersManager.ingest([folderData]);
// Force tree refresh to update structure
foldersManager.invalidateTree();
}
await selectFolder(folderData.id, { immediate: true });
succeeded = true;
@@ -293,7 +232,7 @@ const useFolderTreeActions = ({
selectFolder,
selectedFolder,
setCreatingFolder,
setFolderNodes,
foldersManager,
showToast,
],
);
@@ -310,26 +249,13 @@ const useFolderTreeActions = ({
try {
await deleteFolder(folderId);
setFolderNodes((prev: Map<FolderKey, FolderNode>) => {
const next = new Map(prev);
const node = next.get(folderId);
next.delete(folderId);
if (node) {
const parentId = node.parentId || 'root';
const parentNode = next.get(parentId);
if (parentNode) {
const remaining = parentNode.children.filter((id) => id !== folderId);
next.set(parentId, {
...parentNode,
children: remaining,
hasChildren: remaining.length > 0,
});
}
}
return next;
});
if (foldersManager) {
foldersManager.remove([folderId]);
foldersManager.invalidateTree();
}
if (selectedFolder === folderId) {
// Fallback selection logic
const node = folderNodes.get(folderId);
const parentId = node?.parentId || 'root';
setSelectedFolder(parentId);
@@ -352,7 +278,7 @@ const useFolderTreeActions = ({
folderNodes,
notifyApiError,
selectedFolder,
setFolderNodes,
foldersManager,
setSelectedFolder,
showToast,
],