-
Notifications
You must be signed in to change notification settings - Fork 20
/
useYorkieDocument.ts
118 lines (102 loc) · 3.1 KB
/
useYorkieDocument.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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import Color from "color";
import randomColor from "randomcolor";
import { useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useSearchParams } from "react-router-dom";
import * as yorkie from "yorkie-js-sdk";
import { selectAuth } from "../store/authSlice";
import { CodePairDocType } from "../store/editorSlice";
import { YorkieCodeMirrorDocType, YorkieCodeMirrorPresenceType } from "../utils/yorkie/yorkieSync";
const YORKIE_API_ADDR = import.meta.env.VITE_YORKIE_API_ADDR;
const YORKIE_API_KEY = import.meta.env.VITE_YORKIE_API_KEY;
yorkie.setLogLevel(4);
export const useYorkieDocument = (
yorkieDocumentId?: string | null,
presenceName?: string | null
) => {
const [searchParams] = useSearchParams();
const authStore = useSelector(selectAuth);
const [client, setClient] = useState<yorkie.Client | null>(null);
const [doc, setDoc] = useState<CodePairDocType | null>(null);
const getYorkieToken = useCallback(() => {
const shareToken = searchParams.get("token");
return shareToken ? `share:${shareToken}` : `default:${authStore.accessToken}`;
}, [authStore.accessToken, searchParams]);
const createYorkieClient = useCallback(async (yorkieToken: string) => {
const newClient = new yorkie.Client(YORKIE_API_ADDR, {
apiKey: YORKIE_API_KEY,
token: yorkieToken,
});
await newClient.activate();
return newClient;
}, []);
const createYorkieDocument = useCallback(
(client: yorkie.Client, yorkieDocumentId: string, presenceName: string) => {
const newDocument = new yorkie.Document<
YorkieCodeMirrorDocType,
YorkieCodeMirrorPresenceType
>(yorkieDocumentId, { enableDevtools: true });
return client.attach(newDocument, {
initialPresence: {
name: presenceName,
color: Color(randomColor()).fade(0.15).toString(),
selection: null,
cursor: null,
},
});
},
[]
);
const cleanUpYorkieDocument = useCallback(async () => {
if (!client || !doc) return;
try {
await client.detach(doc);
await client.deactivate();
} catch (error) {
console.error("Error during Yorkie cleanup:", error);
}
}, [client, doc]);
useEffect(() => {
let mounted = true;
if (!yorkieDocumentId || !presenceName || doc || client) return;
const initializeYorkie = async () => {
try {
const yorkieToken = getYorkieToken();
const newClient = await createYorkieClient(yorkieToken);
const newDoc = await createYorkieDocument(
newClient,
yorkieDocumentId,
presenceName
);
// Clean up if the component is unmounted before the initialization is done
if (!mounted) {
await newClient.detach(newDoc);
await newClient.deactivate();
return;
}
setClient(newClient);
setDoc(newDoc);
} catch (error) {
console.error("Error initializing Yorkie: ", error);
}
};
initializeYorkie();
return () => {
mounted = false;
};
}, [
presenceName,
yorkieDocumentId,
doc,
client,
getYorkieToken,
createYorkieClient,
createYorkieDocument,
]);
useEffect(() => {
return () => {
cleanUpYorkieDocument();
};
}, [cleanUpYorkieDocument]);
return { client, doc };
};