feat: 逐次编辑导航 + 状态栏增强 + 依赖更新

- 新增 nextEdit/prevEdit/showEditAtIndex 命令支持逐次查看编辑
- DiffViewer 增加 editIndex/totalEdits 跟踪编辑进度
- StatusBar 增加编辑计数和逐次导航按钮
- SnapshotManager 改进 EditRecord 粒度的 accept/reject
- HookHandler 支持多次编辑的二级选择(聚合/逐次)
- 更新 package.json 依赖(esbuild win32-x64)
- 将 .claude/hooks/ 加入 .gitignore
- 删除测试.md
This commit is contained in:
2026-06-24 18:09:19 +08:00
parent fa44163ca3
commit 122c38c51e
9 changed files with 237 additions and 128 deletions
+63 -2
View File
@@ -19,6 +19,10 @@ import { ChangeSetManager } from '../snapshot/snapshotManager';
export interface DiffSession {
fileId: string;
editId?: string;
/** ★ 当前查看的编辑索引(undefined 表示聚合视图) */
editIndex?: number;
/** ★ 当前文件的总编辑数 */
totalEdits?: number;
beforeTmpPath: string;
afterTmpPath: string;
beforeUri: vscode.Uri;
@@ -65,7 +69,7 @@ export class DiffViewer {
'vscode.diff',
this.activeSession!.beforeUri,
this.activeSession!.afterUri,
`${fileName} — AI ${toolLabel} #${editRecord.id.slice(0, 6)} · 状态栏操作`
`${fileName} — AI ${toolLabel} · 编辑 #${editRecord.id.slice(0, 6)}`
);
this.isOpening = false;
@@ -92,7 +96,7 @@ export class DiffViewer {
'vscode.diff',
this.activeSession!.beforeUri,
this.activeSession!.afterUri,
`${fileName} — ${fileChange.edits.length} 次 AI 编辑 · 状态栏操作`
`${fileName} — 聚合视图 (${fileChange.edits.length} 次编辑)`
);
this.isOpening = false;
@@ -112,6 +116,63 @@ export class DiffViewer {
else vscode.window.showInformationMessage('AI Diff: 当前文件无待处理变更');
}
// ---- ★ 逐次编辑导航 ----
/** 显示文件的第 N 次编辑的 diff */
async showEditAtIndex(fileChange: FileChange, editIndex: number): Promise<void> {
if (editIndex < 0 || editIndex >= fileChange.edits.length) return;
const edit = fileChange.edits[editIndex];
await this.showEditDiff(edit, fileChange.id);
// ★ 更新 session 的编辑索引信息
if (this.activeSession) {
this.activeSession.editIndex = editIndex;
this.activeSession.totalEdits = fileChange.edits.length;
}
this.onDiffAction?.();
}
/** 显示下一次编辑 */
async showNextEdit(): Promise<void> {
if (!this.activeSession) return;
const { fileId, editIndex } = this.activeSession;
if (editIndex === undefined) return;
const fc = this.findFileChange(fileId);
if (!fc) return;
const nextIdx = editIndex + 1;
if (nextIdx < fc.edits.length) {
await this.showEditAtIndex(fc, nextIdx);
} else {
vscode.window.showInformationMessage(`AI Diff: 已是最后一次编辑 (${fc.edits.length}/${fc.edits.length})`);
}
}
/** 显示上一次编辑 */
async showPrevEdit(): Promise<void> {
if (!this.activeSession) return;
const { fileId, editIndex } = this.activeSession;
if (editIndex === undefined) return;
const fc = this.findFileChange(fileId);
if (!fc) return;
const prevIdx = editIndex - 1;
if (prevIdx >= 0) {
await this.showEditAtIndex(fc, prevIdx);
} else {
vscode.window.showInformationMessage('AI Diff: 已是第一次编辑 (1)');
}
}
/** 切换到聚合视图(查看文件整体 diff) */
async showAggregatedDiff(): Promise<void> {
if (!this.activeSession) return;
const fc = this.findFileChange(this.activeSession.fileId);
if (fc) await this.showFileDiff(fc);
}
private findFileChange(fileId: string): FileChange | undefined {
const set = this.changeSetManager.getCurrentSet();
return set?.changes.find(c => c.id === fileId);
}
// ---- Accept/Reject(Accept/Reject 后删除临时文件 + 关闭 Diff) ----
async acceptCurrentDiff(): Promise<void> {
+40 -1
View File
@@ -19,6 +19,10 @@ export class StatusBarManager {
private acceptBtn: vscode.StatusBarItem;
/** Diff 模式 Reject 按钮(拒绝当前文件所有变更) */
private rejectBtn: vscode.StatusBarItem;
/** ★ 上一次编辑按钮 */
private prevEditBtn: vscode.StatusBarItem;
/** ★ 下一次编辑按钮 */
private nextEditBtn: vscode.StatusBarItem;
constructor(
private changeSetManager: ChangeSetManager,
@@ -38,9 +42,19 @@ export class StatusBarManager {
// Reject 按钮(拒绝当前文件所有变更)
this.rejectBtn = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 99);
this.rejectBtn.command = 'aiDiffPreview.rejectCurrentDiff';
// ★ 上一次编辑按钮
this.prevEditBtn = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 98);
this.prevEditBtn.command = 'aiDiffPreview.prevEdit';
this.prevEditBtn.tooltip = '上一次编辑 (Alt+Left)';
// ★ 下一次编辑按钮
this.nextEditBtn = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 97);
this.nextEditBtn.command = 'aiDiffPreview.nextEdit';
this.nextEditBtn.tooltip = '下一次编辑 (Alt+Right)';
}
enterDiffMode(_session: DiffSession): void {
enterDiffMode(session: DiffSession): void {
this.acceptBtn.text = '$(check) Accept';
this.acceptBtn.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground');
this.acceptBtn.tooltip = '接受此文件所有变更';
@@ -50,11 +64,34 @@ export class StatusBarManager {
this.rejectBtn.backgroundColor = new vscode.ThemeColor('statusBarItem.errorBackground');
this.rejectBtn.tooltip = '拒绝此文件所有变更';
this.rejectBtn.show();
// ★ 根据 session 状态显示编辑导航按钮
if (session.editIndex !== undefined && session.totalEdits !== undefined) {
// 逐次编辑模式:显示 Prev/Next 和计数
this.prevEditBtn.text = `$(arrow-left) ${session.editIndex + 1}/${session.totalEdits}`;
this.prevEditBtn.command = 'aiDiffPreview.prevEdit';
this.prevEditBtn.tooltip = `上一次编辑 (Alt+Left) — 当前第 ${session.editIndex + 1}/${session.totalEdits} 次`;
this.prevEditBtn.show();
this.nextEditBtn.text = '$(arrow-right)';
this.nextEditBtn.command = 'aiDiffPreview.nextEdit';
this.nextEditBtn.tooltip = '下一次编辑 (Alt+Right)';
this.nextEditBtn.show();
} else {
// 聚合视图模式:显示"逐次查看"入口
this.prevEditBtn.text = '$(list-ordered) 逐次查看';
this.prevEditBtn.command = 'aiDiffPreview.showEditAtIndex';
this.prevEditBtn.tooltip = '切换到逐次编辑查看模式';
this.prevEditBtn.show();
this.nextEditBtn.hide();
}
}
exitDiffMode(): void {
this.acceptBtn.hide();
this.rejectBtn.hide();
this.prevEditBtn.hide();
this.nextEditBtn.hide();
}
/** ★ 常驻刷新 */
@@ -98,5 +135,7 @@ export class StatusBarManager {
this.summaryItem.dispose();
this.acceptBtn.dispose();
this.rejectBtn.dispose();
this.prevEditBtn.dispose();
this.nextEditBtn.dispose();
}
}