feat: implement DnD roadmap Step 3 - editor path injection
This commit is contained in:
+32
-40
@@ -157,6 +157,23 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
case 'proactiveTrigger':
|
||||
await this._handleProactiveSuggestion(data.context);
|
||||
break;
|
||||
case 'filesDropped':
|
||||
// ⭐ Roadmap Step 3: 핵심 데이터 변환 및 에디터 주입
|
||||
if (data.paths && data.paths.length > 0) {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
// 1. URI 변환 (크로스 플랫폼 호환성 보장)
|
||||
const uris = data.paths.map((p: string) => vscode.Uri.file(p));
|
||||
const formattedText = uris.map(u => u.fsPath).join('\n');
|
||||
|
||||
// 2. 에디터 API를 통한 주입
|
||||
await editor.edit(editBuilder => {
|
||||
editBuilder.insert(editor.selection.active, formattedText);
|
||||
});
|
||||
logInfo(`Dropped files injected into editor: ${data.paths.length} files`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'exportResponse':
|
||||
const workspacePath = vscode.workspace.workspaceFolders?.[0].uri.fsPath || '';
|
||||
const defaultPath = path.join(workspacePath, 'g1_response.md');
|
||||
@@ -1049,8 +1066,6 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
position: relative; /* Toast 위치 앙커 */
|
||||
}
|
||||
.input-box:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
|
||||
.input-box.is-dragging { border-color: var(--accent); background: rgba(88, 166, 255, 0.05); border-style: dashed; }
|
||||
|
||||
|
||||
textarea {
|
||||
width: 100%; background: transparent; border: none; color: var(--text-bright);
|
||||
@@ -1356,9 +1371,8 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
<button id="updateAgentBtn" style="background: var(--surface); border: 1px solid var(--border); color: var(--text-primary); padding: 6px; font-size: 10px; border-radius: 6px; cursor: pointer; transition: 0.2s;">Update Agent Skill</button>
|
||||
</div>
|
||||
<div class="input-box" id="inputBox">
|
||||
<div class="input-box">
|
||||
<div id="attachPreview" class="attachment-preview"></div>
|
||||
<div id="pathDisplay" style="font-size: 10px; color: var(--text-dim); padding: 4px 8px; border-bottom: 1px solid var(--border); display: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"></div>
|
||||
<textarea id="input" rows="1" placeholder="Type your request..."></textarea>
|
||||
<div class="input-footer">
|
||||
<div class="footer-left">
|
||||
@@ -1388,8 +1402,6 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
const sendBtn = document.getElementById('sendBtn');
|
||||
const stopBtn = document.getElementById('stopBtn');
|
||||
const cancelBtn = document.getElementById('cancelBtn');
|
||||
const inputBox = document.getElementById('inputBox');
|
||||
const pathDisplay = document.getElementById('pathDisplay');
|
||||
const toastNotif = document.getElementById('toastNotif');
|
||||
const thinkingBar = document.getElementById('thinkingBar');
|
||||
const statusLabel = document.getElementById('statusLabel');
|
||||
@@ -1731,24 +1743,13 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
function renderAttachments() {
|
||||
attachPreview.innerHTML = '';
|
||||
const paths = [];
|
||||
|
||||
if (pendingFiles.length > 0) {
|
||||
attachPreview.classList.add('visible');
|
||||
pathDisplay.style.display = 'block';
|
||||
pendingFiles.forEach((f, idx) => {
|
||||
const chip = document.createElement('div');
|
||||
chip.className = 'file-chip';
|
||||
const sizeStr = f.size ? \`(\${f.size} KB)\` : '';
|
||||
chip.innerHTML = \`<span>📎</span> \${f.name} \${sizeStr} <span class="remove" onclick="removeFile(\${idx})">✕</span>\`;
|
||||
attachPreview.appendChild(chip);
|
||||
paths.push(\`\${f.name} \${sizeStr}\`);
|
||||
});
|
||||
pathDisplay.textContent = '📂 ' + paths.join(' | ');
|
||||
} else {
|
||||
attachPreview.classList.remove('visible');
|
||||
pathDisplay.style.display = 'none';
|
||||
}
|
||||
if (pendingFiles.length === 0) { attachPreview.classList.remove('visible'); return; }
|
||||
attachPreview.classList.add('visible');
|
||||
pendingFiles.forEach((f, i) => {
|
||||
const chip = document.createElement('div'); chip.className = 'file-chip';
|
||||
chip.innerHTML = \`<span>📎</span> \${f.name} <span class="remove" onclick="removeFile(\${i})">✕</span>\`;
|
||||
attachPreview.appendChild(chip);
|
||||
});
|
||||
}
|
||||
window.removeFile = (i) => {
|
||||
pendingFiles.splice(i, 1);
|
||||
@@ -1761,15 +1762,9 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
Array.from(files).forEach(file => {
|
||||
const reader = new FileReader();
|
||||
const sizeKB = (file.size / 1024).toFixed(1);
|
||||
reader.onload = () => {
|
||||
const base64 = reader.result.split(',')[1];
|
||||
pendingFiles.push({
|
||||
name: file.name,
|
||||
type: file.type,
|
||||
size: sizeKB,
|
||||
data: base64
|
||||
});
|
||||
pendingFiles.push({ name: file.name, type: file.type, data: base64 });
|
||||
renderAttachments();
|
||||
setDraftActive(true);
|
||||
};
|
||||
@@ -1802,18 +1797,9 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
['dragleave', 'drop'].forEach(eventName => {
|
||||
document.body.addEventListener(eventName, () => {
|
||||
document.body.classList.remove('drag-over');
|
||||
inputBox.classList.remove('is-dragging');
|
||||
}, false);
|
||||
});
|
||||
|
||||
// 입력 박스 자체의 시각적 피드백
|
||||
inputBox.addEventListener('dragover', () => {
|
||||
inputBox.classList.add('is-dragging');
|
||||
}, false);
|
||||
inputBox.addEventListener('dragleave', () => {
|
||||
inputBox.classList.remove('is-dragging');
|
||||
}, false);
|
||||
|
||||
document.body.addEventListener('drop', e => {
|
||||
const dt = e.dataTransfer;
|
||||
const files = dt.files;
|
||||
@@ -1822,6 +1808,12 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
if (files && files.length > 0) {
|
||||
fileInput.files = files; // Input의 files 속성 업데이트
|
||||
console.log(\`✅ [DnD] Input 상태 동기화 성공: \${files[0].name} 외 \${files.length - 1}개\`);
|
||||
|
||||
// ⭐ Roadmap Step 2: 브릿지 전송 (경로 데이터를 확장 프로그램으로 전달)
|
||||
const paths = Array.from(files).map(f => (f as any).path).filter(p => !!p);
|
||||
if (paths.length > 0) {
|
||||
vscode.postMessage({ type: 'filesDropped', paths: paths });
|
||||
}
|
||||
}
|
||||
|
||||
processFiles(files);
|
||||
|
||||
Reference in New Issue
Block a user