From 8ebf839d8e7360db8204df9364a150eb107495a0 Mon Sep 17 00:00:00 2001
From: Jaw <53564781+jaw52@users.noreply.github.com>
Date: Sat, 7 Nov 2026 11:12:50 +0800
Subject: [PATCH] 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 <53564781+jaw52@users.noreply.github.com>
---
src/features/project-tree/HeaderActions.tsx | 20 ++++++-----
.../project-tree/ProjectView.test.tsx | 35 ++++++++++++++++++-
src/features/project-tree/actions.ts | 3 +-
src/features/project-tree/store.ts | 2 +-
src/platform/locales/text/es.json | 1 +
src/platform/locales/text/fr.json | 1 +
src/platform/locales/text/ko.json | 1 +
src/platform/locales/text/pl.json | 1 +
src/platform/locales/text/pt.json | 1 +
src/platform/locales/text/zh.json | 1 +
10 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/src/features/project-tree/HeaderActions.tsx b/src/features/project-tree/HeaderActions.tsx
index 4c979fc0..a7296361 100644
--- a/src/features/project-tree/HeaderActions.tsx
+++ b/src/features/project-tree/HeaderActions.tsx
@@ -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 (
<>
-
+ {!alwaysSelect && (
+
+ )}
>
diff --git a/src/features/project-tree/ProjectView.test.tsx b/src/features/project-tree/ProjectView.test.tsx
index 2e588057..1822a795 100644
--- a/src/features/project-tree/ProjectView.test.tsx
+++ b/src/features/project-tree/ProjectView.test.tsx
@@ -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();
+ 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"));
diff --git a/src/features/project-tree/actions.ts b/src/features/project-tree/actions.ts
index 5e02d211..77f604b6 100644
--- a/src/features/project-tree/actions.ts
+++ b/src/features/project-tree/actions.ts
@@ -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]),
}));
diff --git a/src/features/project-tree/store.ts b/src/features/project-tree/store.ts
index 3b51e349..8619341c 100644
--- a/src/features/project-tree/store.ts
+++ b/src/features/project-tree/store.ts
@@ -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;
diff --git a/src/platform/locales/text/es.json b/src/platform/locales/text/es.json
index 442e2260..ec1d5d60 100644
--- a/src/platform/locales/text/es.json
+++ b/src/platform/locales/text/es.json
@@ -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…",
diff --git a/src/platform/locales/text/fr.json b/src/platform/locales/text/fr.json
index 057fe0ee..fb9398f3 100644
--- a/src/platform/locales/text/fr.json
+++ b/src/platform/locales/text/fr.json
@@ -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…",
diff --git a/src/platform/locales/text/ko.json b/src/platform/locales/text/ko.json
index 89da00ab..847280f0 100644
--- a/src/platform/locales/text/ko.json
+++ b/src/platform/locales/text/ko.json
@@ -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…": "분석 중…",
diff --git a/src/platform/locales/text/pl.json b/src/platform/locales/text/pl.json
index ecc1d63e..dff586ba 100644
--- a/src/platform/locales/text/pl.json
+++ b/src/platform/locales/text/pl.json
@@ -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…",
diff --git a/src/platform/locales/text/pt.json b/src/platform/locales/text/pt.json
index 5db18741..81f418cf 100644
--- a/src/platform/locales/text/pt.json
+++ b/src/platform/locales/text/pt.json
@@ -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…",
diff --git a/src/platform/locales/text/zh.json b/src/platform/locales/text/zh.json
index d2de7cb8..663bef61 100644
--- a/src/platform/locales/text/zh.json
+++ b/src/platform/locales/text/zh.json
@@ -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…": "正在分析…",