yjs / y-prosemirror

ProseMirror editor binding for Yjs

Home Page:https://demos.yjs.dev/prosemirror/prosemirror.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add meta to all ysync triggered transactions

TeemuKoivisto opened this issue · comments

Is your feature request related to a problem? Please describe.
If you want to track transactions and depend on knowing what to intercept and what to pass, having some way of knowing what plugin created what transaction is quite crucial.

Describe the solution you'd like
So as of now, the ySync triggers some transactions with its own pluginKey to notify itself to update its state. However, it also triggers other transactions that modify the document without any meta fields added. For example, the _forceRerender replaces the whole document and it's quite impossible to detect where it originated from. In my own repo, I added a field tr.setMeta('_forceRerender', true) to be able to omit those transactions as non-user originated.

Describe alternatives you've considered
The other solution is to add meta to all user-created transactions yourself but that seems quite burdensome and flaky.

Additional context
na

The ySync plugin has a meta property isChangeOrigin which is true only if the state was changed by a remote user. Is this what you are looking for?

const { isChangeorigin } = tr.getMeta(ySyncPluginKey)

No, I dont think so. As I mount the editor and the ySync plugin replaces the PM doc with the ydoc that transaction is triggered without any meta fields. This is an issue as I want to track and in times prevent changes made by the user to some nodes.

Update: I have the same problem with the snapshots; without distinguishing meta fields I can't skip them. I guess the most prudent option would be to use the ySyncPluginKey for all transactions originating from the ySync plugin (and do the same for other y-prosemirror plugins if necessary) but instead of passing directy the plugin change in the payload, they would use actions/named events to know what transactions update the plugin state. Or they add some additional "plugin-update" meta-field for the payload. Or just use "true" for transactions that don't update and the regular change objects for those that change.

@dmonad if you have time to look at it, I created a PR regarding this. Even after a couple of months I still think this is a valid feature as the other options are less clean on my side eg adding a meta tag to all transactions PM creates and then checking if it doesn't exist instead of just ySyncPluginKey.

EDIT: What I did for a temporary fix was copy paste ySyncPlugin and then shim the view instance passed to the ProsemirrorBinding:

const viewShim = new class ShimmedEditorView {
  get state() {
    return view.state
  }
  get _root() {
    // @ts-ignore
    return view._root
  }
  dispatch = (tr: Transaction) => view.dispatch(tr.setMeta(yjsPluginKey, true))
  hasFocus = () => view.hasFocus()
}
const binding = new ProsemirrorBinding(yXmlFragment, viewShim)

This was merged by #74 and can confirm it works with the latest (v1.0.11) version. Thanks a ton @dmonad!