mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Stop local and remote ops being batched together in the undo manager if they happen in the same flush
This commit is contained in:
parent
a8756432b7
commit
a6679a1aeb
3 changed files with 77 additions and 30 deletions
|
@ -322,10 +322,6 @@ define [
|
|||
doc = session.getDocument()
|
||||
doc.on "change", onChange
|
||||
|
||||
sharejs_doc.on "remoteop.recordRemote", (op, oldSnapshot, msg) ->
|
||||
undoManager.nextUpdateIsRemote = true
|
||||
trackChangesManager.nextUpdateMetaData = msg?.meta
|
||||
|
||||
editor.initing = true
|
||||
sharejs_doc.attachToAce(editor)
|
||||
editor.initing = false
|
||||
|
|
|
@ -11,10 +11,10 @@ define [
|
|||
show_remote_warning: false
|
||||
|
||||
@reset()
|
||||
@nextUpdateIsRemote = false
|
||||
|
||||
@editor.on "changeSession", (e) =>
|
||||
@reset()
|
||||
@session = e.session
|
||||
e.session.setUndoManager(@)
|
||||
|
||||
showUndoConflictWarning: () ->
|
||||
|
@ -38,20 +38,44 @@ define [
|
|||
@firstUpdate = false
|
||||
return
|
||||
aceDeltaSets = options.args[0]
|
||||
@session = options.args[1]
|
||||
return if !aceDeltaSets?
|
||||
@session = options.args[1]
|
||||
|
||||
lines = @session.getDocument().getAllLines()
|
||||
linesBeforeChange = @_revertAceDeltaSetsOnDocLines(aceDeltaSets, lines)
|
||||
simpleDeltaSets = @_aceDeltaSetsToSimpleDeltaSets(aceDeltaSets, linesBeforeChange)
|
||||
@undoStack.push(
|
||||
deltaSets: simpleDeltaSets
|
||||
remote: @nextUpdateIsRemote
|
||||
)
|
||||
# We need to split the delta sets into local or remote groups before pushing onto
|
||||
# the undo stack, since these are treated differently.
|
||||
splitDeltaSets = []
|
||||
currentDeltaSet = null # Make global to this function
|
||||
do newDeltaSet = () ->
|
||||
currentDeltaSet = {group: "doc", deltas: []}
|
||||
splitDeltaSets.push currentDeltaSet
|
||||
currentRemoteState = null
|
||||
|
||||
for deltaSet in aceDeltaSets or []
|
||||
if deltaSet.group == "doc" # ignore code folding etc.
|
||||
for delta in deltaSet.deltas
|
||||
if currentDeltaSet.remote? and currentDeltaSet.remote != !!delta.remote
|
||||
newDeltaSet()
|
||||
currentDeltaSet.deltas.push delta
|
||||
currentDeltaSet.remote = !!delta.remote
|
||||
|
||||
# The lines are currently as they are after applying all these deltas, but to turn into simple deltas,
|
||||
# we need the lines before each delta group.
|
||||
docLines = @session.getDocument().getAllLines()
|
||||
docLines = @_revertAceDeltaSetsOnDocLines(aceDeltaSets, docLines)
|
||||
for deltaSet in splitDeltaSets
|
||||
{simpleDeltaSet, docLines} = @_aceDeltaSetToSimpleDeltaSet(deltaSet, docLines)
|
||||
frame = {
|
||||
deltaSets: [simpleDeltaSet]
|
||||
remote: deltaSet.remote
|
||||
}
|
||||
@undoStack.push frame
|
||||
@redoStack = []
|
||||
@nextUpdateIsRemote = false
|
||||
|
||||
undo: (dontSelect) ->
|
||||
# We rely on the doclines being in sync with the undo stack, so make sure
|
||||
# any pending undo deltas are processed.
|
||||
@session.$syncInformUndoManager()
|
||||
|
||||
localUpdatesMade = @_shiftLocalChangeToTopOfUndoStack()
|
||||
return if !localUpdatesMade
|
||||
|
||||
|
@ -206,19 +230,16 @@ define [
|
|||
throw "Unknown delta type"
|
||||
return doc.split("\n")
|
||||
|
||||
_aceDeltaSetsToSimpleDeltaSets: (aceDeltaSets, docLines) ->
|
||||
simpleDeltaSets = []
|
||||
for deltaSet in aceDeltaSets
|
||||
if deltaSet.group == "doc" # ignore fold changes
|
||||
simpleDeltas = []
|
||||
for delta in deltaSet.deltas
|
||||
simpleDeltas.push @_aceDeltaToSimpleDelta(delta, docLines)
|
||||
docLines = @_applyAceDeltasToDocLines([delta], docLines)
|
||||
simpleDeltaSets.push {
|
||||
deltas: simpleDeltas
|
||||
group: deltaSet.group
|
||||
}
|
||||
return simpleDeltaSets
|
||||
_aceDeltaSetToSimpleDeltaSet: (deltaSet, docLines) ->
|
||||
simpleDeltas = []
|
||||
for delta in deltaSet.deltas
|
||||
simpleDeltas.push @_aceDeltaToSimpleDelta(delta, docLines)
|
||||
docLines = @_applyAceDeltasToDocLines([delta], docLines)
|
||||
simpleDeltaSet = {
|
||||
deltas: simpleDeltas
|
||||
group: deltaSet.group
|
||||
}
|
||||
return {simpleDeltaSet, docLines}
|
||||
|
||||
_simpleDeltaSetsToAceDeltaSets: (simpleDeltaSets, docLines) ->
|
||||
for deltaSet in simpleDeltaSets
|
||||
|
|
|
@ -110,16 +110,46 @@ window.sharejs.extendDoc 'attach_ace', (editor, keepEditorContents, maxDocLength
|
|||
|
||||
row:row, column:offset
|
||||
|
||||
# We want to insert a remote:true into the delta if the op comes from the
|
||||
# underlying sharejs doc (which means it is from a remote op), so we have to do
|
||||
# the work of editorDoc.insert and editorDoc.remove manually. These methods are
|
||||
# copied from ace.js doc#insert and #remove, and then inject the remote:true
|
||||
# flag into the delta.
|
||||
doc.on 'insert', (pos, text) ->
|
||||
if (editorDoc.getLength() <= 1)
|
||||
editorDoc.$detectNewLine(text)
|
||||
|
||||
lines = editorDoc.$split(text)
|
||||
position = offsetToPos(pos)
|
||||
start = editorDoc.clippedPos(position.row, position.column)
|
||||
end = {
|
||||
row: start.row + lines.length - 1,
|
||||
column: (if lines.length == 1 then start.column else 0) + lines[lines.length - 1].length
|
||||
}
|
||||
|
||||
suppress = true
|
||||
editorDoc.insert offsetToPos(pos), text
|
||||
editorDoc.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "insert",
|
||||
lines: lines,
|
||||
remote: true
|
||||
});
|
||||
suppress = false
|
||||
check()
|
||||
|
||||
doc.on 'delete', (pos, text) ->
|
||||
suppress = true
|
||||
range = Range.fromPoints offsetToPos(pos), offsetToPos(pos + text.length)
|
||||
editorDoc.remove range
|
||||
start = editorDoc.clippedPos(range.start.row, range.start.column)
|
||||
end = editorDoc.clippedPos(range.end.row, range.end.column)
|
||||
suppress = true
|
||||
editorDoc.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "remove",
|
||||
lines: editorDoc.getLinesForRange({start: start, end: end})
|
||||
remote: true
|
||||
});
|
||||
suppress = false
|
||||
check()
|
||||
|
||||
|
|
Loading…
Reference in a new issue