How to show peers' cursors on CM6 collab editor?

Hi,

I’ve been doing collaborative editing based on CM6(thanks for this excellent work btw).

Now my co-editor works, but I have a problem at this moment. The editor can’t show the peer’s cursor while they were inputting. Words can be seen during the inputting, but no cursor.

Trying to read the docs but didn’t figure it out yet.

This isn’t a feature that any of the core modules provides—you’ll have to implement it yourself, by sharing the cursor positions over the network and displaying some widget or tooltip at those locations.

2 Likes

Hey, could you please share your github repo? I am doing the same thing with codemirror and react but my problem is that multiple users can’t work on the same project at the same time. I wonder how you did it. Thanks you!

Hey, sorry but I didn’t post anything on my github. I used vue and codemirror6 to finish my project, Perhaps we can discuss your code to see what’s going wrong?

1 Like

Really sorry for responding this late. Actually I was expecting to have an email notification if I get any reply but I didn’t. Today I just stumbled upon here and found your kind reply.

Yes, we can definitely discuss together. You can email me here - hmshuvo314@gmail.com.

By the way, I’m still working on the project and it is live at - intercode.vercel.app. (please disregard the landing page! I’m yet to work on that and I have really been busy with the core functionality of the app)

Also, I have been able to show peers cursors on a different app of mine. Not sure if that works exactly the way you would want it to. Anyway, we can talk about it more!

I’m also interested in doing this. I have collaborative editing working, backed by the OT algorithm of ShareDB, and I would like to add “presence cursors”. ShareDB has a presence API which takes care of the information handling aspect including broadcasting presence and handling cursor transformations.

I’m curious where the best place to start would be in terms of the CodeMirror API. To implement presence cursors, we need the following:

  • A way to listen for where the user’s cursor is and get updates when it moves around and when selections are made (presence tracks begin and end of a selection)
  • A way to add a “widget” or “decoration” to the CodeMirror editor that is an indication that another person is there.

The design would look something like this, a screenshot from the VSCode LiveShare plugin:

image

I’m guessing that for displaying the widget, this is the best place to start:

https://codemirror.net/examples/decoration/

Or maybe this one, I’m not sure:

https://codemirror.net/examples/tooltip/

In terms of listening for where the cursor is and when selections change, I have no clear idea on where to start. I would guess that we need to create a plugin for this that has a side effect of emitting events when the selection changes. This thread seems relevant to that quest:

which leads to

https://codemirror.net/docs/ref/#view.ViewUpdate

which I notice has a property called selectionSet, which it seems should be true when the selection changes (I assume this also includes changes to just the cursor position).

I’ll attempt an implementation based on these ideas and report back if I can get it working! In the mean time, any guidance on the approach or the APIs to best use would be greatly appreciated. Thanks!

Whoah it looks like this repo might have a full blown presence implementation for CodeMirror!

While investigating the yjs presence implementation, I’m a bit confused at this line here, which is triggered when remote cursors change:

const yRemoteSelectionsAnnotation = cmState.Annotation.define()
...
view.dispatch({ annotations: [yRemoteSelectionsAnnotation.of([])] })

from y-codemirror.next/y-remote-selections.js at main · yjs/y-codemirror.next · GitHub

It seems that this update does not actually contain any information, but rather serves to just trigger the update method, which looks to the Yjs internal state for rendering the presence widgets.

While this does work, it doesn’t quite feel like the best solution since, according to the documentation for Annotations, “Annotations are tagged values that are used to add metadata to transactions in an extensible way.”

What might an alternative solution look like? Intuitively, it should be possible to track the remote presence objects somehow as part of the editor state, and just update that state when receiving remote transactions. A secondary plugin could then be responsible for rendering that state. Is this the correct line of thinking?

Update:

I finally got it to work!

Not sure if the API is being used 100% correctly, but works as a first pass!

1 Like