I am trying to using yjs "yjs": "^13.6.7"
https://github.com/yjs/yjs to implement an online collaboration editor. This is how I initial the yjs in react function component:
import { useRef } from "react";
import { EditorView } from "@codemirror/view";
import { basicSetup } from "codemirror";
import styles from "./CollarCodeEditor.module.css";
import {
syntaxHighlighting,
defaultHighlightStyle,
StreamLanguage,
} from '@codemirror/language';
import { stex } from '@codemirror/legacy-modes/mode/stex';
import * as Y from 'yjs';
import { yCollab } from 'y-codemirror.next';
import { EditorState } from "@codemirror/state";
import { javascript } from '@codemirror/lang-javascript';
import * as random from 'lib0/random';
import { WebsocketProvider } from 'y-websocket';
import React from "react";
export const usercolors = [
{ color: '#30bced', light: '#30bced33' },
{ color: '#6eeb83', light: '#6eeb8333' },
{ color: '#ffbc42', light: '#ffbc4233' },
{ color: '#ecd444', light: '#ecd44433' },
{ color: '#ee6352', light: '#ee635233' },
{ color: '#9ac2c9', light: '#9ac2c933' },
{ color: '#8acb88', light: '#8acb8833' },
{ color: '#1be7ff', light: '#1be7ff33' }
];
export const userColor = usercolors[random.uint32() % usercolors.length];
const extensions = [
EditorView.contentAttributes.of({ spellcheck: 'true' }),
EditorView.lineWrapping,
EditorView.theme({
'.cm-content': {
},
'.cm-scroller': {
maxHeight: '100vh',
minHeight: '100vh',
},
}),
StreamLanguage.define(stex),
syntaxHighlighting(defaultHighlightStyle),
];
export type EditorProps = {
projectId: string;
docId: string;
};
const CollarCodeEditor: React.FC<EditorProps> = (props: EditorProps) => {
const edContainer = useRef<any>();
React.useEffect(() => {
const view = initEditor(props.projectId, props.docId);
return () => {
view.destroy();
};
}, []);
const initEditor = (projectId: string, docId: string): EditorView => {
let docOpt = {
guid: docId,
collectionid: projectId
};
const ydoc = new Y.Doc(docOpt);
const ytext = ydoc.getText('codemirror');
const undoManager = new Y.UndoManager(ytext);
const wsProvider = new WebsocketProvider('wss://ws.example.com', projectId, ydoc);
debugger
wsProvider.awareness.setLocalStateField('user', {
name: 'Anonymous ' + Math.floor(Math.random() * 100),
color: userColor.color,
colorLight: userColor.light
});
const state = EditorState.create({
doc: ytext.toString(),
extensions: [
basicSetup,
javascript(),
yCollab(ytext, wsProvider.awareness, { undoManager })
]
});
const view = new EditorView({
state,
parent: edContainer.current,
extensions: [basicSetup, extensions]
});
return view;
}
return <div ref={edContainer} className={styles.container}></div>;
}
export default CollarCodeEditor;
now I am facing a issue that I can switch the docs by reconnect the websocket. when I choose the doc in UI, I need the editor load different docs reuse the exists websocket connection. is it possible to switch the docs without reconnect the websocket?
y-websocket
does not let you do this. But you could copy and modify its source code so that it takes an existing WebSocket as input instead of making a new one: https://github.com/yjs/y-websocket/Or, you could use the
WebsocketPolyfill
option to provide a class that has the same API asWebSocket
, but whose instances are actually thin wrappers around a single existing WebSocket.