Skip to content

Commit a4420cb

Browse files
committed
Improve WEB UI
1 parent f6df0bd commit a4420cb

File tree

2 files changed

+210
-0
lines changed

2 files changed

+210
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import os from 'os';
3+
import path from 'path';
4+
5+
export async function GET(request: NextRequest) {
6+
try {
7+
// Get the user's home directory
8+
const homeDir = os.homedir();
9+
10+
// Normalize the path for cross-platform compatibility
11+
const normalizedPath = path.resolve(homeDir);
12+
13+
return NextResponse.json({
14+
success: true,
15+
homeDirectory: normalizedPath
16+
});
17+
} catch (error) {
18+
console.error('Error getting home directory:', error);
19+
20+
return NextResponse.json(
21+
{
22+
success: false,
23+
error: 'Failed to get home directory',
24+
details: error instanceof Error ? error.message : 'Unknown error'
25+
},
26+
{ status: 500 }
27+
);
28+
}
29+
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
export interface DiffLine {
2+
lineNumber: number;
3+
content: string;
4+
type: 'added' | 'removed' | 'unchanged' | 'modified';
5+
oldLineNumber?: number;
6+
newLineNumber?: number;
7+
}
8+
9+
export interface FileDiff {
10+
sourcePath: string;
11+
targetPath: string;
12+
sourceContent: string;
13+
targetContent: string;
14+
lines: DiffLine[];
15+
stats: {
16+
additions: number;
17+
deletions: number;
18+
modifications: number;
19+
};
20+
}
21+
22+
export interface DiffOptions {
23+
contextLines?: number;
24+
ignoreWhitespace?: boolean;
25+
caseSensitive?: boolean;
26+
}
27+
28+
class DiffService {
29+
async getFileDiff(
30+
sourcePath: string,
31+
targetPath: string,
32+
options: DiffOptions = {}
33+
): Promise<FileDiff> {
34+
const response = await fetch('/api/comparison/diff', {
35+
method: 'POST',
36+
headers: {
37+
'Content-Type': 'application/json',
38+
},
39+
body: JSON.stringify({
40+
sourceFilePath: sourcePath,
41+
targetFilePath: targetPath,
42+
options,
43+
}),
44+
});
45+
46+
if (!response.ok) {
47+
throw new Error(`Failed to get diff: ${response.statusText}`);
48+
}
49+
50+
return response.json();
51+
}
52+
53+
async getFileContent(filePath: string): Promise<string> {
54+
const response = await fetch('/api/comparison/file-content', {
55+
method: 'POST',
56+
headers: {
57+
'Content-Type': 'application/json',
58+
},
59+
body: JSON.stringify({ filePath }),
60+
});
61+
62+
if (!response.ok) {
63+
throw new Error(`Failed to get file content: ${response.statusText}`);
64+
}
65+
66+
const data = await response.json();
67+
return data.content;
68+
}
69+
70+
// Generate diff lines from two strings using a simple LCS-based algorithm
71+
generateDiffLines(sourceContent: string, targetContent: string): DiffLine[] {
72+
const sourceLines = sourceContent.split('\n');
73+
const targetLines = targetContent.split('\n');
74+
75+
const diffLines: DiffLine[] = [];
76+
let sourceIndex = 0;
77+
let targetIndex = 0;
78+
let lineNumber = 1;
79+
80+
// Simple diff algorithm - can be enhanced with proper LCS
81+
while (sourceIndex < sourceLines.length || targetIndex < targetLines.length) {
82+
const sourceLine = sourceLines[sourceIndex];
83+
const targetLine = targetLines[targetIndex];
84+
85+
if (sourceIndex >= sourceLines.length) {
86+
// Only target lines left (additions)
87+
diffLines.push({
88+
lineNumber: lineNumber++,
89+
content: targetLine,
90+
type: 'added',
91+
newLineNumber: targetIndex + 1,
92+
});
93+
targetIndex++;
94+
} else if (targetIndex >= targetLines.length) {
95+
// Only source lines left (deletions)
96+
diffLines.push({
97+
lineNumber: lineNumber++,
98+
content: sourceLine,
99+
type: 'removed',
100+
oldLineNumber: sourceIndex + 1,
101+
});
102+
sourceIndex++;
103+
} else if (sourceLine === targetLine) {
104+
// Lines are identical
105+
diffLines.push({
106+
lineNumber: lineNumber++,
107+
content: sourceLine,
108+
type: 'unchanged',
109+
oldLineNumber: sourceIndex + 1,
110+
newLineNumber: targetIndex + 1,
111+
});
112+
sourceIndex++;
113+
targetIndex++;
114+
} else {
115+
// Lines are different - check if it's a modification or add/remove
116+
const nextSourceMatch = targetLines.slice(targetIndex + 1).findIndex(line => line === sourceLine);
117+
const nextTargetMatch = sourceLines.slice(sourceIndex + 1).findIndex(line => line === targetLine);
118+
119+
if (nextSourceMatch === -1 && nextTargetMatch === -1) {
120+
// Likely a modification
121+
diffLines.push({
122+
lineNumber: lineNumber++,
123+
content: sourceLine,
124+
type: 'removed',
125+
oldLineNumber: sourceIndex + 1,
126+
});
127+
diffLines.push({
128+
lineNumber: lineNumber++,
129+
content: targetLine,
130+
type: 'added',
131+
newLineNumber: targetIndex + 1,
132+
});
133+
sourceIndex++;
134+
targetIndex++;
135+
} else if (nextSourceMatch !== -1 && (nextTargetMatch === -1 || nextSourceMatch < nextTargetMatch)) {
136+
// Source line appears later in target, so target lines are additions
137+
diffLines.push({
138+
lineNumber: lineNumber++,
139+
content: targetLine,
140+
type: 'added',
141+
newLineNumber: targetIndex + 1,
142+
});
143+
targetIndex++;
144+
} else {
145+
// Target line appears later in source, so source line is deletion
146+
diffLines.push({
147+
lineNumber: lineNumber++,
148+
content: sourceLine,
149+
type: 'removed',
150+
oldLineNumber: sourceIndex + 1,
151+
});
152+
sourceIndex++;
153+
}
154+
}
155+
}
156+
157+
return diffLines;
158+
}
159+
160+
calculateDiffStats(lines: DiffLine[]) {
161+
return lines.reduce(
162+
(stats, line) => {
163+
switch (line.type) {
164+
case 'added':
165+
stats.additions++;
166+
break;
167+
case 'removed':
168+
stats.deletions++;
169+
break;
170+
case 'modified':
171+
stats.modifications++;
172+
break;
173+
}
174+
return stats;
175+
},
176+
{ additions: 0, deletions: 0, modifications: 0 }
177+
);
178+
}
179+
}
180+
181+
export const diffService = new DiffService();

0 commit comments

Comments
 (0)