fix(file-tree): propagate path simplification to parents

When all childs of a folder are selected in the tree, the selected path
was only simplifiyng one level. But if the reduction was also making its
own parent "fully selected" it was not correctly reporting only the
parent as selected
This commit is contained in:
Nicolas Meienberger 2026-01-02 15:49:09 +01:00
parent f836e2f9df
commit cd1d65167a
2 changed files with 43 additions and 36 deletions

View file

@ -182,7 +182,8 @@ export const FileTree = memo((props: Props) => {
if ( if (
item.fullPath.startsWith(`${selectedParentPath}/`) && item.fullPath.startsWith(`${selectedParentPath}/`) &&
!item.fullPath.startsWith(`${path}/`) && !item.fullPath.startsWith(`${path}/`) &&
item.fullPath !== path item.fullPath !== path &&
!path.startsWith(`${item.fullPath}/`)
) { ) {
newSelection.add(item.fullPath); newSelection.add(item.fullPath);
} }
@ -190,39 +191,45 @@ export const FileTree = memo((props: Props) => {
} }
} }
const childrenByParent = new Map<string, string[]>(); let changed = true;
for (const selectedPath of newSelection) { while (changed) {
const lastSlashIndex = selectedPath.lastIndexOf("/"); changed = false;
if (lastSlashIndex > 0) { const childrenByParent = new Map<string, string[]>();
const parentPath = selectedPath.slice(0, lastSlashIndex); for (const selectedPath of newSelection) {
if (!childrenByParent.has(parentPath)) { const lastSlashIndex = selectedPath.lastIndexOf("/");
childrenByParent.set(parentPath, []); if (lastSlashIndex > 0) {
} const parentPath = selectedPath.slice(0, lastSlashIndex);
childrenByParent.get(parentPath)?.push(selectedPath); if (!childrenByParent.has(parentPath)) {
} childrenByParent.set(parentPath, []);
} }
childrenByParent.get(parentPath)?.push(selectedPath);
// For each parent, check if all its children are selected }
for (const [parentPath, selectedChildren] of childrenByParent.entries()) { }
// Get all children of this parent from the file list
const allChildren = fileList.filter((item) => { // For each parent, check if all its children are selected
const itemParentPath = item.fullPath.slice(0, item.fullPath.lastIndexOf("/")); for (const [parentPath, selectedChildren] of childrenByParent.entries()) {
return itemParentPath === parentPath; // Get all children of this parent from the file list
}); const allChildren = fileList.filter((item) => {
const itemParentPath = item.fullPath.slice(0, item.fullPath.lastIndexOf("/"));
// If all children are selected, replace them with the parent return itemParentPath === parentPath;
if (allChildren.length > 0 && selectedChildren.length === allChildren.length) { });
// Check that we have every child
const allChildrenPaths = new Set(allChildren.map((c) => c.fullPath)); // If all children are selected, replace them with the parent
const allChildrenSelected = selectedChildren.every((c) => allChildrenPaths.has(c)); if (allChildren.length > 0 && selectedChildren.length === allChildren.length) {
// Check that we have every child
if (allChildrenSelected) { const allChildrenPaths = new Set(allChildren.map((c) => c.fullPath));
// Remove all children const allChildrenSelected = selectedChildren.every((c) => allChildrenPaths.has(c));
for (const childPath of selectedChildren) {
newSelection.delete(childPath); if (allChildrenSelected) {
// Remove all children
for (const childPath of selectedChildren) {
newSelection.delete(childPath);
}
// Add the parent
newSelection.add(parentPath);
changed = true;
break;
} }
// Add the parent
newSelection.add(parentPath);
} }
} }
} }

View file

@ -57,7 +57,7 @@ export const VolumeFileBrowser = ({
if (fileBrowser.isLoading) { if (fileBrowser.isLoading) {
return ( return (
<div className="flex items-center justify-center h-full min-h-[200px]"> <div className="flex items-center justify-center h-full min-h-50">
<p className="text-muted-foreground">Loading files...</p> <p className="text-muted-foreground">Loading files...</p>
</div> </div>
); );
@ -65,7 +65,7 @@ export const VolumeFileBrowser = ({
if (error) { if (error) {
return ( return (
<div className="flex items-center justify-center h-full min-h-[200px]"> <div className="flex items-center justify-center h-full min-h-50">
<p className="text-destructive">Failed to load files: {(error as Error).message}</p> <p className="text-destructive">Failed to load files: {(error as Error).message}</p>
</div> </div>
); );
@ -73,7 +73,7 @@ export const VolumeFileBrowser = ({
if (fileBrowser.isEmpty) { if (fileBrowser.isEmpty) {
return ( return (
<div className="flex flex-col items-center justify-center h-full text-center p-8 min-h-[200px]"> <div className="flex flex-col items-center justify-center h-full text-center p-8 min-h-50">
<FolderOpen className="mb-4 h-12 w-12 text-muted-foreground" /> <FolderOpen className="mb-4 h-12 w-12 text-muted-foreground" />
<p className="text-muted-foreground">{emptyMessage}</p> <p className="text-muted-foreground">{emptyMessage}</p>
{emptyDescription && <p className="text-sm text-muted-foreground mt-2">{emptyDescription}</p>} {emptyDescription && <p className="text-sm text-muted-foreground mt-2">{emptyDescription}</p>}