import _ from 'lodash'; import { useEffect, useState } from 'react'; import { getUpdatedDocFromText, initDoc, SyncClient } from '../app/sync'; import { withErrorHandlingAsync } from './util'; import { addEntry, getHistory, registerTextState } from 'src/_aqua/app'; const broadcastUpdates = _.debounce((text: string, syncClient: SyncClient) => { let doc = syncClient.getDoc(); if (doc) { let newDoc = getUpdatedDocFromText(doc, text); syncClient.syncDoc(newDoc); } }, 100); export const CollaborativeEditor = () => { const [text, setText] = useState(null); const [syncClient, setSyncClient] = useState(new SyncClient()); useEffect(() => { syncClient.handleDocUpdate = (doc) => { setText(doc.text.toString()); }; syncClient.handleSendChanges = (changes: string) => { withErrorHandlingAsync(async () => { const res = await addEntry(changes); if (res.ret_code !== 0) { throw new Error( `Failed to add message to history service, code=${res.ret_code}, message=${res.err_msg}`, ); } }); }; registerTextState({ notifyTextUpdate: (changes, isAuthorized) => { if (changes) { syncClient.receiveChanges(changes); } } }) syncClient.start(); // don't block withErrorHandlingAsync(async () => { const res = await getHistory(); for (let e of res.entries) { syncClient.receiveChanges(e.body); } if (syncClient.getDoc() === undefined) { syncClient.syncDoc(initDoc()); } }); return () => { syncClient.stop(); }; }, []); const handleTextUpdate = (e: React.ChangeEvent) => { const newText = e.target.value; setText(newText); broadcastUpdates(newText, syncClient); }; return (