enzostvs HF Staff commited on
Commit
6e64a00
·
1 Parent(s): 8fc01e0

✨ update ui to show what changed

Browse files
server.js CHANGED
@@ -498,6 +498,8 @@ ${REPLACE_END}
498
 
499
  if (chunk) {
500
  let newHtml = html;
 
 
501
 
502
  // Find all search/replace blocks in the chunk
503
  let position = 0;
@@ -536,9 +538,30 @@ ${REPLACE_END}
536
  if (searchBlock.trim() === "") {
537
  // Inserting at the beginning
538
  newHtml = `${replaceBlock}\n${newHtml}`;
 
 
 
539
  } else {
540
- // Replacing existing code
541
- newHtml = newHtml.replace(searchBlock, replaceBlock);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  }
543
 
544
  // Move position to after this block to find the next one
@@ -548,6 +571,7 @@ ${REPLACE_END}
548
  return res.status(200).send({
549
  ok: true,
550
  html: newHtml,
 
551
  });
552
  } else {
553
  return res.status(400).send({
 
498
 
499
  if (chunk) {
500
  let newHtml = html;
501
+ // array of arrays to hold updated lines (start and end line numbers)
502
+ const updatedLines = [];
503
 
504
  // Find all search/replace blocks in the chunk
505
  let position = 0;
 
538
  if (searchBlock.trim() === "") {
539
  // Inserting at the beginning
540
  newHtml = `${replaceBlock}\n${newHtml}`;
541
+
542
+ // Track first line as updated
543
+ updatedLines.push([1, replaceBlock.split("\n").length]);
544
  } else {
545
+ // Find the position of the search block in the HTML
546
+ const blockPosition = newHtml.indexOf(searchBlock);
547
+ if (blockPosition !== -1) {
548
+ // Count lines before the search block
549
+ const beforeText = newHtml.substring(0, blockPosition);
550
+ const startLineNumber = beforeText.split("\n").length;
551
+
552
+ // Count lines in search and replace blocks
553
+ const searchLines = searchBlock.split("\n").length;
554
+ const replaceLines = replaceBlock.split("\n").length;
555
+
556
+ // Calculate end line (start + length of replaced content)
557
+ const endLineNumber = startLineNumber + replaceLines - 1;
558
+
559
+ // Track the line numbers that were updated
560
+ updatedLines.push([startLineNumber, endLineNumber]);
561
+
562
+ // Perform the replacement
563
+ newHtml = newHtml.replace(searchBlock, replaceBlock);
564
+ }
565
  }
566
 
567
  // Move position to after this block to find the next one
 
571
  return res.status(200).send({
572
  ok: true,
573
  html: newHtml,
574
+ updatedLines,
575
  });
576
  } else {
577
  return res.status(400).send({
src/assets/index.css CHANGED
@@ -136,3 +136,7 @@
136
  .monaco-editor .line-numbers {
137
  @apply !text-neutral-500;
138
  }
 
 
 
 
 
136
  .monaco-editor .line-numbers {
137
  @apply !text-neutral-500;
138
  }
139
+
140
+ .matched-line {
141
+ @apply bg-sky-500/30;
142
+ }
src/components/ask-ai/ask-ai.tsx CHANGED
@@ -31,7 +31,7 @@ function AskAI({
31
  isAiWorking: boolean;
32
  onNewPrompt: (prompt: string) => void;
33
  setisAiWorking: React.Dispatch<React.SetStateAction<boolean>>;
34
- onSuccess: (h: string, p: string) => void;
35
  }) {
36
  const refThink = useRef<HTMLDivElement | null>(null);
37
 
@@ -100,7 +100,7 @@ function AskAI({
100
  setPreviousPrompt(prompt);
101
  setPrompt("");
102
  setisAiWorking(false);
103
- onSuccess(res.html, prompt);
104
  audio.play();
105
  }
106
  } else {
 
31
  isAiWorking: boolean;
32
  onNewPrompt: (prompt: string) => void;
33
  setisAiWorking: React.Dispatch<React.SetStateAction<boolean>>;
34
+ onSuccess: (h: string, p: string, n?: number[][]) => void;
35
  }) {
36
  const refThink = useRef<HTMLDivElement | null>(null);
37
 
 
100
  setPreviousPrompt(prompt);
101
  setPrompt("");
102
  setisAiWorking(false);
103
+ onSuccess(res.html, prompt, res.updatedLines);
104
  audio.play();
105
  }
106
  } else {
src/components/settings/settings.tsx CHANGED
@@ -105,7 +105,7 @@ function Settings({
105
  label: string;
106
  isNew?: boolean;
107
  }) => (
108
- <SelectItem value={value} className="">
109
  {label}
110
  {isNew && (
111
  <span className="text-xs bg-gradient-to-br from-sky-400 to-sky-600 text-white rounded-full px-1.5 py-0.5">
 
105
  label: string;
106
  isNew?: boolean;
107
  }) => (
108
+ <SelectItem key={value} value={value} className="">
109
  {label}
110
  {isNew && (
111
  <span className="text-xs bg-gradient-to-br from-sky-400 to-sky-600 text-white rounded-full px-1.5 py-0.5">
src/views/App.tsx CHANGED
@@ -34,6 +34,8 @@ export default function App() {
34
  const resizer = useRef<HTMLDivElement>(null);
35
  const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
36
  const iframeRef = useRef<HTMLIFrameElement | null>(null);
 
 
37
 
38
  const [html, setHtml] = useState((htmlStorage as string) ?? defaultHTML);
39
  const [isAiWorking, setisAiWorking] = useState(false);
@@ -222,14 +224,21 @@ export default function App() {
222
  const newValue = value ?? "";
223
  setHtml(newValue);
224
  }}
225
- onMount={(editor) => (editorRef.current = editor)}
 
 
 
226
  />
227
  <AskAI
228
  html={html}
229
  setHtml={(newHtml: string) => {
230
  setHtml(newHtml);
231
  }}
232
- onSuccess={(finalHtml: string, p: string) => {
 
 
 
 
233
  const currentHistory = [...htmlHistory];
234
  currentHistory.unshift({
235
  html: finalHtml,
@@ -241,6 +250,24 @@ export default function App() {
241
  if (window.innerWidth <= 1024) {
242
  setCurrentTab("preview");
243
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  }}
245
  isAiWorking={isAiWorking}
246
  setisAiWorking={setisAiWorking}
 
34
  const resizer = useRef<HTMLDivElement>(null);
35
  const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
36
  const iframeRef = useRef<HTMLIFrameElement | null>(null);
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const monacoRef = useRef<any>(null);
39
 
40
  const [html, setHtml] = useState((htmlStorage as string) ?? defaultHTML);
41
  const [isAiWorking, setisAiWorking] = useState(false);
 
224
  const newValue = value ?? "";
225
  setHtml(newValue);
226
  }}
227
+ onMount={(editor, monaco) => {
228
+ editorRef.current = editor;
229
+ monacoRef.current = monaco;
230
+ }}
231
  />
232
  <AskAI
233
  html={html}
234
  setHtml={(newHtml: string) => {
235
  setHtml(newHtml);
236
  }}
237
+ onSuccess={(
238
+ finalHtml: string,
239
+ p: string,
240
+ updatedLines?: number[][]
241
+ ) => {
242
  const currentHistory = [...htmlHistory];
243
  currentHistory.unshift({
244
  html: finalHtml,
 
250
  if (window.innerWidth <= 1024) {
251
  setCurrentTab("preview");
252
  }
253
+ if (updatedLines && updatedLines?.length > 0) {
254
+ const decorations = updatedLines.map((line) => ({
255
+ range: new monacoRef.current.Range(
256
+ line[0],
257
+ 1,
258
+ line[1],
259
+ 1
260
+ ),
261
+ options: {
262
+ inlineClassName: "matched-line",
263
+ },
264
+ }));
265
+ setTimeout(() => {
266
+ editorRef?.current
267
+ ?.getModel()
268
+ ?.deltaDecorations([], decorations);
269
+ }, 100);
270
+ }
271
  }}
272
  isAiWorking={isAiWorking}
273
  setisAiWorking={setisAiWorking}