Collaborative Editing & Monaco

Introduction #

I love Visual Studio Code and I use it everyday. Visual Studio Code uses Monaco as it’s code editor.

Monaco is a really impressive code editor with some amazing features. One of the best features is really how fast it feels. Here is a HN discussion about why Monaco is really really fast. As i started to experiment with the editor more, I realized how amazing it would be if someone used Monaco as the base of a new collaborative editor. Maybe, I should do it.

Thinking about this problem a bit more, if I was going to build a collaborative editor it would need to have the following featureset:

Choosing my backend #

There are a couple of choices.

Web Sockets / WebRTC #

One approach is the use of Web Sockets / WebRTC, and operational transforms. I could use something like Socket.IO. The client could use the OT model of Monaco editor.

Disadvantages #

Google Drive Realtime API #

I could use the Google Drive Realtime APIs.

Advantages #

Firebase Realtime Database and Firebase Cloud Fire Store #

Advantages #

Disadvantages #

Looking at all the above options, I decided to go with Google Drive Realtime API, given that I get all the permissions management for free. The Firebase Cloud Fire Store API is another great option. It could be another alternative datastore that I could support in the future.

Okay, Let’s really build this #

I realized I need a couple of Cloud functions that will create new documents on Google Drive, using their REST API and annotate them with custom attributes, to help with discovering them.

The official documentation for Google Drive Realtime APIs stated that I need the https://www.googleapis.com/auth/drive scope. That was going to be too broad. So I figured out that I could use shortcut files. One shortcoming of shortcut files however, is they seem to get implicitly filtered by the Drive v3 list files API. So need to attach custom attributes that will help surface these files. Now i can finally use the less scary https://www.googleapis.com/auth/drive.file scope.

I started diving into Monaco editor, to understand the underlying editor model. I discovered Monaco exposes low level change events, that can be transformed into a set of changes that can be applied using the applyEdits API. I use the Google Realtime API to store these changes in Google Drive.

I had also fortunately authored AppAuth-JS. This is the library that I used to help the users log in, and request the drive scopes I need.

Once I got the basic mechanics of synchronizing changes working, I started to work on synchronizing cursor selections which turned into a slightly bigger challenge. I also had to synchronize selection invalidations and some spurious selections while editing a range. But eventually i got that working.

Demo time #

Here is a demo of all of this working.

Try it out #

Try it out here. For more information about the application take a look at this.

Epilogue #

Google Drive Realtime API deprecation. #

Google Drive Realtime APIs are now deprecated in favor of the Firebase platform (Firestore and the Realtime database). So I am in the middle of migrating my datastores at the moment.

Video Editing / Recording #

My apologies for the slight cold I had when i recorded the video.

 
215
Kudos
 
215
Kudos

Now read this

Security Providers and BouncyCastle

BouncyCastle is a pretty cool library, but lacks useful documentation. The website is a mess. If you want to setup BouncyCastle as your Java Security Provider (you should, the defaults are pretty bad) you need to do the following. First... Continue →