feat(project): rename Autoscroll from Source to Always Select Opened File (#1694)

Following the active editor already worked, but the option kept IDEA's pre-2023 name and sat second under Behavior, so people didn't find it (#1666). It is now Always Select Opened File, listed first, and the header's Select Opened File button hides while it's on. Find Action still matches the old name; the setting key is unchanged.

Closes #1666

Co-authored-by: jaw52 <[email protected]>
This commit is contained in:
Jaw authored and GitHub committed 2026-11-07 11:12:50 +08:00
1 parent 14a31fe8a1
commit 8ebf839d8e
10 files changed
+55 -11

No files matched your search

+12 -8
View File
@@ -29,8 +29,8 @@ export const OPTION_LABELS: Array<[ToggleOption, string]> = [
["showMembers", "Show Members"],
["compact", "Compact Middle Packages"],
["foldersFirst", "Sort Folders First"],
["autoscrollFromSource", "Always Select Opened File"],
["autoscrollToSource", "Autoscroll to Source"],
["autoscrollFromSource", "Autoscroll from Source"],
["singleClickOpen", "Open Files with Single Click"],
["singleClickExpand", "Expand Directories with Single Click"],
["previewTab", "Enable Preview Tab"],
@@ -38,15 +38,19 @@ export const OPTION_LABELS: Array<[ToggleOption, string]> = [
/** Header controls of the Project tool window (IDEA: Locate, Expand/Collapse All). */
export function ProjectHeaderActions() {
// IDEA hides Select Opened File while Always Select Opened File keeps the tree in sync.
const alwaysSelect = useProjectTree((s) => s.options.autoscrollFromSource);
return (
<>
<IconButton
icon="locate"
action="navigate.selectInProjectView"
title="Select Opened File"
shortcut={shortcutLabel("navigate.selectInProjectView")}
size="small"
/>
{!alwaysSelect && (
<IconButton
icon="locate"
action="navigate.selectInProjectView"
title="Select Opened File"
shortcut={shortcutLabel("navigate.selectInProjectView")}
size="small"
/>
)}
<IconButton icon="expand-all" action="project.expandAll" title="Expand All" size="small" />
<IconButton icon="collapse-all" action="project.collapseAll" title="Collapse All" size="small" />
</>
+34 -1
View File
@@ -14,7 +14,8 @@ import { ProjectView } from "./ProjectView";
import { beginNew, canPaste } from "./operations";
import { initProjectTree, setViewOption, useProjectTree } from "./store";
import type { OutlineItem } from "@/bindings";
import { _emitEditorEvent } from "@/editor/api";
import { _emitEditorEvent, useEditorRegistry } from "@/editor/api";
import { ProjectHeaderActions } from "./HeaderActions";
import { loadOutline } from "./store";
const ipc = vi.hoisted(() => ({
@@ -220,6 +221,38 @@ describe("ProjectView", () => {
act(() => setViewOption("previewTab", false));
});
it("follows tab switches with Always Select Opened File, hiding Select Opened File", async () => {
const focusEditor = (path: string) => act(() => useEditorRegistry.setState({ active: { ctx: { path } } } as never));
const selected = () =>
screen
.getAllByRole("treeitem")
.filter((r) => r.getAttribute("aria-selected") === "true")
.map((r) => r.textContent);
try {
render(<ProjectHeaderActions />);
const { rows } = setup();
await waitFor(() => expect(rows()).toContain("README.md"));
expect(screen.getByRole("button", { name: "Select Opened File" })).toBeTruthy();
focusEditor("/w/acme/src/Util.kt");
expect(rows()).not.toContain("Util.kt");
act(() => setViewOption("autoscrollFromSource", true));
await waitFor(() => expect(selected()).toEqual(["Util.kt"]));
expect(screen.queryByRole("button", { name: "Select Opened File" })).toBeNull();
focusEditor("/w/acme/README.md");
await waitFor(() => expect(selected()).toEqual(["README.md"]));
focusEditor("/w/acme/src/App.kt");
await waitFor(() => expect(selected()).toEqual(["App.kt"]));
act(() => setViewOption("autoscrollFromSource", false));
focusEditor("/w/acme/README.md");
expect(selected()).toEqual(["App.kt"]);
expect(screen.getByRole("button", { name: "Select Opened File" })).toBeTruthy();
} finally {
act(() => useEditorRegistry.setState({ active: null }));
}
});
it("expands and collapses folders on single click only when enabled", async () => {
const { row, rows } = setup();
await waitFor(() => expect(rows()).toContain("README.md"));
+2 -1
View File
@@ -166,7 +166,8 @@ export function registerProjectActions(): () => void {
id: `project.option.${key}`,
title: tx`Project View: ${label}`,
category: "View",
keywords: ["project", "tree", "toggle"],
// IDEA's former name of Always Select Opened File.
keywords: ["project", "tree", "toggle", ...(key === "autoscrollFromSource" ? ["autoscroll from source"] : [])],
toggled: () => useProjectTree.getState().options[key],
run: () => setViewOption(key, !useProjectTree.getState().options[key]),
}));
+1 -1
View File
@@ -38,7 +38,7 @@ import { projectViewRoots, useProjectViewRoots, type ProjectViewRootContribution
import { ancestorsWithin, isSameOrInside, nameOf, type PackageKind } from "./paths";
export interface ViewOptions extends TreeOptions {
/** Select the active editor's file in the tree. */
/** Select the active editor's file in the tree (IDEA: Always Select Opened File). */
autoscrollFromSource: boolean;
/** Open the selected file while navigating the tree (preview, no focus change). */
autoscrollToSource: boolean;
+1
View File
@@ -227,6 +227,7 @@
"Allow placing breakpoints in any file": "Permitir colocar puntos de interrupción en cualquier archivo",
"Also expand in comments and strings": "Expandir también en comentarios y cadenas",
"Always": "Siempre",
"Always Select Opened File": "Seleccionar siempre el archivo abierto",
"Always show full path in window header": "Mostrar siempre la ruta completa en el encabezado de la ventana",
"Amend": "Enmendar",
"Analysing…": "Analizando…",
+1
View File
@@ -175,6 +175,7 @@
"Allow placing breakpoints in any file": "Autoriser les points d'arrêt dans n'importe quel fichier",
"Also expand in comments and strings": "Développer aussi dans les commentaires et les chaînes",
"Always": "Toujours",
"Always Select Opened File": "Toujours sélectionner le fichier ouvert",
"Always show full path in window header": "Toujours afficher le chemin complet dans l'en-tête de la fenêtre",
"Amend": "Amender",
"Analysing…": "Analyse…",
+1
View File
@@ -267,6 +267,7 @@
"Allow placing breakpoints in any file": "모든 파일에 중단점 설정 허용",
"Also expand in comments and strings": "주석과 문자열에서도 확장",
"Always": "항상",
"Always Select Opened File": "항상 열린 파일 선택",
"Always show full path in window header": "항상 창 헤더에 전체 경로 표시",
"Amend": "수정",
"Analysing…": "분석 중…",
+1
View File
@@ -219,6 +219,7 @@
"Allow placing breakpoints in any file": "Zezwalaj na umieszczanie punktów przerwania w dowolnym pliku",
"Also expand in comments and strings": "Rozwijaj również w komentarzach i ciągach znaków",
"Always": "Zawsze",
"Always Select Opened File": "Zawsze zaznaczaj otwarty plik",
"Always show full path in window header": "Zawsze pokazuj pełną ścieżkę w nagłówku okna",
"Amend": "Popraw (Amend)",
"Analysing…": "Analizowanie…",
+1
View File
@@ -219,6 +219,7 @@
"Allow placing breakpoints in any file": "Permitir colocar pontos de interrupção em qualquer arquivo",
"Also expand in comments and strings": "Também expandir em comentários e strings",
"Always": "Sempre",
"Always Select Opened File": "Sempre selecionar o arquivo aberto",
"Always show full path in window header": "Sempre mostrar o caminho completo no cabeçalho da janela",
"Amend": "Amend",
"Analysing…": "Analisando…",
+1
View File
@@ -271,6 +271,7 @@
"Allow placing breakpoints in any file": "允许在任意文件中设置断点",
"Also expand in comments and strings": "也在注释和字符串中展开",
"Always": "始终",
"Always Select Opened File": "始终选择打开的文件",
"Always show full path in window header": "始终在窗口标题中显示完整路径",
"Amend": "修改",
"Analysing…": "正在分析…",