Shun Miyazawa 1 год назад
Родитель
Сommit
e13c8bbee5
1 измененных файлов с 42 добавлено и 15 удалено
  1. 42 15
      apps/app/src/features/openai/client/services/editor-assistant.ts

+ 42 - 15
apps/app/src/features/openai/client/services/editor-assistant.ts

@@ -1,4 +1,6 @@
-import { useCallback, useEffect, useState } from 'react';
+import {
+  useCallback, useEffect, useState, useRef,
+} from 'react';
 
 import { GlobalCodeMirrorEditorKey } from '@growi/editor';
 import { acceptChange, rejectChange } from '@growi/editor/dist/client/services/unified-merge-view';
@@ -38,11 +40,13 @@ type DetectedDiff = Array<{
 }>
 
 export const useEditorAssistant = (): {postMessage: PostMessage, processMessage: ProcessMessage, accept: () => void, reject: () => void } => {
+  const positionRef = useRef<number>(0);
+
   const [detectedDiff, setDetectedDiff] = useState<DetectedDiff>();
 
   const { data: currentPageId } = useCurrentPageId();
-  const { data: isEnableUnifiedMergeView, mutate: mutateIsEnableUnifiedMergeView } = useIsEnableUnifiedMergeView();
   const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);
+  const { data: isEnableUnifiedMergeView, mutate: mutateIsEnableUnifiedMergeView } = useIsEnableUnifiedMergeView();
   const ydocs = useSecondaryYdocs(isEnableUnifiedMergeView ?? false, { pageId: currentPageId ?? undefined, useSecondary: isEnableUnifiedMergeView ?? false });
 
   const postMessage: PostMessage = useCallback(async(threadId, userMessage, markdown) => {
@@ -89,21 +93,43 @@ export const useEditorAssistant = (): {postMessage: PostMessage, processMessage:
   }, [codeMirrorEditor?.view, mutateIsEnableUnifiedMergeView]);
 
   useEffect(() => {
+    const markdown = codeMirrorEditor?.getDoc();
+
     const pendingDetectedDiff: DetectedDiff | undefined = detectedDiff?.filter(diff => diff.applied === false);
-    if (ydocs?.secondaryDoc != null && pendingDetectedDiff != null && pendingDetectedDiff.length > 0) {
+    if (markdown != null && ydocs?.secondaryDoc != null && pendingDetectedDiff != null && pendingDetectedDiff.length > 0) {
+
+      // For debug
+      // const testDetectedDiff = [
+      //   {
+      //     data: { diff: { retain: 9 } },
+      //     applied: false,
+      //     id: crypto.randomUUID(),
+      //   },
+      //   {
+      //     data: { diff: { delete: 5 } },
+      //     applied: false,
+      //     id: crypto.randomUUID(),
+      //   },
+      //   {
+      //     data: { diff: { insert: 'growi' } },
+      //     applied: false,
+      //     id: crypto.randomUUID(),
+      //   },
+      // ];
 
-      // Apply detectedDiffs to secondaryDoc
       const ytext = ydocs.secondaryDoc.getText('codemirror');
-      pendingDetectedDiff.forEach((detectedDiff) => {
-        if (isInsertDiff(detectedDiff.data)) {
-          ytext.insert(0, detectedDiff.data.diff.insert);
-        }
-        if (isDeleteDiff(detectedDiff.data)) {
-          // TODO: https://redmine.weseek.co.jp/issues/163945
-        }
-        if (isRetainDiff(detectedDiff.data)) {
-          // TODO: https://redmine.weseek.co.jp/issues/163945
-        }
+      ydocs.secondaryDoc.transact(() => {
+        pendingDetectedDiff.forEach((detectedDiff) => {
+          if (isInsertDiff(detectedDiff.data)) {
+            ytext.insert(positionRef.current, detectedDiff.data.diff.insert);
+          }
+          if (isDeleteDiff(detectedDiff.data)) {
+            ytext.delete(positionRef.current, detectedDiff.data.diff.delete);
+          }
+          if (isRetainDiff(detectedDiff.data)) {
+            positionRef.current += detectedDiff.data.diff.retain;
+          }
+        });
       });
 
       // Mark as applied: true after applying to secondaryDoc
@@ -120,9 +146,10 @@ export const useEditorAssistant = (): {postMessage: PostMessage, processMessage:
       // Set detectedDiff to undefined after applying all detectedDiff to secondaryDoc
       if (detectedDiff?.filter(detectedDiff => detectedDiff.applied === false).length === 0) {
         setDetectedDiff(undefined);
+        positionRef.current = 0;
       }
     }
-  }, [detectedDiff, ydocs?.secondaryDoc]);
+  }, [codeMirrorEditor, detectedDiff, ydocs?.secondaryDoc]);
 
   return {
     postMessage,