y-prosemirror
Advanced tools
Comparing version 0.0.11 to 0.1.0
@@ -121,3 +121,3 @@ 'use strict'; | ||
} | ||
while (type !== yDoc) { | ||
while (type !== yDoc && type._item !== null) { | ||
// @ts-ignore | ||
@@ -150,2 +150,31 @@ const parent = type._item.parent; | ||
/* | ||
class PermanentUserData { | ||
/** | ||
* @param {Y.Doc} doc | ||
* @param {string} userid | ||
* | ||
constructor (doc, userid) { | ||
const users = doc.getMap('users') | ||
this.doc = doc | ||
this.users = users | ||
let user = users.get(userid) | ||
if (!user) { | ||
user = new Y.Map() | ||
const ids = new Y.Array() | ||
const ds = new Y.Array() | ||
ids.push([userid]) | ||
user.set('ids', ids) | ||
user.set('ds', ds) | ||
users.set(userid, user) | ||
} | ||
users.observe(event => { | ||
event.changes.added.forEach(item => { | ||
item.content.type | ||
}) | ||
}) | ||
} | ||
} | ||
*/ | ||
/** | ||
@@ -155,3 +184,7 @@ * @module bindings/prosemirror | ||
const isVisible = (item, snapshot) => snapshot === undefined ? !item._deleted : (snapshot.sm.has(item._id.user) && snapshot.sm.get(item._id.user) > item._id.clock && !snapshot.ds.isDeleted(item._id)); | ||
/** | ||
* @param {Y.Item} item | ||
* @param {Y.Snapshot} [snapshot] | ||
*/ | ||
const isVisible = (item, snapshot) => snapshot === undefined ? !item.deleted : (snapshot.sv.has(item.id.client) && /** @type {number} */ (snapshot.sv.get(item.id.client)) > item.id.clock && !Y.isDeleted(snapshot.ds, item.id)); | ||
@@ -191,2 +224,3 @@ /** | ||
snapshot: null, | ||
prevSnapshot: null, | ||
isChangeOrigin: false | ||
@@ -206,3 +240,3 @@ } | ||
if (pluginState.binding !== null) { | ||
if (change !== undefined && change.snapshot !== undefined) { | ||
if (change !== undefined && change.snapshot != null) { | ||
// snapshot changed, rerender next | ||
@@ -300,6 +334,26 @@ setTimeout(() => { | ||
this.doc.on('beforeTransaction', e => { | ||
this.beforeTransactionSelection = getRelativeSelection(this, prosemirrorView.state); | ||
if (this.beforeTransactionSelection === null) { | ||
this.beforeTransactionSelection = getRelativeSelection(this, prosemirrorView.state); | ||
} | ||
}); | ||
this.doc.on('afterTransaction', e => { | ||
this.beforeTransactionSelection = null; | ||
}); | ||
yXmlFragment.observeDeep(this._observeFunction); | ||
} | ||
renderSnapshot (snapshot, prevSnapshot) { | ||
if (!prevSnapshot) { | ||
prevSnapshot = Y.createSnapshot(Y.createDeleteSet(), new Map()); | ||
} | ||
this.prosemirrorView.dispatch(this.prosemirrorView.state.tr.setMeta(ySyncPluginKey, { snapshot, prevSnapshot })); | ||
} | ||
unrenderSnapshot () { | ||
this.mapping = new Map(); | ||
this.mux(() => { | ||
const fragmentContent = this.type.toArray().map(t => createNodeFromYElement(/** @type {Y.XmlElement} */ (t), this.prosemirrorView.state.schema, this.mapping)).filter(n => n !== null); | ||
const tr = this.prosemirrorView.state.tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(new PModel.Fragment(fragmentContent), 0, 0)); | ||
tr.setMeta(ySyncPluginKey, { snapshot: null, prevSnapshot: null }); | ||
this.prosemirrorView.dispatch(tr); | ||
}); | ||
} | ||
_forceRerender () { | ||
@@ -314,3 +368,2 @@ this.mapping = new Map(); | ||
/** | ||
* | ||
* @param {Y.Snapshot} snapshot | ||
@@ -323,3 +376,3 @@ * @param {Y.Snapshot} prevSnapshot | ||
this.mux(() => { | ||
const fragmentContent = Y.typeListToArraySnapshot(this.type, new Y.Snapshot(prevSnapshot.ds, snapshot.sm)).map(t => createNodeFromYElement(t, this.prosemirrorView.state.schema, new Map(), snapshot, prevSnapshot)).filter(n => n !== null); | ||
const fragmentContent = Y.typeListToArraySnapshot(this.type, new Y.Snapshot(prevSnapshot.ds, snapshot.sv)).map(t => createNodeFromYElement(t, this.prosemirrorView.state.schema, new Map(), snapshot, prevSnapshot)).filter(n => n !== null); | ||
const tr = this.prosemirrorView.state.tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(new PModel.Fragment(fragmentContent), 0, 0)); | ||
@@ -334,7 +387,7 @@ this.prosemirrorView.dispatch(tr); | ||
_typeChanged (events, transaction) { | ||
if (events.length === 0 || ySyncPluginKey.getState(this.prosemirrorView.state).snapshot != null) { | ||
// drop out if snapshot is active | ||
return | ||
} | ||
this.mux(() => { | ||
if (events.length === 0 || ySyncPluginKey.getState(this.prosemirrorView.state).snapshot != null) { | ||
// drop out if snapshot is active | ||
return | ||
} | ||
/** | ||
@@ -360,3 +413,6 @@ * @param {any} _ | ||
this.mux(() => { | ||
updateYFragment(this.doc, this.type, doc, this.mapping); | ||
this.doc.transact(() => { | ||
updateYFragment(this.doc, this.type, doc, this.mapping); | ||
this.beforeTransactionSelection = getRelativeSelection(this, this.prosemirrorView.state); | ||
}); | ||
}); | ||
@@ -403,7 +459,7 @@ } | ||
if (snapshot !== undefined && prevSnapshot !== undefined) { | ||
if (!isVisible(el, snapshot)) { | ||
if (!isVisible(/** @type {Y.Item} */ (el._item), snapshot)) { | ||
// if this element is already rendered as deleted (ychange), then do not render children as deleted | ||
_snapshot = new Y.Snapshot(prevSnapshot.ds, snapshot.sm); | ||
_snapshot = new Y.Snapshot(prevSnapshot.ds, snapshot.sv); | ||
_prevSnapshot = _snapshot; | ||
} else if (!isVisible(el, prevSnapshot)) { | ||
} else if (!isVisible(/** @type {Y.Item} */(el._item), prevSnapshot)) { | ||
_prevSnapshot = _snapshot; | ||
@@ -433,3 +489,3 @@ } | ||
} else { | ||
Y.typeListToArraySnapshot(el, new Y.Snapshot(prevSnapshot.ds, snapshot.sm)).forEach(createChildren); | ||
Y.typeListToArraySnapshot(el, new Y.Snapshot(prevSnapshot.ds, snapshot.sv)).forEach(createChildren); | ||
} | ||
@@ -439,6 +495,6 @@ try { | ||
if (snapshot !== undefined) { | ||
if (!isVisible(el, snapshot)) { | ||
attrs.ychange = { client: /** @type {Y.Item} */ (el._item).id.client, state: 'removed' }; | ||
} else if (!isVisible(el, prevSnapshot)) { | ||
attrs.ychange = { client: /** @type {Y.Item} */ (el._item).id.client, state: 'added' }; | ||
if (!isVisible(/** @type {Y.Item} */ (el._item), snapshot)) { | ||
attrs.ychange = { user: /** @type {Y.Item} */ (el._item).id.client, state: 'removed' }; | ||
} else if (!isVisible(/** @type {Y.Item} */ (el._item), prevSnapshot)) { | ||
attrs.ychange = { user: /** @type {Y.Item} */ (el._item).id.client, state: 'added' }; | ||
} | ||
@@ -828,2 +884,52 @@ } | ||
/** | ||
* @param {any} state | ||
* @param {Awareness} awareness | ||
* @return {DecorationSet} | ||
*/ | ||
const createDecorations = (state, awareness) => { | ||
const ystate = ySyncPluginKey.getState(state); | ||
const y = ystate.doc; | ||
const decorations = []; | ||
if (ystate.snapshot != null || ystate.binding === null) { | ||
// do not render cursors while snapshot is active | ||
return prosemirrorView.DecorationSet.create(state.doc, []) | ||
} | ||
awareness.getStates().forEach((aw, clientId) => { | ||
if (clientId === y.clientID) { | ||
return | ||
} | ||
if (aw.cursor != null) { | ||
let user = aw.user || {}; | ||
if (user.color == null) { | ||
user.color = '#ffa500'; | ||
} | ||
if (user.name == null) { | ||
user.name = `User: ${clientId}`; | ||
} | ||
let anchor = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.anchor), ystate.binding.mapping); | ||
let head = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.head), ystate.binding.mapping); | ||
if (anchor !== null && head !== null) { | ||
let maxsize = math.max(state.doc.content.size - 1, 0); | ||
anchor = math.min(anchor, maxsize); | ||
head = math.min(head, maxsize); | ||
decorations.push(prosemirrorView.Decoration.widget(head, () => { | ||
const cursor = document.createElement('span'); | ||
cursor.classList.add('ProseMirror-yjs-cursor'); | ||
cursor.setAttribute('style', `border-color: ${user.color}`); | ||
const userDiv = document.createElement('div'); | ||
userDiv.setAttribute('style', `background-color: ${user.color}`); | ||
userDiv.insertBefore(document.createTextNode(user.name), null); | ||
cursor.insertBefore(userDiv, null); | ||
return cursor | ||
}, { key: clientId + '', side: 10 })); | ||
const from = math.min(anchor, head); | ||
const to = math.max(anchor, head); | ||
decorations.push(prosemirrorView.Decoration.inline(from, to, { style: `background-color: ${user.color}70` }, { inclusiveEnd: true, inclusiveStart: false })); | ||
} | ||
} | ||
}); | ||
return prosemirrorView.DecorationSet.create(state.doc, decorations) | ||
}; | ||
/** | ||
* A prosemirror plugin that listens to awareness information on Yjs. | ||
@@ -838,46 +944,18 @@ * This requires that a `prosemirrorPlugin` is also bound to the prosemirror. | ||
key: yCursorPluginKey, | ||
state: { | ||
init (_, state) { | ||
return createDecorations(state, awareness) | ||
}, | ||
apply (tr, prevState, oldState, newState) { | ||
const ystate = ySyncPluginKey.getState(newState); | ||
const yCursorState = tr.getMeta(yCursorPluginKey); | ||
if ((ystate && ystate.isChangeOrigin) || (yCursorState && yCursorState.awarenessUpdated)) { | ||
return createDecorations(newState, awareness) | ||
} | ||
return prevState.map(tr.mapping, tr.doc) | ||
} | ||
}, | ||
props: { | ||
decorations: state => { | ||
const ystate = ySyncPluginKey.getState(state); | ||
const y = ystate.doc; | ||
const decorations = []; | ||
if (ystate.snapshot != null || ystate.binding === null) { | ||
// do not render cursors while snapshot is active | ||
return | ||
} | ||
awareness.getStates().forEach((aw, clientId) => { | ||
if (clientId === y.clientID) { | ||
return | ||
} | ||
if (aw.cursor != null) { | ||
let user = aw.user || {}; | ||
if (user.color == null) { | ||
user.color = '#ffa500'; | ||
} | ||
if (user.name == null) { | ||
user.name = `User: ${clientId}`; | ||
} | ||
let anchor = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.anchor), ystate.binding.mapping); | ||
let head = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.head), ystate.binding.mapping); | ||
if (anchor !== null && head !== null) { | ||
let maxsize = math.max(state.doc.content.size - 1, 0); | ||
anchor = math.min(anchor, maxsize); | ||
head = math.min(head, maxsize); | ||
decorations.push(prosemirrorView.Decoration.widget(head, () => { | ||
const cursor = document.createElement('span'); | ||
cursor.classList.add('ProseMirror-yjs-cursor'); | ||
cursor.setAttribute('style', `border-color: ${user.color}`); | ||
const userDiv = document.createElement('div'); | ||
userDiv.setAttribute('style', `background-color: ${user.color}`); | ||
userDiv.insertBefore(document.createTextNode(user.name), null); | ||
cursor.insertBefore(userDiv, null); | ||
return cursor | ||
}, { key: clientId + '' })); | ||
const from = math.min(anchor, head); | ||
const to = math.max(anchor, head); | ||
decorations.push(prosemirrorView.Decoration.inline(from, to, { style: `background-color: ${user.color}70` })); | ||
} | ||
} | ||
}); | ||
return prosemirrorView.DecorationSet.create(state.doc, decorations) | ||
return yCursorPluginKey.getState(state) | ||
} | ||
@@ -887,3 +965,5 @@ }, | ||
const awarenessListener = () => { | ||
view.updateState(view.state); | ||
setTimeout(() => { | ||
view.dispatch(view.state.tr.setMeta(yCursorPluginKey, { awarenessUpdated: true })); | ||
}); | ||
}; | ||
@@ -1011,2 +1091,3 @@ const updateCursorInfo = () => { | ||
exports.ProsemirrorBinding = ProsemirrorBinding; | ||
exports.createDecorations = createDecorations; | ||
exports.createNodeFromYElement = createNodeFromYElement; | ||
@@ -1013,0 +1094,0 @@ exports.createNodeIfNotExists = createNodeIfNotExists; |
{ | ||
"name": "y-prosemirror", | ||
"version": "0.0.11", | ||
"version": "0.1.0", | ||
"description": "Prosemirror bindings for Yjs", | ||
@@ -22,3 +22,3 @@ "main": "./dist/y-prosemirror.js", | ||
"type": "git", | ||
"url": "git+https://github.com/y-js/y-prosemirror.git" | ||
"url": "git+https://github.com/yjs/y-prosemirror.git" | ||
}, | ||
@@ -38,11 +38,11 @@ "keywords": [ | ||
"bugs": { | ||
"url": "https://github.com/y-js/y-prosemirror/issues" | ||
"url": "https://github.com/yjs/y-prosemirror/issues" | ||
}, | ||
"homepage": "https://github.com/y-js/y-prosemirror#readme", | ||
"homepage": "https://github.com/yjs/y-prosemirror#readme", | ||
"dependencies": { | ||
"lib0": "0.0.6" | ||
"lib0": "^0.1.0" | ||
}, | ||
"peerDependencies": { | ||
"yjs": ">=13.0.0-96", | ||
"y-protocols": ">=0.0.7", | ||
"yjs": ">=13.0.0-97", | ||
"y-protocols": "^0.1.0", | ||
"prosemirror-model": "^1.7.0", | ||
@@ -64,5 +64,5 @@ "prosemirror-state": "^1.2.2", | ||
"standard": "^12.0.1", | ||
"y-protocols": "0.0.7", | ||
"yjs": "13.0.0-96" | ||
"y-protocols": "^0.1.0", | ||
"yjs": "13.0.0-97" | ||
} | ||
} |
# y-prosemirror | ||
> [ProseMirror](http://prosemirror.net/) Binding for [Yjs](https://github.com/y-js/yjs) - [Demo](https://yjs-demos.now.sh/prosemirror/) | ||
> [ProseMirror](http://prosemirror.net/) Binding for [Yjs](https://github.com/yjs/yjs) - [Demo](https://yjs-demos.now.sh/prosemirror/) | ||
@@ -41,3 +41,3 @@ This binding maps a Y.XmlFragment to the ProseMirror state. | ||
Also look [here](https://github.com/y-js/yjs-demos/tree/master/prosemirror) for a working example. | ||
Also look [here](https://github.com/yjs/yjs-demos/tree/master/prosemirror) for a working example. | ||
@@ -44,0 +44,0 @@ ### License |
@@ -112,3 +112,3 @@ import { ProsemirrorMapping } from './plugins/sync-plugin.js' // eslint-disable-line | ||
} | ||
while (type !== yDoc) { | ||
while (type !== yDoc && type._item !== null) { | ||
// @ts-ignore | ||
@@ -140,1 +140,30 @@ const parent = type._item.parent | ||
} | ||
/* | ||
class PermanentUserData { | ||
/** | ||
* @param {Y.Doc} doc | ||
* @param {string} userid | ||
* | ||
constructor (doc, userid) { | ||
const users = doc.getMap('users') | ||
this.doc = doc | ||
this.users = users | ||
let user = users.get(userid) | ||
if (!user) { | ||
user = new Y.Map() | ||
const ids = new Y.Array() | ||
const ds = new Y.Array() | ||
ids.push([userid]) | ||
user.set('ids', ids) | ||
user.set('ds', ds) | ||
users.set(userid, user) | ||
} | ||
users.observe(event => { | ||
event.changes.added.forEach(item => { | ||
item.content.type | ||
}) | ||
}) | ||
} | ||
} | ||
*/ |
@@ -19,2 +19,52 @@ | ||
/** | ||
* @param {any} state | ||
* @param {Awareness} awareness | ||
* @return {DecorationSet} | ||
*/ | ||
export const createDecorations = (state, awareness) => { | ||
const ystate = ySyncPluginKey.getState(state) | ||
const y = ystate.doc | ||
const decorations = [] | ||
if (ystate.snapshot != null || ystate.binding === null) { | ||
// do not render cursors while snapshot is active | ||
return DecorationSet.create(state.doc, []) | ||
} | ||
awareness.getStates().forEach((aw, clientId) => { | ||
if (clientId === y.clientID) { | ||
return | ||
} | ||
if (aw.cursor != null) { | ||
let user = aw.user || {} | ||
if (user.color == null) { | ||
user.color = '#ffa500' | ||
} | ||
if (user.name == null) { | ||
user.name = `User: ${clientId}` | ||
} | ||
let anchor = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.anchor), ystate.binding.mapping) | ||
let head = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.head), ystate.binding.mapping) | ||
if (anchor !== null && head !== null) { | ||
let maxsize = math.max(state.doc.content.size - 1, 0) | ||
anchor = math.min(anchor, maxsize) | ||
head = math.min(head, maxsize) | ||
decorations.push(Decoration.widget(head, () => { | ||
const cursor = document.createElement('span') | ||
cursor.classList.add('ProseMirror-yjs-cursor') | ||
cursor.setAttribute('style', `border-color: ${user.color}`) | ||
const userDiv = document.createElement('div') | ||
userDiv.setAttribute('style', `background-color: ${user.color}`) | ||
userDiv.insertBefore(document.createTextNode(user.name), null) | ||
cursor.insertBefore(userDiv, null) | ||
return cursor | ||
}, { key: clientId + '', side: 10 })) | ||
const from = math.min(anchor, head) | ||
const to = math.max(anchor, head) | ||
decorations.push(Decoration.inline(from, to, { style: `background-color: ${user.color}70` }, { inclusiveEnd: true, inclusiveStart: false })) | ||
} | ||
} | ||
}) | ||
return DecorationSet.create(state.doc, decorations) | ||
} | ||
/** | ||
* A prosemirror plugin that listens to awareness information on Yjs. | ||
@@ -29,46 +79,18 @@ * This requires that a `prosemirrorPlugin` is also bound to the prosemirror. | ||
key: yCursorPluginKey, | ||
state: { | ||
init (_, state) { | ||
return createDecorations(state, awareness) | ||
}, | ||
apply (tr, prevState, oldState, newState) { | ||
const ystate = ySyncPluginKey.getState(newState) | ||
const yCursorState = tr.getMeta(yCursorPluginKey) | ||
if ((ystate && ystate.isChangeOrigin) || (yCursorState && yCursorState.awarenessUpdated)) { | ||
return createDecorations(newState, awareness) | ||
} | ||
return prevState.map(tr.mapping, tr.doc) | ||
} | ||
}, | ||
props: { | ||
decorations: state => { | ||
const ystate = ySyncPluginKey.getState(state) | ||
const y = ystate.doc | ||
const decorations = [] | ||
if (ystate.snapshot != null || ystate.binding === null) { | ||
// do not render cursors while snapshot is active | ||
return | ||
} | ||
awareness.getStates().forEach((aw, clientId) => { | ||
if (clientId === y.clientID) { | ||
return | ||
} | ||
if (aw.cursor != null) { | ||
let user = aw.user || {} | ||
if (user.color == null) { | ||
user.color = '#ffa500' | ||
} | ||
if (user.name == null) { | ||
user.name = `User: ${clientId}` | ||
} | ||
let anchor = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.anchor), ystate.binding.mapping) | ||
let head = relativePositionToAbsolutePosition(y, ystate.type, Y.createRelativePositionFromJSON(aw.cursor.head), ystate.binding.mapping) | ||
if (anchor !== null && head !== null) { | ||
let maxsize = math.max(state.doc.content.size - 1, 0) | ||
anchor = math.min(anchor, maxsize) | ||
head = math.min(head, maxsize) | ||
decorations.push(Decoration.widget(head, () => { | ||
const cursor = document.createElement('span') | ||
cursor.classList.add('ProseMirror-yjs-cursor') | ||
cursor.setAttribute('style', `border-color: ${user.color}`) | ||
const userDiv = document.createElement('div') | ||
userDiv.setAttribute('style', `background-color: ${user.color}`) | ||
userDiv.insertBefore(document.createTextNode(user.name), null) | ||
cursor.insertBefore(userDiv, null) | ||
return cursor | ||
}, { key: clientId + '' })) | ||
const from = math.min(anchor, head) | ||
const to = math.max(anchor, head) | ||
decorations.push(Decoration.inline(from, to, { style: `background-color: ${user.color}70` })) | ||
} | ||
} | ||
}) | ||
return DecorationSet.create(state.doc, decorations) | ||
return yCursorPluginKey.getState(state) | ||
} | ||
@@ -78,3 +100,5 @@ }, | ||
const awarenessListener = () => { | ||
view.updateState(view.state) | ||
setTimeout(() => { | ||
view.dispatch(view.state.tr.setMeta(yCursorPluginKey, { awarenessUpdated: true })) | ||
}) | ||
} | ||
@@ -81,0 +105,0 @@ const updateCursorInfo = () => { |
@@ -16,3 +16,7 @@ /** | ||
export const isVisible = (item, snapshot) => snapshot === undefined ? !item._deleted : (snapshot.sm.has(item._id.user) && snapshot.sm.get(item._id.user) > item._id.clock && !snapshot.ds.isDeleted(item._id)) | ||
/** | ||
* @param {Y.Item} item | ||
* @param {Y.Snapshot} [snapshot] | ||
*/ | ||
export const isVisible = (item, snapshot) => snapshot === undefined ? !item.deleted : (snapshot.sv.has(item.id.client) && /** @type {number} */ (snapshot.sv.get(item.id.client)) > item.id.clock && !Y.isDeleted(snapshot.ds, item.id)) | ||
@@ -52,2 +56,3 @@ /** | ||
snapshot: null, | ||
prevSnapshot: null, | ||
isChangeOrigin: false | ||
@@ -67,3 +72,3 @@ } | ||
if (pluginState.binding !== null) { | ||
if (change !== undefined && change.snapshot !== undefined) { | ||
if (change !== undefined && change.snapshot != null) { | ||
// snapshot changed, rerender next | ||
@@ -161,6 +166,26 @@ setTimeout(() => { | ||
this.doc.on('beforeTransaction', e => { | ||
this.beforeTransactionSelection = getRelativeSelection(this, prosemirrorView.state) | ||
if (this.beforeTransactionSelection === null) { | ||
this.beforeTransactionSelection = getRelativeSelection(this, prosemirrorView.state) | ||
} | ||
}) | ||
this.doc.on('afterTransaction', e => { | ||
this.beforeTransactionSelection = null | ||
}) | ||
yXmlFragment.observeDeep(this._observeFunction) | ||
} | ||
renderSnapshot (snapshot, prevSnapshot) { | ||
if (!prevSnapshot) { | ||
prevSnapshot = Y.createSnapshot(Y.createDeleteSet(), new Map()) | ||
} | ||
this.prosemirrorView.dispatch(this.prosemirrorView.state.tr.setMeta(ySyncPluginKey, { snapshot, prevSnapshot })) | ||
} | ||
unrenderSnapshot () { | ||
this.mapping = new Map() | ||
this.mux(() => { | ||
const fragmentContent = this.type.toArray().map(t => createNodeFromYElement(/** @type {Y.XmlElement} */ (t), this.prosemirrorView.state.schema, this.mapping)).filter(n => n !== null) | ||
const tr = this.prosemirrorView.state.tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(new PModel.Fragment(fragmentContent), 0, 0)) | ||
tr.setMeta(ySyncPluginKey, { snapshot: null, prevSnapshot: null }) | ||
this.prosemirrorView.dispatch(tr) | ||
}) | ||
} | ||
_forceRerender () { | ||
@@ -175,3 +200,2 @@ this.mapping = new Map() | ||
/** | ||
* | ||
* @param {Y.Snapshot} snapshot | ||
@@ -184,3 +208,3 @@ * @param {Y.Snapshot} prevSnapshot | ||
this.mux(() => { | ||
const fragmentContent = Y.typeListToArraySnapshot(this.type, new Y.Snapshot(prevSnapshot.ds, snapshot.sm)).map(t => createNodeFromYElement(t, this.prosemirrorView.state.schema, new Map(), snapshot, prevSnapshot)).filter(n => n !== null) | ||
const fragmentContent = Y.typeListToArraySnapshot(this.type, new Y.Snapshot(prevSnapshot.ds, snapshot.sv)).map(t => createNodeFromYElement(t, this.prosemirrorView.state.schema, new Map(), snapshot, prevSnapshot)).filter(n => n !== null) | ||
const tr = this.prosemirrorView.state.tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(new PModel.Fragment(fragmentContent), 0, 0)) | ||
@@ -195,7 +219,7 @@ this.prosemirrorView.dispatch(tr) | ||
_typeChanged (events, transaction) { | ||
if (events.length === 0 || ySyncPluginKey.getState(this.prosemirrorView.state).snapshot != null) { | ||
// drop out if snapshot is active | ||
return | ||
} | ||
this.mux(() => { | ||
if (events.length === 0 || ySyncPluginKey.getState(this.prosemirrorView.state).snapshot != null) { | ||
// drop out if snapshot is active | ||
return | ||
} | ||
/** | ||
@@ -221,3 +245,6 @@ * @param {any} _ | ||
this.mux(() => { | ||
updateYFragment(this.doc, this.type, doc, this.mapping) | ||
this.doc.transact(() => { | ||
updateYFragment(this.doc, this.type, doc, this.mapping) | ||
this.beforeTransactionSelection = getRelativeSelection(this, this.prosemirrorView.state) | ||
}) | ||
}) | ||
@@ -264,7 +291,7 @@ } | ||
if (snapshot !== undefined && prevSnapshot !== undefined) { | ||
if (!isVisible(el, snapshot)) { | ||
if (!isVisible(/** @type {Y.Item} */ (el._item), snapshot)) { | ||
// if this element is already rendered as deleted (ychange), then do not render children as deleted | ||
_snapshot = new Y.Snapshot(prevSnapshot.ds, snapshot.sm) | ||
_snapshot = new Y.Snapshot(prevSnapshot.ds, snapshot.sv) | ||
_prevSnapshot = _snapshot | ||
} else if (!isVisible(el, prevSnapshot)) { | ||
} else if (!isVisible(/** @type {Y.Item} */(el._item), prevSnapshot)) { | ||
_prevSnapshot = _snapshot | ||
@@ -294,3 +321,3 @@ } | ||
} else { | ||
Y.typeListToArraySnapshot(el, new Y.Snapshot(prevSnapshot.ds, snapshot.sm)).forEach(createChildren) | ||
Y.typeListToArraySnapshot(el, new Y.Snapshot(prevSnapshot.ds, snapshot.sv)).forEach(createChildren) | ||
} | ||
@@ -300,6 +327,6 @@ try { | ||
if (snapshot !== undefined) { | ||
if (!isVisible(el, snapshot)) { | ||
attrs.ychange = { client: /** @type {Y.Item} */ (el._item).id.client, state: 'removed' } | ||
} else if (!isVisible(el, prevSnapshot)) { | ||
attrs.ychange = { client: /** @type {Y.Item} */ (el._item).id.client, state: 'added' } | ||
if (!isVisible(/** @type {Y.Item} */ (el._item), snapshot)) { | ||
attrs.ychange = { user: /** @type {Y.Item} */ (el._item).id.client, state: 'removed' } | ||
} else if (!isVisible(/** @type {Y.Item} */ (el._item), prevSnapshot)) { | ||
attrs.ychange = { user: /** @type {Y.Item} */ (el._item).id.client, state: 'added' } | ||
} | ||
@@ -306,0 +333,0 @@ } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
2397101
21694
+ Addedlib0@0.1.7(transitive)
+ Addedy-protocols@0.1.0(transitive)
- Removedlib0@0.0.6(transitive)
- Removedy-protocols@1.0.6(transitive)
Updatedlib0@^0.1.0