Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

registerPlugin() will break UndoManger in Collaboration Extension #2761

Closed
2 tasks done
Alecyrus opened this issue May 6, 2022 · 17 comments
Closed
2 tasks done

registerPlugin() will break UndoManger in Collaboration Extension #2761

Alecyrus opened this issue May 6, 2022 · 17 comments
Labels
Type: Bug The issue or pullrequest is related to a bug

Comments

@Alecyrus
Copy link
Contributor

Alecyrus commented May 6, 2022

What’s the bug you are facing?

Collaboration Extension cannot not work well with BubbleMenu, which is registered by using registerPlugin() after editori s initialized.

Specifically, once you call registerPlugin() after editor is initialized, UndoManger does not work.

import { Editor, EditorContent } from '@tiptap/vue-3';
import Collaboration from '@tiptap/extension-collaboration';
import StarterKit from '@tiptap/starter-kit';
import CollaborationCursor from '@tiptap/extension-collaboration-cursor';
import * as Y from 'yjs';
import { WebrtcProvider } from 'y-webrtc';
import Placeholder from '@tiptap/extension-placeholder';
import { Plugin } from 'prosemirror-state';

const editor = shallowRef<Editor>();

const ydoc = new Y.Doc();

const provider = new WebrtcProvider(
  'tiptap-collaboration-cursor-extension',
  ydoc,
);

editor.value = new Editor({
  extensions: [
    StarterKit.configure({
      // The Collaboration extension comes with its own history handling
      history: false,
    }),
    Collaboration.configure({
      document: ydoc
    }),
    CollaborationCursor.configure({
      provider: provider,
      user: {
        name: 'Cyndi Lauper',
        color: '#f783ac',
      },
    }),
    Placeholder.configure({
      placeholder:
        'Write something … It’ll be shared with everyone else looking at this example.',
    }),
  ],
});
// comment this line to make undoManager work
editor.value.registerPlugin(new Plugin({}));
</script>

If you comment last line, UndoManger is back to work.

Can you provide a CodeSandbox?

Reproduction Link

Did you update your dependencies?

  • Yes, I’ve updated my dependencies to use the latest version of all packages.

Are you sponsoring us?

  • Yes, I’m a sponsor. 💖
@Alecyrus Alecyrus added the Type: Bug The issue or pullrequest is related to a bug label May 6, 2022
@Alecyrus
Copy link
Contributor Author

yjs/y-prosemirror#114

@Alecyrus
Copy link
Contributor Author

Alecyrus commented May 28, 2022

There is a workaround (make sure yUndoPlugin() is the last plugin registered ):

// collaboration.ts
addProseMirrorPlugins() {
    const fragment = this.options.fragment
      ? this.options.fragment
      : this.options.document.getXmlFragment(this.options.field);
 
    // delete yUndoPlugin()
    // return [ySyncPlugin(fragment), yUndoPlugin()]; 
    retuern [ySyncPlugin(fragment)]
  },

and register yUndoPlugin() manually after all other plugins are registered.

// in onCreate() Hook
editor.registerPlugin(yUndoPlugin());

@ruslanchek
Copy link

There is a workaround (make sure yUndoPlugin() is the last plugin registered ):

// collaboration.ts
addProseMirrorPlugins() {
    const fragment = this.options.fragment
      ? this.options.fragment
      : this.options.document.getXmlFragment(this.options.field);
 
    // delete yUndoPlugin()
    // return [ySyncPlugin(fragment), yUndoPlugin()]; 
    retuern [ySyncPlugin(fragment)]
  },

and register yUndoPlugin() manually after all other plugins are registered.

// in onCreate() Hook
editor.registerPlugin(yUndoPlugin());

What file is this? I mean collaboration.ts is the plugin's file?

@Alecyrus
Copy link
Contributor Author

Yeah.... You need to fork the code of @tiptap/extension-collaboration.

@ruslanchek
Copy link

Yeah.... You need to fork the code of @tiptap/extension-collaboration.

Ok i will try. Thank you. If this will fix that, I'll make a PR

@Alecyrus
Copy link
Contributor Author

@ruslanchek I prefer the upstream library to fix this problem.

@ryanb
Copy link

ryanb commented Jun 27, 2022

What worked for me is re-register the plugin after all other plugins are registered.

editor.unregisterPlugin(yUndoPluginKey);
editor.registerPlugin(yUndoPlugin());

This allows you to use the collaboration plugin without forking. I haven't done any benchmarking to see if registering the y-undo plugin twice impacts performance, but at least it works as a quick fix until a more permanent solution is implemented.

@Alecyrus
Copy link
Contributor Author

I maintain all extensions of my own to gain more flexibility for my project, after all, the code for these extensions is very simple and easy to modify.

@DenysPoliarush
Copy link

It doesn't work for me, are there any other solutions to this problem?

@hamflx
Copy link
Contributor

hamflx commented Jul 13, 2022

It doesn't work for me, are there any other solutions to this problem?

You can try my solution: yjs/y-prosemirror#114 (comment)

@DenysPoliarush
Copy link

You can try my solution: yjs/y-prosemirror#114 (comment)

When I try to fork or extend the collaboration extension I always get an error Applying a mismatched transaction

@Alecyrus
Copy link
Contributor Author

Alecyrus commented Jul 13, 2022

@DenysPoliarush Downgrade the y-prosemirror to v1.0.20, yjs/y-prosemirror#117

@DenysPoliarush
Copy link

@Alecyrus It seems to have worked, I will test it, thanks

@codewitch
Copy link

It doesn't work for me, are there any other solutions to this problem?

You can try my solution: yjs/y-prosemirror#114 (comment)

hi @hamflx. Your solution works like a charm! Thank you. To make sure I understood your code correctly, could you confirm my understanding? It customizes the destroy logic so the yUndoManager gets restored on the view destroy life cycle? Would that create any memory leaks in the undomanager never getting destroyed?

@hamflx
Copy link
Contributor

hamflx commented Aug 10, 2022

@codewitch My logic is to save the snapshot when the UndoManager state is destroyed. This state is restored the next time the view is executed. If you destroy it last and don't execute the view method again, the state is not restored, so there should be no memory leak.

@andrem0
Copy link

andrem0 commented Mar 1, 2023

Why is this closed? The problem persists, and only a poor workaround of copying the original extension currently exists.

@svenadlung
Copy link
Contributor

We released the fix in 2.0.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug The issue or pullrequest is related to a bug
Projects
None yet
Development

No branches or pull requests

8 participants