81 lines
2.2 KiB
TypeScript
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;
|
|
}
|