Merge pull request #22527 from overleaf/revert-22471-em-tracked-deletes-at-same-position

Revert "Improve handling of tracked delete rejections"

GitOrigin-RevId: 444a5a73aa2b93162036dfc463cd76d9c463aadb
This commit is contained in:
Eric Mc Sween
2024-12-16 09:05:10 +00:00
committed by Copybot
parent f2d6c73f75
commit a323a5c915
5 changed files with 10 additions and 202 deletions
+8 -29
View File
@@ -313,11 +313,10 @@ class RangesTracker {
let alreadyMerged = false
let previousChange = null
let trackedDeleteRejected = false
const movedChanges = []
const removeChanges = []
const newChanges = []
const trackedDeletesAtOpPosition = []
for (let i = 0; i < this.changes.length; i++) {
change = this.changes[i]
const changeStart = change.op.p
@@ -328,22 +327,13 @@ class RangesTracker {
change.op.p += opLength
movedChanges.push(change)
} else if (opStart === changeStart) {
// Keep track of tracked deletes that are at the same position as the
// insert. At the end of the loop, if we didn't find a tracked delete
// to reject, we'll move these deletes after the insert.
trackedDeletesAtOpPosition.push(change)
if (trackedDeleteRejected && op.orderedRejections) {
// We rejected a tracked delete. Move the remaining tracked deletes after the insert
change.op.p += opLength
movedChanges.push(change)
} else if (
// If we are undoing, then we want to cancel any existing delete ranges if we can.
// Check if the insert matches the start of the delete, and just remove it from the delete instead if so.
if (
undoing &&
change.op.d.length >= op.i.length &&
change.op.d.slice(0, op.i.length) === op.i
) {
// If we are undoing, then we want to reject any existing tracked delete if we can.
// Check if the insert matches the start of the delete, and just remove it from the delete instead if so.
change.op.d = change.op.d.slice(op.i.length)
change.op.p += op.i.length
if (change.op.d === '') {
@@ -352,7 +342,9 @@ class RangesTracker {
movedChanges.push(change)
}
alreadyMerged = true
trackedDeleteRejected = true
} else {
change.op.p += opLength
movedChanges.push(change)
}
}
} else if (change.op.i != null) {
@@ -457,15 +449,6 @@ class RangesTracker {
previousChange = change
}
if (!trackedDeleteRejected || !op.orderedRejections) {
// We didn't reject any tracked delete. Move all existing tracked deletes
// at the insert position after the insert
for (const change of trackedDeletesAtOpPosition) {
change.op.p += opLength
movedChanges.push(change)
}
}
if (this.track_changes && !alreadyMerged) {
this._addOp(op, metadata)
}
@@ -641,13 +624,9 @@ class RangesTracker {
}
_addOp(op, metadata) {
// Don't take a reference to the existing op since we'll modify this in place with future changes
op = this._clone(op)
// TODO: Remove this when the orderedRejections transition is over
delete op.orderedRejections
const change = {
id: this.newId(),
op,
op: this._clone(op), // Don't take a reference to the existing op since we'll modify this in place with future changes
metadata: this._clone(metadata),
}
this.changes.push(change)
@@ -4,7 +4,6 @@ const RangesTracker = require('../..')
describe('RangesTracker', function () {
describe('with duplicate change ids', function () {
beforeEach(function () {
this.comments = []
this.changes = [
{ id: 'id1', op: { p: 1, i: 'hello' } },
{ id: 'id2', op: { p: 10, i: 'world' } },
@@ -27,116 +26,4 @@ describe('RangesTracker', function () {
expect(this.rangesTracker.changes).to.deep.equal([this.changes[2]])
})
})
describe('with multiple tracked deletes at the same position', function () {
beforeEach(function () {
this.comments = []
this.changes = [
{ id: 'id1', op: { p: 33, d: 'before' } },
{ id: 'id2', op: { p: 50, d: 'right before' } },
{ id: 'id3', op: { p: 50, d: 'this one' } },
{ id: 'id4', op: { p: 50, d: 'right after' } },
{ id: 'id5', op: { p: 75, d: 'long after' } },
]
this.rangesTracker = new RangesTracker(this.changes, this.comments)
})
describe('with the orderedRejections flag', function () {
it('preserves the text order when rejecting changes', function () {
this.rangesTracker.applyOp(
{ p: 50, i: 'this one', u: true, orderedRejections: true },
{ user_id: 'user-id' }
)
expect(this.rangesTracker.changes).to.deep.equal([
{ id: 'id1', op: { p: 33, d: 'before' } },
{ id: 'id2', op: { p: 50, d: 'right before' } },
{ id: 'id4', op: { p: 58, d: 'right after' } },
{ id: 'id5', op: { p: 83, d: 'long after' } },
])
})
it('moves all tracked deletes after the insert if not rejecting changes', function () {
this.rangesTracker.applyOp(
{ p: 50, i: 'some other text', u: true, orderedRejections: true },
{ user_id: 'user-id' }
)
expect(this.rangesTracker.changes).to.deep.equal([
{ id: 'id1', op: { p: 33, d: 'before' } },
{ id: 'id2', op: { p: 65, d: 'right before' } },
{ id: 'id3', op: { p: 65, d: 'this one' } },
{ id: 'id4', op: { p: 65, d: 'right after' } },
{ id: 'id5', op: { p: 90, d: 'long after' } },
])
})
})
describe('without the orderedRejections flag', function () {
it('puts the insert before tracked deletes when rejecting changes', function () {
this.rangesTracker.applyOp(
{ p: 50, i: 'this one', u: true },
{ user_id: 'user-id' }
)
expect(this.rangesTracker.changes).to.deep.equal([
{ id: 'id1', op: { p: 33, d: 'before' } },
{ id: 'id2', op: { p: 58, d: 'right before' } },
{ id: 'id4', op: { p: 58, d: 'right after' } },
{ id: 'id5', op: { p: 83, d: 'long after' } },
])
})
it('moves all tracked deletes after the insert if not rejecting changes', function () {
this.rangesTracker.applyOp(
{ p: 50, i: 'some other text', u: true },
{ user_id: 'user-id' }
)
expect(this.rangesTracker.changes).to.deep.equal([
{ id: 'id1', op: { p: 33, d: 'before' } },
{ id: 'id2', op: { p: 65, d: 'right before' } },
{ id: 'id3', op: { p: 65, d: 'this one' } },
{ id: 'id4', op: { p: 65, d: 'right after' } },
{ id: 'id5', op: { p: 90, d: 'long after' } },
])
})
})
})
describe('with multiple tracked deletes at the same position with the same content', function () {
beforeEach(function () {
this.comments = []
this.changes = [
{ id: 'id1', op: { p: 10, d: 'cat' } },
{ id: 'id2', op: { p: 10, d: 'giraffe' } },
{ id: 'id3', op: { p: 10, d: 'cat' } },
{ id: 'id4', op: { p: 10, d: 'giraffe' } },
]
this.rangesTracker = new RangesTracker(this.changes, this.comments)
})
describe('with the orderedRejections flag', function () {
it('removes only the first matching tracked delete', function () {
this.rangesTracker.applyOp(
{ p: 10, i: 'giraffe', u: true, orderedRejections: true },
{ user_id: 'user-id' }
)
expect(this.rangesTracker.changes).to.deep.equal([
{ id: 'id1', op: { p: 10, d: 'cat' } },
{ id: 'id3', op: { p: 17, d: 'cat' } },
{ id: 'id4', op: { p: 17, d: 'giraffe' } },
])
})
})
describe('without the orderedRejections flag', function () {
it('removes all matching tracked delete', function () {
this.rangesTracker.applyOp(
{ p: 10, i: 'giraffe', u: true },
{ user_id: 'user-id' }
)
expect(this.rangesTracker.changes).to.deep.equal([
{ id: 'id1', op: { p: 17, d: 'cat' } },
{ id: 'id3', op: { p: 17, d: 'cat' } },
])
})
})
})
})