diff --git a/services/web/frontend/js/features/ide-react/editor/share-js-doc.ts b/services/web/frontend/js/features/ide-react/editor/share-js-doc.ts index a773684dcb..96e866afec 100644 --- a/services/web/frontend/js/features/ide-react/editor/share-js-doc.ts +++ b/services/web/frontend/js/features/ide-react/editor/share-js-doc.ts @@ -365,7 +365,7 @@ export class ShareJsDoc extends EventEmitter { attachToCM6(cm6: EditorFacade) { this.attachToEditor(cm6, () => { - cm6.attachShareJs(this._doc, getMeta('ol-maxDocLength'), this.type) + cm6.attachShareJs(this._doc, getMeta('ol-maxDocLength')) }) } diff --git a/services/web/frontend/js/features/source-editor/extensions/realtime.ts b/services/web/frontend/js/features/source-editor/extensions/realtime.ts index 44c28cb9ad..36d9956a76 100644 --- a/services/web/frontend/js/features/source-editor/extensions/realtime.ts +++ b/services/web/frontend/js/features/source-editor/extensions/realtime.ts @@ -5,7 +5,6 @@ import RangesTracker from '@overleaf/ranges-tracker' import { ShareDoc } from '../../../../../types/share-doc' import { debugConsole } from '@/utils/debugging' import { DocumentContainer } from '@/features/ide-react/editor/document-container' -import { OTType } from '@/features/ide-react/editor/share-js-doc' /* * Integrate CodeMirror 6 with the real-time system, via ShareJS. @@ -77,22 +76,15 @@ export const realtime = ( return Prec.highest([realtimePlugin, ensureRealtimePlugin]) } -type OTAdapter = { - handleUpdateFromCM( - transactions: readonly Transaction[], - ranges?: RangesTracker - ): void - attachShareJs(): void -} - export class EditorFacade extends EventEmitter { - private otAdapter: OTAdapter | null + public shareDoc: ShareDoc | null public events: EventEmitter + private maxDocLength?: number constructor(public view: EditorView) { super() this.view = view - this.otAdapter = null + this.shareDoc = null this.events = new EventEmitter() } @@ -126,56 +118,23 @@ export class EditorFacade extends EventEmitter { this.cmChange({ from: position, to: position + text.length }, origin) } - attachShareJs(shareDoc: ShareDoc, maxDocLength?: number, type?: OTType) { - this.otAdapter = - type === 'history-ot' - ? new HistoryOTAdapter(this, shareDoc, maxDocLength) - : new ShareLatexOTAdapter(this, shareDoc, maxDocLength) - this.otAdapter.attachShareJs() - } - - detachShareJs() { - this.otAdapter = null - } - - handleUpdateFromCM( - transactions: readonly Transaction[], - ranges?: RangesTracker - ) { - if (this.otAdapter == null) { - throw new Error('Trying to process updates with no otAdapter') - } - - this.otAdapter.handleUpdateFromCM(transactions, ranges) - } -} - -class ShareLatexOTAdapter { - constructor( - public editor: EditorFacade, - private shareDoc: ShareDoc, - private maxDocLength?: number - ) { - this.editor = editor - this.shareDoc = shareDoc - this.maxDocLength = maxDocLength - } - // Connect to ShareJS, passing changes to the CodeMirror view // as new transactions. // This is a broad immitation of helper functions supplied in // the sharejs library. (See vendor/libs/sharejs, in particular // the 'attach_ace' helper) - attachShareJs() { - const shareDoc = this.shareDoc + attachShareJs(shareDoc: ShareDoc, maxDocLength?: number) { + this.shareDoc = shareDoc + this.maxDocLength = maxDocLength + const check = () => { // run in a timeout so it checks the editor content once this update has been applied window.setTimeout(() => { - const editorText = this.editor.getValue() + const editorText = this.getValue() const otText = shareDoc.getText() if (editorText !== otText) { - this.shareDoc.emit('error', 'Text does not match in CodeMirror 6') + shareDoc.emit('error', 'Text does not match in CodeMirror 6') debugConsole.error('Text does not match!') debugConsole.error('editor: ' + editorText) debugConsole.error('ot: ' + otText) @@ -184,12 +143,12 @@ class ShareLatexOTAdapter { } const onInsert = (pos: number, text: string) => { - this.editor.cmInsert(pos, text, 'remote') + this.cmInsert(pos, text, 'remote') check() } const onDelete = (pos: number, text: string) => { - this.editor.cmDelete(pos, text, 'remote') + this.cmDelete(pos, text, 'remote') check() } @@ -202,7 +161,7 @@ class ShareLatexOTAdapter { shareDoc.removeListener('insert', onInsert) shareDoc.removeListener('delete', onDelete) delete shareDoc.detach_cm6 - this.editor.detachShareJs() + this.shareDoc = null } } @@ -216,6 +175,10 @@ class ShareLatexOTAdapter { const trackedDeletesLength = ranges != null ? ranges.getTrackedDeletesLength() : 0 + if (!shareDoc) { + throw new Error('Trying to process updates with no shareDoc') + } + for (const transaction of transactions) { if (transaction.docChanged) { const origin = chooseOrigin(transaction) @@ -271,7 +234,7 @@ class ShareLatexOTAdapter { removed, } - this.editor.emit('change', this, changeDescription) + this.emit('change', this, changeDescription) } ) } @@ -279,8 +242,6 @@ class ShareLatexOTAdapter { } } -class HistoryOTAdapter extends ShareLatexOTAdapter {} - export const trackChangesAnnotation = Annotation.define() const chooseOrigin = (transaction: Transaction) => {