From 5078d987f83943671f1d23ebe66bcc8d2af902c3 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 24 Aug 2026 21:15:54 -0400 Subject: [PATCH] refac --- .../components/common/RichTextInput.svelte | 4 +- .../common/RichTextInput/Collaboration.ts | 58 +++++++++++-------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte index 2654c319fd..7ea71d5921 100644 --- a/src/lib/components/common/RichTextInput.svelte +++ b/src/lib/components/common/RichTextInput.svelte @@ -765,7 +765,7 @@ } } - if (collaboration && documentId && socket && user) { + if (collaboration && editable && documentId && socket && user) { const { SocketIOCollaborationProvider } = await import('./RichTextInput/Collaboration'); provider = new SocketIOCollaborationProvider(documentId, socket, user, content); } @@ -909,7 +909,7 @@ : []), ...(collaboration && provider ? [provider.getEditorExtension()] : []) ], - content: collaboration ? undefined : content, + content: provider ? undefined : content, autofocus: messageInput ? true : false, onTransaction: () => { if (!editor) return; diff --git a/src/lib/components/common/RichTextInput/Collaboration.ts b/src/lib/components/common/RichTextInput/Collaboration.ts index e261af01a1..539da07a1e 100644 --- a/src/lib/components/common/RichTextInput/Collaboration.ts +++ b/src/lib/components/common/RichTextInput/Collaboration.ts @@ -32,7 +32,7 @@ const generateUserColor = () => { export type EditorContentGetter = () => { md: string; html: string; - json: string; + json: unknown; }; // Custom Yjs Socket.IO provider @@ -48,7 +48,7 @@ export class SocketIOCollaborationProvider { private readonly documentId: string, private readonly socket: Socket, private readonly user: SessionUser, - private readonly initialContent: string | null = null + private readonly initialContent: unknown = null ) { this.setupEventListeners(); } @@ -82,9 +82,30 @@ export class SocketIOCollaborationProvider { public setEditor(editor: Editor, editorContentGetter: EditorContentGetter) { this.editor = editor; this.editorContentGetter = editorContentGetter; + + if (this.socket.connected && !this.isConnected) { + this.isConnected = true; + } + if (this.isConnected) { + this.joinDocument(); + } + } + + private applyInitialContent() { + if (!this.editor || !this.initialContent) return; + + if (typeof this.initialContent === 'string') { + this.editor.commands.setContent(this.initialContent); + return; + } + + const doc = prosemirrorJSONToYDoc(this.editor.schema, this.initialContent); + Y.applyUpdate(this.doc, Y.encodeStateAsUpdate(doc)); } private joinDocument() { + if (!this.editor) return; + const userColor = generateUserColor(); this.socket.emit('ydoc:document:join', { document_id: this.documentId, @@ -124,28 +145,16 @@ export class SocketIOCollaborationProvider { const state = new Uint8Array(data.state); if (state.length === 2 && state[0] === 0 && state[1] === 0) { - // Empty state, check if we have content to initialize - // check if editor empty as well - // const editor = await getEditorInstance(); - - const isEmptyEditor = !this.editor?.getText().trim(); - if (isEmptyEditor && this.editor) { - if (this.initialContent && (data?.sessions ?? ['']).length === 1) { - // Check if initialContent is HTML (string) or JSON (object) - if (typeof this.initialContent === 'string') { - // HTML content - let the editor parse it, then sync to Yjs - this.editor.commands.setContent(this.initialContent); - // The Yjs plugin will automatically sync the content - } else { - // JSON content - use the existing approach - const editorYdoc = prosemirrorJSONToYDoc( - this.editor.schema, - this.initialContent - ); - if (editorYdoc) { - Y.applyUpdate(this.doc, Y.encodeStateAsUpdate(editorYdoc)); - } - } + if ( + this.editor && + !this.editor.getText().trim() && + this.doc.getXmlFragment('prosemirror').length === 0 + ) { + if ( + this.initialContent && + [...(data.sessions ?? [])].sort()[0] === this.socket.id + ) { + this.applyInitialContent(); } } else { // If the editor already has content, we don't need to send an empty state @@ -233,7 +242,6 @@ export class SocketIOCollaborationProvider { if (this.socket.connected) { this.isConnected = true; - this.joinDocument(); } }