Yuki Takei 1 an în urmă
părinte
comite
bebf64b15f

+ 24 - 56
packages/editor/src/client/services-internal/unified-merge-view/use-unified-merge-view.ts

@@ -5,44 +5,13 @@ import {
   originalDocChangeEffect,
   getOriginalDoc,
 } from '@codemirror/merge';
-import { ChangeSet, type ChangeSpec, StateField } from '@codemirror/state';
+import { StateField, ChangeSet } from '@codemirror/state';
 
-import type { Delta } from '../../../interfaces';
+import { deltaToChangeSpecs } from '../../../utils/delta-to-changespecs';
 import type { UseCodeMirrorEditor } from '../../services';
 import { collaborativeChange } from '../../stores/use-collaborative-editor-mode';
 
 
-function deltaToChangeSet(delta: Delta, docLength: number): ChangeSet {
-  const changes: ChangeSpec[] = [];
-  let pos = 0;
-
-  for (const op of delta) {
-    if (op.retain != null) {
-      pos += op.retain;
-    }
-
-    if (op.delete != null) {
-      changes.push({
-        from: pos,
-        to: pos + op.delete,
-      });
-    }
-
-    if (op.insert != null) {
-      changes.push({
-        from: pos,
-        insert: typeof op.insert === 'string' ? op.insert : '',
-      });
-      if (typeof op.insert === 'string') {
-        pos += op.insert.length;
-      }
-    }
-  }
-
-  return ChangeSet.of(changes, docLength);
-}
-
-
 export const useUnifiedMergeView = (
     unifiedMergeViewEnabled?: boolean,
     codeMirrorEditor?: UseCodeMirrorEditor,
@@ -63,36 +32,35 @@ export const useUnifiedMergeView = (
     return cleanupFunction;
   }, [codeMirrorEditor, unifiedMergeViewEnabled]);
 
+  // effect for updating orignal document by collaborative changes
   useEffect(() => {
     if (!unifiedMergeViewEnabled || codeMirrorEditor == null) {
       return;
     }
 
-    const extension = unifiedMergeViewEnabled ? [
-      // collaborative changes を追跡し、original document を更新する
-      StateField.define({
-        create: () => null,
-        update(value, tr) {
-          if (codeMirrorEditor.view?.state == null) {
-            return value;
+    const extension = StateField.define({
+      create: () => null,
+      update(value, tr) {
+        if (codeMirrorEditor.state == null) {
+          return value;
+        }
+
+        for (const e of tr.effects) {
+          if (e.is(collaborativeChange)) {
+            const changeSpecs = deltaToChangeSpecs(e.value);
+            const changeSet = ChangeSet.of(changeSpecs, getOriginalDoc(tr.state).length);
+            const effect = originalDocChangeEffect(tr.state, changeSet);
+            setTimeout(() => {
+              codeMirrorEditor.view?.dispatch({
+                effects: effect,
+              });
+            }, 0);
           }
+        }
 
-          for (const e of tr.effects) {
-            if (e.is(collaborativeChange)) {
-              // original document を更新
-              const changeSet = deltaToChangeSet(e.value, getOriginalDoc(codeMirrorEditor.view.state).length);
-              const effect = originalDocChangeEffect(tr.state, changeSet);
-              setTimeout(() => {
-                codeMirrorEditor.view?.dispatch({
-                  effects: effect,
-                });
-              }, 0);
-            }
-          }
-          return value;
-        },
-      }),
-    ] : [];
+        return value;
+      },
+    });
 
     const cleanupFunction = codeMirrorEditor.appendExtensions(extension);
     return cleanupFunction;

+ 33 - 0
packages/editor/src/utils/delta-to-changespecs.ts

@@ -0,0 +1,33 @@
+import { type ChangeSpec } from '@codemirror/state';
+
+import type { Delta } from '../interfaces';
+
+export const deltaToChangeSpecs = (delta: Delta): ChangeSpec[] => {
+  const changes: ChangeSpec[] = [];
+  let pos = 0;
+
+  for (const op of delta) {
+    if (op.retain != null) {
+      pos += op.retain;
+    }
+
+    if (op.delete != null) {
+      changes.push({
+        from: pos,
+        to: pos + op.delete,
+      });
+    }
+
+    if (op.insert != null) {
+      changes.push({
+        from: pos,
+        insert: typeof op.insert === 'string' ? op.insert : '',
+      });
+      if (typeof op.insert === 'string') {
+        pos += op.insert.length;
+      }
+    }
+  }
+
+  return changes;
+};