| import { useEffect, useState } from "react"; | |
| import type * as Y from "yjs"; | |
| export interface PublishStatus { | |
| active: boolean; | |
| userName: string | null; | |
| startedAt: number | null; | |
| jobId: string | null; | |
| } | |
| const INACTIVE: PublishStatus = { | |
| active: false, | |
| userName: null, | |
| startedAt: null, | |
| jobId: null, | |
| }; | |
| /** | |
| * Observe the `publish-status` Y.Map on a document. The backend populates | |
| * this map at the start and end of a publish so that all connected editors | |
| * can disable their Publish button while a publish is running. | |
| * | |
| * `doc` may be `null` while the provider is still connecting; the hook simply | |
| * returns an inactive status in that case and re-subscribes when `doc` is set. | |
| */ | |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | |
| export function usePublishStatus(doc: Y.Doc | null): PublishStatus { | |
| const [status, setStatus] = useState<PublishStatus>(INACTIVE); | |
| useEffect(() => { | |
| if (!doc) { | |
| setStatus(INACTIVE); | |
| return; | |
| } | |
| const map = doc.getMap("publish-status"); | |
| const read = (): PublishStatus => ({ | |
| active: (map.get("active") as boolean) === true, | |
| userName: (map.get("userName") as string | null | undefined) ?? null, | |
| startedAt: (map.get("startedAt") as number | null | undefined) ?? null, | |
| jobId: (map.get("jobId") as string | null | undefined) ?? null, | |
| }); | |
| setStatus(read()); | |
| const observer = () => setStatus(read()); | |
| map.observe(observer); | |
| return () => map.unobserve(observer); | |
| }, [doc]); | |
| return status; | |
| } | |