fluent-pad/client/src/components/CollaborativeEditor.tsx

69 lines
2.2 KiB
TypeScript
Raw Normal View History

2021-01-16 12:28:01 +03:00
import _ from 'lodash';
import { useEffect, useState } from 'react';
import { subscribeToEvent } from '@fluencelabs/fluence';
2021-01-16 13:24:26 +03:00
import { fluentPadServiceId, notifyTextUpdateFnName } from 'src/app/constants';
import { useFluenceClient } from '../app/FluenceClientContext';
import { getUpdatedDocFromText, initDoc, SyncClient } from '../app/sync';
import * as calls from 'src/app/api';
2021-01-14 13:17:48 +03:00
2021-01-16 12:28:01 +03:00
const broadcastUpdates = _.debounce((text: string, syncClient: SyncClient) => {
let doc = syncClient.getDoc();
if (doc) {
let newDoc = getUpdatedDocFromText(doc, text);
syncClient.syncDoc(newDoc);
2021-01-14 23:57:24 +03:00
}
2021-01-16 12:28:01 +03:00
}, 100);
2021-01-14 13:17:48 +03:00
export const CollaborativeEditor = () => {
const client = useFluenceClient()!;
2021-01-16 01:38:09 +03:00
const [text, setText] = useState('');
2021-01-16 12:28:01 +03:00
const [syncClient, setSyncClient] = useState(new SyncClient());
2021-01-14 13:17:48 +03:00
useEffect(() => {
2021-01-16 12:28:01 +03:00
syncClient.syncDoc(initDoc());
syncClient.handleDocUpdate = (doc) => {
console.log('syncClient.handleDocUpdate');
setText(doc.text.toString());
};
syncClient.handleSendChanges = (changes: string) => {
console.log('syncClient.handleSendChanges');
calls.addEntry(client, changes);
};
2021-01-16 01:38:09 +03:00
2021-01-16 12:28:01 +03:00
const unsub = subscribeToEvent(client, fluentPadServiceId, notifyTextUpdateFnName, (args, tetraplets) => {
const [authorPeerId, changes, isAuthorized] = args;
if (authorPeerId === client.selfPeerId.toB58String()) {
return;
}
2021-01-16 12:28:01 +03:00
if (changes) {
syncClient.receiveChanges(changes);
2021-01-14 23:57:24 +03:00
}
2021-01-14 13:17:48 +03:00
});
2021-01-16 12:28:01 +03:00
syncClient.start();
2021-01-14 13:17:48 +03:00
// don't block
calls.getHistory(client).then((res) => {
2021-01-16 01:38:09 +03:00
for (let e of res) {
2021-01-16 12:28:01 +03:00
syncClient.receiveChanges(e.body);
2021-01-16 01:38:09 +03:00
}
2021-01-14 13:17:48 +03:00
});
return () => {
2021-01-16 12:28:01 +03:00
unsub();
syncClient.stop();
2021-01-14 13:17:48 +03:00
};
}, []);
const handleTextUpdate = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
2021-01-16 12:28:01 +03:00
const newText = e.target.value;
setText(newText);
broadcastUpdates(newText, syncClient);
2021-01-14 13:17:48 +03:00
};
2021-01-16 16:25:28 +03:00
return <textarea spellCheck={false} className="code-editor" value={text} onChange={handleTextUpdate} />;
2021-01-14 13:17:48 +03:00
};