-
Notifications
You must be signed in to change notification settings - Fork 0
/
useY.ts
62 lines (53 loc) · 2.05 KB
/
useY.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { useCallback, useEffect, useMemo } from 'react';
import { Awareness, applyAwarenessUpdate, encodeAwarenessUpdate } from 'y-protocols/awareness';
import * as Y from 'yjs';
import { NetworkId } from '../api/RtcNetwork';
import { useDataChannel, useDataChannelLifecycle } from './RtcHooks';
export default function useY(network: NetworkId, channel: string) {
const yDoc = useMemo(() => new Y.Doc(), []);
const emit = useDataChannelLifecycle(
network,
channel,
// On Data Received
useCallback((...[event, data, emit]) => {
switch (event) {
case 'connect':
console.debug('Sending initial Y state to', data.who.id);
emit(Y.encodeStateAsUpdateV2(yDoc), { target: [data.who.id] });
break;
case 'message':
Y.applyUpdateV2(yDoc, data.content);
}
}, [yDoc]),
);
useEffect(() => {
const handler = (update: Uint8Array) => {
emit(Y.convertUpdateFormatV1ToV2(update));
};
yDoc.on('update', handler);
return () => yDoc.off('update', handler);
}, [yDoc, emit]);
return yDoc;
}
/**
* Returns a Y awareness instance. See https://github.com/yjs/y-protocols for details.
*/
export function useYAwareness(network: NetworkId, channel: string, doc: Y.Doc, extraFields: Record<string, any> = {}) {
const awareness = useMemo(() => new Awareness(doc), [doc]);
const emit = useDataChannel(
network,
channel,
useCallback((update) => {
applyAwarenessUpdate(awareness, update, null);
}, [awareness])
);
useEffect(() => {
const handler = () => {
awareness.setLocalState({ ...extraFields, ...awareness.getLocalState() });
emit(encodeAwarenessUpdate(awareness, Array.from(awareness.getStates().keys())));
};
awareness.on('change', handler);
return () => awareness.off('change', handler);
}, [awareness, emit, extraFields]);
return awareness;
}