fix: open agent file links that carry line-range selectors (#1412)

This commit is contained in:
Clément Fiere
2026-06-17 21:32:40 +02:00
committed by GitHub
parent 67037fd936
commit a71ee2e2c1
14 changed files with 798 additions and 52 deletions
+37
View File
@@ -18,6 +18,7 @@ import type { FileContentResponse } from "@/lib/types/backend";
import { useSaveDeleteActions } from "./use-file-save-delete";
import { PREVIEW_FILE_EDITOR_ID } from "@/lib/state/dockview-panel-actions";
import { useOpenFileWorkspaceSync } from "./file-editors-sync";
import { getMonacoInstance } from "@/components/editors/monaco/monaco-init";
// Module-level guard: ensures restoration only runs once across all hook instances
let _restoredSessionId: string | null = null;
@@ -39,6 +40,42 @@ export function consumePendingCursorPosition(
return pos;
}
/**
* Scroll an already-mounted Monaco editor for `path` to the given position.
* Returns true if an editor was found and scrolled. The editor's model URI is
* built as `${worktreePath}/${path}` (see use-monaco-editor-lsp), so the same
* `path` used for setPendingCursorPosition resolves the right editor here.
*
* Used for the already-open case: when a file link is clicked but its tab is
* already open, no editor mounts, so handleEditorDidMount never consumes the
* pending position — this scrolls the live editor instead (and consumes the
* pending entry so a later remount doesn't double-apply it).
*/
export function scrollEditorIfMounted(
path: string,
worktreePath: string | null,
line: number,
column: number,
): boolean {
const monaco = getMonacoInstance();
if (!monaco) return false;
const monacoPath = worktreePath ? `${worktreePath}/${path}` : path;
for (const editor of monaco.editor.getEditors()) {
const model = editor.getModel();
if (!model) continue;
const modelPath = model.uri.path;
if (modelPath === `/${monacoPath}` || modelPath === monacoPath) {
consumePendingCursorPosition(path);
editor.setPosition({ lineNumber: line, column });
editor.revealLineInCenter(line);
editor.focus();
return true;
}
}
return false;
}
/** Read openFiles from the store without subscribing to changes. */
function getOpenFiles() {
return useDockviewStore.getState().openFiles;
+1 -34
View File
@@ -5,42 +5,9 @@ import { useAppStore } from "@/components/state-provider";
import {
useFileEditors,
setPendingCursorPosition,
consumePendingCursorPosition,
scrollEditorIfMounted,
} from "@/hooks/use-file-editors";
import { lspClientManager } from "@/lib/lsp/lsp-client-manager";
import { getMonacoInstance } from "@/components/editors/monaco/monaco-init";
/**
* Try to scroll an already-mounted editor to the given position.
* Returns true if the editor was found and scrolled, false otherwise.
* If successful, consumes the pending cursor position so handleEditorDidMount
* doesn't double-apply it.
*/
function scrollEditorIfMounted(
relativePath: string,
worktreePath: string | null,
line: number,
column: number,
): boolean {
const monaco = getMonacoInstance();
if (!monaco) return false;
const monacoPath = worktreePath ? `${worktreePath}/${relativePath}` : relativePath;
for (const editor of monaco.editor.getEditors()) {
const model = editor.getModel();
if (!model) continue;
const modelPath = model.uri.path;
if (modelPath === `/${monacoPath}` || modelPath === monacoPath) {
consumePendingCursorPosition(relativePath);
editor.setPosition({ lineNumber: line, column });
editor.revealLineInCenter(line);
editor.focus();
return true;
}
}
return false;
}
/**
* Connects LSP Go-to-Definition / Find References navigation to dockview file tabs.