v3/src/hooks/use-note.tsx

81 lines
2.2 KiB
TypeScript

import React from "react";
import * as Y from "yjs";
import type { NoteId } from "~/lib/metadata";
import { useYDoc } from "./use-ydoc";
import type { WebsocketProvider } from "y-websocket";
import type { IndexeddbPersistence } from "y-indexeddb";
const NoteContext = React.createContext<{
doc: Y.Doc,
providers: {
indexeddb: IndexeddbPersistence,
websocket: WebsocketProvider,
}
} | null>(null);
export function NoteProvider(props: { children: React.ReactNode, id: NoteId }) {
const { ydoc, indexeddbProvider, websocketProvider } = useYDoc(`note-${props.id}`);
// If we don't have the provider yet, delay rendering until we do.
if (!indexeddbProvider || !websocketProvider) {
return null;
}
return (
<NoteContext.Provider value={{
doc: ydoc,
providers: {
indexeddb: indexeddbProvider,
websocket: websocketProvider,
}
}}>
{props.children}
</NoteContext.Provider>
);
}
export function useNoteDoc() {
const ctx = React.useContext(NoteContext);
if (!ctx) {
throw new Error("useNoteDoc must be used within a NoteProvider")
}
return ctx.doc;
}
export function useNoteMap(name: string) {
const ctx = React.useContext(NoteContext);
if (!ctx) {
throw new Error("useNoteMap must be used within a NoteProvider")
}
const map = ctx.doc.getMap(name);
return map;
}
export function useNoteArray(name: string) {
const ctx = React.useContext(NoteContext);
if (!ctx) {
throw new Error("useNoteArray must be used within a NoteProvider")
}
const array = ctx.doc.getArray(name);
return array;
}
export function useNoteProviders() {
const ctx = React.useContext(NoteContext);
if (!ctx) {
throw new Error("useNoteProviders must be used within a NoteProvider")
}
return ctx.providers;
}
export function useNoteAwareness() {
const ctx = React.useContext(NoteContext);
if (!ctx) {
throw new Error("useNoteAwareness must be used within a NoteProvider")
}
const awareness = ctx.providers.websocket.awareness;
return awareness;
}