mirror of
https://github.com/andrepimenta/claude-code-chat.git
synced 2025-12-13 13:49:47 +00:00
Allow copy paste images and screenshots
This commit is contained in:
@@ -234,6 +234,9 @@ class ClaudeChatProvider {
|
|||||||
case 'openFile':
|
case 'openFile':
|
||||||
this._openFileInEditor(message.filePath);
|
this._openFileInEditor(message.filePath);
|
||||||
return;
|
return;
|
||||||
|
case 'createImageFile':
|
||||||
|
this._createImageFile(message.imageData, message.imageType);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
@@ -1406,6 +1409,44 @@ class ClaudeChatProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _createImageFile(imageData: string, imageType: string) {
|
||||||
|
try {
|
||||||
|
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||||
|
if (!workspaceFolder) {return;}
|
||||||
|
|
||||||
|
// Extract base64 data from data URL
|
||||||
|
const base64Data = imageData.split(',')[1];
|
||||||
|
const buffer = Buffer.from(base64Data, 'base64');
|
||||||
|
|
||||||
|
// Get file extension from image type
|
||||||
|
const extension = imageType.split('/')[1] || 'png';
|
||||||
|
|
||||||
|
// Create unique filename with timestamp
|
||||||
|
const timestamp = Date.now();
|
||||||
|
const imageFileName = `image_${timestamp}.${extension}`;
|
||||||
|
|
||||||
|
// Create images folder in workspace .vscode directory
|
||||||
|
const imagesDir = vscode.Uri.joinPath(workspaceFolder.uri, '.vscode', 'claude-code-chat-images');
|
||||||
|
await vscode.workspace.fs.createDirectory(imagesDir);
|
||||||
|
|
||||||
|
// Create the image file
|
||||||
|
const imagePath = vscode.Uri.joinPath(imagesDir, imageFileName);
|
||||||
|
await vscode.workspace.fs.writeFile(imagePath, buffer);
|
||||||
|
|
||||||
|
// Send the file path back to webview
|
||||||
|
this._panel?.webview.postMessage({
|
||||||
|
type: 'imagePath',
|
||||||
|
data: {
|
||||||
|
filePath: imagePath.fsPath
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating image file:', error);
|
||||||
|
vscode.window.showErrorMessage('Failed to create image file');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
if (this._panel) {
|
if (this._panel) {
|
||||||
this._panel.dispose();
|
this._panel.dispose();
|
||||||
|
|||||||
67
src/ui.ts
67
src/ui.ts
@@ -1299,6 +1299,44 @@ const html = `<!DOCTYPE html>
|
|||||||
try {
|
try {
|
||||||
// Try to get clipboard data from the event first
|
// Try to get clipboard data from the event first
|
||||||
const clipboardData = e.clipboardData;
|
const clipboardData = e.clipboardData;
|
||||||
|
|
||||||
|
// Check for images first
|
||||||
|
if (clipboardData && clipboardData.items) {
|
||||||
|
let hasImage = false;
|
||||||
|
for (let i = 0; i < clipboardData.items.length; i++) {
|
||||||
|
const item = clipboardData.items[i];
|
||||||
|
if (item.type.startsWith('image/')) {
|
||||||
|
// Found an image, handle it
|
||||||
|
console.log('Image detected in clipboard:', item.type);
|
||||||
|
hasImage = true;
|
||||||
|
const blob = item.getAsFile();
|
||||||
|
if (blob) {
|
||||||
|
console.log('Converting image blob to base64...');
|
||||||
|
// Convert blob to base64
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function(event) {
|
||||||
|
const base64Data = event.target.result;
|
||||||
|
console.log('Sending image to extension for file creation');
|
||||||
|
// Send to extension to create file
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'createImageFile',
|
||||||
|
imageData: base64Data,
|
||||||
|
imageType: item.type
|
||||||
|
});
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
}
|
||||||
|
break; // Process only the first image found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found an image, don't process any text
|
||||||
|
if (hasImage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No image found, handle text
|
||||||
let text = '';
|
let text = '';
|
||||||
|
|
||||||
if (clipboardData) {
|
if (clipboardData) {
|
||||||
@@ -1771,6 +1809,35 @@ const html = `<!DOCTYPE html>
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'imagePath':
|
||||||
|
// Handle image file path response
|
||||||
|
if (message.data.filePath) {
|
||||||
|
// Get current cursor position and content
|
||||||
|
const cursorPosition = messageInput.selectionStart || messageInput.value.length;
|
||||||
|
const currentValue = messageInput.value || '';
|
||||||
|
|
||||||
|
// Insert the file path at the current cursor position
|
||||||
|
const textBefore = currentValue.substring(0, cursorPosition);
|
||||||
|
const textAfter = currentValue.substring(cursorPosition);
|
||||||
|
|
||||||
|
// Add a space before the path if there's text before and it doesn't end with whitespace
|
||||||
|
const separator = (textBefore && !textBefore.endsWith(' ') && !textBefore.endsWith('\\n')) ? ' ' : '';
|
||||||
|
|
||||||
|
messageInput.value = textBefore + separator + message.data.filePath + textAfter;
|
||||||
|
|
||||||
|
// Move cursor to end of inserted path
|
||||||
|
const newCursorPosition = cursorPosition + separator.length + message.data.filePath.length;
|
||||||
|
messageInput.setSelectionRange(newCursorPosition, newCursorPosition);
|
||||||
|
|
||||||
|
// Focus back on textarea and adjust height
|
||||||
|
messageInput.focus();
|
||||||
|
adjustTextareaHeight();
|
||||||
|
|
||||||
|
console.log('Inserted image path:', message.data.filePath);
|
||||||
|
console.log('Full textarea value:', messageInput.value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'updateTokens':
|
case 'updateTokens':
|
||||||
console.log('Tokens updated in real-time:', message.data);
|
console.log('Tokens updated in real-time:', message.data);
|
||||||
// Update token totals in real-time
|
// Update token totals in real-time
|
||||||
|
|||||||
Reference in New Issue
Block a user