Add Open Diff button to open VS Code's native side-by-side diff editor

- Add _openDiffEditor method using vscode.diff command
- Store temp files in extension's storageUri instead of workspace
- Clean up temp files when diff editor is closed
- Force side-by-side mode when opening diff
- Add Open Diff button with red/green icon in summary row

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
andrepimenta
2025-12-01 16:20:11 +00:00
parent 2b1ad70f6b
commit 6c37394015
3 changed files with 157 additions and 6 deletions

View File

@@ -297,6 +297,9 @@ class ClaudeChatProvider {
case 'openFile':
this._openFileInEditor(message.filePath);
return;
case 'openDiff':
this._openDiffEditor(message.oldContent, message.newContent, message.filePath);
return;
case 'createImageFile':
this._createImageFile(message.imageData, message.imageType);
return;
@@ -2340,6 +2343,74 @@ class ClaudeChatProvider {
}
}
private async _openDiffEditor(oldContent: string, newContent: string, filePath: string) {
try {
const storageUri = this._context.storageUri;
if (!storageUri) {
vscode.window.showErrorMessage('No storage location available');
return;
}
const baseName = path.basename(filePath);
const ext = path.extname(filePath);
const nameWithoutExt = baseName.slice(0, -ext.length) || baseName;
const timestamp = Date.now();
// Create temp files in extension's storage directory
const tempDirUri = vscode.Uri.joinPath(storageUri, 'diff-temp');
// Ensure temp directory exists
try {
await vscode.workspace.fs.createDirectory(tempDirUri);
} catch {
// Directory might already exist, ignore error
}
const oldUri = vscode.Uri.joinPath(tempDirUri, `${nameWithoutExt}.old.${timestamp}${ext}`);
const newUri = vscode.Uri.joinPath(tempDirUri, `${nameWithoutExt}.new.${timestamp}${ext}`);
// Write content to temp files using VS Code filesystem API
await vscode.workspace.fs.writeFile(oldUri, Buffer.from(oldContent, 'utf8'));
await vscode.workspace.fs.writeFile(newUri, Buffer.from(newContent, 'utf8'));
// Ensure side-by-side diff mode is enabled
const diffConfig = vscode.workspace.getConfiguration('diffEditor');
const wasInlineMode = diffConfig.get('renderSideBySide') === false;
if (wasInlineMode) {
await diffConfig.update('renderSideBySide', true, vscode.ConfigurationTarget.Global);
}
// Open diff editor
await vscode.commands.executeCommand('vscode.diff', oldUri, newUri, `${baseName} (Changes)`);
// Track which files need to be cleaned up
const filesToCleanup = new Set([oldUri.toString(), newUri.toString()]);
// Listen for document close events to clean up temp files
const closeListener = vscode.workspace.onDidCloseTextDocument(async (doc) => {
if (filesToCleanup.has(doc.uri.toString())) {
filesToCleanup.delete(doc.uri.toString());
try {
await vscode.workspace.fs.delete(doc.uri, { useTrash: false });
} catch {
// File might already be deleted, ignore
}
// Dispose listener when both files are cleaned up
if (filesToCleanup.size === 0) {
closeListener.dispose();
}
}
});
// Also add to disposables to clean up on extension deactivate
this._disposables.push(closeListener);
} catch (error) {
vscode.window.showErrorMessage(`Failed to open diff editor: ${error}`);
console.error('Error opening diff editor:', error);
}
}
private async _createImageFile(imageData: string, imageType: string) {
try {
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];