Skip to content

Commit 243dd60

Browse files
committed
fix(explorer): fix selection reactivity, rename escape bug, and multi-select cut/copy
- Fix #21783: Move isSelected, gitDecoration, and isEntering computations from const variables inside the For callback to inline expressions in JSX props, preserving SolidJS reactivity tracking. - Fix #21770: Add a renameCancelled flag in VirtualItem. Set it in the Escape keydown handler before calling onRename, and check it in onBlur to skip the duplicate rename call when Escape was pressed. Reset the flag when entering rename mode and after the blur guard fires. - Fix #21711: Change context menu Cut and Copy handlers to operate on the full selection set (props.selectedPaths) when the right-clicked file is part of the selection, instead of only the single contextMenuTarget path.
1 parent 3fd1e18 commit 243dd60

File tree

3 files changed

+24
-13
lines changed

3 files changed

+24
-13
lines changed

src/components/explorer/VirtualItem.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { VirtualItemProps } from "./types";
77
export function VirtualItem(props: VirtualItemProps) {
88
const [renameValue, setRenameValue] = createSignal("");
99
let inputRef: HTMLInputElement | undefined;
10+
let renameCancelled = false;
1011

1112
const isFocused = () => props.focusedPath === props.item.entry.path;
1213
const isRenaming = () => props.renamingPath === props.item.entry.path;
@@ -35,6 +36,7 @@ export function VirtualItem(props: VirtualItemProps) {
3536

3637
createEffect(() => {
3738
if (isRenaming()) {
39+
renameCancelled = false;
3840
setRenameValue(props.item.entry.name);
3941
setTimeout(() => {
4042
inputRef?.focus();
@@ -105,6 +107,7 @@ export function VirtualItem(props: VirtualItemProps) {
105107
}
106108
} else if (e.key === "Escape") {
107109
e.preventDefault();
110+
renameCancelled = true;
108111
props.onRename(props.item.entry.path, props.item.entry.name);
109112
}
110113
return;
@@ -269,6 +272,10 @@ export function VirtualItem(props: VirtualItemProps) {
269272
onInput={(e) => setRenameValue(e.currentTarget.value)}
270273
onKeyDown={handleKeyDown}
271274
onBlur={() => {
275+
if (renameCancelled) {
276+
renameCancelled = false;
277+
return;
278+
}
272279
if (renameError()) {
273280
props.onRename(props.item.entry.path, props.item.entry.name);
274281
} else {

src/components/explorer/VirtualizedFileTree.tsx

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,19 @@ export function VirtualizedFileTree(props: VirtualizedFileTreeProps) {
5454
style={{ transform: `translateY(${tree.offsetY()}px)` }}
5555
>
5656
<For each={tree.visibleItems()}>
57-
{(item) => {
58-
const gitDecoration = tree.gitDecorationsMap().get(item.id);
59-
const isEntering = item.parentPath !== null && tree.recentlyExpandedPaths().has(item.parentPath);
60-
const isSelected = tree.selectedPathsSet().has(item.entry.path);
61-
62-
return (
57+
{(item) => (
6358
<VirtualItem
6459
item={item}
65-
isSelected={isSelected}
60+
isSelected={tree.selectedPathsSet().has(item.entry.path)}
6661
focusedPath={tree.focusedPath()}
6762
renamingPath={tree.renamingPath()}
6863
dragOverPath={tree.dragOverPath()}
6964
isDragCopy={tree.isDragCopy()}
7065
isCut={tree.isCutFile(item.entry.path)}
71-
gitDecoration={gitDecoration}
66+
gitDecoration={tree.gitDecorationsMap().get(item.id)}
7267
indentGuidesEnabled={props.indentGuidesEnabled}
7368
enablePreview={props.enablePreview}
74-
isEntering={isEntering}
69+
isEntering={item.parentPath !== null && tree.recentlyExpandedPaths().has(item.parentPath)}
7570
onSelect={tree.handleSelect}
7671
onOpen={tree.handleOpen}
7772
onOpenPreview={tree.handleOpenPreview}
@@ -86,8 +81,7 @@ export function VirtualizedFileTree(props: VirtualizedFileTreeProps) {
8681
onDrop={tree.handleDrop}
8782
onFocus={tree.setFocusedPath}
8883
/>
89-
);
90-
}}
84+
)}
9185
</For>
9286

9387
<Show when={tree.loadingDirs().size > 0}>

src/components/explorer/useFileTree.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -956,11 +956,21 @@ export function useFileTree(props: VirtualizedFileTreeProps) {
956956
break;
957957

958958
case "cut":
959-
setClipboardFiles({ paths: [entry.path], operation: 'cut' });
959+
{
960+
const pathsToCut = props.selectedPaths.length > 1 && props.selectedPaths.includes(entry.path)
961+
? [...props.selectedPaths]
962+
: [entry.path];
963+
setClipboardFiles({ paths: pathsToCut, operation: 'cut' });
964+
}
960965
break;
961966

962967
case "copy":
963-
setClipboardFiles({ paths: [entry.path], operation: 'copy' });
968+
{
969+
const pathsToCopy = props.selectedPaths.length > 1 && props.selectedPaths.includes(entry.path)
970+
? [...props.selectedPaths]
971+
: [entry.path];
972+
setClipboardFiles({ paths: pathsToCopy, operation: 'copy' });
973+
}
964974
break;
965975

966976
case "paste":

0 commit comments

Comments
 (0)