vg-coder-cli 2.0.33 → 2.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/vg-coder-bundle.js +3 -3
- package/package.json +2 -3
- package/src/server/api-server.js +111 -0
- package/src/server/views/css/commands-panel.css +75 -0
- package/src/server/views/css/editor.css +1 -1
- package/src/server/views/css/git-panel.css +361 -0
- package/src/server/views/css/git-view.css +1 -77
- package/src/server/views/css/project-panel.css +242 -0
- package/src/server/views/css/tool-window.css +267 -0
- package/src/server/views/dashboard.css +1 -1
- package/src/server/views/dashboard.html +59 -102
- package/src/server/views/js/api.js +13 -0
- package/src/server/views/js/event-protocol.js +1 -0
- package/src/server/views/js/features/bubble-features/copy-prompt-feature.js +14 -0
- package/src/server/views/js/features/bubble-features/index.js +6 -1
- package/src/server/views/js/features/commands-panel.js +63 -0
- package/src/server/views/js/features/git-panel.js +481 -0
- package/src/server/views/js/features/git-view.js +79 -307
- package/src/server/views/js/features/project-panel.js +452 -0
- package/src/server/views/js/features/resize.js +7 -10
- package/src/server/views/js/features/tool-window.js +148 -0
- package/src/server/views/js/handlers.js +11 -0
- package/src/server/views/js/main.js +13 -31
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
import { getGitStatus, getGitDiff, stageFile, unstageFile, commitChanges, discardChange, gitPush } from '../api.js';
|
|
2
|
+
import { showToast, getById, qsa } from '../utils.js';
|
|
3
|
+
|
|
4
|
+
let currentStaged = [];
|
|
5
|
+
let currentChanges = [];
|
|
6
|
+
let isInitialized = false;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Initialize Git Panel
|
|
10
|
+
*/
|
|
11
|
+
export function initGitPanel() {
|
|
12
|
+
// Listen for panel open events
|
|
13
|
+
document.addEventListener('tool-panel-opened', (event) => {
|
|
14
|
+
if (event.detail.panelId === 'git') {
|
|
15
|
+
if (!isInitialized) {
|
|
16
|
+
renderGitPanel();
|
|
17
|
+
isInitialized = true;
|
|
18
|
+
}
|
|
19
|
+
loadGitData();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Listen for project switched to reload git data
|
|
24
|
+
window.addEventListener('project-switched', (e) => {
|
|
25
|
+
console.log('[GitPanel] 🔄 Project switched event detected:', e.detail);
|
|
26
|
+
|
|
27
|
+
// Wait a bit for backend to switch project context
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
// Reload git data for new project if panel has been rendered
|
|
30
|
+
const gitPanelContent = getById('git-panel-content');
|
|
31
|
+
if (gitPanelContent && gitPanelContent.innerHTML.trim() !== '') {
|
|
32
|
+
console.log('[GitPanel] ✅ Git panel is visible, reloading git data for new project...');
|
|
33
|
+
loadGitData();
|
|
34
|
+
} else {
|
|
35
|
+
console.log('[GitPanel] ⏭️ Git panel not rendered yet, will load when opened');
|
|
36
|
+
}
|
|
37
|
+
}, 200); // Small delay to ensure backend has switched context
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Listen for refresh button in panel header
|
|
41
|
+
const refreshBtn = getById('git-panel-refresh-btn');
|
|
42
|
+
if (refreshBtn) {
|
|
43
|
+
refreshBtn.addEventListener('click', loadGitData);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log('[GitPanel] Initialized');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Render Git Panel UI structure
|
|
51
|
+
*/
|
|
52
|
+
function renderGitPanel() {
|
|
53
|
+
const container = getById('git-panel-content');
|
|
54
|
+
if (!container) return;
|
|
55
|
+
|
|
56
|
+
container.innerHTML = `
|
|
57
|
+
<div class="git-panel-commit-section">
|
|
58
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
|
|
59
|
+
<span style="font-size:11px;font-weight:bold;color:#8b949e;text-transform:uppercase;">Commit</span>
|
|
60
|
+
<button id="git-panel-push-btn" class="git-panel-push-btn" title="Push to remote">
|
|
61
|
+
↑ Push
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
<textarea id="git-panel-commit-message" class="git-panel-commit-input" placeholder="Commit message (Ctrl+Enter to commit)" rows="2"></textarea>
|
|
65
|
+
<button id="git-panel-commit-btn" class="git-panel-commit-btn">
|
|
66
|
+
<span>✓</span> Commit
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
<div>
|
|
70
|
+
<div class="git-panel-section-header">
|
|
71
|
+
<div style="display:flex;align-items:center;gap:6px;">
|
|
72
|
+
<span>Staged Changes</span>
|
|
73
|
+
<span class="git-panel-badge" id="git-panel-badge-staged">0</span>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="git-panel-section-actions">
|
|
76
|
+
<button class="git-panel-section-action-btn" id="git-panel-unstage-all" title="Unstage All" style="display:none;">−</button>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<ul class="git-panel-tree" id="git-panel-tree-staged"></ul>
|
|
80
|
+
</div>
|
|
81
|
+
<div>
|
|
82
|
+
<div class="git-panel-section-header">
|
|
83
|
+
<div style="display:flex;align-items:center;gap:6px;">
|
|
84
|
+
<span>Changes</span>
|
|
85
|
+
<span class="git-panel-badge" id="git-panel-badge-changes">0</span>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="git-panel-section-actions">
|
|
88
|
+
<button class="git-panel-section-action-btn destructive" id="git-panel-discard-all" title="Discard All" style="display:none;">↺</button>
|
|
89
|
+
<button class="git-panel-section-action-btn" id="git-panel-stage-all" title="Stage All" style="display:none;">+</button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<ul class="git-panel-tree" id="git-panel-tree-changes"></ul>
|
|
93
|
+
</div>
|
|
94
|
+
`;
|
|
95
|
+
|
|
96
|
+
// Attach event listeners
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
const stageAllBtn = getById('git-panel-stage-all');
|
|
99
|
+
const unstageAllBtn = getById('git-panel-unstage-all');
|
|
100
|
+
const discardAllBtn = getById('git-panel-discard-all');
|
|
101
|
+
const commitBtn = getById('git-panel-commit-btn');
|
|
102
|
+
const pushBtn = getById('git-panel-push-btn');
|
|
103
|
+
const commitInput = getById('git-panel-commit-message');
|
|
104
|
+
|
|
105
|
+
if (stageAllBtn) stageAllBtn.addEventListener('click', () => handleStage('*'));
|
|
106
|
+
if (unstageAllBtn) unstageAllBtn.addEventListener('click', () => handleUnstage('*'));
|
|
107
|
+
if (discardAllBtn) discardAllBtn.addEventListener('click', () => handleDiscard('*'));
|
|
108
|
+
if (commitBtn) commitBtn.addEventListener('click', handleCommit);
|
|
109
|
+
if (pushBtn) pushBtn.addEventListener('click', handlePush);
|
|
110
|
+
|
|
111
|
+
if (commitInput) {
|
|
112
|
+
commitInput.addEventListener('keydown', (e) => {
|
|
113
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
|
|
114
|
+
e.preventDefault();
|
|
115
|
+
handleCommit();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}, 0);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Load Git data
|
|
124
|
+
*/
|
|
125
|
+
export async function loadGitData() {
|
|
126
|
+
const stagedTree = getById('git-panel-tree-staged');
|
|
127
|
+
const changesTree = getById('git-panel-tree-changes');
|
|
128
|
+
|
|
129
|
+
if (stagedTree) stagedTree.innerHTML = '<li class="git-panel-loading">Loading...</li>';
|
|
130
|
+
if (changesTree) changesTree.innerHTML = '<li class="git-panel-loading">Loading...</li>';
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const { staged, changes } = await getGitStatus();
|
|
134
|
+
currentStaged = staged;
|
|
135
|
+
currentChanges = changes;
|
|
136
|
+
renderTrees();
|
|
137
|
+
} catch (err) {
|
|
138
|
+
if (stagedTree) stagedTree.innerHTML = '';
|
|
139
|
+
if (changesTree) changesTree.innerHTML = `<li class="git-panel-empty">Error: ${err.message}</li>`;
|
|
140
|
+
showToast('Error loading git status: ' + err.message, 'error');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Render trees
|
|
146
|
+
*/
|
|
147
|
+
function renderTrees() {
|
|
148
|
+
const stagedTree = getById('git-panel-tree-staged');
|
|
149
|
+
const stagedBadge = getById('git-panel-badge-staged');
|
|
150
|
+
const unstageAllBtn = getById('git-panel-unstage-all');
|
|
151
|
+
|
|
152
|
+
if (stagedBadge) stagedBadge.textContent = currentStaged.length;
|
|
153
|
+
if (unstageAllBtn) unstageAllBtn.style.display = currentStaged.length > 0 ? 'block' : 'none';
|
|
154
|
+
|
|
155
|
+
if (stagedTree) {
|
|
156
|
+
stagedTree.innerHTML = '';
|
|
157
|
+
if (currentStaged.length > 0) {
|
|
158
|
+
const root = buildFileTree(currentStaged);
|
|
159
|
+
renderTreeNodes(root, stagedTree, 'staged', 0);
|
|
160
|
+
} else {
|
|
161
|
+
stagedTree.innerHTML = '<li class="git-panel-empty">No staged changes</li>';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const changesTree = getById('git-panel-tree-changes');
|
|
166
|
+
const changesBadge = getById('git-panel-badge-changes');
|
|
167
|
+
const stageAllBtn = getById('git-panel-stage-all');
|
|
168
|
+
const discardAllBtn = getById('git-panel-discard-all');
|
|
169
|
+
|
|
170
|
+
if (changesBadge) changesBadge.textContent = currentChanges.length;
|
|
171
|
+
if (stageAllBtn) stageAllBtn.style.display = currentChanges.length > 0 ? 'block' : 'none';
|
|
172
|
+
if (discardAllBtn) discardAllBtn.style.display = currentChanges.length > 0 ? 'block' : 'none';
|
|
173
|
+
|
|
174
|
+
if (changesTree) {
|
|
175
|
+
changesTree.innerHTML = '';
|
|
176
|
+
if (currentChanges.length > 0) {
|
|
177
|
+
const root = buildFileTree(currentChanges);
|
|
178
|
+
renderTreeNodes(root, changesTree, 'changes', 0);
|
|
179
|
+
} else {
|
|
180
|
+
changesTree.innerHTML = '<li class="git-panel-empty">No changes</li>';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Build file tree from flat list
|
|
187
|
+
*/
|
|
188
|
+
function buildFileTree(files) {
|
|
189
|
+
const root = {};
|
|
190
|
+
files.forEach(file => {
|
|
191
|
+
const parts = file.path.split('/');
|
|
192
|
+
let current = root;
|
|
193
|
+
parts.forEach((part, index) => {
|
|
194
|
+
if (!current[part]) {
|
|
195
|
+
current[part] = { name: part, children: {}, fileData: null };
|
|
196
|
+
}
|
|
197
|
+
if (index === parts.length - 1) {
|
|
198
|
+
current[part].fileData = file;
|
|
199
|
+
}
|
|
200
|
+
current = current[part].children;
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
return root;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Render tree nodes
|
|
208
|
+
*/
|
|
209
|
+
function renderTreeNodes(nodes, container, type, depth) {
|
|
210
|
+
const items = Object.values(nodes);
|
|
211
|
+
items.sort((a, b) => {
|
|
212
|
+
const aIsFolder = Object.keys(a.children).length > 0;
|
|
213
|
+
const bIsFolder = Object.keys(b.children).length > 0;
|
|
214
|
+
if (aIsFolder && !bIsFolder) return -1;
|
|
215
|
+
if (!aIsFolder && bIsFolder) return 1;
|
|
216
|
+
return a.name.localeCompare(b.name);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
items.forEach(node => {
|
|
220
|
+
const isFolder = Object.keys(node.children).length > 0;
|
|
221
|
+
const li = document.createElement('li');
|
|
222
|
+
li.className = 'git-panel-tree-node';
|
|
223
|
+
|
|
224
|
+
const content = document.createElement('div');
|
|
225
|
+
content.className = 'git-panel-tree-content';
|
|
226
|
+
content.style.paddingLeft = (depth * 16 + 8) + 'px';
|
|
227
|
+
|
|
228
|
+
const arrow = document.createElement('span');
|
|
229
|
+
arrow.className = 'git-panel-arrow';
|
|
230
|
+
arrow.textContent = isFolder ? '▼' : '';
|
|
231
|
+
content.appendChild(arrow);
|
|
232
|
+
|
|
233
|
+
const iconSpan = document.createElement('span');
|
|
234
|
+
iconSpan.className = 'git-panel-icon';
|
|
235
|
+
if (isFolder) {
|
|
236
|
+
iconSpan.textContent = '📂';
|
|
237
|
+
} else {
|
|
238
|
+
const status = node.fileData.status;
|
|
239
|
+
iconSpan.textContent = getStatusIcon(status);
|
|
240
|
+
iconSpan.className += ' git-status-' + status;
|
|
241
|
+
}
|
|
242
|
+
content.appendChild(iconSpan);
|
|
243
|
+
|
|
244
|
+
const label = document.createElement('span');
|
|
245
|
+
label.className = isFolder ? 'git-panel-label git-panel-dir-label' : 'git-panel-label git-panel-file-label';
|
|
246
|
+
label.textContent = node.name;
|
|
247
|
+
content.appendChild(label);
|
|
248
|
+
|
|
249
|
+
if (!isFolder && node.fileData) {
|
|
250
|
+
const actions = document.createElement('div');
|
|
251
|
+
actions.className = 'git-panel-actions';
|
|
252
|
+
|
|
253
|
+
if (type === 'changes') {
|
|
254
|
+
const discardBtn = document.createElement('button');
|
|
255
|
+
discardBtn.className = 'git-panel-btn-action destructive';
|
|
256
|
+
discardBtn.textContent = '↺';
|
|
257
|
+
discardBtn.title = 'Discard';
|
|
258
|
+
discardBtn.onclick = (e) => { e.stopPropagation(); handleDiscard(node.fileData.path); };
|
|
259
|
+
actions.appendChild(discardBtn);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const btn = document.createElement('button');
|
|
263
|
+
btn.className = 'git-panel-btn-action';
|
|
264
|
+
if (type === 'staged') {
|
|
265
|
+
btn.textContent = '−';
|
|
266
|
+
btn.title = 'Unstage';
|
|
267
|
+
btn.onclick = (e) => { e.stopPropagation(); handleUnstage(node.fileData.path); };
|
|
268
|
+
} else {
|
|
269
|
+
btn.textContent = '+';
|
|
270
|
+
btn.title = 'Stage';
|
|
271
|
+
btn.onclick = (e) => { e.stopPropagation(); handleStage(node.fileData.path); };
|
|
272
|
+
}
|
|
273
|
+
actions.appendChild(btn);
|
|
274
|
+
content.appendChild(actions);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
content.addEventListener('click', (e) => {
|
|
278
|
+
e.stopPropagation();
|
|
279
|
+
if (isFolder) {
|
|
280
|
+
console.log('[GitPanel] Toggling folder');
|
|
281
|
+
li.classList.toggle('collapsed');
|
|
282
|
+
} else {
|
|
283
|
+
console.log('[GitPanel] 🔥 FILE CLICKED:', node.fileData.path, 'Type:', type);
|
|
284
|
+
qsa('.git-panel-tree-content').forEach(el => el.classList.remove('selected'));
|
|
285
|
+
content.classList.add('selected');
|
|
286
|
+
console.log('[GitPanel] File selected, attempting to open diff view');
|
|
287
|
+
|
|
288
|
+
// Open file diff in the existing Git view overlay
|
|
289
|
+
if (node.fileData) {
|
|
290
|
+
console.log('[GitPanel] Calling openGitDiffView with:', {
|
|
291
|
+
path: node.fileData.path,
|
|
292
|
+
type: type
|
|
293
|
+
});
|
|
294
|
+
openGitDiffView(node.fileData.path, type);
|
|
295
|
+
} else {
|
|
296
|
+
console.error('[GitPanel] No fileData found for node!');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
li.appendChild(content);
|
|
302
|
+
|
|
303
|
+
if (isFolder) {
|
|
304
|
+
const ul = document.createElement('ul');
|
|
305
|
+
renderTreeNodes(node.children, ul, type, depth + 1);
|
|
306
|
+
li.appendChild(ul);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
container.appendChild(li);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Get status icon
|
|
315
|
+
*/
|
|
316
|
+
function getStatusIcon(status) {
|
|
317
|
+
if (status === 'M') return 'M';
|
|
318
|
+
if (status === 'A' || status === 'U') return 'U';
|
|
319
|
+
if (status === 'D') return 'D';
|
|
320
|
+
if (status === 'R') return 'R';
|
|
321
|
+
return '?';
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Handle stage
|
|
326
|
+
*/
|
|
327
|
+
async function handleStage(path) {
|
|
328
|
+
try {
|
|
329
|
+
await stageFile(path);
|
|
330
|
+
await loadGitData();
|
|
331
|
+
showToast(path === '*' ? 'All changes staged' : 'File staged', 'success');
|
|
332
|
+
} catch (err) {
|
|
333
|
+
showToast('Stage failed: ' + err.message, 'error');
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Handle unstage
|
|
339
|
+
*/
|
|
340
|
+
async function handleUnstage(path) {
|
|
341
|
+
try {
|
|
342
|
+
await unstageFile(path);
|
|
343
|
+
await loadGitData();
|
|
344
|
+
showToast(path === '*' ? 'All changes unstaged' : 'File unstaged', 'success');
|
|
345
|
+
} catch (err) {
|
|
346
|
+
showToast('Unstage failed: ' + err.message, 'error');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Handle discard
|
|
352
|
+
*/
|
|
353
|
+
async function handleDiscard(path) {
|
|
354
|
+
const isAll = path === '*';
|
|
355
|
+
const msg = isAll
|
|
356
|
+
? 'Discard ALL changes? This is irreversible!'
|
|
357
|
+
: `Discard changes to ${path}? This is irreversible!`;
|
|
358
|
+
|
|
359
|
+
if (confirm(msg)) {
|
|
360
|
+
try {
|
|
361
|
+
await discardChange(path);
|
|
362
|
+
await loadGitData();
|
|
363
|
+
showToast('Changes discarded', 'success');
|
|
364
|
+
} catch (err) {
|
|
365
|
+
showToast('Discard failed: ' + err.message, 'error');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Handle commit
|
|
372
|
+
*/
|
|
373
|
+
async function handleCommit() {
|
|
374
|
+
const input = getById('git-panel-commit-message');
|
|
375
|
+
const message = input ? input.value.trim() : '';
|
|
376
|
+
const btn = getById('git-panel-commit-btn');
|
|
377
|
+
|
|
378
|
+
if (!message) {
|
|
379
|
+
showToast('Please enter a commit message', 'error');
|
|
380
|
+
if (input) input.focus();
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (currentStaged.length === 0) {
|
|
385
|
+
showToast('Nothing to commit. Stage changes first.', 'error');
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (btn) btn.disabled = true;
|
|
390
|
+
if (btn) btn.innerHTML = '<span>...</span> Committing...';
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
await commitChanges(message);
|
|
394
|
+
showToast('Commit successful', 'success');
|
|
395
|
+
if (input) input.value = '';
|
|
396
|
+
await loadGitData();
|
|
397
|
+
} catch (err) {
|
|
398
|
+
showToast('Commit failed: ' + err.message, 'error');
|
|
399
|
+
} finally {
|
|
400
|
+
if (btn) btn.disabled = false;
|
|
401
|
+
if (btn) btn.innerHTML = '<span>✓</span> Commit';
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Handle Push
|
|
407
|
+
*/
|
|
408
|
+
async function handlePush() {
|
|
409
|
+
const btn = getById('git-panel-push-btn');
|
|
410
|
+
|
|
411
|
+
if (!btn) {
|
|
412
|
+
console.error('[GitPanel] Push button not found');
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
btn.disabled = true;
|
|
417
|
+
btn.innerHTML = '\u2191 Pushing...';
|
|
418
|
+
console.log('[GitPanel] Pushing to remote...');
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
const result = await gitPush();
|
|
422
|
+
console.log('[GitPanel] Push successful:', result);
|
|
423
|
+
showToast(`Pushed to ${result.remote}/${result.branch}`, 'success');
|
|
424
|
+
} catch (err) {
|
|
425
|
+
console.error('[GitPanel] Push failed:', err);
|
|
426
|
+
showToast('Push failed: ' + err.message, 'error');
|
|
427
|
+
} finally {
|
|
428
|
+
btn.disabled = false;
|
|
429
|
+
btn.innerHTML = '\u2191 Push';
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Open Git diff view in the overlay (uses existing git-view.js functionality)
|
|
435
|
+
*/
|
|
436
|
+
async function openGitDiffView(filePath, type) {
|
|
437
|
+
console.log('[GitPanel] 🔥 openGitDiffView called with:', { filePath, type });
|
|
438
|
+
|
|
439
|
+
// Strategy: Directly trigger the Git view overlay, then call loadDiffView
|
|
440
|
+
const gitToggleBtn = getById('git-view-toggle');
|
|
441
|
+
const gitViewContainer = getById('git-view-container');
|
|
442
|
+
|
|
443
|
+
console.log('[GitPanel] Git view elements:', {
|
|
444
|
+
toggleBtn: !!gitToggleBtn,
|
|
445
|
+
container: !!gitViewContainer,
|
|
446
|
+
containerActive: gitViewContainer?.classList.contains('active')
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// Activate Git view overlay if not active
|
|
450
|
+
if (gitViewContainer && !gitViewContainer.classList.contains('active')) {
|
|
451
|
+
console.log('[GitPanel] Activating Git view overlay...');
|
|
452
|
+
if (gitToggleBtn) {
|
|
453
|
+
gitToggleBtn.click();
|
|
454
|
+
} else {
|
|
455
|
+
console.error('[GitPanel] Git toggle button not found!');
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Wait for Git view to load, then trigger diff
|
|
461
|
+
// setTimeout(() => {
|
|
462
|
+
console.log('[GitPanel] Attempting to load diff view for:', filePath);
|
|
463
|
+
|
|
464
|
+
// Check if global loadGitDiffView function exists (from git-view.js)
|
|
465
|
+
if (typeof window.loadGitDiffView === 'function') {
|
|
466
|
+
console.log('[GitPanel] ✅ Calling window.loadGitDiffView');
|
|
467
|
+
window.loadGitDiffView(filePath, type);
|
|
468
|
+
} else {
|
|
469
|
+
console.error('[GitPanel] ❌ window.loadGitDiffView not available');
|
|
470
|
+
console.log('[GitPanel] Available window functions:', Object.keys(window).filter(k => k.includes('git') || k.includes('diff')));
|
|
471
|
+
|
|
472
|
+
// Fallback: Try to find and click the file in the tree manually
|
|
473
|
+
// But Git view doesn't use data-path, it stores path in closure
|
|
474
|
+
// So we need to trigger via the global function
|
|
475
|
+
showToast('Git diff view not available. Please use the Git button in tabs header.', 'warning');
|
|
476
|
+
}
|
|
477
|
+
// }, 400);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|