From 23337a2aefa421d646839498861739c523b222b3 Mon Sep 17 00:00:00 2001 From: Gmaker689 <1711322114@qq.com> Date: Thu, 18 Jun 2026 21:31:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Diff=E6=89=93=E5=BC=80=E5=90=8E=E7=AB=8B?= =?UTF-8?q?=E5=8D=B3=E8=A7=A6=E5=8F=91=E7=8A=B6=E6=80=81=E6=A0=8F=E5=88=B7?= =?UTF-8?q?=E6=96=B0=20+=20=E4=B8=B4=E6=97=B6=E6=96=87=E4=BB=B6=E5=8F=AA?= =?UTF-8?q?=E5=9C=A8Accept/Reject=E6=97=B6=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/render/diffViewer.ts | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/render/diffViewer.ts b/src/render/diffViewer.ts index 29d673f..b3e25f9 100644 --- a/src/render/diffViewer.ts +++ b/src/render/diffViewer.ts @@ -30,6 +30,7 @@ export class DiffViewer { private tmpFiles: string[] = []; /** ★ 原子锁:Diff 正在打开中,禁止清除 session */ private isOpening = false; + private closeListener: vscode.Disposable | null = null; /** 外部回调:Diff 操作完成后通知(用于刷新 UI) */ onDiffAction?: () => void; @@ -51,19 +52,19 @@ export class DiffViewer { const afterPath = this.makeTmpFile(`ai-diff-after-${editRecord.id.slice(0, 8)}${ext}`, editRecord.afterContent); this.isOpening = true; - this.activeSession = { + this.setSession({ fileId: fileChangeId, editId: editRecord.id, beforeTmpPath: beforePath, afterTmpPath: afterPath, beforeUri: vscode.Uri.file(beforePath), afterUri: vscode.Uri.file(afterPath), - }; + }); await vscode.commands.executeCommand( 'vscode.diff', - this.activeSession.beforeUri, - this.activeSession.afterUri, + this.activeSession!.beforeUri, + this.activeSession!.afterUri, `${fileName} — AI ${toolLabel} #${editRecord.id.slice(0, 6)} · 状态栏操作` ); @@ -79,18 +80,18 @@ export class DiffViewer { const afterPath = this.makeTmpFile(`ai-diff-after-${fileChange.id.slice(0, 8)}${ext}`, fileChange.latestContent); this.isOpening = true; - this.activeSession = { + this.setSession({ fileId: fileChange.id, beforeTmpPath: beforePath, afterTmpPath: afterPath, beforeUri: vscode.Uri.file(beforePath), afterUri: vscode.Uri.file(afterPath), - }; + }); await vscode.commands.executeCommand( 'vscode.diff', - this.activeSession.beforeUri, - this.activeSession.afterUri, + this.activeSession!.beforeUri, + this.activeSession!.afterUri, `${fileName} — ${fileChange.edits.length} 次 AI 编辑 · 状态栏操作` ); @@ -188,11 +189,31 @@ export class DiffViewer { if (this.activeSession) { try { await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); } catch { /* ok */ } } - this.activeSession = null; + this.clearSession(); } // ---- 内部 ---- + private setSession(session: DiffSession): void { + this.clearSession(); + this.activeSession = session; + // ★ isOpening 锁保护:只有非 opening 状态下的关闭才清除 session + this.closeListener = vscode.window.onDidChangeVisibleTextEditors(() => { + if (this.isOpening) return; // ← 打开中,不检测 + if (!this.activeSession) return; + const stillOpen = vscode.window.visibleTextEditors.some( + e => e.document.uri.toString() === this.activeSession!.beforeUri.toString() || + e.document.uri.toString() === this.activeSession!.afterUri.toString() + ); + if (!stillOpen) this.clearSession(); + }); + } + + private clearSession(): void { + this.activeSession = null; + if (this.closeListener) { this.closeListener.dispose(); this.closeListener = null; } + } + private makeTmpFile(name: string, content: string): string { const dir = path.join(os.tmpdir(), 'ai-diff-preview'); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });