Merge remote-tracking branch 'origin' into y-richtext-rewrite
This commit is contained in:
commit
250050e83b
@ -18,7 +18,7 @@ window.undoManager = new Y.utils.UndoManager(window.yXmlType, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
document.onkeydown = function interceptUndoRedo (e) {
|
document.onkeydown = function interceptUndoRedo (e) {
|
||||||
if (e.keyCode === 90 && e.metaKey) {
|
if (e.keyCode === 90 && (e.metaKey || e.ctrlKey)) {
|
||||||
if (!e.shiftKey) {
|
if (!e.shiftKey) {
|
||||||
window.undoManager.undo()
|
window.undoManager.undo()
|
||||||
} else {
|
} else {
|
||||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.0.0-50",
|
"version": "13.0.0-53",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.0.0-50",
|
"version": "13.0.0-53",
|
||||||
"description": "A framework for real-time p2p shared editing on any data",
|
"description": "A framework for real-time p2p shared editing on any data",
|
||||||
"main": "./y.node.js",
|
"main": "./y.node.js",
|
||||||
"browser": "./y.js",
|
"browser": "./y.js",
|
||||||
|
@ -4,8 +4,10 @@ import { readDeleteSet, writeDeleteSet } from './deleteSet.js'
|
|||||||
import BinaryEncoder from '../Binary/Encoder.js'
|
import BinaryEncoder from '../Binary/Encoder.js'
|
||||||
|
|
||||||
export function fromBinary (y, decoder) {
|
export function fromBinary (y, decoder) {
|
||||||
integrateRemoteStructs(y, decoder)
|
y.transact(function () {
|
||||||
readDeleteSet(y, decoder)
|
integrateRemoteStructs(y, decoder)
|
||||||
|
readDeleteSet(y, decoder)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toBinary (y) {
|
export function toBinary (y) {
|
||||||
|
@ -56,22 +56,56 @@ export default class Item {
|
|||||||
this._parent = null
|
this._parent = null
|
||||||
this._parentSub = null
|
this._parentSub = null
|
||||||
this._deleted = false
|
this._deleted = false
|
||||||
|
this._redone = null
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Copy the effect of struct
|
* Create a operation with the same effect (without position effect)
|
||||||
*/
|
*/
|
||||||
_copy (undeleteChildren, copyPosition) {
|
_copy () {
|
||||||
let struct = new this.constructor()
|
return new this.constructor()
|
||||||
if (copyPosition) {
|
}
|
||||||
struct._origin = this._left
|
/**
|
||||||
struct._left = this._left
|
* Redo the effect of this operation.
|
||||||
struct._right = this
|
*/
|
||||||
struct._right_origin = this
|
_redo (y) {
|
||||||
struct._parent = this._parent
|
if (this._redone !== null) {
|
||||||
struct._parentSub = this._parentSub
|
return this._redone
|
||||||
}
|
}
|
||||||
|
let struct = this._copy()
|
||||||
|
let left = this._left
|
||||||
|
let right = this
|
||||||
|
let parent = this._parent
|
||||||
|
// make sure that parent is redone
|
||||||
|
if (parent._deleted === true && parent._redone === null) {
|
||||||
|
parent._redo(y)
|
||||||
|
}
|
||||||
|
if (parent._redone !== null) {
|
||||||
|
parent = parent._redone
|
||||||
|
// find next cloned items
|
||||||
|
while (left !== null && left._redone === null) {
|
||||||
|
left = left._left
|
||||||
|
}
|
||||||
|
if (left !== null) {
|
||||||
|
left = left._redone
|
||||||
|
}
|
||||||
|
while (right !== null && right._redone === null) {
|
||||||
|
right = right._right
|
||||||
|
}
|
||||||
|
if (right !== null) {
|
||||||
|
right = right._redone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct._origin = left
|
||||||
|
struct._left = left
|
||||||
|
struct._right = right
|
||||||
|
struct._right_origin = right
|
||||||
|
struct._parent = parent
|
||||||
|
struct._parentSub = this._parentSub
|
||||||
|
struct._integrate(y)
|
||||||
|
this._redone = struct
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
|
||||||
get _lastId () {
|
get _lastId () {
|
||||||
return new ID(this._id.user, this._id.clock + this._length - 1)
|
return new ID(this._id.user, this._id.clock + this._length - 1)
|
||||||
}
|
}
|
||||||
@ -104,11 +138,15 @@ export default class Item {
|
|||||||
if (!this._deleted) {
|
if (!this._deleted) {
|
||||||
this._deleted = true
|
this._deleted = true
|
||||||
y.ds.markDeleted(this._id, this._length)
|
y.ds.markDeleted(this._id, this._length)
|
||||||
|
let del = new Delete()
|
||||||
|
del._targetID = this._id
|
||||||
|
del._length = this._length
|
||||||
if (createDelete) {
|
if (createDelete) {
|
||||||
let del = new Delete()
|
// broadcast and persists Delete
|
||||||
del._targetID = this._id
|
|
||||||
del._length = this._length
|
|
||||||
del._integrate(y, true)
|
del._integrate(y, true)
|
||||||
|
} else if (y.persistence !== null) {
|
||||||
|
// only persist Delete
|
||||||
|
y.persistence.saveStruct(y, del)
|
||||||
}
|
}
|
||||||
transactionTypeChanged(y, this._parent, this._parentSub)
|
transactionTypeChanged(y, this._parent, this._parentSub)
|
||||||
y._transaction.deletedStructs.add(this)
|
y._transaction.deletedStructs.add(this)
|
||||||
|
@ -6,8 +6,8 @@ export default class ItemJSON extends Item {
|
|||||||
super()
|
super()
|
||||||
this._content = null
|
this._content = null
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren, copyPosition) {
|
_copy () {
|
||||||
let struct = super._copy(undeleteChildren, copyPosition)
|
let struct = super._copy()
|
||||||
struct._content = this._content
|
struct._content = this._content
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ export default class ItemString extends Item {
|
|||||||
super()
|
super()
|
||||||
this._content = null
|
this._content = null
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren, copyPosition) {
|
_copy () {
|
||||||
let struct = super._copy(undeleteChildren, copyPosition)
|
let struct = super._copy()
|
||||||
struct._content = this._content
|
struct._content = this._content
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
@ -79,40 +79,6 @@ export default class Type extends Item {
|
|||||||
type = type._parent
|
type = type._parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren, copyPosition) {
|
|
||||||
let copy = super._copy(undeleteChildren, copyPosition)
|
|
||||||
let map = new Map()
|
|
||||||
copy._map = map
|
|
||||||
for (let [key, value] of this._map) {
|
|
||||||
if (undeleteChildren.has(value) || !value.deleted) {
|
|
||||||
let _item = value._copy(undeleteChildren, false)
|
|
||||||
_item._parent = copy
|
|
||||||
_item._parentSub = key
|
|
||||||
map.set(key, _item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let prevUndeleted = null
|
|
||||||
copy._start = null
|
|
||||||
let item = this._start
|
|
||||||
while (item !== null) {
|
|
||||||
if (undeleteChildren.has(item) || !item.deleted) {
|
|
||||||
let _item = item._copy(undeleteChildren, false)
|
|
||||||
_item._left = prevUndeleted
|
|
||||||
_item._origin = prevUndeleted
|
|
||||||
_item._right = null
|
|
||||||
_item._right_origin = null
|
|
||||||
_item._parent = copy
|
|
||||||
if (prevUndeleted === null) {
|
|
||||||
copy._start = _item
|
|
||||||
} else {
|
|
||||||
prevUndeleted._right = _item
|
|
||||||
}
|
|
||||||
prevUndeleted = _item
|
|
||||||
}
|
|
||||||
item = item._right
|
|
||||||
}
|
|
||||||
return copy
|
|
||||||
}
|
|
||||||
_transact (f) {
|
_transact (f) {
|
||||||
const y = this._y
|
const y = this._y
|
||||||
if (y !== null) {
|
if (y !== null) {
|
||||||
|
@ -20,8 +20,8 @@ export default class YXmlElement extends YXmlFragment {
|
|||||||
this._domFilter = arg2
|
this._domFilter = arg2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren, copyPosition) {
|
_copy () {
|
||||||
let struct = super._copy(undeleteChildren, copyPosition)
|
let struct = super._copy()
|
||||||
struct.nodeName = this.nodeName
|
struct.nodeName = this.nodeName
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
@ -36,7 +36,8 @@ export default class YXmlElement extends YXmlFragment {
|
|||||||
let attributes = new Map()
|
let attributes = new Map()
|
||||||
for (let i = 0; i < dom.attributes.length; i++) {
|
for (let i = 0; i < dom.attributes.length; i++) {
|
||||||
let attr = dom.attributes[i]
|
let attr = dom.attributes[i]
|
||||||
attributes.set(attr.name, attr.value)
|
// get attribute via getAttribute for custom element support (some write something different in attr.value)
|
||||||
|
attributes.set(attr.name, dom.getAttribute(attr.name))
|
||||||
}
|
}
|
||||||
attributes = this._domFilter(dom, attributes)
|
attributes = this._domFilter(dom, attributes)
|
||||||
attributes.forEach((value, name) => {
|
attributes.forEach((value, name) => {
|
||||||
|
@ -14,8 +14,8 @@ export default class YXmlHook extends YMap {
|
|||||||
getHook(hookName).fillType(dom, this)
|
getHook(hookName).fillType(dom, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_copy (undeleteChildren, copyPosition) {
|
_copy () {
|
||||||
const struct = super._copy(undeleteChildren, copyPosition)
|
const struct = super._copy()
|
||||||
struct.hookName = this.hookName
|
struct.hookName = this.hookName
|
||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@ class ReverseOperation {
|
|||||||
constructor (y, transaction) {
|
constructor (y, transaction) {
|
||||||
this.created = new Date()
|
this.created = new Date()
|
||||||
const beforeState = transaction.beforeState
|
const beforeState = transaction.beforeState
|
||||||
this.toState = new ID(y.userID, y.ss.getState(y.userID) - 1)
|
|
||||||
if (beforeState.has(y.userID)) {
|
if (beforeState.has(y.userID)) {
|
||||||
|
this.toState = new ID(y.userID, y.ss.getState(y.userID) - 1)
|
||||||
this.fromState = new ID(y.userID, beforeState.get(y.userID))
|
this.fromState = new ID(y.userID, beforeState.get(y.userID))
|
||||||
} else {
|
} else {
|
||||||
this.fromState = this.toState
|
this.toState = null
|
||||||
|
this.fromState = null
|
||||||
}
|
}
|
||||||
this.deletedStructs = transaction.deletedStructs
|
this.deletedStructs = transaction.deletedStructs
|
||||||
}
|
}
|
||||||
@ -30,28 +31,32 @@ function applyReverseOperation (y, scope, reverseBuffer) {
|
|||||||
while (!performedUndo && reverseBuffer.length > 0) {
|
while (!performedUndo && reverseBuffer.length > 0) {
|
||||||
let undoOp = reverseBuffer.pop()
|
let undoOp = reverseBuffer.pop()
|
||||||
// make sure that it is possible to iterate {from}-{to}
|
// make sure that it is possible to iterate {from}-{to}
|
||||||
y.os.getItemCleanStart(undoOp.fromState)
|
if (undoOp.fromState !== null) {
|
||||||
y.os.getItemCleanEnd(undoOp.toState)
|
y.os.getItemCleanStart(undoOp.fromState)
|
||||||
y.os.iterate(undoOp.fromState, undoOp.toState, op => {
|
y.os.getItemCleanEnd(undoOp.toState)
|
||||||
if (!op._deleted && isStructInScope(y, op, scope)) {
|
y.os.iterate(undoOp.fromState, undoOp.toState, op => {
|
||||||
performedUndo = true
|
while (op._deleted && op._redone !== null) {
|
||||||
op._delete(y)
|
op = op._redone
|
||||||
}
|
}
|
||||||
})
|
if (op._deleted === false && isStructInScope(y, op, scope)) {
|
||||||
|
performedUndo = true
|
||||||
|
op._delete(y)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
for (let op of undoOp.deletedStructs) {
|
for (let op of undoOp.deletedStructs) {
|
||||||
if (
|
if (
|
||||||
isStructInScope(y, op, scope) &&
|
isStructInScope(y, op, scope) &&
|
||||||
op._parent !== y &&
|
op._parent !== y &&
|
||||||
!op._parent._deleted &&
|
|
||||||
(
|
(
|
||||||
op._parent._id.user !== y.userID ||
|
op._id.user !== y.userID ||
|
||||||
op._parent._id.clock < undoOp.fromState.clock ||
|
undoOp.fromState === null ||
|
||||||
op._parent._id.clock > undoOp.fromState.clock
|
op._id.clock < undoOp.fromState.clock ||
|
||||||
|
op._id.clock > undoOp.toState.clock
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
performedUndo = true
|
performedUndo = true
|
||||||
op = op._copy(undoOp.deletedStructs, true)
|
op._redo(y)
|
||||||
op._integrate(y)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +82,12 @@ export default class UndoManager {
|
|||||||
let lastUndoOp = this._undoBuffer.length > 0 ? this._undoBuffer[this._undoBuffer.length - 1] : null
|
let lastUndoOp = this._undoBuffer.length > 0 ? this._undoBuffer[this._undoBuffer.length - 1] : null
|
||||||
if (lastUndoOp !== null && reverseOperation.created - lastUndoOp.created <= options.captureTimeout) {
|
if (lastUndoOp !== null && reverseOperation.created - lastUndoOp.created <= options.captureTimeout) {
|
||||||
lastUndoOp.created = reverseOperation.created
|
lastUndoOp.created = reverseOperation.created
|
||||||
lastUndoOp.toState = reverseOperation.toState
|
if (reverseOperation.toState !== null) {
|
||||||
|
lastUndoOp.toState = reverseOperation.toState
|
||||||
|
if (lastUndoOp.fromState === null) {
|
||||||
|
lastUndoOp.fromState = reverseOperation.fromState
|
||||||
|
}
|
||||||
|
}
|
||||||
reverseOperation.deletedStructs.forEach(lastUndoOp.deletedStructs.add, lastUndoOp.deletedStructs)
|
reverseOperation.deletedStructs.forEach(lastUndoOp.deletedStructs.add, lastUndoOp.deletedStructs)
|
||||||
} else {
|
} else {
|
||||||
this._undoBuffer.push(reverseOperation)
|
this._undoBuffer.push(reverseOperation)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user