diff --git a/services/web/public/coffee/ide/editor/Document.coffee b/services/web/public/coffee/ide/editor/Document.coffee index 78431b8b6b..005d722a56 100644 --- a/services/web/public/coffee/ide/editor/Document.coffee +++ b/services/web/public/coffee/ide/editor/Document.coffee @@ -265,10 +265,10 @@ define [ @ide.pushEvent "externalUpdate", doc_id: @doc_id @trigger "externalUpdate", update - @doc.on "remoteop", () => + @doc.on "remoteop", (args...) => @ide.pushEvent "remoteop", doc_id: @doc_id - @trigger "remoteop" + @trigger "remoteop", args... @doc.on "op:sent", (op) => @ide.pushEvent "op:sent", doc_id: @doc_id diff --git a/services/web/public/coffee/ide/editor/ShareJsDoc.coffee b/services/web/public/coffee/ide/editor/ShareJsDoc.coffee index 27d325676c..4f9960f9a0 100644 --- a/services/web/public/coffee/ide/editor/ShareJsDoc.coffee +++ b/services/web/public/coffee/ide/editor/ShareJsDoc.coffee @@ -47,11 +47,11 @@ define [ @trigger "change" @_doc.on "acknowledge", () => @trigger "acknowledge" - @_doc.on "remoteop", () => + @_doc.on "remoteop", (args...) => # As soon as we're working with a collaborator, start sending # ops as quickly as possible for low latency. @_doc.setFlushDelay(0) - @trigger "remoteop" + @trigger "remoteop", args... @_doc.on "error", (e) => @_handleError(e) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index 4a697f39f9..bc4e656a1c 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee @@ -235,8 +235,9 @@ define [ doc = session.getDocument() doc.on "change", onChange - sharejs_doc.on "remoteop.recordForUndo", () => + sharejs_doc.on "remoteop.recordRemote", (op, oldSnapshot, msg) -> undoManager.nextUpdateIsRemote = true + trackChangesManager.nextUpdateMetaData = msg?.meta editor.initing = true sharejs_doc.attachToAce(editor) @@ -255,7 +256,7 @@ define [ detachFromAce = (sharejs_doc) -> sharejs_doc.detachFromAce() - sharejs_doc.off "remoteop.recordForUndo" + sharejs_doc.off "remoteop.recordRemote" session = editor.getSession() session.off "changeScrollTop" diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.coffee index 47026eeb04..abcb8817c1 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.coffee @@ -23,10 +23,24 @@ define [ onChange = (e) => if !@editor.initing and @enabled - @applyChange(e) + # This change is trigger by a sharejs 'change' event, which is before the + # sharejs 'remoteop' event. So wait until the next event loop when the 'remoteop' + # will have fired, before we decide if it was a remote op. setTimeout () => - @checkMapping() - , 100 + if @nextUpdateMetaData? + # The remote op may have contained multiple atomic ops, each of which is an Ace + # 'change' event (i.e. bulk commenting out of lines is a single remote op + # but gives us one event for each % inserted). These all come in a single event loop + # though, so wait until the next one before clearing the metadata. + setTimeout () => + @nextUpdateMetaData = null + + @applyChange(e) + + # TODO: Just for debugging, remove before going live. + setTimeout () => + @checkMapping() + , 100 @editor.on "changeSession", (e) => e.oldSession?.getDocument().off "change", onChange @@ -176,6 +190,7 @@ define [ marker = markers[marker_id] marker.range.start = start marker.range.end = end + @editor.renderer.updateBackMarkers() @updateReviewEntriesScope() class ChangesTracker extends EventEmitter diff --git a/services/web/public/coffee/ide/editor/sharejs/vendor/client/doc.coffee b/services/web/public/coffee/ide/editor/sharejs/vendor/client/doc.coffee index dd4f26ceb0..d25baf89d5 100644 --- a/services/web/public/coffee/ide/editor/sharejs/vendor/client/doc.coffee +++ b/services/web/public/coffee/ide/editor/sharejs/vendor/client/doc.coffee @@ -64,7 +64,7 @@ class Doc server_ = @type.transform server, client, 'right' return [client_, server_] - _otApply: (docOp, isRemote) -> + _otApply: (docOp, isRemote, msg) -> oldSnapshot = @snapshot @snapshot = @type.apply(@snapshot, docOp) @@ -72,7 +72,7 @@ class Doc # The reason is that the OT type APIs might need to access the snapshots to # determine information about the received op. @emit 'change', docOp, oldSnapshot - @emit 'remoteop', docOp, oldSnapshot if isRemote + @emit 'remoteop', docOp, oldSnapshot, msg if isRemote _connectionStateChanged: (state, data) -> switch state @@ -185,7 +185,7 @@ class Doc # functionality, because its really a local op. Basically, the problem is that # if the client's op is rejected by the server, the editor window should update # to reflect the undo. - @_otApply undo, true + @_otApply undo, true, msg else @emit 'error', "Op apply failed (#{error}) and the op could not be reverted" @@ -234,7 +234,7 @@ class Doc @version++ # Finally, apply the op to @snapshot and trigger any event listeners - @_otApply docOp, true + @_otApply docOp, true, msg else if msg.meta {path, value} = msg.meta