Skip to content
File

Blob: src/client/components/editor/use-editor-session.ts

typescript49 lines
1import * as Y from "yjs";
2import type YProvider from "y-partyserver/provider";
3import { getCachedDocKey } from "@/client/lib/constants";
4import { useDocSyncSession, type DocSyncSessionState } from "@/client/lib/doc-sync-session";
5import { YJS_DOCUMENT_STORE } from "@/shared/constants";
6 
7interface EditorRuntime {
8 fragment: Y.XmlFragment;
9}
10 
11export type EditorSessionState = DocSyncSessionState<EditorRuntime>;
12export type EditorSessionLoadingState = Extract<EditorSessionState, { kind: "loading" }>;
13export type EditorSessionReadyState = Extract<EditorSessionState, { kind: "ready" }>;
14export type EditorSessionErrorState = Extract<EditorSessionState, { kind: "error" }>;
15 
16interface UseEditorSessionOptions {
17 pageId: string;
18 initialTitle: string;
19 onTitleChange?: (title: string) => void;
20 onProvider?: (provider: YProvider | null) => void;
21 shareToken?: string;
22 workspaceId?: string;
23 enabled?: boolean;
24}
25 
26function editorRoots(ydoc: Y.Doc): EditorRuntime {
27 return { fragment: ydoc.getXmlFragment(YJS_DOCUMENT_STORE) };
28}
29 
30function editorHasBody({ fragment }: EditorRuntime): boolean {
31 return fragment.length > 0;
32}
33 
34export function useEditorSession(opts: UseEditorSessionOptions): EditorSessionState {
35 return useDocSyncSession<EditorRuntime>({
36 pageId: opts.pageId,
37 initialTitle: opts.initialTitle,
38 onTitleChange: opts.onTitleChange,
39 onProvider: opts.onProvider,
40 shareToken: opts.shareToken,
41 workspaceId: opts.workspaceId,
42 enabled: opts.enabled,
43 cacheKey: getCachedDocKey(opts.pageId),
44 errorSource: "editor.snapshot-bootstrap",
45 roots: editorRoots,
46 hasBody: editorHasBody,
47 });
48}