Skip to content
File

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

typescript55 lines
1import * as Y from "yjs";
2import type YProvider from "y-partyserver/provider";
3import { getCachedCanvasKey } from "@/client/lib/constants";
4import { useDocSyncSession, type DocSyncSessionState } from "@/client/lib/doc-sync-session";
5import { YJS_CANVAS_APP_STATE, YJS_CANVAS_ELEMENTS, YJS_CANVAS_FILE_REFS } from "@/shared/constants";
6 
7interface CanvasRuntime {
8 yElements: Y.Map<Y.Map<unknown>>;
9 yAppState: Y.Map<unknown>;
10 yFileRefs: Y.Map<string>;
11}
12 
13export type CanvasSessionState = DocSyncSessionState<CanvasRuntime>;
14export type CanvasSessionLoadingState = Extract<CanvasSessionState, { kind: "loading" }>;
15export type CanvasSessionReadyState = Extract<CanvasSessionState, { kind: "ready" }>;
16export type CanvasSessionErrorState = Extract<CanvasSessionState, { kind: "error" }>;
17 
18interface UseCanvasSessionOptions {
19 pageId: string;
20 initialTitle: string;
21 onTitleChange?: (title: string) => void;
22 onProvider?: (provider: YProvider | null) => void;
23 shareToken?: string;
24 workspaceId?: string;
25 enabled?: boolean;
26}
27 
28function canvasRoots(ydoc: Y.Doc): CanvasRuntime {
29 return {
30 yElements: ydoc.getMap<Y.Map<unknown>>(YJS_CANVAS_ELEMENTS),
31 yAppState: ydoc.getMap<unknown>(YJS_CANVAS_APP_STATE),
32 yFileRefs: ydoc.getMap<string>(YJS_CANVAS_FILE_REFS),
33 };
34}
35 
36function canvasHasBody({ yElements }: CanvasRuntime): boolean {
37 return yElements.size > 0;
38}
39 
40export function useCanvasSession(opts: UseCanvasSessionOptions): CanvasSessionState {
41 return useDocSyncSession<CanvasRuntime>({
42 pageId: opts.pageId,
43 initialTitle: opts.initialTitle,
44 onTitleChange: opts.onTitleChange,
45 onProvider: opts.onProvider,
46 shareToken: opts.shareToken,
47 workspaceId: opts.workspaceId,
48 enabled: opts.enabled,
49 cacheKey: getCachedCanvasKey(opts.pageId),
50 errorSource: "canvas.snapshot-bootstrap",
51 roots: canvasRoots,
52 hasBody: canvasHasBody,
53 });
54}