{"version":3,"file":"use-link-stats.cjs","names":[],"sources":["../../src/webrtc/use-link-stats.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport { useDocumentVisibility } from \"../hooks/use-document-visibility\";\nimport { useInterval } from \"../hooks/use-interval\";\nimport {\n    createLinkStatsSampler,\n    type LinkStats,\n    type LinkStatsKind,\n    type LinkStatsSampler,\n} from \"./link-stats\";\n\n/** Options for {@link useLinkStats}. */\nexport interface UseLinkStatsOptions {\n    /**\n     * How often to sample, in milliseconds. Default `2000`.\n     *\n     * `getStats()` walks every report a connection holds, and a mesh runs one\n     * per participant — on the device least able to pay for it. The numbers feed\n     * a latency badge and a throughput figure nobody reads at 1 Hz, so the\n     * default is deliberately slower than a frame budget suggests.\n     */\n    intervalMs?: number;\n    /**\n     * Stop sampling while the tab is in the background. Default `true`.\n     *\n     * The audio path is untouched by this — people in a backgrounded call still\n     * expect to hear it. What stops is the measuring, which nobody can see.\n     */\n    pauseWhenHidden?: boolean;\n    /** Which media the throughput counts. Default `\"video\"`. */\n    kind?: LinkStatsKind;\n}\n\n/**\n * Poll one connection's throughput, resolution and round trip.\n *\n * Sampling runs only while the connection is `\"connected\"`, so a link that is\n * still negotiating or already gone costs nothing. The last reading is kept\n * across pauses rather than cleared, because a badge that blanks every time the\n * tab loses focus reads as a broken connection.\n *\n * Coming back from a pause resets the baseline first. Without that, the sample\n * after a five-minute background stretch divides five minutes of bytes by five\n * minutes and reports the average of a period the person is not asking about.\n *\n * @param connection - The connection to watch, or `null` before one exists.\n * @param options - See {@link UseLinkStatsOptions}.\n * @returns The latest reading, or `null` before the first sample lands.\n *\n * @example\n * const stats = useLinkStats(pc);\n *\n * return <span>{stats ? `${stats.kbps} kbps · ${stats.rttMs ?? \"—\"} ms` : \"medindo…\"}</span>;\n */\nexport function useLinkStats(\n    connection: RTCPeerConnection | null,\n    options: UseLinkStatsOptions = {},\n): LinkStats | null {\n    const { intervalMs = 2000, pauseWhenHidden = true, kind } = options;\n    const [stats, setStats] = useState<LinkStats | null>(null);\n    const samplerRef = useRef<LinkStatsSampler | null>(null);\n    const inFlightRef = useRef(false);\n    const visibility = useDocumentVisibility();\n    const hidden = pauseWhenHidden && visibility === \"hidden\";\n\n    useEffect(() => {\n        samplerRef.current = createLinkStatsSampler(kind === undefined ? {} : { kind });\n        setStats(null);\n    }, [connection, kind]);\n\n    useEffect(() => {\n        if (!hidden) samplerRef.current?.reset();\n    }, [hidden]);\n\n    const paused = connection === null || hidden;\n\n    useInterval(\n        () => {\n            const sampler = samplerRef.current;\n            if (connection === null || sampler === null) return;\n            if (connection.connectionState !== \"connected\") return;\n            if (inFlightRef.current) return;\n            inFlightRef.current = true;\n            void sampler\n                .sample(connection)\n                .then((next) => setStats(next))\n                .catch(() => undefined)\n                .finally(() => {\n                    inFlightRef.current = false;\n                });\n        },\n        paused ? null : intervalMs,\n    );\n\n    return stats;\n}\n"],"mappings":"oJAsDA,SAAgB,EACZ,EACA,EAA+B,CAAC,EAChB,CAChB,GAAM,CAAE,aAAa,IAAM,kBAAkB,GAAM,QAAS,EACtD,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAA2B,IAAI,EACnD,GAAA,EAAa,EAAA,OAAA,CAAgC,IAAI,EACjD,GAAA,EAAc,EAAA,OAAA,CAAO,EAAK,EAC1B,EAAa,EAAA,sBAAsB,EACnC,EAAS,GAAmB,IAAe,SA+BjD,OA7BA,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAW,QAAU,EAAA,uBAAuB,IAAS,IAAA,GAAY,CAAC,EAAI,CAAE,MAAK,CAAC,EAC9E,EAAS,IAAI,CACjB,EAAG,CAAC,EAAY,CAAI,CAAC,GAErB,EAAA,EAAA,UAAA,KAAgB,CACP,GAAQ,EAAW,SAAS,MAAM,CAC3C,EAAG,CAAC,CAAM,CAAC,EAIX,EAAA,gBACU,CACF,IAAM,EAAU,EAAW,QACvB,IAAe,MAAQ,IAAY,MACnC,EAAW,kBAAoB,cAC/B,EAAY,UAChB,EAAY,QAAU,GACtB,EACK,OAAO,CAAU,CAAC,CAClB,KAAM,GAAS,EAAS,CAAI,CAAC,CAAC,CAC9B,UAAY,IAAA,EAAS,CAAC,CACtB,YAAc,CACX,EAAY,QAAU,EAC1B,CAAC,GACT,EAhBW,IAAe,MAAQ,EAiBzB,KAAO,CACpB,EAEO,CACX"}