|
1 | 1 | import { useEffect, useState } from 'react';
|
2 |
| -import { EditorState, StateEffect } from '@codemirror/state'; |
| 2 | +import { Annotation, EditorState, StateEffect } from '@codemirror/state'; |
3 | 3 | import { indentWithTab } from '@codemirror/commands';
|
4 | 4 | import { EditorView, keymap, ViewUpdate, placeholder } from '@codemirror/view';
|
5 | 5 | import { basicSetup } from '@uiw/codemirror-extensions-basic-setup';
|
6 | 6 | import { oneDark } from '@codemirror/theme-one-dark';
|
7 | 7 | import { getStatistics } from './utils';
|
8 | 8 | import { ReactCodeMirrorProps } from '.';
|
9 | 9 |
|
| 10 | +const External = Annotation.define<boolean>(); |
| 11 | + |
10 | 12 | export interface UseCodeMirror extends ReactCodeMirrorProps {
|
11 | 13 | container?: HTMLDivElement | null;
|
12 | 14 | }
|
@@ -60,7 +62,13 @@ export function useCodeMirror(props: UseCodeMirror) {
|
60 | 62 | },
|
61 | 63 | });
|
62 | 64 | const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
|
63 |
| - if (vu.docChanged && typeof onChange === 'function') { |
| 65 | + if ( |
| 66 | + vu.docChanged && |
| 67 | + typeof onChange === 'function' && |
| 68 | + // Fix echoing of the remote changes: |
| 69 | + // If transaction is market as remote we don't have to call `onChange` handler again |
| 70 | + !vu.transactions.some((tr) => tr.annotation(External)) |
| 71 | + ) { |
64 | 72 | const doc = vu.state.doc;
|
65 | 73 | const value = doc.toString();
|
66 | 74 | onChange(value, vu);
|
@@ -188,6 +196,7 @@ export function useCodeMirror(props: UseCodeMirror) {
|
188 | 196 | if (view && value !== currentValue) {
|
189 | 197 | view.dispatch({
|
190 | 198 | changes: { from: 0, to: currentValue.length, insert: value || '' },
|
| 199 | + annotations: [External.of(true)], |
191 | 200 | });
|
192 | 201 | }
|
193 | 202 | }, [value, view]);
|
|
0 commit comments