|
|
@@ -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;
|