seeclaudecode 1.0.5 → 1.0.7
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 +2 -1
- package/landing/index.html +12 -12
- package/landing/screenshot.jpg +0 -0
- package/package.json +1 -1
- package/public/app.js +187 -12
- package/server.js +69 -7
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# SeeClaudeCode
|
|
2
2
|
|
|
3
3
|
Real-time visualization of your repository structure while Claude Code edits your codebase.
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+

|
|
5
6
|
|
|
6
7
|
## Features
|
|
7
8
|
|
package/landing/index.html
CHANGED
|
@@ -819,7 +819,7 @@
|
|
|
819
819
|
<div class="nav-links">
|
|
820
820
|
<a href="#features">Features</a>
|
|
821
821
|
<a href="#how-it-works">How it works</a>
|
|
822
|
-
|
|
822
|
+
<!--<a href="https://github.com/ninajlu/seeclaudecode">GitHub</a>-->
|
|
823
823
|
</div>
|
|
824
824
|
|
|
825
825
|
<div class="nav-buttons">
|
|
@@ -841,9 +841,9 @@
|
|
|
841
841
|
WATCH AGENTS WRITE CODE
|
|
842
842
|
</div>
|
|
843
843
|
|
|
844
|
-
<h1>See what Claude Code<br>is actually doing.</h1>
|
|
844
|
+
<h1>See what Claude Code<br>is <em>actually</em> doing.</h1>
|
|
845
845
|
|
|
846
|
-
<p>SeeClaudeCode visualizes your codebase changes
|
|
846
|
+
<p>SeeClaudeCode visualizes your codebase for changes in real-time so you know what files and directories Claude Code is editing.</p>
|
|
847
847
|
|
|
848
848
|
<div class="hero-buttons">
|
|
849
849
|
<a href="https://www.npmjs.com/package/seeclaudecode" class="btn btn-primary btn-lg">
|
|
@@ -853,9 +853,9 @@
|
|
|
853
853
|
<polyline points="12 5 19 12 12 19"></polyline>
|
|
854
854
|
</svg>
|
|
855
855
|
</a>
|
|
856
|
-
|
|
856
|
+
<!--<a href="https://github.com/ninajlu/seeclaudecode" class="btn btn-outline btn-lg">
|
|
857
857
|
View on GitHub
|
|
858
|
-
</a
|
|
858
|
+
</a>-->
|
|
859
859
|
</div>
|
|
860
860
|
</div>
|
|
861
861
|
|
|
@@ -865,7 +865,7 @@
|
|
|
865
865
|
<div class="preview-dot red"></div>
|
|
866
866
|
<div class="preview-dot yellow"></div>
|
|
867
867
|
<div class="preview-dot green"></div>
|
|
868
|
-
<span class="preview-title">
|
|
868
|
+
<span class="preview-title">seeclaudecode.exe</span>
|
|
869
869
|
</div>
|
|
870
870
|
<div class="preview-content">
|
|
871
871
|
<div class="rf-graph">
|
|
@@ -1060,8 +1060,8 @@
|
|
|
1060
1060
|
<!-- Features -->
|
|
1061
1061
|
<section id="features" class="features">
|
|
1062
1062
|
<div class="section-header">
|
|
1063
|
-
<h2>
|
|
1064
|
-
<p>
|
|
1063
|
+
<h2>Can't figure out what Claude Code is doing?</h2>
|
|
1064
|
+
<p>Don't worry! SeeClaudeCode visualizes your code base and shows you which files and folders Claude is editing in real-time.</p>
|
|
1065
1065
|
</div>
|
|
1066
1066
|
|
|
1067
1067
|
<div class="features-grid">
|
|
@@ -1095,8 +1095,8 @@
|
|
|
1095
1095
|
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
|
|
1096
1096
|
</svg>
|
|
1097
1097
|
</div>
|
|
1098
|
-
<h3>
|
|
1099
|
-
<p>Visual cues and color-coded status indicators help non-technical builders code.</p>
|
|
1098
|
+
<h3>Built for Ah-Ha Moments</h3>
|
|
1099
|
+
<p>Visual cues and color-coded status indicators help non-technical builders learn how to code.</p>
|
|
1100
1100
|
</div>
|
|
1101
1101
|
</div>
|
|
1102
1102
|
</section>
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
<div class="terminal-container">
|
|
1107
1107
|
<div class="terminal-content">
|
|
1108
1108
|
<h3>Bridging the Gap</h3>
|
|
1109
|
-
<p>
|
|
1109
|
+
<p>Development shouldn't be a black box. We bridge the gap between AI coding agents and humans.</p>
|
|
1110
1110
|
|
|
1111
1111
|
<ul class="check-list">
|
|
1112
1112
|
<li>
|
|
@@ -1181,7 +1181,7 @@
|
|
|
1181
1181
|
</div>
|
|
1182
1182
|
|
|
1183
1183
|
<div class="footer-links">
|
|
1184
|
-
|
|
1184
|
+
<!--<a href="https://github.com/ninajlu/seeclaudecode">GitHub</a>-->
|
|
1185
1185
|
<a href="https://www.npmjs.com/package/seeclaudecode">npm</a>
|
|
1186
1186
|
</div>
|
|
1187
1187
|
|
|
Binary file
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -68,8 +68,17 @@ class SeeClaude {
|
|
|
68
68
|
switch (data.type) {
|
|
69
69
|
case 'init':
|
|
70
70
|
data.activeFiles?.forEach(f => this.activeFiles.add(f));
|
|
71
|
-
data.changedFiles?.forEach(f =>
|
|
71
|
+
data.changedFiles?.forEach(f => {
|
|
72
|
+
this.changedFiles.add(f);
|
|
73
|
+
this.updateChangedPaths(f);
|
|
74
|
+
});
|
|
75
|
+
// Restore activity history from server
|
|
76
|
+
if (data.activities && data.activities.length > 0) {
|
|
77
|
+
this.activities = data.activities;
|
|
78
|
+
this.renderActivityFeed();
|
|
79
|
+
}
|
|
72
80
|
this.updateActivePaths();
|
|
81
|
+
this.buildGraphData(); // Rebuild graph with change data
|
|
73
82
|
this.render();
|
|
74
83
|
break;
|
|
75
84
|
|
|
@@ -97,25 +106,86 @@ class SeeClaude {
|
|
|
97
106
|
|
|
98
107
|
handleActiveEdit(data) {
|
|
99
108
|
this.activeFiles.add(data.file);
|
|
109
|
+
this.changedFiles.add(data.file); // Also mark as changed immediately
|
|
100
110
|
this.updateActivePaths();
|
|
111
|
+
this.updateChangedPaths(data.file); // Update parent paths
|
|
101
112
|
|
|
102
113
|
const fileName = data.file.split('/').pop();
|
|
103
114
|
document.getElementById('current-task').textContent = `Editing ${fileName}`;
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
// Use activity from server if available, otherwise create one
|
|
117
|
+
if (data.activity) {
|
|
118
|
+
// Check if we already have this activity
|
|
119
|
+
if (!this.activities.find(a => a.id === data.activity.id)) {
|
|
120
|
+
this.activities.unshift(data.activity);
|
|
121
|
+
if (this.activities.length > 20) this.activities.pop();
|
|
122
|
+
this.renderActivityFeed();
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
this.addActivity('edit', `Editing ${fileName}`, data.file, true);
|
|
126
|
+
}
|
|
127
|
+
|
|
106
128
|
this.expandPathTo(data.file);
|
|
129
|
+
|
|
130
|
+
// Rebuild graph to include the new file
|
|
131
|
+
this.buildGraphData();
|
|
107
132
|
this.render();
|
|
108
133
|
}
|
|
109
134
|
|
|
135
|
+
updateChangedPaths(filePath) {
|
|
136
|
+
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
137
|
+
const parts = normalizedPath.split('/');
|
|
138
|
+
let currentPath = '';
|
|
139
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
140
|
+
currentPath = currentPath ? `${currentPath}/${parts[i]}` : parts[i];
|
|
141
|
+
this.changedPaths.add(currentPath);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
110
145
|
handleEditComplete(data) {
|
|
111
146
|
this.activeFiles.clear();
|
|
112
147
|
this.activePaths.clear();
|
|
113
|
-
|
|
148
|
+
|
|
149
|
+
// Use fresh changedFiles from server if available (reflects actual git status)
|
|
150
|
+
if (data.changedFiles) {
|
|
151
|
+
this.changedFiles.clear();
|
|
152
|
+
this.changedPaths.clear();
|
|
153
|
+
data.changedFiles.forEach(f => {
|
|
154
|
+
this.changedFiles.add(f);
|
|
155
|
+
this.updateChangedPaths(f);
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
// Fallback: use diff data
|
|
159
|
+
if (data.diff) {
|
|
160
|
+
[...(data.diff.modified || []), ...(data.diff.created || []), ...(data.diff.deleted || [])].forEach(f => {
|
|
161
|
+
this.changedFiles.add(f);
|
|
162
|
+
this.updateChangedPaths(f);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
114
166
|
|
|
115
167
|
document.getElementById('current-task').textContent = `Finished editing ${data.files.length} file(s)`;
|
|
116
168
|
|
|
117
|
-
|
|
169
|
+
// Mark all "Editing" activities as no longer active
|
|
170
|
+
this.activities.forEach(a => {
|
|
171
|
+
if (a.isActive) a.isActive = false;
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Use activity from server if available, otherwise create one
|
|
175
|
+
if (data.activity) {
|
|
176
|
+
if (!this.activities.find(a => a.id === data.activity.id)) {
|
|
177
|
+
this.activities.unshift(data.activity);
|
|
178
|
+
if (this.activities.length > 20) this.activities.pop();
|
|
179
|
+
}
|
|
180
|
+
this.renderActivityFeed();
|
|
181
|
+
} else {
|
|
182
|
+
this.addActivity('complete', `Completed editing`, `${data.files.length} file(s) modified`);
|
|
183
|
+
}
|
|
184
|
+
|
|
118
185
|
this.updateDiffPanel(data.diff);
|
|
186
|
+
|
|
187
|
+
// Rebuild graph with updated change data
|
|
188
|
+
this.buildGraphData();
|
|
119
189
|
this.render();
|
|
120
190
|
|
|
121
191
|
setTimeout(() => {
|
|
@@ -368,6 +438,25 @@ class SeeClaude {
|
|
|
368
438
|
const horizontalGap = 50;
|
|
369
439
|
const verticalGap = 200; // Extra space for vertical file lists below directories
|
|
370
440
|
|
|
441
|
+
// Build a map of changed files for quick lookup by directory
|
|
442
|
+
const changedFilesByDir = new Map();
|
|
443
|
+
this.changedFiles.forEach(filePath => {
|
|
444
|
+
const parts = filePath.split('/');
|
|
445
|
+
const fileName = parts.pop();
|
|
446
|
+
const dirPath = parts.length > 0 ? parts.join('/') : '.';
|
|
447
|
+
|
|
448
|
+
if (!changedFilesByDir.has(dirPath)) {
|
|
449
|
+
changedFilesByDir.set(dirPath, []);
|
|
450
|
+
}
|
|
451
|
+
changedFilesByDir.get(dirPath).push({
|
|
452
|
+
name: fileName,
|
|
453
|
+
path: filePath,
|
|
454
|
+
type: 'file',
|
|
455
|
+
extension: fileName.split('.').pop() || '',
|
|
456
|
+
category: this.getFileCategoryByExt(fileName.split('.').pop() || '')
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
|
|
371
460
|
// Count changed files in a directory (recursive)
|
|
372
461
|
const countChangedFiles = (node) => {
|
|
373
462
|
if (!node) return 0;
|
|
@@ -383,7 +472,13 @@ class SeeClaude {
|
|
|
383
472
|
if (!node.children) return thisChanged;
|
|
384
473
|
|
|
385
474
|
const childCount = node.children.reduce((sum, child) => sum + countChangedFiles(child), 0);
|
|
386
|
-
|
|
475
|
+
|
|
476
|
+
// Also count changed files that might not be in the structure
|
|
477
|
+
const extraChangedFiles = changedFilesByDir.get(node.path) || [];
|
|
478
|
+
const structureFilePaths = new Set((node.children || []).filter(c => c.type === 'file').map(c => c.path));
|
|
479
|
+
const extraCount = extraChangedFiles.filter(f => !structureFilePaths.has(f.path)).length;
|
|
480
|
+
|
|
481
|
+
return childCount + extraCount;
|
|
387
482
|
};
|
|
388
483
|
|
|
389
484
|
// Calculate subtree width
|
|
@@ -399,6 +494,9 @@ class SeeClaude {
|
|
|
399
494
|
return Math.max(nodeWidth, childWidths.reduce((a, b) => a + b, 0) + horizontalGap * (dirs.length - 1));
|
|
400
495
|
};
|
|
401
496
|
|
|
497
|
+
// Track which files we've already added
|
|
498
|
+
const addedFilePaths = new Set();
|
|
499
|
+
|
|
402
500
|
// Position directories and changed files
|
|
403
501
|
const positionNode = (node, depth, x, y, parentId = null) => {
|
|
404
502
|
if (node.type !== 'directory') return;
|
|
@@ -409,8 +507,13 @@ class SeeClaude {
|
|
|
409
507
|
const dirs = node.children?.filter(c => c.type === 'directory') || [];
|
|
410
508
|
const changedCount = countChangedFiles(node);
|
|
411
509
|
|
|
412
|
-
// Get changed files in this directory
|
|
413
|
-
const
|
|
510
|
+
// Get changed files in this directory - combine structure files and any extra changed files
|
|
511
|
+
const structureChangedFiles = files.filter(f => this.changedFiles.has(f.path));
|
|
512
|
+
const structureFilePaths = new Set(files.map(f => f.path));
|
|
513
|
+
|
|
514
|
+
// Also get changed files that aren't in the structure
|
|
515
|
+
const extraChangedFiles = (changedFilesByDir.get(nodeId) || []).filter(f => !structureFilePaths.has(f.path));
|
|
516
|
+
const allChangedFiles = [...structureChangedFiles, ...extraChangedFiles];
|
|
414
517
|
|
|
415
518
|
this.graphNodes.push({
|
|
416
519
|
id: nodeId,
|
|
@@ -425,7 +528,7 @@ class SeeClaude {
|
|
|
425
528
|
dirCount: dirs.length,
|
|
426
529
|
childCount: node.children?.length || 0,
|
|
427
530
|
changedCount,
|
|
428
|
-
hasChangedFiles:
|
|
531
|
+
hasChangedFiles: allChangedFiles.length > 0
|
|
429
532
|
});
|
|
430
533
|
|
|
431
534
|
if (parentId) {
|
|
@@ -433,15 +536,18 @@ class SeeClaude {
|
|
|
433
536
|
}
|
|
434
537
|
|
|
435
538
|
// Show changed files VERTICALLY below the directory
|
|
436
|
-
if (
|
|
539
|
+
if (allChangedFiles.length > 0) {
|
|
437
540
|
const fileWidth = 130;
|
|
438
541
|
const fileHeight = 22;
|
|
439
542
|
const fileGap = 4;
|
|
440
|
-
const visibleFiles =
|
|
543
|
+
const visibleFiles = allChangedFiles.slice(0, 5); // Limit to 5 files
|
|
441
544
|
const fileX = x; // Centered below directory
|
|
442
545
|
const startY = y + nodeHeight / 2 + 30; // Start below the directory
|
|
443
546
|
|
|
444
547
|
visibleFiles.forEach((file, idx) => {
|
|
548
|
+
if (addedFilePaths.has(file.path)) return; // Skip if already added
|
|
549
|
+
addedFilePaths.add(file.path);
|
|
550
|
+
|
|
445
551
|
const fileY = startY + idx * (fileHeight + fileGap);
|
|
446
552
|
|
|
447
553
|
this.graphNodes.push({
|
|
@@ -462,11 +568,11 @@ class SeeClaude {
|
|
|
462
568
|
});
|
|
463
569
|
|
|
464
570
|
// Show "+N more" indicator if there are more files
|
|
465
|
-
if (
|
|
571
|
+
if (allChangedFiles.length > 5) {
|
|
466
572
|
const moreY = startY + visibleFiles.length * (fileHeight + fileGap);
|
|
467
573
|
this.graphNodes.push({
|
|
468
574
|
id: `${nodeId}-more`,
|
|
469
|
-
label: `+${
|
|
575
|
+
label: `+${allChangedFiles.length - 5} more`,
|
|
470
576
|
path: node.path,
|
|
471
577
|
x: fileX,
|
|
472
578
|
y: moreY,
|
|
@@ -491,6 +597,75 @@ class SeeClaude {
|
|
|
491
597
|
};
|
|
492
598
|
|
|
493
599
|
positionNode(this.structure, 0, 0, 50);
|
|
600
|
+
|
|
601
|
+
// Add any remaining changed files that weren't in the structure at all
|
|
602
|
+
// (files in directories not shown in the graph)
|
|
603
|
+
const orphanedFiles = [];
|
|
604
|
+
this.changedFiles.forEach(filePath => {
|
|
605
|
+
if (!addedFilePaths.has(filePath)) {
|
|
606
|
+
const parts = filePath.split('/');
|
|
607
|
+
const fileName = parts.pop();
|
|
608
|
+
orphanedFiles.push({
|
|
609
|
+
name: fileName,
|
|
610
|
+
path: filePath,
|
|
611
|
+
category: this.getFileCategoryByExt(fileName.split('.').pop() || '')
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
// If there are orphaned files, add them to the root
|
|
617
|
+
if (orphanedFiles.length > 0) {
|
|
618
|
+
const rootNode = this.graphNodes.find(n => n.id === '.');
|
|
619
|
+
if (rootNode) {
|
|
620
|
+
const fileHeight = 22;
|
|
621
|
+
const fileGap = 4;
|
|
622
|
+
const startY = rootNode.y + nodeHeight / 2 + 30;
|
|
623
|
+
|
|
624
|
+
// Check if root already has changed files below it
|
|
625
|
+
const existingRootFiles = this.graphNodes.filter(n =>
|
|
626
|
+
n.isChangedFile && this.graphEdges.some(e => e.source === '.' && e.target === n.id)
|
|
627
|
+
);
|
|
628
|
+
const offsetY = existingRootFiles.length * (fileHeight + fileGap);
|
|
629
|
+
|
|
630
|
+
orphanedFiles.slice(0, 5).forEach((file, idx) => {
|
|
631
|
+
const fileY = startY + offsetY + idx * (fileHeight + fileGap);
|
|
632
|
+
|
|
633
|
+
this.graphNodes.push({
|
|
634
|
+
id: file.path,
|
|
635
|
+
label: file.name,
|
|
636
|
+
type: file.category || 'file',
|
|
637
|
+
path: file.path,
|
|
638
|
+
x: rootNode.x,
|
|
639
|
+
y: fileY,
|
|
640
|
+
category: file.category,
|
|
641
|
+
isDirectory: false,
|
|
642
|
+
isFile: true,
|
|
643
|
+
isChangedFile: true,
|
|
644
|
+
isOrphanedFile: true,
|
|
645
|
+
childCount: 0
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
this.graphEdges.push({ source: '.', target: file.path, hasChanges: true, isFileEdge: true });
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
getFileCategoryByExt(ext) {
|
|
655
|
+
const categories = {
|
|
656
|
+
code: ['js', 'ts', 'jsx', 'tsx', 'py', 'rb', 'go', 'rs', 'java', 'c', 'cpp', 'h', 'cs', 'php', 'swift', 'kt'],
|
|
657
|
+
style: ['css', 'scss', 'sass', 'less', 'styl'],
|
|
658
|
+
markup: ['html', 'htm', 'xml', 'svg'],
|
|
659
|
+
config: ['json', 'yaml', 'yml', 'toml', 'ini', 'env', 'config'],
|
|
660
|
+
docs: ['md', 'mdx', 'txt', 'rst', 'doc', 'pdf'],
|
|
661
|
+
data: ['sql', 'graphql', 'prisma'],
|
|
662
|
+
image: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'ico', 'bmp']
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
for (const [category, extensions] of Object.entries(categories)) {
|
|
666
|
+
if (extensions.includes(ext)) return category;
|
|
667
|
+
}
|
|
668
|
+
return 'other';
|
|
494
669
|
}
|
|
495
670
|
|
|
496
671
|
getNodeType(node) {
|
package/server.js
CHANGED
|
@@ -29,9 +29,27 @@ const state = {
|
|
|
29
29
|
activeFiles: new Set(),
|
|
30
30
|
changedFiles: new Set(),
|
|
31
31
|
repoStructure: null,
|
|
32
|
-
lastActivity: Date.now()
|
|
32
|
+
lastActivity: Date.now(),
|
|
33
|
+
activities: [] // Persist activity history
|
|
33
34
|
};
|
|
34
35
|
|
|
36
|
+
// Add activity to history
|
|
37
|
+
function addActivity(type, action, description, filePath = null, isActive = false) {
|
|
38
|
+
const activity = {
|
|
39
|
+
id: Date.now(),
|
|
40
|
+
type,
|
|
41
|
+
action,
|
|
42
|
+
description,
|
|
43
|
+
filePath,
|
|
44
|
+
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
|
|
45
|
+
isActive
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
state.activities.unshift(activity);
|
|
49
|
+
if (state.activities.length > 50) state.activities.pop(); // Keep last 50 activities
|
|
50
|
+
return activity;
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
// Serve static files
|
|
36
54
|
app.use(express.static(join(__dirname, 'public')));
|
|
37
55
|
|
|
@@ -363,14 +381,30 @@ function broadcast(data) {
|
|
|
363
381
|
}
|
|
364
382
|
|
|
365
383
|
// WebSocket connection handler
|
|
366
|
-
wss.on('connection', (ws) => {
|
|
384
|
+
wss.on('connection', async (ws) => {
|
|
367
385
|
console.log('📱 Client connected');
|
|
368
386
|
|
|
369
|
-
//
|
|
387
|
+
// Get FRESH git status - only show files with actual pending changes
|
|
388
|
+
let changedFiles = [];
|
|
389
|
+
try {
|
|
390
|
+
const gitStatus = await git.status();
|
|
391
|
+
changedFiles = [
|
|
392
|
+
...gitStatus.modified,
|
|
393
|
+
...gitStatus.created,
|
|
394
|
+
...gitStatus.deleted
|
|
395
|
+
];
|
|
396
|
+
// Update server state with fresh git status
|
|
397
|
+
state.changedFiles = new Set(changedFiles);
|
|
398
|
+
} catch (e) {
|
|
399
|
+
// Ignore git errors
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Send current state to new client including activity history
|
|
370
403
|
ws.send(JSON.stringify({
|
|
371
404
|
type: 'init',
|
|
372
405
|
activeFiles: Array.from(state.activeFiles),
|
|
373
|
-
changedFiles:
|
|
406
|
+
changedFiles: changedFiles,
|
|
407
|
+
activities: state.activities
|
|
374
408
|
}));
|
|
375
409
|
|
|
376
410
|
ws.on('close', () => {
|
|
@@ -415,12 +449,17 @@ function handleFileActivity(eventType, filePath) {
|
|
|
415
449
|
state.changedFiles.add(relativePath);
|
|
416
450
|
state.lastActivity = Date.now();
|
|
417
451
|
|
|
418
|
-
//
|
|
452
|
+
// Add to activity history
|
|
453
|
+
const fileName = relativePath.split('/').pop();
|
|
454
|
+
const activity = addActivity('edit', `Editing ${fileName}`, relativePath, relativePath, true);
|
|
455
|
+
|
|
456
|
+
// Broadcast active edit with activity
|
|
419
457
|
broadcast({
|
|
420
458
|
type: 'active',
|
|
421
459
|
file: relativePath,
|
|
422
460
|
event: eventType,
|
|
423
|
-
timestamp: Date.now()
|
|
461
|
+
timestamp: Date.now(),
|
|
462
|
+
activity
|
|
424
463
|
});
|
|
425
464
|
|
|
426
465
|
// Clear previous timer and set new one
|
|
@@ -434,11 +473,34 @@ function handleFileActivity(eventType, filePath) {
|
|
|
434
473
|
// Get git diff for changed files
|
|
435
474
|
const diff = await getGitDiff();
|
|
436
475
|
|
|
476
|
+
// Update state.changedFiles to reflect ACTUAL git status (not accumulated)
|
|
477
|
+
state.changedFiles = new Set([
|
|
478
|
+
...(diff.modified || []),
|
|
479
|
+
...(diff.created || []),
|
|
480
|
+
...(diff.deleted || [])
|
|
481
|
+
]);
|
|
482
|
+
|
|
483
|
+
// Add completion activity
|
|
484
|
+
const completeActivity = addActivity(
|
|
485
|
+
'complete',
|
|
486
|
+
'Completed editing',
|
|
487
|
+
`${completedFiles.length} file(s) modified`,
|
|
488
|
+
null,
|
|
489
|
+
false
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
// Mark all "Editing" activities as no longer active
|
|
493
|
+
state.activities.forEach(a => {
|
|
494
|
+
if (a.isActive) a.isActive = false;
|
|
495
|
+
});
|
|
496
|
+
|
|
437
497
|
broadcast({
|
|
438
498
|
type: 'complete',
|
|
439
499
|
files: completedFiles,
|
|
440
500
|
diff,
|
|
441
|
-
|
|
501
|
+
changedFiles: Array.from(state.changedFiles), // Send fresh list
|
|
502
|
+
timestamp: Date.now(),
|
|
503
|
+
activity: completeActivity
|
|
442
504
|
});
|
|
443
505
|
|
|
444
506
|
console.log(`✅ Editing complete. Changed files: ${completedFiles.join(', ')}`);
|