mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-09-06 13:04:53 +08:00
Merge undo stack for collaborative editing (#433)
This commit is contained in:
parent
0c9e25d1be
commit
6d9fb90953
1 changed files with 32 additions and 9 deletions
|
@ -10,11 +10,15 @@ export default class MonacoEditorAdapter {
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this._onDelta = null;
|
this._onDelta = null;
|
||||||
|
this.isLastChangeRemote = false;
|
||||||
|
|
||||||
this.editor.onDidChangeModelContent((event) => {
|
this.editor.onDidChangeModelContent((event) => {
|
||||||
if (this.ignoreChange) {
|
if (this.ignoreChange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isLastChangeRemote = false;
|
||||||
|
|
||||||
const delta = this.__deltaFromEditorChange(event);
|
const delta = this.__deltaFromEditorChange(event);
|
||||||
this._onDelta && this._onDelta(delta);
|
this._onDelta && this._onDelta(delta);
|
||||||
});
|
});
|
||||||
|
@ -32,19 +36,38 @@ export default class MonacoEditorAdapter {
|
||||||
* Applies the given delta to the editor content.
|
* Applies the given delta to the editor content.
|
||||||
*/
|
*/
|
||||||
applyDelta(delta) {
|
applyDelta(delta) {
|
||||||
|
const isStandaloneChange = delta.ops.some((op) => {
|
||||||
|
if (isDelete(op)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInsert(op)) {
|
||||||
|
return op.insert.match(/\s+/);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Explicitly close the last stack element when the remote
|
||||||
|
// change inserts whitespace or deletes text. Otherwise
|
||||||
|
// merge subsequent remote changes whenever possible.
|
||||||
|
if (isStandaloneChange || !this.isLastChangeRemote) {
|
||||||
|
this.editor.getModel().pushStackElement();
|
||||||
|
} else {
|
||||||
|
this.editor.getModel().popStackElement();
|
||||||
|
}
|
||||||
|
|
||||||
const operations = this.__deltaToEditorOperations(delta);
|
const operations = this.__deltaToEditorOperations(delta);
|
||||||
this.ignoreChange = true;
|
this.ignoreChange = true;
|
||||||
// Apply the operations without adding them to the undo stack
|
// Apply the operations and add them to the undo stack
|
||||||
this.editor.getModel().applyEdits(operations);
|
this.editor.getModel().pushEditOperations(null, operations, null);
|
||||||
|
// Close the stack element upfront in case the next
|
||||||
|
// change is local. If another remote change comes,
|
||||||
|
// we open the element back using `popStackElement`.
|
||||||
|
this.editor.getModel().pushStackElement();
|
||||||
this.ignoreChange = false;
|
this.ignoreChange = false;
|
||||||
|
|
||||||
// Clear the undo/redo stack as the operations may no longer be valid
|
this.isLastChangeRemote = true;
|
||||||
// after applying the concurrent change.
|
|
||||||
// Note: there's not public method for getting EditStack for the text model,
|
|
||||||
// so we use the private attribute.
|
|
||||||
// (https://github.com/microsoft/vscode/blob/11ac71b27220a2354b6bb28966ed3ead183cc495/src/vs/editor/common/model/textModel.ts#L287)
|
|
||||||
const editStack = this.editor.getModel()._commandManager;
|
|
||||||
editStack.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__deltaFromEditorChange(event) {
|
__deltaFromEditorChange(event) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue