Hello!
I’m working with yjs on my college project, intending to use it on a collaborative editor for coding for schools, but I’m having some trouble making it work with a backend. As a background, I am mainly a backend Rails developer, though this is my first time using action cable for anything, for this project I have to use Angular (not my choice) so I’m trying to build a proof of concept before actually working on the real deal.
My problem is that even though I get no error messages, the editors do work collaboratively between tabs of the same browser, and I do see messages being sent and received between backend and frontend, I do not see the actual document from the backend in the frontend.
I’ll post the code below, but here’s a link to the repo: https://github.com/DJA89/crdt_yjs_matefun/tree/add_collaborative_eidition_libraries_for_help
// crdt_yjs_matefun/frontend/src/app/code-editor/code-editor.component.ts
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'
import { OnInit } from '@angular/core';
import * as Y from "yjs";
import { WebsocketProvider } from "@y-rb/actioncable";
import CodeMirror from "codemirror";
import { CodeMirrorBinding } from 'y-codemirror'
import ActionCable from 'actioncable'
@Component({
selector: 'code-editor',
templateUrl: './code-editor.component.html',
styleUrls: ['./code-editor.component.scss']
})
export class CodeEditorComponent implements OnInit {
constructor(private http: HttpClient) {
}
ngOnInit() {
const accessToken = localStorage.getItem('accessToken')
const uid = localStorage.getItem('uid')
const client = localStorage.getItem('client')
const yDocument = new Y.Doc();
const consumer = ActionCable.createConsumer(`ws://localhost:3000/cable?uid=${uid}&access-token=${accessToken}&client=${client}`);
const provider = new WebsocketProvider(
yDocument,
consumer,
"ApplicationCable::DocumentChannel",
{}
);
const yText = yDocument.getText('codemirror')
const yUndoManager = new Y.UndoManager(yText)
const editorContainer = document.createElement('div')
editorContainer.setAttribute('id', 'editor')
document.body.insertBefore(editorContainer, null)
const editor = CodeMirror(editorContainer, {
mode: 'javascript',
lineNumbers: true,
})
const binding = new CodeMirrorBinding(yText, editor, provider.awareness, { yUndoManager })
// @ts-ignore
//window.example = { provider, ydoc, yText, binding, Y }
}
}
# backend/app/channels/application_cable/document_channel.rb
require 'y-rb'
module ApplicationCable
class DocumentChannel < ApplicationCable::Channel
include Y::Actioncable::Sync
def initialize(connection, identifier, params = nil)
super
load { |id| load_doc 1 }
end
def subscribed
sync_from("document-1")
end
def receive(data)
sync_to("document-1", data)
end
def unsubscribed
end
private
def load_doc(id)
doc_content = Document.first.content
ydoc = Y::Doc.new
ytext = ydoc.get_text('mine')
ytext << doc_content
data = []
data = ydoc.diff unless doc_content.nil?
data
end
end
end
Could anyone guide me to make this work, or hint at what could the problem be?