codesandbox / sandpack

A component toolkit for creating live-running code editing experiences, using the power of CodeSandbox.
https://sandpack.codesandbox.io
Apache License 2.0
4.83k stars 340 forks source link

[Feature Request] Multi-user support #405

Closed kylemh closed 2 years ago

kylemh commented 2 years ago

Tell us how you think we can improve Sandpack

Packages affected

What is this feature?

Offer documentation or first-class support for setting up multiple user editing in Sandbox.

danilowoz commented 2 years ago

Hey @kylemh, interesting feature request. Could you please describe a bit more of your use case and how Sandpack might solve it? Assets and examples can help.

kylemh commented 2 years ago

Sure! There are 2 examples, I can think of:

  1. Imagine a sort of CSS Garden where want many people to contribute to an artistic project.
  2. Providing an editor for some sort of Markdown CMS. If I'm doing headless wordpress, but wanted to create my own editor for clients to use for reasons. Those clients may wish to be able to edit something real-time with multiple users making edits. For example, live updates to some event (like the Apple event yesterday).

I would love to use Sandpack client for these, but there are aspects of a multi-user experience that likely should be 1st-class (such as UI bits indicating who is who via colored carets). Something that I can understand NOT being first class, but could use documentation would be how one might implement resolutions of same-spot editing from multiple users or implementing a multi-user editor service to compat with Sandpack.

danilowoz commented 2 years ago

I think I got, so here's the main challenge I see in this feature:

Screenshot 2022-03-15 at 09 41 36

I have added your feature request to our internal backlog which we use to prioritize what to build next. We can't make any promises about the timing, but it's on the list!

For others landing on this issue, feel free to add more context or simply leave a thumbs up 👍 on this comment if you find this feature useful.

kylemh commented 2 years ago

Thanks so much. Your post is already so helpful.

hkngoc commented 2 years ago

I have chrome extension use sandpack. I use firestore to store source code for sandpcack i also custom sandpack-context to use monaco-editor.

Your idea is very interesting. And, Firepad is very helpful with this.

hussamkhatib commented 2 years ago

How about using useSandpack hook to sync multiple users.

When a user makes a change to the editor, send the state to other users using web sockets. Once received, call updateCurrentFile to keep all the editors in sync.

This might not be possible as

How is live code editing done in codesandbox ? Does it update content with row and column position or does it update as a whole new file

@danilowoz

danilowoz commented 2 years ago

Hey @hussamkhatib, you can get the file changes using the following hook https://sandpack.codesandbox.io/docs/advanced-usage/hooks#useactivecode. However, it's still not ideal because:

I'm looking forward to making progress in this discussion. I'll try to find some time to explore more about it.

stevenfabre commented 2 years ago

It would be amazing to enable multiplayer collaboration on Sandpack!

You could use Liveblocks for this to add presence (e.g line people have selected, where they cursor is positioned in the code, etc.) and sync the data in real-time across users. That being said, as of today we only support LiveObject, LiveMap, and LiveList data structures. Meaning there is no easy way today to have conflict resolution at the string level — which would be quite handy for a code editor. We're planning to add a LiveText data structure in the coming months, so this could be something we could enable for this once that's available.

hussamkhatib commented 2 years ago

Hi @danilowoz , I was able to get it working with firepad.It gives live text updates, and cursor positions, and I am able to see the changes in the iframe as well. It stops working when the default active tab is changed (eg in a react template default file is App.js, when we switch to say styles.css, it breaks)

danilowoz commented 2 years ago

Awesome @hussamkhatib! Could you share your progress? I'm looking forward to seeing this working!

hussamkhatib commented 2 years ago

I finally got it working. I had 2 lines of code missing in the useEffect cleanup that had it not working before.

The only thing missing is syncing of code when users are editing files in different files For eg User A is on App.js and User B on styles.css User B changes some css which is reflected only in his screen and not in User A, User A would have to navigate to styles.css to get the changes and see it live in the preview.

One solution I thought of is to listen to changes (sockets etc) , if the change is in the same file ignore as the library handles that , else call updateCode method which might help in syncing the preview for everyone. I couldn't find a way to call updateCode which updates the content of the non-active files though. I didn't try it out as the team is fine without it.

Thanks a lot, @danilowoz for helping throughout the process. I had been trying play with codeMirror, monaco and other options. In the end, I am glad the library takes cares of everything like race conditions etc.

Let me know if is useful for you to have a minimalistic example in a codesandbox.

danilowoz commented 2 years ago

@hussamkhatib amazing! Could you share the project? We're looking forward to seeing this working.

Plus, what do you think about creating a new topic in the documentation (Guide section) telling about how to implement this? I think it'd very useful for future contributors.

hussamkhatib commented 2 years ago

Sure, My PR is not merged yet 😅.I will share a link once it goes live in production.

I can work on the documentation as well. If a live example is required to play with, I can reproduce a codesandbox with working code and .env.sample so that you can embed the hosted version later.