@arbidocs/react 0.5.85 → 0.5.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/artifacts/index.cjs +46 -48
- package/dist/artifacts/index.cjs.map +1 -1
- package/dist/artifacts/index.js +7 -9
- package/dist/artifacts/index.js.map +1 -1
- package/dist/calls/livekit/index.cjs +60 -62
- package/dist/calls/livekit/index.cjs.map +1 -1
- package/dist/calls/livekit/index.js +6 -8
- package/dist/calls/livekit/index.js.map +1 -1
- package/dist/{chunk-Z3LLUO32.cjs → chunk-5NOZDH3F.cjs} +12 -2
- package/dist/chunk-5NOZDH3F.cjs.map +1 -0
- package/dist/{chunk-WQY3RQ6G.js → chunk-73ENECAT.js} +5 -6
- package/dist/{chunk-LUDIYWT7.cjs.map → chunk-73ENECAT.js.map} +1 -1
- package/dist/{chunk-2Y2WOIHH.cjs → chunk-AOPGD23L.cjs} +60 -148
- package/dist/chunk-AOPGD23L.cjs.map +1 -0
- package/dist/{chunk-G4Z3IP4J.js → chunk-BF5KW5ZI.js} +3 -17
- package/dist/chunk-BF5KW5ZI.js.map +1 -0
- package/dist/{chunk-TK7ERJPE.js → chunk-BFNY3RZG.js} +22 -12
- package/dist/chunk-BFNY3RZG.js.map +1 -0
- package/dist/{chunk-U4PWVSCT.cjs → chunk-C4WODQGO.cjs} +24 -11
- package/dist/chunk-C4WODQGO.cjs.map +1 -0
- package/dist/{chunk-E7VD5WNY.cjs → chunk-DS7NTSKH.cjs} +41 -74
- package/dist/chunk-DS7NTSKH.cjs.map +1 -0
- package/dist/{chunk-JT7PN7JH.js → chunk-DU2P354H.js} +6 -37
- package/dist/chunk-DU2P354H.js.map +1 -0
- package/dist/{chunk-TAVS54EN.cjs → chunk-GKWMT64A.cjs} +6 -6
- package/dist/{chunk-TAVS54EN.cjs.map → chunk-GKWMT64A.cjs.map} +1 -1
- package/dist/{chunk-AXKHDLBB.cjs → chunk-HEVPIVF2.cjs} +15 -15
- package/dist/{chunk-AXKHDLBB.cjs.map → chunk-HEVPIVF2.cjs.map} +1 -1
- package/dist/{chunk-XPLD4LFC.js → chunk-KTXZ222T.js} +6 -91
- package/dist/chunk-KTXZ222T.js.map +1 -0
- package/dist/{chunk-PXWKJI4K.cjs → chunk-LBAG7KL7.cjs} +35 -261
- package/dist/chunk-LBAG7KL7.cjs.map +1 -0
- package/dist/{chunk-CSPAEVZS.js → chunk-MS43RNXM.js} +5 -5
- package/dist/{chunk-CSPAEVZS.js.map → chunk-MS43RNXM.js.map} +1 -1
- package/dist/{chunk-OC7F5SNA.cjs → chunk-MXP4O4DI.cjs} +5 -5
- package/dist/{chunk-OC7F5SNA.cjs.map → chunk-MXP4O4DI.cjs.map} +1 -1
- package/dist/{chunk-ZWFMFOGP.cjs → chunk-NDIKMOBJ.cjs} +4 -4
- package/dist/{chunk-ZWFMFOGP.cjs.map → chunk-NDIKMOBJ.cjs.map} +1 -1
- package/dist/{chunk-XAEVT7ZM.js → chunk-NNAJLY6B.js} +34 -257
- package/dist/chunk-NNAJLY6B.js.map +1 -0
- package/dist/{chunk-LUDIYWT7.cjs → chunk-QLRDHLWR.cjs} +72 -73
- package/dist/chunk-QLRDHLWR.cjs.map +1 -0
- package/dist/{chunk-DZUBZ45Y.cjs → chunk-RLSBRZ6Z.cjs} +2 -17
- package/dist/chunk-RLSBRZ6Z.cjs.map +1 -0
- package/dist/{chunk-VGAA7AFS.js → chunk-S3OGDLDC.js} +4 -13
- package/dist/chunk-S3OGDLDC.js.map +1 -0
- package/dist/{chunk-NNWMHMEC.js → chunk-UW2SGTI5.js} +3 -3
- package/dist/{chunk-NNWMHMEC.js.map → chunk-UW2SGTI5.js.map} +1 -1
- package/dist/{chunk-QRCMKEE6.js → chunk-VSCU7K4V.js} +11 -3
- package/dist/chunk-VSCU7K4V.js.map +1 -0
- package/dist/{chunk-C44GO33B.js → chunk-WL2Y2T47.js} +3 -3
- package/dist/{chunk-C44GO33B.js.map → chunk-WL2Y2T47.js.map} +1 -1
- package/dist/{chunk-47YVW3J4.js → chunk-YQBDEOVE.js} +4 -4
- package/dist/{chunk-47YVW3J4.js.map → chunk-YQBDEOVE.js.map} +1 -1
- package/dist/{chunk-Q6U7ALNV.cjs → chunk-ZHXYFJIA.cjs} +44 -54
- package/dist/chunk-ZHXYFJIA.cjs.map +1 -0
- package/dist/document-tools/core.cjs +100 -110
- package/dist/document-tools/core.d.cts +3 -78
- package/dist/document-tools/core.d.ts +3 -78
- package/dist/document-tools/core.js +5 -7
- package/dist/document-tools/index.cjs +102 -112
- package/dist/document-tools/index.cjs.map +1 -1
- package/dist/document-tools/index.d.cts +2 -2
- package/dist/document-tools/index.d.ts +2 -2
- package/dist/document-tools/index.js +6 -8
- package/dist/document-tools/index.js.map +1 -1
- package/dist/index.cjs +1767 -2301
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-BDcwpFVa.d.cts → index.d-1_bJB-Yl.d.cts} +1 -58
- package/dist/{index.d-BDcwpFVa.d.ts → index.d-1_bJB-Yl.d.ts} +1 -58
- package/dist/{index.d-Deqz5-pF.d.ts → index.d-ChaR6kMc.d.cts} +1 -6
- package/dist/{index.d-Deqz5-pF.d.cts → index.d-ChaR6kMc.d.ts} +1 -6
- package/dist/index.d.cts +192 -1423
- package/dist/index.d.ts +192 -1423
- package/dist/index.js +311 -799
- package/dist/index.js.map +1 -1
- package/dist/{query-keys.d-Dm0NL9nr.d.cts → query-keys.d-D6SAUl7S.d.cts} +0 -9
- package/dist/{query-keys.d-Dm0NL9nr.d.ts → query-keys.d-D6SAUl7S.d.ts} +0 -9
- package/dist/shell/index.cjs +48 -53
- package/dist/shell/index.d.cts +1 -1
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.js +4 -5
- package/dist/ui/index.cjs +156 -169
- package/dist/ui/index.d.cts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +3 -4
- package/dist/viewers/index.cjs +0 -120
- package/dist/viewers/index.cjs.map +1 -1
- package/dist/viewers/index.d.cts +3 -40
- package/dist/viewers/index.d.ts +3 -40
- package/dist/viewers/index.js +1 -120
- package/dist/viewers/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-2Y2WOIHH.cjs.map +0 -1
- package/dist/chunk-CPZ36AQS.js +0 -11
- package/dist/chunk-CPZ36AQS.js.map +0 -1
- package/dist/chunk-DZUBZ45Y.cjs.map +0 -1
- package/dist/chunk-E7VD5WNY.cjs.map +0 -1
- package/dist/chunk-G4Z3IP4J.js.map +0 -1
- package/dist/chunk-JT7PN7JH.js.map +0 -1
- package/dist/chunk-PXWKJI4K.cjs.map +0 -1
- package/dist/chunk-Q6U7ALNV.cjs.map +0 -1
- package/dist/chunk-QRCMKEE6.js.map +0 -1
- package/dist/chunk-RCKA7BEF.cjs +0 -14
- package/dist/chunk-RCKA7BEF.cjs.map +0 -1
- package/dist/chunk-TK7ERJPE.js.map +0 -1
- package/dist/chunk-U4PWVSCT.cjs.map +0 -1
- package/dist/chunk-VGAA7AFS.js.map +0 -1
- package/dist/chunk-VGMMK5OM.cjs +0 -26
- package/dist/chunk-VGMMK5OM.cjs.map +0 -1
- package/dist/chunk-VGO77X5U.js +0 -22
- package/dist/chunk-VGO77X5U.js.map +0 -1
- package/dist/chunk-WQY3RQ6G.js.map +0 -1
- package/dist/chunk-XAEVT7ZM.js.map +0 -1
- package/dist/chunk-XPLD4LFC.js.map +0 -1
- package/dist/chunk-Z3LLUO32.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/calls/livekit/room.ts","../../../src/calls/livekit/useCallTranscriber.ts","../../../src/calls/livekit/useCallRecorder.ts","../../../src/calls/livekit/useInCallChat.ts","../../../src/calls/livekit/useWebinar.ts","../../../src/calls/livekit/useHostMuteNotice.ts"],"names":["useRoomContext","useState","useEffect","RoomEvent","useQueryClient","useLocalParticipant","useRef","useCallback","calls","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The LiveKit room of a call, end-to-end encrypted.\n *\n * E2EE uses LiveKit insertable streams in shared-key mode: the 32-byte frame key K (from the call\n * link or my sealed copy) goes into an `ExternalE2EEKeyProvider`, so the SFU only forwards\n * ciphertext. With no key (a session without client keys) the room connects unencrypted.\n */\n\nimport { useEffect, useState } from 'react'\nimport {\n ExternalE2EEKeyProvider,\n Room,\n RoomEvent,\n type Participant,\n type RoomOptions,\n} from 'livekit-client'\nimport { useRoomContext } from '@livekit/components-react'\nimport { notify } from '../../notifications/notify-store'\nimport type { JoinChoices } from '../session'\n\n/** The LiveKit end-to-end encryption worker (bundled from `livekit-client`). */\nexport function createE2EEWorker(): Worker {\n return new Worker(new URL('livekit-client/e2ee-worker', import.meta.url), { type: 'module' })\n}\n\ninterface RoomBundle {\n room: Room\n worker: Worker | null\n}\n\nfunction createRoom(\n e2eeKey: Uint8Array | null,\n choices: JoinChoices,\n createWorker: () => Worker\n): { bundle: RoomBundle; ready: Promise<void> } {\n const options: RoomOptions = {\n adaptiveStream: true,\n dynacast: true,\n audioCaptureDefaults: choices.audioDeviceId ? { deviceId: choices.audioDeviceId } : undefined,\n videoCaptureDefaults: choices.videoDeviceId ? { deviceId: choices.videoDeviceId } : undefined,\n }\n let worker: Worker | null = null\n let keyProvider: ExternalE2EEKeyProvider | null = null\n if (e2eeKey) {\n keyProvider = new ExternalE2EEKeyProvider()\n worker = createWorker()\n options.e2ee = { keyProvider, worker }\n }\n const room = new Room(options)\n const ready = (async () => {\n if (!keyProvider || !e2eeKey) return\n // Copy into a standalone ArrayBuffer (the key view may sit inside a larger buffer).\n await keyProvider.setKey(e2eeKey.slice().buffer as ArrayBuffer)\n await room.setE2EEEnabled(true)\n })()\n return { bundle: { room, worker }, ready }\n}\n\nexport interface CallRoomState {\n /** The room, ready to connect (`<LiveKitRoom room>`); null while it is being set up. */\n room: Room | null\n /** Why the room could not be set up in this browser, if it could not. */\n error: string | null\n}\n\n/**\n * A Room for the call, built once per key: with K, the frames are encrypted in a worker before they\n * leave the browser. Built in an effect (not render) so StrictMode's double mount does not leak a\n * worker; disconnected and torn down on unmount. The device choices only seed it.\n */\nexport function useCallRoom(\n e2eeKey: Uint8Array | null,\n choices: JoinChoices,\n options: { createWorker?: () => Worker } = {}\n): CallRoomState {\n const [room, setRoom] = useState<Room | null>(null)\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n let created: RoomBundle | null = null\n try {\n const { bundle, ready } = createRoom(\n e2eeKey,\n choices,\n options.createWorker ?? createE2EEWorker\n )\n created = bundle\n ready\n .then(() => {\n if (!cancelled) setRoom(bundle.room)\n })\n .catch((err: unknown) => {\n console.error('[calls] E2EE setup failed', err)\n if (!cancelled) setError('This browser cannot encrypt the call (E2EE unsupported).')\n })\n } catch (err) {\n console.error('[calls] room setup failed', err)\n setError('Could not set up the call in this browser.')\n }\n return () => {\n cancelled = true\n if (created) {\n void created.room.disconnect()\n created.worker?.terminate()\n }\n setRoom(null)\n }\n // The room is built once per key; the device choices only seed it.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [e2eeKey])\n return { room, error }\n}\n\nconst MUTE_REQUEST_TOPIC = 'arbi.mute-request'\n\n/**\n * Inside `<LiveKitRoom>`: ask someone to mute (anyone may ask; only the host can mute others\n * server-side), and show such a request when it is for me, with a Mute action.\n */\nexport function useMuteRequests(): (identity: string) => void {\n const room = useRoomContext()\n useEffect(() => {\n const onData = (payload: Uint8Array, from?: Participant, _kind?: unknown, topic?: string) => {\n if (topic !== MUTE_REQUEST_TOPIC || !from) return\n const who = from.name || from.identity\n notify.info(`${who} asks you to mute your microphone`, {\n action: {\n label: 'Mute',\n onClick: () => void room.localParticipant.setMicrophoneEnabled(false),\n },\n })\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room])\n return (identity: string) =>\n void room.localParticipant\n .publishData(new TextEncoder().encode('{\"v\":1}'), {\n reliable: true,\n topic: MUTE_REQUEST_TOPIC,\n destinationIdentities: [identity],\n })\n .then(() => notify.info('Asked to mute'))\n .catch((err: Error) => notify.error(`Could not ask: ${err.message}`))\n}\n","/**\n * Live transcription state of a LiveKit room (ARBI `docs/meeting-chats-plan.md` §5). Must run inside\n * <LiveKitRoom>.\n *\n * - Transcription is the HOST's setting: only the call's creator can turn it on or off.\n * - The state comes from the call row on join, then from the server's `arbi.transcription` data\n * message and WS `call.transcription`. A participant cannot fake it: only a server-sent packet\n * (no sender) is accepted.\n * - My audio is sent only while transcription is on AND its indicator is on screen\n * (`indicatorShown`, set by the indicator itself once mounted) AND I have not muted my\n * transcription AND (checked by <TranscriptionSender>) my microphone is on.\n * - Each of my transcribed segments becomes a caption for everyone (data channel, under K) and a\n * transcript line in the meeting chat — stored by me, or, when I cannot post there (a workspace\n * guest), by the members who receive my `proxy` caption. It is stored under my real display name\n * (the UI shows \"You\" for my own lines; the stored line never says \"You\").\n * - The line being spoken when sending stops (transcription off, my transcription muted, hang-up,\n * page hide) is still flushed and sent: the server takes a segment for {@link FINAL_SEGMENT_GRACE_MS}\n * after transcription went off if it started before that.\n * - Every clip carries the user's language and my previous line (a continuity prompt).\n */\n\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../../useArbi'\nimport { useAudioRecorder, type AudioSegment } from '../../documents/useAudioRecorder'\nimport { toProfileView } from '../../account/profile'\nimport {\n onCallEvent,\n useCallTranscriptionAvailable,\n CALL_CAPTION_TOPIC,\n CALL_TRANSCRIPTION_TOPIC,\n decodeCaptionPacket,\n encodeCaptionPacket,\n newSegmentId,\n persistTranscriptSegment,\n transcriptPersistRole,\n type CaptionLine,\n type TranscriptSegment,\n} from '..'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useLocalParticipant, useRoomContext } from '@livekit/components-react'\nimport { CallApiError, calls, continuityPrompt } from '@arbidocs/sdk/browser'\nimport { notify } from '../../notifications/notify-store'\n\n/** Captions kept in memory (the overlay shows the last few). */\nconst MAX_CAPTIONS = 30\n/**\n * After sending stops, the segment that was open then is still sent (the server's grace for a final\n * segment is 30 s after transcription is turned off, for a segment that started before).\n */\nexport const FINAL_SEGMENT_GRACE_MS = 30_000\n/** My previous text kept for the continuity prompt (a little more than it sends). */\nconst PROMPT_HISTORY_CHARS = 400\n\n/**\n * Whether one of my segments may still be sent: while sending, always; after sending stopped, only\n * the segment that was open then (it started before the stop) and within the server's grace.\n */\nexport function mayStillSend(params: {\n sending: boolean\n /** When sending last stopped (ms since epoch); null if it never did. */\n stoppedAt: number | null\n segmentStartedAt: number\n now: number\n}): boolean {\n if (params.sending) return true\n if (params.stoppedAt === null) return false\n return (\n params.segmentStartedAt <= params.stoppedAt &&\n params.now - params.stoppedAt <= FINAL_SEGMENT_GRACE_MS\n )\n}\n\n/**\n * The name my transcript lines are stored under: my LiveKit name, else my profile's display name,\n * else my identity — never \"You\" (that is only how the UI shows my own lines to me).\n */\nexport function storedSpeakerName(\n participantName: string | null | undefined,\n profileName: string | null | undefined,\n identity: string\n): string {\n return participantName?.trim() || profileName?.trim() || identity\n}\n\nexport interface CallTranscription {\n /** The deployment has a transcriber and the call has a key. */\n available: boolean\n on: boolean\n startedByName: string | null\n startedByMe: boolean\n /** I host the call: only I see and use the on/off control. */\n canToggle: boolean\n busy: boolean\n /** I muted my own transcription (nothing of mine is sent). */\n muted: boolean\n setMuted(muted: boolean): void\n /** Turn on / off (the host only). */\n toggle(): Promise<void>\n /** The indicator reports itself on screen; nothing is sent before it is. */\n setIndicatorShown(shown: boolean): void\n /** On, shown and not muted: <TranscriptionSender> records while this (and the mic) is on. */\n shouldSend: boolean\n captions: CaptionLine[]\n /** <TranscriptionSender> hands each of my speech segments here. */\n handleSegment(segment: AudioSegment): Promise<void>\n}\n\nexport function useCallTranscriber({\n callExtId,\n callKey,\n isCreator,\n canPost,\n linkVersion = null,\n}: {\n callExtId: string\n /** The link version I joined with (sent with each segment). */\n linkVersion?: number | null\n callKey: Uint8Array | null\n isCreator: boolean\n /** I can post to the meeting chat (false for a workspace guest on a thread call). */\n canPost: boolean\n}): CallTranscription {\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const profile = arbi.isLoggedIn ? arbi.user.profile() : null\n const myProfileName = (profile && toProfileView(profile).fullName) || null\n const deploymentAvailable = useCallTranscriptionAvailable()\n const available = deploymentAvailable && !!callKey\n\n const [state, setState] = useState<calls.CallTranscriptionState | null>(null)\n const [creatorExtId, setCreatorExtId] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [muted, setMuted] = useState(false)\n const [indicatorShown, setIndicatorShown] = useState(false)\n const [captions, setCaptions] = useState<CaptionLine[]>([])\n const liveUpdate = useRef(false)\n const persisted = useRef(new Set<string>())\n const saveFailureShown = useRef(false)\n // Whether my own segments are stored by me; flips off if the meeting chat refuses my posts.\n const selfPosts = useRef(canPost)\n useEffect(() => {\n selfPosts.current = canPost\n }, [canPost])\n\n const on = available && !!state?.on\n const shouldSend = on && indicatorShown && !muted\n const shouldSendRef = useRef(shouldSend)\n // When sending last stopped: the segment open then is still flushed and sent (see mayStillSend).\n const sendStoppedAtRef = useRef<number | null>(null)\n if (shouldSendRef.current !== shouldSend) {\n sendStoppedAtRef.current = shouldSend ? null : Date.now()\n }\n shouldSendRef.current = shouldSend\n // My previous text, for the continuity prompt of my next segment.\n const myPreviousText = useRef('')\n\n const applyState = useCallback((next: calls.CallTranscriptionState | null) => {\n liveUpdate.current = true\n setState(next)\n }, [])\n\n // Join: the call row says whether transcription is already on (and who created the call).\n useEffect(() => {\n if (!available) return\n let cancelled = false\n arbi.calls\n .get(callExtId)\n .then((call) => {\n if (cancelled) return\n setCreatorExtId(call.creator_ext_id ?? null)\n // A live announcement that already arrived is newer than this read.\n if (!liveUpdate.current) {\n setState(calls.transcriptionStateFrom(call.transcription))\n }\n })\n .catch((err: unknown) => console.warn('[calls] could not read the transcription state', err))\n return () => {\n cancelled = true\n }\n }, [available, callExtId])\n\n // WS `call.transcription`.\n useEffect(\n () =>\n onCallEvent('call.transcription', (message) => {\n if (message.call_ext_id === callExtId) applyState(message)\n }),\n [callExtId, applyState]\n )\n\n const addCaption = useCallback((line: CaptionLine) => {\n setCaptions((prev) => {\n if (prev.some((c) => c.segmentId === line.segmentId && c.identity === line.identity)) {\n return prev\n }\n return [...prev, line].sort((a, b) => a.t - b.t).slice(-MAX_CAPTIONS)\n })\n }, [])\n\n /** Store a segment when it is mine to store (see `transcriptPersistRole`). */\n const persist = useCallback(\n (segment: TranscriptSegment, speakerNeedsProxy: boolean) => {\n if (!callKey || persisted.current.has(segment.segmentId)) return\n const role = transcriptPersistRole({\n myIdentity,\n canPost: canPost && (segment.speakerIdentity !== myIdentity || selfPosts.current),\n hasCallKey: true,\n speakerIdentity: segment.speakerIdentity,\n speakerNeedsProxy,\n })\n if (!role) return\n persisted.current.add(segment.segmentId)\n persistTranscriptSegment(arbi, queryClient, callExtId, callKey, segment).catch(\n (err: unknown) => {\n persisted.current.delete(segment.segmentId)\n // Refused (not a member of the meeting chat): members store my next segments.\n if (role === 'own' && (err as { status?: number } | null)?.status === 403) {\n selfPosts.current = false\n }\n console.warn('[calls] could not keep the transcript line', err)\n // Never silently: say so once per call (captions keep working).\n if (!saveFailureShown.current) {\n saveFailureShown.current = true\n notify.warning(\n `Transcript lines are not being saved to the meeting chat: ${(err as Error)?.message ?? 'unknown error'}`\n )\n }\n }\n )\n },\n [callExtId, callKey, myIdentity, canPost]\n )\n\n // Data channel: the server's state announcements and everyone's captions.\n useEffect(() => {\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic === CALL_TRANSCRIPTION_TOPIC) {\n // Only the server may announce the state: a packet from a participant is ignored.\n if (participant || participantIdentity) return\n try {\n const next = calls.transcriptionStateFrom(JSON.parse(new TextDecoder().decode(payload)))\n if (next) applyState(next)\n } catch {\n // Not ours.\n }\n return\n }\n if (topic !== CALL_CAPTION_TOPIC || !callKey) return\n const identity = participant?.identity ?? participantIdentity\n if (!identity || identity === myIdentity) return\n void decodeCaptionPacket(payload, callKey).then((packet) => {\n // A caption speaks for its sender only.\n if (!packet || packet.identity !== identity) return\n const name = participant?.name || packet.name || identity\n const t = Math.min(packet.t, Date.now())\n addCaption({\n segmentId: packet.segment_id,\n identity,\n name,\n text: packet.text,\n t,\n mine: false,\n receivedAt: Date.now(),\n })\n persist(\n {\n segmentId: packet.segment_id,\n text: packet.text,\n speakerIdentity: identity,\n speakerName: name,\n startedAt: new Date(t).toISOString(),\n },\n packet.proxy === true\n )\n })\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room, callKey, myIdentity, addCaption, applyState, persist])\n\n const handleSegment = useCallback(\n async (segment: AudioSegment) => {\n // While sending, or the segment that was open when sending stopped (transcription off, my\n // transcription muted, hang-up): flushed then, still sent within the server's grace.\n // Anything that started after the stop is dropped.\n if (\n !callKey ||\n !mayStillSend({\n sending: shouldSendRef.current,\n stoppedAt: sendStoppedAtRef.current,\n segmentStartedAt: segment.startedAt,\n now: Date.now(),\n })\n ) {\n return\n }\n const segmentId = newSegmentId()\n const startedAt = new Date(segment.startedAt).toISOString()\n let text: string\n try {\n const result = await arbi.calls.transcription.transcribe(callExtId, {\n audio: segment.blob,\n segmentId,\n startedAt,\n linkVersion,\n prompt: continuityPrompt(myPreviousText.current),\n })\n text = result.text.trim()\n } catch (err) {\n if (err instanceof CallApiError && err.status === 409) {\n applyState({ on: false, by_identity: null, by_name: null })\n }\n console.warn('[calls] could not transcribe a segment', err)\n return\n }\n if (!text) return\n myPreviousText.current = `${myPreviousText.current} ${text}`.slice(-PROMPT_HISTORY_CHARS)\n // Stored (and shown to others) under my real name; my own caption reads \"You\" on screen.\n const name = storedSpeakerName(localParticipant.name, myProfileName, myIdentity)\n const proxy = !selfPosts.current\n addCaption({\n segmentId,\n identity: myIdentity,\n name,\n text,\n t: segment.startedAt,\n mine: true,\n receivedAt: Date.now(),\n })\n try {\n await localParticipant.publishData(\n await encodeCaptionPacket(\n {\n v: 1,\n segment_id: segmentId,\n text,\n identity: myIdentity,\n name,\n t: segment.startedAt,\n ...(proxy ? { proxy: true } : {}),\n },\n callKey\n ),\n { reliable: true, topic: CALL_CAPTION_TOPIC }\n )\n } catch (err) {\n console.warn('[calls] could not broadcast a caption', err)\n }\n if (!proxy) {\n persist(\n { segmentId, text, speakerIdentity: myIdentity, speakerName: name, startedAt },\n false\n )\n }\n },\n [\n callExtId,\n callKey,\n linkVersion,\n localParticipant,\n myIdentity,\n myProfileName,\n addCaption,\n applyState,\n persist,\n ]\n )\n\n const startedByMe = !!state?.on && state.by_identity === myIdentity\n const canToggle = available && (isCreator || (!!creatorExtId && creatorExtId === myIdentity))\n\n const toggle = useCallback(async () => {\n if (!canToggle) return\n const next = !on\n setBusy(true)\n try {\n const answer = await arbi.calls.transcription.set(callExtId, next)\n applyState(\n answer ??\n (next\n ? { on: true, by_identity: myIdentity, by_name: localParticipant.name || null }\n : { on: false, by_identity: null, by_name: null })\n )\n } catch (err) {\n notify.error(`Could not turn transcription ${next ? 'on' : 'off'}: ${(err as Error).message}`)\n } finally {\n setBusy(false)\n }\n }, [on, canToggle, callExtId, myIdentity, localParticipant, applyState])\n\n return useMemo(\n () => ({\n available,\n on,\n startedByName: on ? (state?.by_name ?? null) : null,\n startedByMe,\n canToggle,\n busy,\n muted,\n setMuted,\n toggle,\n setIndicatorShown,\n shouldSend,\n captions,\n handleSegment,\n }),\n [\n available,\n on,\n state,\n startedByMe,\n canToggle,\n busy,\n muted,\n toggle,\n shouldSend,\n captions,\n handleSegment,\n ]\n )\n}\n","/**\n * Recording state of a LiveKit room (ARBI `docs/meeting-chats-plan.md` §6). Must run inside\n * <LiveKitRoom>. Mirrors {@link useCallTranscription}:\n *\n * - Recording is the HOST's action: only the call's creator starts (choosing Audio or Audio + video)\n * or stops it. Before starting, the host is warned when the storage quota is nearly full.\n * - The state comes from the call row on join, then from the server's `arbi.recording` data message\n * and WS `call.recording`. Only a server-sent packet (no sender) is accepted.\n * - Nothing is captured before the \"Recording\" indicator is on screen (`indicatorShown`, reported\n * by the indicator itself once mounted): `shouldCapture` gates every recorder.\n */\n\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../../useArbi'\nimport {\n onCallEvent,\n CALL_RECORDING_TOPIC,\n conversationKeyForCall,\n ensureMeetingChat,\n trackUploaderFor,\n type TrackUploader,\n} from '..'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useLocalParticipant, useRoomContext } from '@livekit/components-react'\nimport { calls } from '@arbidocs/sdk/browser'\nimport { notify } from '../../notifications/notify-store'\n\nexport interface PendingRecordingStart {\n mode: calls.RecordingMode\n quota: calls.RecordingQuota\n}\n\nexport interface CallRecordingControl {\n /** The call has a key (recordings are encrypted under the conversation key; no key, no recording). */\n available: boolean\n on: boolean\n mode: calls.RecordingMode | null\n recordingExtId: string | null\n /** The recording's start when the state carried it (uploaders otherwise read it). */\n startedAt: string | null\n startedByName: string | null\n startedByMe: boolean\n /** I host the call: only I see and use the controls. */\n canControl: boolean\n busy: boolean\n /** The call row (its meeting chat / locked workspace decide the conversation key). */\n call: calls.CallResponse | null\n /** The call link version I joined with (sent when creating my track). */\n linkVersion: number | null\n /** Start in a mode: checks the quota first; near the limit it asks for confirmation instead. */\n requestStart(mode: calls.RecordingMode): Promise<void>\n /** The start waiting for the host to confirm past the quota warning. */\n pendingStart: PendingRecordingStart | null\n confirmStart(): Promise<void>\n cancelStart(): void\n stop(): Promise<void>\n /** The indicator reports itself on screen; nothing is captured before it is. */\n setIndicatorShown(shown: boolean): void\n /** On, a recording id known, the indicator shown and a key to encrypt under. */\n shouldCapture: boolean\n /** The server stopped the recording at the storage quota: reflect (and say) it immediately. */\n markStopped(): void\n}\n\n/** Whether a recording state lets a client capture (the gating rule, testable on its own). */\nexport function captureAllowed(params: {\n available: boolean\n state: calls.CallRecordingState | null\n indicatorShown: boolean\n}): boolean {\n return (\n params.available &&\n !!params.state?.on &&\n !!params.state.recording_ext_id &&\n params.indicatorShown\n )\n}\n\nexport function useCallRecorder({\n callExtId,\n callKey,\n isCreator,\n linkVersion = null,\n}: {\n callExtId: string\n callKey: Uint8Array | null\n isCreator: boolean\n linkVersion?: number | null\n}): CallRecordingControl {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const available = !!callKey\n\n const [state, setState] = useState<calls.CallRecordingState | null>(null)\n const [call, setCall] = useState<calls.CallResponse | null>(null)\n const [busy, setBusy] = useState(false)\n const [indicatorShown, setIndicatorShown] = useState(false)\n const [pendingStart, setPendingStart] = useState<PendingRecordingStart | null>(null)\n const liveUpdate = useRef(false)\n const stateRef = useRef<calls.CallRecordingState | null>(null)\n stateRef.current = state\n\n const applyState = useCallback((next: calls.CallRecordingState | null) => {\n liveUpdate.current = true\n // The server stopped it on its own (the storage quota): say why, once.\n if (stateRef.current?.on && next && !next.on && next.reason === 'storage_quota_exceeded') {\n notify.warning('Recording stopped: the storage is full.')\n }\n stateRef.current = next\n setState(next)\n }, [])\n\n // Join: the call row says whether a recording is running (and who created the call).\n useEffect(() => {\n let cancelled = false\n arbi.calls\n .get(callExtId)\n .then((row) => {\n if (cancelled) return\n setCall(row)\n if (!liveUpdate.current) setState(calls.recordingStateOfCall(row))\n })\n .catch((err: unknown) => console.warn('[calls] could not read the recording state', err))\n return () => {\n cancelled = true\n }\n }, [callExtId])\n\n // WS `call.recording`.\n useEffect(\n () =>\n onCallEvent('call.recording', (message) => {\n if (message.call_ext_id === callExtId) applyState(message)\n }),\n [callExtId, applyState]\n )\n\n // The server's data message (a participant's packet on this topic is ignored).\n useEffect(() => {\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_RECORDING_TOPIC) return\n if (participant || participantIdentity) return\n try {\n const next = calls.recordingStateFrom(JSON.parse(new TextDecoder().decode(payload)))\n if (next) applyState(next)\n } catch {\n // Not ours.\n }\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room, applyState])\n\n const canControl = available && (isCreator || (!!call && call.creator_ext_id === myIdentity))\n const on = !!state?.on\n\n const start = useCallback(\n async (mode: calls.RecordingMode) => {\n setBusy(true)\n try {\n // A contacts call keeps its recording in the E2E meeting chat: make it first, so every\n // participant's track key can be wrapped under the chat key from the first part on.\n const row = call ?? (await arbi.calls.get(callExtId))\n if (!row.workspace_locked && !row.chat_ext_id && callKey) {\n const ref = await ensureMeetingChat(arbi, queryClient, callExtId, callKey)\n if (ref.kind === 'chat') setCall({ ...row, chat_ext_id: ref.chatExtId })\n }\n const answer = await arbi.calls.recording.start(callExtId, mode)\n if (answer) applyState(answer)\n } catch (err) {\n notify.error(`Could not start recording: ${(err as Error).message}`)\n } finally {\n setBusy(false)\n }\n },\n [callExtId, callKey, call, applyState]\n )\n\n const requestStart = useCallback(\n async (mode: calls.RecordingMode) => {\n if (!canControl || on) return\n setBusy(true)\n let quota: calls.RecordingQuota | null = null\n try {\n quota = await arbi.calls.recording.quota(callExtId)\n } catch (err) {\n // The server enforces the quota anyway; a failed read only skips the warning.\n console.warn('[calls] could not read the recording quota', err)\n }\n setBusy(false)\n if (quota && calls.quotaNeedsWarning(quota)) {\n setPendingStart({ mode, quota })\n return\n }\n await start(mode)\n },\n [canControl, on, callExtId, start]\n )\n\n const confirmStart = useCallback(async () => {\n const pending = pendingStart\n setPendingStart(null)\n if (pending) await start(pending.mode)\n }, [pendingStart, start])\n\n const cancelStart = useCallback(() => setPendingStart(null), [])\n\n const stop = useCallback(async () => {\n if (!canControl || !on) return\n setBusy(true)\n try {\n const answer = await arbi.calls.recording.stop(callExtId)\n applyState(answer ?? { ...(state as calls.CallRecordingState), on: false })\n } catch (err) {\n notify.error(`Could not stop recording: ${(err as Error).message}`)\n } finally {\n setBusy(false)\n }\n }, [canControl, on, callExtId, state, applyState])\n\n const markStopped = useCallback(() => {\n const prev = stateRef.current\n if (prev?.on) applyState({ ...prev, on: false, reason: 'storage_quota_exceeded' })\n }, [applyState])\n\n const shouldCapture = captureAllowed({ available, state, indicatorShown })\n\n return useMemo(\n () => ({\n available,\n on,\n mode: on ? (state?.mode ?? 'audio') : null,\n recordingExtId: state?.recording_ext_id ?? null,\n startedAt: state?.started_at ?? null,\n startedByName: on ? (state?.by_name ?? null) : null,\n startedByMe: on && state?.by_identity === myIdentity,\n canControl,\n busy,\n call,\n linkVersion,\n requestStart,\n pendingStart,\n confirmStart,\n cancelStart,\n stop,\n setIndicatorShown,\n shouldCapture,\n markStopped,\n }),\n [\n available,\n on,\n state,\n myIdentity,\n canControl,\n busy,\n call,\n linkVersion,\n requestStart,\n pendingStart,\n confirmStart,\n cancelStart,\n stop,\n shouldCapture,\n markStopped,\n ]\n )\n}\n\n/** The uploader of one of my tracks for the running recording (null while not capturing). */\nexport function useTrackUploader(\n recording: CallRecordingControl,\n callKey: Uint8Array | null,\n kind: 'speaker' | 'composite',\n mimeType: string\n): TrackUploader | null {\n const { recordingExtId, call, startedAt, shouldCapture, markStopped, linkVersion } = recording\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMemo(() => {\n if (!shouldCapture || !recordingExtId || !call) return null\n return trackUploaderFor({\n arbi,\n callExtId: call.external_id,\n recordingExtId,\n kind,\n mimeType,\n recordingStartedAt: startedAt,\n linkVersion,\n conversationKey: () => conversationKeyForCall(arbi, queryClient, call, { callKey }),\n // The server stopped the recording at the quota (its state event says so too).\n onStopped: () => markStopped(),\n })\n }, [\n arbi,\n queryClient,\n shouldCapture,\n recordingExtId,\n call,\n startedAt,\n linkVersion,\n kind,\n mimeType,\n callKey,\n markStopped,\n ])\n}\n","/**\n * The in-call chat state of a LiveKit room: live data-channel messages (encrypted under the call\n * key), persisted to the meeting chat for signed-in members. Must run inside <LiveKitRoom>. A\n * webinar's live chat (when its audience may chat) is this; with no call key it stays inert.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useLocalParticipant, useRoomContext } from '@livekit/components-react'\nimport { notify } from '../../notifications/notify-store'\nimport {\n CALL_CHAT_MAX_CHARS,\n CALL_CHAT_TOPIC,\n decodeCallChatPacket,\n encodeCallChatPacket,\n loadMeetingHistory,\n mergeChatLines,\n newPacketId,\n persistMeetingMessage,\n type CallChatLine,\n type HistoryMessage,\n ensureMeetingChat,\n type MeetingChatRef,\n} from '..'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../../useArbi'\nimport { useArbiHost } from '../../host/config'\n\nexport interface InCallChatState {\n lines: CallChatLine[]\n /** Messages from others received while the panel was closed. */\n unread: number\n /** False without a call key: nothing could be encrypted, so chat is off. */\n available: boolean\n /** My messages are kept in the meeting chat. */\n persists: boolean\n /** A workspace guest on a thread call: the meeting chat is read-only (no composer). */\n readOnly: boolean\n historyLoading: boolean\n historyError: string | null\n meetingChat: MeetingChatRef | null\n send(text: string): Promise<void>\n openMeeting(): Promise<void>\n}\n\n/** The room's chat state. `open` is whether the panel is showing (it clears unread). */\nexport function useInCallChat({\n callExtId,\n callKey,\n open,\n readOnly = false,\n persist = true,\n}: {\n callExtId: string\n callKey: Uint8Array | null\n open: boolean\n /** Workspace guest on a thread call: read the meeting chat, never post. */\n readOnly?: boolean\n /**\n * Keep messages in (and read history from) the meeting chat. Off for a webinar's attendees: they\n * are not its members, so their chat is live only.\n */\n persist?: boolean\n}): InCallChatState {\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const openMeetingChat = useArbiHost().calls?.openMeetingChat\n const signedIn = arbi.isLoggedIn\n const persists = !!callKey && signedIn && !readOnly && persist\n\n const [live, setLive] = useState<CallChatLine[]>([])\n const [history, setHistory] = useState<HistoryMessage[]>([])\n const [historyLoading, setHistoryLoading] = useState(false)\n const [historyError, setHistoryError] = useState<string | null>(null)\n const [meetingChat, setMeetingChat] = useState<MeetingChatRef | null>(null)\n const [unread, setUnread] = useState(0)\n const openRef = useRef(open)\n openRef.current = open\n const historyRequested = useRef(false)\n const seen = useRef(new Set<string>())\n\n useEffect(() => {\n if (open) setUnread(0)\n }, [open])\n\n // Receive: open each packet with K; drop anything that is not ours.\n useEffect(() => {\n if (!callKey) return\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_CHAT_TOPIC) return\n const identity = participant?.identity ?? participantIdentity\n if (!identity || identity === myIdentity) return\n void decodeCallChatPacket(payload, callKey).then((packet) => {\n if (!packet) return\n // A reliable packet can arrive twice (reconnect): count and show it once.\n const key = `${identity}:${packet.id}`\n if (seen.current.has(key)) return\n seen.current.add(key)\n setLive((prev) => [\n ...prev,\n {\n id: packet.id,\n senderIdentity: identity,\n senderName: participant?.name || identity,\n text: packet.text,\n at: Math.min(packet.at, Date.now()),\n mine: false,\n status: 'live',\n },\n ])\n if (!openRef.current) setUnread((n) => n + 1)\n })\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room, callKey, myIdentity])\n\n // History: once, the first time the panel opens. Never creates the meeting chat.\n const canRead = !!callKey && signedIn && persist\n useEffect(() => {\n if (!open || !canRead || historyRequested.current) return\n historyRequested.current = true\n setHistoryLoading(true)\n loadMeetingHistory(arbi, queryClient, callExtId)\n .then((result) => {\n if (!result) return\n setMeetingChat(result.ref)\n setHistory(result.messages)\n })\n .catch((err: unknown) => {\n console.warn('[calls] could not load the meeting chat', err)\n setHistoryError('Earlier messages could not be loaded.')\n })\n .finally(() => setHistoryLoading(false))\n }, [open, canRead, callExtId])\n\n const send = useCallback(\n async (raw: string) => {\n const text = raw.trim().slice(0, CALL_CHAT_MAX_CHARS)\n if (!text || !callKey || readOnly) return\n const id = newPacketId()\n const at = Date.now()\n await localParticipant.publishData(\n await encodeCallChatPacket({ v: 1, id, text, at }, callKey),\n { reliable: true, topic: CALL_CHAT_TOPIC }\n )\n setLive((prev) => [\n ...prev,\n {\n id,\n senderIdentity: myIdentity,\n senderName: localParticipant.name || 'You',\n text,\n at,\n mine: true,\n status: persists ? 'saving' : 'live',\n },\n ])\n if (!persists) return\n const mark = (status: CallChatLine['status']) =>\n setLive((prev) =>\n prev.map((l) => (l.id === id && l.senderIdentity === myIdentity ? { ...l, status } : l))\n )\n try {\n setMeetingChat(await persistMeetingMessage(arbi, queryClient, callExtId, callKey, text))\n mark('saved')\n } catch (err) {\n console.warn('[calls] could not keep the message in the meeting chat', err)\n mark('unsaved')\n }\n },\n [callKey, callExtId, localParticipant, myIdentity, persists, readOnly]\n )\n\n const openMeeting = useCallback(async () => {\n if (!callKey) return\n try {\n const ref = meetingChat ?? (await ensureMeetingChat(arbi, queryClient, callExtId, callKey))\n setMeetingChat(ref)\n openMeetingChat?.(ref)\n } catch (err) {\n notify.error(`Could not open the meeting chat: ${(err as Error).message}`)\n }\n }, [callExtId, callKey, meetingChat])\n\n const lines = useMemo(\n () =>\n mergeChatLines(history, live, {\n myIdentity,\n nameOf: (identity) =>\n identity === myIdentity\n ? localParticipant.name || 'You'\n : room.remoteParticipants.get(identity)?.name || null,\n }),\n [history, live, myIdentity, localParticipant, room]\n )\n\n return {\n lines,\n unread,\n available: !!callKey,\n persists,\n readOnly,\n historyLoading,\n historyError,\n meetingChat,\n send,\n openMeeting,\n }\n}\n","/**\n * The webinar state of a LiveKit room (ARBI `docs/webinars-plan.md`). Must run inside\n * <LiveKitRoom>; with `enabled` false (an ordinary call) it does nothing.\n *\n * - The state (live, chat, my role and stage, the moderators' hands and audience) comes from\n * `GET /webinar`, then from the server's `arbi.webinar` data messages and WS `call.webinar`.\n * Only server-sent packets count: one from a participant is ignored.\n * - Whether I am on stage is the room's own word (my publish permission), so it flips the moment\n * the server promotes or demotes me.\n * - `promoted`: the \"You're on stage\" device check opens; joining it publishes my microphone (and\n * camera) with the devices I picked. `demoted` (and stepping down myself): the server removes me\n * from the room and the dock joins me again as the audience (`webinar-join.ts`).\n * - Q&A text is end-to-end under the call key K (`webinar-packets.ts`).\n */\n\nimport { useArbi } from '../../useArbi'\nimport { onCallEvent, type JoinChoices } from '..'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport {\n useLocalParticipant,\n useLocalParticipantPermissions,\n useRoomContext,\n} from '@livekit/components-react'\nimport { calls } from '@arbidocs/sdk/browser'\nimport { notify } from '../../notifications/notify-store'\nimport {\n CALL_WEBINAR_TOPIC,\n markRejoining,\n openQuestion,\n parseWebinarPacket,\n sealQuestionText,\n type OpenQuestion,\n} from '../webinar'\n\n/** After `demoted`, the server removes me at once; if it has not after this, I leave the room myself. */\nexport const DEMOTE_REJOIN_FALLBACK_MS = 5_000\n\nexport type WebinarHandRow = NonNullable<calls.WebinarState['hands']>[number]\nexport type WebinarAttendeeRow = NonNullable<calls.WebinarState['attendees']>[number]\n\nexport interface WebinarControl {\n /** The call is a webinar (everything below is inert otherwise). */\n enabled: boolean\n role: calls.WebinarRole | null\n /** Host or co-host: go live / end, chat setting, hands and audience, promote / demote. */\n moderator: boolean\n /** Host, co-host or panelist: moderates Q&A. */\n team: boolean\n live: boolean\n chat: calls.WebinarChat\n /** I may publish: on stage (always true outside a webinar). */\n onStage: boolean\n handRaised: boolean\n /** Moderators: the raised hands, oldest first. */\n hands: WebinarHandRow[]\n /** Moderators: everyone in the room (hidden audience included). */\n attendees: WebinarAttendeeRow[]\n questions: OpenQuestion[]\n /** A moderator brought me on stage: the device check is open. */\n stageCheck: boolean\n refresh(): Promise<void>\n goLive(): Promise<void>\n end(): Promise<void>\n setChat(chat: calls.WebinarChat): Promise<void>\n setHand(raised: boolean): Promise<void>\n promote(identity: string): Promise<void>\n demote(identity: string): Promise<void>\n /** Leave the stage myself (also \"Stay in audience\" on the device check). */\n stepDown(): Promise<void>\n /** Go on stage with the devices picked in the check. */\n joinStage(choices: JoinChoices): Promise<void>\n ask(text: string): Promise<void>\n vote(questionId: string, up: boolean): Promise<void>\n setQuestionStatus(questionId: string, status: calls.CallQuestionStatus): Promise<void>\n answer(questionId: string, text: string): Promise<void>\n removeQuestion(questionId: string): Promise<void>\n}\n\n/** Toast a failed action, then reject (the blocks keep their state on a rejection). */\nfunction failed(what: string) {\n return (err: unknown): never => {\n notify.error(`Could not ${what}: ${(err as Error)?.message ?? 'unknown error'}`)\n throw err\n }\n}\n\nexport function useWebinar({\n role: roleHint = null,\n callExtId,\n linkVersion = null,\n callKey,\n}: {\n /** My role from the call (null: not a webinar). Until the room says, the team counts as on stage. */\n role?: calls.WebinarRole | null\n callExtId: string\n linkVersion?: number | null\n callKey: Uint8Array | null\n}): WebinarControl {\n const arbi = useArbi()\n const webinarApi = useCallback(() => arbi.calls.webinar, [arbi])\n const enabled = !!roleHint\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const permissions = useLocalParticipantPermissions()\n const [state, setState] = useState<calls.WebinarState | null>(null)\n const [questions, setQuestions] = useState<OpenQuestion[]>([])\n const [stageCheck, setStageCheck] = useState(false)\n const stateRead = useRef(0)\n const questionsRead = useRef(0)\n\n const refresh = useCallback(async () => {\n if (!enabled) return\n const n = ++stateRead.current\n try {\n const next = await webinarApi().get(callExtId, linkVersion)\n if (n === stateRead.current) setState(next)\n } catch (err) {\n console.warn('[calls] could not read the webinar state', err)\n }\n }, [enabled, callExtId, linkVersion])\n\n const refreshQuestions = useCallback(async () => {\n if (!enabled || !callKey) return\n const n = ++questionsRead.current\n try {\n const rows = await webinarApi().questions.list(callExtId, linkVersion)\n const opened = await Promise.all(rows.map((q) => openQuestion(q, callKey)))\n if (n === questionsRead.current) setQuestions(opened)\n } catch (err) {\n console.warn('[calls] could not load the questions', err)\n }\n }, [enabled, callExtId, linkVersion, callKey])\n\n useEffect(() => {\n void refresh()\n void refreshQuestions()\n }, [refresh, refreshQuestions])\n\n // Live / ended / chat setting, over WS (the room's own packet says the same).\n useEffect(() => {\n if (!enabled) return\n return onCallEvent('call.webinar', (m) => {\n if (m.call_ext_id !== callExtId) return\n setState((s) => (s ? { ...s, live: m.live, chat: m.chat } : s))\n })\n }, [enabled, callExtId])\n\n // The server's `arbi.webinar` messages.\n const fallback = useRef<ReturnType<typeof setTimeout> | null>(null)\n useEffect(() => {\n if (!enabled) return\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_WEBINAR_TOPIC) return\n const packet = parseWebinarPacket(payload, !!(participant || participantIdentity))\n if (!packet) return\n switch (packet.type) {\n case 'state':\n setState((s) =>\n s ? { ...s, live: packet.live, live_at: packet.live_at, chat: packet.chat } : s\n )\n // Roles may have changed too: read them again.\n void refresh()\n return\n case 'hands':\n setState((s) => (s ? { ...s, hands: packet.hands } : s))\n return\n case 'questions':\n void refreshQuestions()\n return\n case 'promoted':\n setStageCheck(true)\n void refresh()\n return\n case 'demoted':\n setStageCheck(false)\n // The server removes me from the room now; the dock then joins me again as the audience.\n markRejoining(callExtId)\n if (fallback.current) clearTimeout(fallback.current)\n fallback.current = setTimeout(() => void room.disconnect(), DEMOTE_REJOIN_FALLBACK_MS)\n return\n }\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [enabled, room, callExtId, refresh, refreshQuestions])\n useEffect(\n () => () => {\n if (fallback.current) clearTimeout(fallback.current)\n },\n []\n )\n\n const role = enabled ? (state?.my_role ?? null) : null\n // The room's word once connected, else the server's, else my role: the team starts on stage, so\n // its UI (and the dock's placement) never flickers through the audience viewer while joining.\n const onStage =\n !enabled ||\n (permissions ? permissions.canPublish : state ? state.on_stage : roleHint !== 'attendee')\n\n const patch = useCallback(\n async (body: { live?: boolean; chat?: calls.WebinarChat }, what: string) => {\n const next = await webinarApi().update(callExtId, body, linkVersion).catch(failed(what))\n setState(next)\n },\n [callExtId, linkVersion]\n )\n\n const stepDown = useCallback(async () => {\n // The server removes me during the request: that disconnect is a rejoin, not a leave.\n markRejoining(callExtId)\n setStageCheck(false)\n try {\n await webinarApi().demote(callExtId, myIdentity, linkVersion)\n } catch (err) {\n markRejoining(callExtId, false)\n failed('leave the stage')(err)\n }\n }, [callExtId, myIdentity, linkVersion])\n\n const joinStage = useCallback(\n async (choices: JoinChoices) => {\n const lp = room.localParticipant\n try {\n await lp.setMicrophoneEnabled(\n choices.audioEnabled,\n choices.audioDeviceId ? { deviceId: choices.audioDeviceId } : undefined\n )\n await lp.setCameraEnabled(\n choices.videoEnabled,\n choices.videoDeviceId ? { deviceId: choices.videoDeviceId } : undefined\n )\n } catch (err) {\n failed('turn on your microphone or camera')(err)\n }\n setStageCheck(false)\n },\n [room]\n )\n\n const questionAction = useCallback(\n async (run: () => Promise<unknown>, what: string) => {\n await run().catch(failed(what))\n // Everyone (me too) also gets `questions` from the server; this makes my own change instant.\n void refreshQuestions()\n },\n [refreshQuestions]\n )\n\n return useMemo<WebinarControl>(\n () => ({\n enabled,\n role,\n moderator: !!role && calls.WEBINAR_MODERATORS.has(role),\n team: !!role && calls.WEBINAR_TEAM.has(role),\n live: !!state?.live,\n chat: state?.chat ?? 'panelists',\n onStage,\n handRaised: !!state?.hand_raised,\n hands: state?.hands ?? [],\n attendees: state?.attendees ?? [],\n questions,\n stageCheck: enabled && stageCheck,\n refresh,\n goLive: () => patch({ live: true }, 'go live'),\n end: () => patch({ live: false }, 'end the webinar'),\n setChat: (chat) => patch({ chat }, 'change who can chat'),\n setHand: async (raised) => {\n const next = await webinarApi()\n .setHand(callExtId, raised, linkVersion)\n .catch(failed(raised ? 'raise your hand' : 'lower your hand'))\n setState(next)\n },\n promote: (identity) =>\n webinarApi()\n .promote(callExtId, identity, linkVersion)\n .catch(failed('bring them on stage'))\n .then(refresh),\n demote: (identity) =>\n webinarApi()\n .demote(callExtId, identity, linkVersion)\n .catch(failed('move them to the audience'))\n .then(refresh),\n stepDown,\n joinStage,\n ask: (text) =>\n questionAction(async () => {\n if (!callKey) throw new Error('This call has no key.')\n await webinarApi().questions.ask(\n callExtId,\n await sealQuestionText(text, callKey),\n linkVersion\n )\n }, 'ask the question'),\n vote: (id, up) =>\n questionAction(() => webinarApi().questions.vote(callExtId, id, up, linkVersion), 'vote'),\n setQuestionStatus: (id, status) =>\n questionAction(\n () => webinarApi().questions.update(callExtId, id, { status }, linkVersion),\n 'update the question'\n ),\n answer: (id, text) =>\n questionAction(async () => {\n if (!callKey) throw new Error('This call has no key.')\n await webinarApi().questions.update(\n callExtId,\n id,\n { answer: await sealQuestionText(text, callKey) },\n linkVersion\n )\n }, 'answer the question'),\n removeQuestion: (id) =>\n questionAction(\n () => webinarApi().questions.delete(callExtId, id, linkVersion),\n 'delete the question'\n ),\n }),\n [\n enabled,\n role,\n state,\n onStage,\n questions,\n stageCheck,\n refresh,\n patch,\n callExtId,\n linkVersion,\n callKey,\n stepDown,\n joinStage,\n questionAction,\n ]\n )\n}\n","/**\n * Inside <LiveKitRoom>: tell me when the host muted my mic or turned off my camera. Listens to the\n * server's `arbi.moderation` data messages (a packet sent by a participant is ignored — only the\n * server may moderate) and to WS `call.muted` for this call; one toast per mute.\n */\n\nimport { useEffect } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useRoomContext } from '@livekit/components-react'\nimport { notify } from '../../notifications/notify-store'\nimport { CALL_MODERATION_TOPIC, createMutedNotifier, mutedNoticeFromPacket, onCallEvent } from '..'\n\nexport function useHostMuteNotice(callExtId: string): void {\n const room = useRoomContext()\n useEffect(() => {\n const notifyMuted = createMutedNotifier((text) => notify.info(text))\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_MODERATION_TOPIC) return\n // Only the server moderates: a packet from a participant is ignored.\n if (participant || participantIdentity) return\n const notice = mutedNoticeFromPacket(payload)\n if (notice) notifyMuted(notice)\n }\n room.on(RoomEvent.DataReceived, onData)\n const offWs = onCallEvent('call.muted', (message) => {\n if (message.callExtId === callExtId) notifyMuted(message)\n })\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n offWs()\n }\n }, [room, callExtId])\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/calls/livekit/room.ts","../../../src/calls/livekit/useCallTranscriber.ts","../../../src/calls/livekit/useCallRecorder.ts","../../../src/calls/livekit/useInCallChat.ts","../../../src/calls/livekit/useWebinar.ts","../../../src/calls/livekit/useHostMuteNotice.ts"],"names":["useRoomContext","useState","useEffect","RoomEvent","useQueryClient","useLocalParticipant","useRef","useCallback","calls","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The LiveKit room of a call, end-to-end encrypted.\n *\n * E2EE uses LiveKit insertable streams in shared-key mode: the 32-byte frame key K (from the call\n * link or my sealed copy) goes into an `ExternalE2EEKeyProvider`, so the SFU only forwards\n * ciphertext. With no key (a session without client keys) the room connects unencrypted.\n */\n\nimport { useEffect, useState } from 'react'\nimport {\n ExternalE2EEKeyProvider,\n Room,\n RoomEvent,\n type Participant,\n type RoomOptions,\n} from 'livekit-client'\nimport { useRoomContext } from '@livekit/components-react'\nimport { notify } from '../../notifications/notify-store'\nimport type { JoinChoices } from '../session'\n\n/** The LiveKit end-to-end encryption worker (bundled from `livekit-client`). */\nexport function createE2EEWorker(): Worker {\n return new Worker(new URL('livekit-client/e2ee-worker', import.meta.url), { type: 'module' })\n}\n\ninterface RoomBundle {\n room: Room\n worker: Worker | null\n}\n\nfunction createRoom(\n e2eeKey: Uint8Array | null,\n choices: JoinChoices,\n createWorker: () => Worker\n): { bundle: RoomBundle; ready: Promise<void> } {\n const options: RoomOptions = {\n adaptiveStream: true,\n dynacast: true,\n audioCaptureDefaults: choices.audioDeviceId ? { deviceId: choices.audioDeviceId } : undefined,\n videoCaptureDefaults: choices.videoDeviceId ? { deviceId: choices.videoDeviceId } : undefined,\n }\n let worker: Worker | null = null\n let keyProvider: ExternalE2EEKeyProvider | null = null\n if (e2eeKey) {\n keyProvider = new ExternalE2EEKeyProvider()\n worker = createWorker()\n options.e2ee = { keyProvider, worker }\n }\n const room = new Room(options)\n const ready = (async () => {\n if (!keyProvider || !e2eeKey) return\n // Copy into a standalone ArrayBuffer (the key view may sit inside a larger buffer).\n await keyProvider.setKey(e2eeKey.slice().buffer as ArrayBuffer)\n await room.setE2EEEnabled(true)\n })()\n return { bundle: { room, worker }, ready }\n}\n\nexport interface CallRoomState {\n /** The room, ready to connect (`<LiveKitRoom room>`); null while it is being set up. */\n room: Room | null\n /** Why the room could not be set up in this browser, if it could not. */\n error: string | null\n}\n\n/**\n * A Room for the call, built once per key: with K, the frames are encrypted in a worker before they\n * leave the browser. Built in an effect (not render) so StrictMode's double mount does not leak a\n * worker; disconnected and torn down on unmount. The device choices only seed it.\n */\nexport function useCallRoom(\n e2eeKey: Uint8Array | null,\n choices: JoinChoices,\n options: { createWorker?: () => Worker } = {}\n): CallRoomState {\n const [room, setRoom] = useState<Room | null>(null)\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n let created: RoomBundle | null = null\n try {\n const { bundle, ready } = createRoom(\n e2eeKey,\n choices,\n options.createWorker ?? createE2EEWorker\n )\n created = bundle\n ready\n .then(() => {\n if (!cancelled) setRoom(bundle.room)\n })\n .catch((err: unknown) => {\n console.error('[calls] E2EE setup failed', err)\n if (!cancelled) setError('This browser cannot encrypt the call (E2EE unsupported).')\n })\n } catch (err) {\n console.error('[calls] room setup failed', err)\n setError('Could not set up the call in this browser.')\n }\n return () => {\n cancelled = true\n if (created) {\n void created.room.disconnect()\n created.worker?.terminate()\n }\n setRoom(null)\n }\n // The room is built once per key; the device choices only seed it.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [e2eeKey])\n return { room, error }\n}\n\nconst MUTE_REQUEST_TOPIC = 'arbi.mute-request'\n\n/**\n * Inside `<LiveKitRoom>`: ask someone to mute (anyone may ask; only the host can mute others\n * server-side), and show such a request when it is for me, with a Mute action.\n */\nexport function useMuteRequests(): (identity: string) => void {\n const room = useRoomContext()\n useEffect(() => {\n const onData = (payload: Uint8Array, from?: Participant, _kind?: unknown, topic?: string) => {\n if (topic !== MUTE_REQUEST_TOPIC || !from) return\n const who = from.name || from.identity\n notify.info(`${who} asks you to mute your microphone`, {\n action: {\n label: 'Mute',\n onClick: () => void room.localParticipant.setMicrophoneEnabled(false),\n },\n })\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room])\n return (identity: string) =>\n void room.localParticipant\n .publishData(new TextEncoder().encode('{\"v\":1}'), {\n reliable: true,\n topic: MUTE_REQUEST_TOPIC,\n destinationIdentities: [identity],\n })\n .then(() => notify.info('Asked to mute'))\n .catch((err: Error) => notify.error(`Could not ask: ${err.message}`))\n}\n","/**\n * Live transcription state of a LiveKit room (ARBI `docs/meeting-chats-plan.md` §5). Must run inside\n * <LiveKitRoom>.\n *\n * - Transcription is the HOST's setting: only the call's creator can turn it on or off.\n * - The state comes from the call row on join, then from the server's `arbi.transcription` data\n * message and WS `call.transcription`. A participant cannot fake it: only a server-sent packet\n * (no sender) is accepted.\n * - My audio is sent only while transcription is on AND its indicator is on screen\n * (`indicatorShown`, set by the indicator itself once mounted) AND I have not muted my\n * transcription AND (checked by <TranscriptionSender>) my microphone is on.\n * - Each of my transcribed segments becomes a caption for everyone (data channel, under K) and a\n * transcript line in the meeting chat — stored by me, or, when I cannot post there (a workspace\n * guest), by the members who receive my `proxy` caption. It is stored under my real display name\n * (the UI shows \"You\" for my own lines; the stored line never says \"You\").\n * - The line being spoken when sending stops (transcription off, my transcription muted, hang-up,\n * page hide) is still flushed and sent: the server takes a segment for {@link FINAL_SEGMENT_GRACE_MS}\n * after transcription went off if it started before that.\n * - Every clip carries the user's language and my previous line (a continuity prompt).\n */\n\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../../useArbi'\nimport { useAudioRecorder, type AudioSegment } from '../../documents/useAudioRecorder'\nimport { toProfileView } from '../../account/profile'\nimport {\n onCallEvent,\n useCallTranscriptionAvailable,\n CALL_CAPTION_TOPIC,\n CALL_TRANSCRIPTION_TOPIC,\n decodeCaptionPacket,\n encodeCaptionPacket,\n newSegmentId,\n persistTranscriptSegment,\n transcriptPersistRole,\n type CaptionLine,\n type TranscriptSegment,\n} from '..'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useLocalParticipant, useRoomContext } from '@livekit/components-react'\nimport { CallApiError, calls, continuityPrompt } from '@arbidocs/sdk/browser'\nimport { notify } from '../../notifications/notify-store'\n\n/** Captions kept in memory (the overlay shows the last few). */\nconst MAX_CAPTIONS = 30\n/**\n * After sending stops, the segment that was open then is still sent (the server's grace for a final\n * segment is 30 s after transcription is turned off, for a segment that started before).\n */\nexport const FINAL_SEGMENT_GRACE_MS = 30_000\n/** My previous text kept for the continuity prompt (a little more than it sends). */\nconst PROMPT_HISTORY_CHARS = 400\n\n/**\n * Whether one of my segments may still be sent: while sending, always; after sending stopped, only\n * the segment that was open then (it started before the stop) and within the server's grace.\n */\nexport function mayStillSend(params: {\n sending: boolean\n /** When sending last stopped (ms since epoch); null if it never did. */\n stoppedAt: number | null\n segmentStartedAt: number\n now: number\n}): boolean {\n if (params.sending) return true\n if (params.stoppedAt === null) return false\n return (\n params.segmentStartedAt <= params.stoppedAt &&\n params.now - params.stoppedAt <= FINAL_SEGMENT_GRACE_MS\n )\n}\n\n/**\n * The name my transcript lines are stored under: my LiveKit name, else my profile's display name,\n * else my identity — never \"You\" (that is only how the UI shows my own lines to me).\n */\nexport function storedSpeakerName(\n participantName: string | null | undefined,\n profileName: string | null | undefined,\n identity: string\n): string {\n return participantName?.trim() || profileName?.trim() || identity\n}\n\nexport interface CallTranscription {\n /** The deployment has a transcriber and the call has a key. */\n available: boolean\n on: boolean\n startedByName: string | null\n startedByMe: boolean\n /** I host the call: only I see and use the on/off control. */\n canToggle: boolean\n busy: boolean\n /** I muted my own transcription (nothing of mine is sent). */\n muted: boolean\n setMuted(muted: boolean): void\n /** Turn on / off (the host only). */\n toggle(): Promise<void>\n /** The indicator reports itself on screen; nothing is sent before it is. */\n setIndicatorShown(shown: boolean): void\n /** On, shown and not muted: <TranscriptionSender> records while this (and the mic) is on. */\n shouldSend: boolean\n captions: CaptionLine[]\n /** <TranscriptionSender> hands each of my speech segments here. */\n handleSegment(segment: AudioSegment): Promise<void>\n}\n\nexport function useCallTranscriber({\n callExtId,\n callKey,\n isCreator,\n canPost,\n linkVersion = null,\n}: {\n callExtId: string\n /** The link version I joined with (sent with each segment). */\n linkVersion?: number | null\n callKey: Uint8Array | null\n isCreator: boolean\n /** I can post to the meeting chat (false for a workspace guest on a thread call). */\n canPost: boolean\n}): CallTranscription {\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const profile = arbi.isLoggedIn ? arbi.user.profile() : null\n const myProfileName = (profile && toProfileView(profile).fullName) || null\n const deploymentAvailable = useCallTranscriptionAvailable()\n const available = deploymentAvailable && !!callKey\n\n const [state, setState] = useState<calls.CallTranscriptionState | null>(null)\n const [creatorExtId, setCreatorExtId] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [muted, setMuted] = useState(false)\n const [indicatorShown, setIndicatorShown] = useState(false)\n const [captions, setCaptions] = useState<CaptionLine[]>([])\n const liveUpdate = useRef(false)\n const persisted = useRef(new Set<string>())\n const saveFailureShown = useRef(false)\n // Whether my own segments are stored by me; flips off if the meeting chat refuses my posts.\n const selfPosts = useRef(canPost)\n useEffect(() => {\n selfPosts.current = canPost\n }, [canPost])\n\n const on = available && !!state?.on\n const shouldSend = on && indicatorShown && !muted\n const shouldSendRef = useRef(shouldSend)\n // When sending last stopped: the segment open then is still flushed and sent (see mayStillSend).\n const sendStoppedAtRef = useRef<number | null>(null)\n if (shouldSendRef.current !== shouldSend) {\n sendStoppedAtRef.current = shouldSend ? null : Date.now()\n }\n shouldSendRef.current = shouldSend\n // My previous text, for the continuity prompt of my next segment.\n const myPreviousText = useRef('')\n\n const applyState = useCallback((next: calls.CallTranscriptionState | null) => {\n liveUpdate.current = true\n setState(next)\n }, [])\n\n // Join: the call row says whether transcription is already on (and who created the call).\n useEffect(() => {\n if (!available) return\n let cancelled = false\n arbi.calls\n .get(callExtId)\n .then((call) => {\n if (cancelled) return\n setCreatorExtId(call.creator_ext_id ?? null)\n // A live announcement that already arrived is newer than this read.\n if (!liveUpdate.current) {\n setState(calls.transcriptionStateFrom(call.transcription))\n }\n })\n .catch((err: unknown) => console.warn('[calls] could not read the transcription state', err))\n return () => {\n cancelled = true\n }\n }, [available, callExtId])\n\n // WS `call.transcription`.\n useEffect(\n () =>\n onCallEvent('call.transcription', (message) => {\n if (message.call_ext_id === callExtId) applyState(message)\n }),\n [callExtId, applyState]\n )\n\n const addCaption = useCallback((line: CaptionLine) => {\n setCaptions((prev) => {\n if (prev.some((c) => c.segmentId === line.segmentId && c.identity === line.identity)) {\n return prev\n }\n return [...prev, line].sort((a, b) => a.t - b.t).slice(-MAX_CAPTIONS)\n })\n }, [])\n\n /** Store a segment when it is mine to store (see `transcriptPersistRole`). */\n const persist = useCallback(\n (segment: TranscriptSegment, speakerNeedsProxy: boolean) => {\n if (!callKey || persisted.current.has(segment.segmentId)) return\n const role = transcriptPersistRole({\n myIdentity,\n canPost: canPost && (segment.speakerIdentity !== myIdentity || selfPosts.current),\n hasCallKey: true,\n speakerIdentity: segment.speakerIdentity,\n speakerNeedsProxy,\n })\n if (!role) return\n persisted.current.add(segment.segmentId)\n persistTranscriptSegment(arbi, queryClient, callExtId, callKey, segment).catch(\n (err: unknown) => {\n persisted.current.delete(segment.segmentId)\n // Refused (not a member of the meeting chat): members store my next segments.\n if (role === 'own' && (err as { status?: number } | null)?.status === 403) {\n selfPosts.current = false\n }\n console.warn('[calls] could not keep the transcript line', err)\n // Never silently: say so once per call (captions keep working).\n if (!saveFailureShown.current) {\n saveFailureShown.current = true\n notify.warning(\n `Transcript lines are not being saved to the meeting chat: ${(err as Error)?.message ?? 'unknown error'}`\n )\n }\n }\n )\n },\n [callExtId, callKey, myIdentity, canPost]\n )\n\n // Data channel: the server's state announcements and everyone's captions.\n useEffect(() => {\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic === CALL_TRANSCRIPTION_TOPIC) {\n // Only the server may announce the state: a packet from a participant is ignored.\n if (participant || participantIdentity) return\n try {\n const next = calls.transcriptionStateFrom(JSON.parse(new TextDecoder().decode(payload)))\n if (next) applyState(next)\n } catch {\n // Not ours.\n }\n return\n }\n if (topic !== CALL_CAPTION_TOPIC || !callKey) return\n const identity = participant?.identity ?? participantIdentity\n if (!identity || identity === myIdentity) return\n void decodeCaptionPacket(payload, callKey).then((packet) => {\n // A caption speaks for its sender only.\n if (!packet || packet.identity !== identity) return\n const name = participant?.name || packet.name || identity\n const t = Math.min(packet.t, Date.now())\n addCaption({\n segmentId: packet.segment_id,\n identity,\n name,\n text: packet.text,\n t,\n mine: false,\n receivedAt: Date.now(),\n })\n persist(\n {\n segmentId: packet.segment_id,\n text: packet.text,\n speakerIdentity: identity,\n speakerName: name,\n startedAt: new Date(t).toISOString(),\n },\n packet.proxy === true\n )\n })\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room, callKey, myIdentity, addCaption, applyState, persist])\n\n const handleSegment = useCallback(\n async (segment: AudioSegment) => {\n // While sending, or the segment that was open when sending stopped (transcription off, my\n // transcription muted, hang-up): flushed then, still sent within the server's grace.\n // Anything that started after the stop is dropped.\n if (\n !callKey ||\n !mayStillSend({\n sending: shouldSendRef.current,\n stoppedAt: sendStoppedAtRef.current,\n segmentStartedAt: segment.startedAt,\n now: Date.now(),\n })\n ) {\n return\n }\n const segmentId = newSegmentId()\n const startedAt = new Date(segment.startedAt).toISOString()\n let text: string\n try {\n const result = await arbi.calls.transcription.transcribe(callExtId, {\n audio: segment.blob,\n segmentId,\n startedAt,\n linkVersion,\n prompt: continuityPrompt(myPreviousText.current),\n })\n text = result.text.trim()\n } catch (err) {\n if (err instanceof CallApiError && err.status === 409) {\n applyState({ on: false, by_identity: null, by_name: null })\n }\n console.warn('[calls] could not transcribe a segment', err)\n return\n }\n if (!text) return\n myPreviousText.current = `${myPreviousText.current} ${text}`.slice(-PROMPT_HISTORY_CHARS)\n // Stored (and shown to others) under my real name; my own caption reads \"You\" on screen.\n const name = storedSpeakerName(localParticipant.name, myProfileName, myIdentity)\n const proxy = !selfPosts.current\n addCaption({\n segmentId,\n identity: myIdentity,\n name,\n text,\n t: segment.startedAt,\n mine: true,\n receivedAt: Date.now(),\n })\n try {\n await localParticipant.publishData(\n await encodeCaptionPacket(\n {\n v: 1,\n segment_id: segmentId,\n text,\n identity: myIdentity,\n name,\n t: segment.startedAt,\n ...(proxy ? { proxy: true } : {}),\n },\n callKey\n ),\n { reliable: true, topic: CALL_CAPTION_TOPIC }\n )\n } catch (err) {\n console.warn('[calls] could not broadcast a caption', err)\n }\n if (!proxy) {\n persist(\n { segmentId, text, speakerIdentity: myIdentity, speakerName: name, startedAt },\n false\n )\n }\n },\n [\n callExtId,\n callKey,\n linkVersion,\n localParticipant,\n myIdentity,\n myProfileName,\n addCaption,\n applyState,\n persist,\n ]\n )\n\n const startedByMe = !!state?.on && state.by_identity === myIdentity\n const canToggle = available && (isCreator || (!!creatorExtId && creatorExtId === myIdentity))\n\n const toggle = useCallback(async () => {\n if (!canToggle) return\n const next = !on\n setBusy(true)\n try {\n const answer = await arbi.calls.transcription.set(callExtId, next)\n applyState(\n answer ??\n (next\n ? { on: true, by_identity: myIdentity, by_name: localParticipant.name || null }\n : { on: false, by_identity: null, by_name: null })\n )\n } catch (err) {\n notify.error(`Could not turn transcription ${next ? 'on' : 'off'}: ${(err as Error).message}`)\n } finally {\n setBusy(false)\n }\n }, [on, canToggle, callExtId, myIdentity, localParticipant, applyState])\n\n return useMemo(\n () => ({\n available,\n on,\n startedByName: on ? (state?.by_name ?? null) : null,\n startedByMe,\n canToggle,\n busy,\n muted,\n setMuted,\n toggle,\n setIndicatorShown,\n shouldSend,\n captions,\n handleSegment,\n }),\n [\n available,\n on,\n state,\n startedByMe,\n canToggle,\n busy,\n muted,\n toggle,\n shouldSend,\n captions,\n handleSegment,\n ]\n )\n}\n","/**\n * Recording state of a LiveKit room (ARBI `docs/meeting-chats-plan.md` §6). Must run inside\n * <LiveKitRoom>. Mirrors {@link useCallTranscription}:\n *\n * - Recording is the HOST's action: only the call's creator starts (choosing Audio or Audio + video)\n * or stops it. Before starting, the host is warned when the storage quota is nearly full.\n * - The state comes from the call row on join, then from the server's `arbi.recording` data message\n * and WS `call.recording`. Only a server-sent packet (no sender) is accepted.\n * - Nothing is captured before the \"Recording\" indicator is on screen (`indicatorShown`, reported\n * by the indicator itself once mounted): `shouldCapture` gates every recorder.\n */\n\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../../useArbi'\nimport {\n onCallEvent,\n CALL_RECORDING_TOPIC,\n conversationKeyForCall,\n ensureMeetingChat,\n trackUploaderFor,\n type TrackUploader,\n} from '..'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useLocalParticipant, useRoomContext } from '@livekit/components-react'\nimport { calls } from '@arbidocs/sdk/browser'\nimport { notify } from '../../notifications/notify-store'\n\nexport interface PendingRecordingStart {\n mode: calls.RecordingMode\n quota: calls.RecordingQuota\n}\n\nexport interface CallRecordingControl {\n /** The call has a key (recordings are encrypted under the conversation key; no key, no recording). */\n available: boolean\n on: boolean\n mode: calls.RecordingMode | null\n recordingExtId: string | null\n /** The recording's start when the state carried it (uploaders otherwise read it). */\n startedAt: string | null\n startedByName: string | null\n startedByMe: boolean\n /** I host the call: only I see and use the controls. */\n canControl: boolean\n busy: boolean\n /** The call row (its meeting chat / locked workspace decide the conversation key). */\n call: calls.CallResponse | null\n /** The call link version I joined with (sent when creating my track). */\n linkVersion: number | null\n /** Start in a mode: checks the quota first; near the limit it asks for confirmation instead. */\n requestStart(mode: calls.RecordingMode): Promise<void>\n /** The start waiting for the host to confirm past the quota warning. */\n pendingStart: PendingRecordingStart | null\n confirmStart(): Promise<void>\n cancelStart(): void\n stop(): Promise<void>\n /** The indicator reports itself on screen; nothing is captured before it is. */\n setIndicatorShown(shown: boolean): void\n /** On, a recording id known, the indicator shown and a key to encrypt under. */\n shouldCapture: boolean\n /** The server stopped the recording at the storage quota: reflect (and say) it immediately. */\n markStopped(): void\n}\n\n/** Whether a recording state lets a client capture (the gating rule, testable on its own). */\nexport function captureAllowed(params: {\n available: boolean\n state: calls.CallRecordingState | null\n indicatorShown: boolean\n}): boolean {\n return (\n params.available &&\n !!params.state?.on &&\n !!params.state.recording_ext_id &&\n params.indicatorShown\n )\n}\n\nexport function useCallRecorder({\n callExtId,\n callKey,\n isCreator,\n linkVersion = null,\n}: {\n callExtId: string\n callKey: Uint8Array | null\n isCreator: boolean\n linkVersion?: number | null\n}): CallRecordingControl {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const available = !!callKey\n\n const [state, setState] = useState<calls.CallRecordingState | null>(null)\n const [call, setCall] = useState<calls.CallResponse | null>(null)\n const [busy, setBusy] = useState(false)\n const [indicatorShown, setIndicatorShown] = useState(false)\n const [pendingStart, setPendingStart] = useState<PendingRecordingStart | null>(null)\n const liveUpdate = useRef(false)\n const stateRef = useRef<calls.CallRecordingState | null>(null)\n stateRef.current = state\n\n const applyState = useCallback((next: calls.CallRecordingState | null) => {\n liveUpdate.current = true\n // The server stopped it on its own (the storage quota): say why, once.\n if (stateRef.current?.on && next && !next.on && next.reason === 'storage_quota_exceeded') {\n notify.warning('Recording stopped: the storage is full.')\n }\n stateRef.current = next\n setState(next)\n }, [])\n\n // Join: the call row says whether a recording is running (and who created the call).\n useEffect(() => {\n let cancelled = false\n arbi.calls\n .get(callExtId)\n .then((row) => {\n if (cancelled) return\n setCall(row)\n if (!liveUpdate.current) setState(calls.recordingStateOfCall(row))\n })\n .catch((err: unknown) => console.warn('[calls] could not read the recording state', err))\n return () => {\n cancelled = true\n }\n }, [callExtId])\n\n // WS `call.recording`.\n useEffect(\n () =>\n onCallEvent('call.recording', (message) => {\n if (message.call_ext_id === callExtId) applyState(message)\n }),\n [callExtId, applyState]\n )\n\n // The server's data message (a participant's packet on this topic is ignored).\n useEffect(() => {\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_RECORDING_TOPIC) return\n if (participant || participantIdentity) return\n try {\n const next = calls.recordingStateFrom(JSON.parse(new TextDecoder().decode(payload)))\n if (next) applyState(next)\n } catch {\n // Not ours.\n }\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room, applyState])\n\n const canControl = available && (isCreator || (!!call && call.creator_ext_id === myIdentity))\n const on = !!state?.on\n\n const start = useCallback(\n async (mode: calls.RecordingMode) => {\n setBusy(true)\n try {\n // A contacts call keeps its recording in the E2E meeting chat: make it first, so every\n // participant's track key can be wrapped under the chat key from the first part on.\n const row = call ?? (await arbi.calls.get(callExtId))\n if (!row.workspace_locked && !row.chat_ext_id && callKey) {\n const ref = await ensureMeetingChat(arbi, queryClient, callExtId, callKey)\n if (ref.kind === 'chat') setCall({ ...row, chat_ext_id: ref.chatExtId })\n }\n const answer = await arbi.calls.recording.start(callExtId, mode)\n if (answer) applyState(answer)\n } catch (err) {\n notify.error(`Could not start recording: ${(err as Error).message}`)\n } finally {\n setBusy(false)\n }\n },\n [callExtId, callKey, call, applyState]\n )\n\n const requestStart = useCallback(\n async (mode: calls.RecordingMode) => {\n if (!canControl || on) return\n setBusy(true)\n let quota: calls.RecordingQuota | null = null\n try {\n quota = await arbi.calls.recording.quota(callExtId)\n } catch (err) {\n // The server enforces the quota anyway; a failed read only skips the warning.\n console.warn('[calls] could not read the recording quota', err)\n }\n setBusy(false)\n if (quota && calls.quotaNeedsWarning(quota)) {\n setPendingStart({ mode, quota })\n return\n }\n await start(mode)\n },\n [canControl, on, callExtId, start]\n )\n\n const confirmStart = useCallback(async () => {\n const pending = pendingStart\n setPendingStart(null)\n if (pending) await start(pending.mode)\n }, [pendingStart, start])\n\n const cancelStart = useCallback(() => setPendingStart(null), [])\n\n const stop = useCallback(async () => {\n if (!canControl || !on) return\n setBusy(true)\n try {\n const answer = await arbi.calls.recording.stop(callExtId)\n applyState(answer ?? { ...(state as calls.CallRecordingState), on: false })\n } catch (err) {\n notify.error(`Could not stop recording: ${(err as Error).message}`)\n } finally {\n setBusy(false)\n }\n }, [canControl, on, callExtId, state, applyState])\n\n const markStopped = useCallback(() => {\n const prev = stateRef.current\n if (prev?.on) applyState({ ...prev, on: false, reason: 'storage_quota_exceeded' })\n }, [applyState])\n\n const shouldCapture = captureAllowed({ available, state, indicatorShown })\n\n return useMemo(\n () => ({\n available,\n on,\n mode: on ? (state?.mode ?? 'audio') : null,\n recordingExtId: state?.recording_ext_id ?? null,\n startedAt: state?.started_at ?? null,\n startedByName: on ? (state?.by_name ?? null) : null,\n startedByMe: on && state?.by_identity === myIdentity,\n canControl,\n busy,\n call,\n linkVersion,\n requestStart,\n pendingStart,\n confirmStart,\n cancelStart,\n stop,\n setIndicatorShown,\n shouldCapture,\n markStopped,\n }),\n [\n available,\n on,\n state,\n myIdentity,\n canControl,\n busy,\n call,\n linkVersion,\n requestStart,\n pendingStart,\n confirmStart,\n cancelStart,\n stop,\n shouldCapture,\n markStopped,\n ]\n )\n}\n\n/** The uploader of one of my tracks for the running recording (null while not capturing). */\nexport function useTrackUploader(\n recording: CallRecordingControl,\n callKey: Uint8Array | null,\n kind: 'speaker' | 'composite',\n mimeType: string\n): TrackUploader | null {\n const { recordingExtId, call, startedAt, shouldCapture, markStopped, linkVersion } = recording\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMemo(() => {\n if (!shouldCapture || !recordingExtId || !call) return null\n return trackUploaderFor({\n arbi,\n callExtId: call.external_id,\n recordingExtId,\n kind,\n mimeType,\n recordingStartedAt: startedAt,\n linkVersion,\n conversationKey: () => conversationKeyForCall(arbi, queryClient, call, { callKey }),\n // The server stopped the recording at the quota (its state event says so too).\n onStopped: () => markStopped(),\n })\n }, [\n arbi,\n queryClient,\n shouldCapture,\n recordingExtId,\n call,\n startedAt,\n linkVersion,\n kind,\n mimeType,\n callKey,\n markStopped,\n ])\n}\n","/**\n * The in-call chat state of a LiveKit room: live data-channel messages (encrypted under the call\n * key), persisted to the meeting chat for signed-in members. Must run inside <LiveKitRoom>. A\n * webinar's live chat (when its audience may chat) is this; with no call key it stays inert.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useLocalParticipant, useRoomContext } from '@livekit/components-react'\nimport { notify } from '../../notifications/notify-store'\nimport {\n CALL_CHAT_MAX_CHARS,\n CALL_CHAT_TOPIC,\n decodeCallChatPacket,\n encodeCallChatPacket,\n loadMeetingHistory,\n mergeChatLines,\n newPacketId,\n persistMeetingMessage,\n type CallChatLine,\n type HistoryMessage,\n ensureMeetingChat,\n type MeetingChatRef,\n} from '..'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../../useArbi'\nimport { useArbiHost } from '../../host/config'\n\nexport interface InCallChatState {\n lines: CallChatLine[]\n /** Messages from others received while the panel was closed. */\n unread: number\n /** False without a call key: nothing could be encrypted, so chat is off. */\n available: boolean\n /** My messages are kept in the meeting chat. */\n persists: boolean\n /** A workspace guest on a thread call: the meeting chat is read-only (no composer). */\n readOnly: boolean\n historyLoading: boolean\n historyError: string | null\n meetingChat: MeetingChatRef | null\n send(text: string): Promise<void>\n openMeeting(): Promise<void>\n}\n\n/** The room's chat state. `open` is whether the panel is showing (it clears unread). */\nexport function useInCallChat({\n callExtId,\n callKey,\n open,\n readOnly = false,\n persist = true,\n}: {\n callExtId: string\n callKey: Uint8Array | null\n open: boolean\n /** Workspace guest on a thread call: read the meeting chat, never post. */\n readOnly?: boolean\n /**\n * Keep messages in (and read history from) the meeting chat. Off for a webinar's attendees: they\n * are not its members, so their chat is live only.\n */\n persist?: boolean\n}): InCallChatState {\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const openMeetingChat = useArbiHost().calls?.openMeetingChat\n const signedIn = arbi.isLoggedIn\n const persists = !!callKey && signedIn && !readOnly && persist\n\n const [live, setLive] = useState<CallChatLine[]>([])\n const [history, setHistory] = useState<HistoryMessage[]>([])\n const [historyLoading, setHistoryLoading] = useState(false)\n const [historyError, setHistoryError] = useState<string | null>(null)\n const [meetingChat, setMeetingChat] = useState<MeetingChatRef | null>(null)\n const [unread, setUnread] = useState(0)\n const openRef = useRef(open)\n openRef.current = open\n const historyRequested = useRef(false)\n const seen = useRef(new Set<string>())\n\n useEffect(() => {\n if (open) setUnread(0)\n }, [open])\n\n // Receive: open each packet with K; drop anything that is not ours.\n useEffect(() => {\n if (!callKey) return\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_CHAT_TOPIC) return\n const identity = participant?.identity ?? participantIdentity\n if (!identity || identity === myIdentity) return\n void decodeCallChatPacket(payload, callKey).then((packet) => {\n if (!packet) return\n // A reliable packet can arrive twice (reconnect): count and show it once.\n const key = `${identity}:${packet.id}`\n if (seen.current.has(key)) return\n seen.current.add(key)\n setLive((prev) => [\n ...prev,\n {\n id: packet.id,\n senderIdentity: identity,\n senderName: participant?.name || identity,\n text: packet.text,\n at: Math.min(packet.at, Date.now()),\n mine: false,\n status: 'live',\n },\n ])\n if (!openRef.current) setUnread((n) => n + 1)\n })\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [room, callKey, myIdentity])\n\n // History: once, the first time the panel opens. Never creates the meeting chat.\n const canRead = !!callKey && signedIn && persist\n useEffect(() => {\n if (!open || !canRead || historyRequested.current) return\n historyRequested.current = true\n setHistoryLoading(true)\n loadMeetingHistory(arbi, queryClient, callExtId)\n .then((result) => {\n if (!result) return\n setMeetingChat(result.ref)\n setHistory(result.messages)\n })\n .catch((err: unknown) => {\n console.warn('[calls] could not load the meeting chat', err)\n setHistoryError('Earlier messages could not be loaded.')\n })\n .finally(() => setHistoryLoading(false))\n }, [open, canRead, callExtId])\n\n const send = useCallback(\n async (raw: string) => {\n const text = raw.trim().slice(0, CALL_CHAT_MAX_CHARS)\n if (!text || !callKey || readOnly) return\n const id = newPacketId()\n const at = Date.now()\n await localParticipant.publishData(\n await encodeCallChatPacket({ v: 1, id, text, at }, callKey),\n { reliable: true, topic: CALL_CHAT_TOPIC }\n )\n setLive((prev) => [\n ...prev,\n {\n id,\n senderIdentity: myIdentity,\n senderName: localParticipant.name || 'You',\n text,\n at,\n mine: true,\n status: persists ? 'saving' : 'live',\n },\n ])\n if (!persists) return\n const mark = (status: CallChatLine['status']) =>\n setLive((prev) =>\n prev.map((l) => (l.id === id && l.senderIdentity === myIdentity ? { ...l, status } : l))\n )\n try {\n setMeetingChat(await persistMeetingMessage(arbi, queryClient, callExtId, callKey, text))\n mark('saved')\n } catch (err) {\n console.warn('[calls] could not keep the message in the meeting chat', err)\n mark('unsaved')\n }\n },\n [callKey, callExtId, localParticipant, myIdentity, persists, readOnly]\n )\n\n const openMeeting = useCallback(async () => {\n if (!callKey) return\n try {\n const ref = meetingChat ?? (await ensureMeetingChat(arbi, queryClient, callExtId, callKey))\n setMeetingChat(ref)\n openMeetingChat?.(ref)\n } catch (err) {\n notify.error(`Could not open the meeting chat: ${(err as Error).message}`)\n }\n }, [callExtId, callKey, meetingChat])\n\n const lines = useMemo(\n () =>\n mergeChatLines(history, live, {\n myIdentity,\n nameOf: (identity) =>\n identity === myIdentity\n ? localParticipant.name || 'You'\n : room.remoteParticipants.get(identity)?.name || null,\n }),\n [history, live, myIdentity, localParticipant, room]\n )\n\n return {\n lines,\n unread,\n available: !!callKey,\n persists,\n readOnly,\n historyLoading,\n historyError,\n meetingChat,\n send,\n openMeeting,\n }\n}\n","/**\n * The webinar state of a LiveKit room (ARBI `docs/webinars-plan.md`). Must run inside\n * <LiveKitRoom>; with `enabled` false (an ordinary call) it does nothing.\n *\n * - The state (live, chat, my role and stage, the moderators' hands and audience) comes from\n * `GET /webinar`, then from the server's `arbi.webinar` data messages and WS `call.webinar`.\n * Only server-sent packets count: one from a participant is ignored.\n * - Whether I am on stage is the room's own word (my publish permission), so it flips the moment\n * the server promotes or demotes me.\n * - `promoted`: the \"You're on stage\" device check opens; joining it publishes my microphone (and\n * camera) with the devices I picked. `demoted` (and stepping down myself): the server removes me\n * from the room and the dock joins me again as the audience (`webinar-join.ts`).\n * - Q&A text is end-to-end under the call key K (`webinar-packets.ts`).\n */\n\nimport { useArbi } from '../../useArbi'\nimport { onCallEvent, type JoinChoices } from '..'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport {\n useLocalParticipant,\n useLocalParticipantPermissions,\n useRoomContext,\n} from '@livekit/components-react'\nimport { calls } from '@arbidocs/sdk/browser'\nimport { notify } from '../../notifications/notify-store'\nimport {\n CALL_WEBINAR_TOPIC,\n markRejoining,\n openQuestion,\n parseWebinarPacket,\n sealQuestionText,\n type OpenQuestion,\n} from '../webinar'\n\n/** After `demoted`, the server removes me at once; if it has not after this, I leave the room myself. */\nexport const DEMOTE_REJOIN_FALLBACK_MS = 5_000\n\nexport type WebinarHandRow = NonNullable<calls.WebinarState['hands']>[number]\nexport type WebinarAttendeeRow = NonNullable<calls.WebinarState['attendees']>[number]\n\nexport interface WebinarControl {\n /** The call is a webinar (everything below is inert otherwise). */\n enabled: boolean\n role: calls.WebinarRole | null\n /** Host or co-host: go live / end, chat setting, hands and audience, promote / demote. */\n moderator: boolean\n /** Host, co-host or panelist: moderates Q&A. */\n team: boolean\n live: boolean\n chat: calls.WebinarChat\n /** I may publish: on stage (always true outside a webinar). */\n onStage: boolean\n handRaised: boolean\n /** Moderators: the raised hands, oldest first. */\n hands: WebinarHandRow[]\n /** Moderators: everyone in the room (hidden audience included). */\n attendees: WebinarAttendeeRow[]\n questions: OpenQuestion[]\n /** A moderator brought me on stage: the device check is open. */\n stageCheck: boolean\n refresh(): Promise<void>\n goLive(): Promise<void>\n end(): Promise<void>\n setChat(chat: calls.WebinarChat): Promise<void>\n setHand(raised: boolean): Promise<void>\n promote(identity: string): Promise<void>\n demote(identity: string): Promise<void>\n /** Leave the stage myself (also \"Stay in audience\" on the device check). */\n stepDown(): Promise<void>\n /** Go on stage with the devices picked in the check. */\n joinStage(choices: JoinChoices): Promise<void>\n ask(text: string): Promise<void>\n vote(questionId: string, up: boolean): Promise<void>\n setQuestionStatus(questionId: string, status: calls.CallQuestionStatus): Promise<void>\n answer(questionId: string, text: string): Promise<void>\n removeQuestion(questionId: string): Promise<void>\n}\n\n/** Toast a failed action, then reject (the blocks keep their state on a rejection). */\nfunction failed(what: string) {\n return (err: unknown): never => {\n notify.error(`Could not ${what}: ${(err as Error)?.message ?? 'unknown error'}`)\n throw err\n }\n}\n\nexport function useWebinar({\n role: roleHint = null,\n callExtId,\n linkVersion = null,\n callKey,\n}: {\n /** My role from the call (null: not a webinar). Until the room says, the team counts as on stage. */\n role?: calls.WebinarRole | null\n callExtId: string\n linkVersion?: number | null\n callKey: Uint8Array | null\n}): WebinarControl {\n const arbi = useArbi()\n const webinarApi = useCallback(() => arbi.calls.webinar, [arbi])\n const enabled = !!roleHint\n const room = useRoomContext()\n const { localParticipant } = useLocalParticipant()\n const myIdentity = localParticipant.identity\n const permissions = useLocalParticipantPermissions()\n const [state, setState] = useState<calls.WebinarState | null>(null)\n const [questions, setQuestions] = useState<OpenQuestion[]>([])\n const [stageCheck, setStageCheck] = useState(false)\n const stateRead = useRef(0)\n const questionsRead = useRef(0)\n\n const refresh = useCallback(async () => {\n if (!enabled) return\n const n = ++stateRead.current\n try {\n const next = await webinarApi().get(callExtId, linkVersion)\n if (n === stateRead.current) setState(next)\n } catch (err) {\n console.warn('[calls] could not read the webinar state', err)\n }\n }, [enabled, callExtId, linkVersion])\n\n const refreshQuestions = useCallback(async () => {\n if (!enabled || !callKey) return\n const n = ++questionsRead.current\n try {\n const rows = await webinarApi().questions.list(callExtId, linkVersion)\n const opened = await Promise.all(rows.map((q) => openQuestion(q, callKey)))\n if (n === questionsRead.current) setQuestions(opened)\n } catch (err) {\n console.warn('[calls] could not load the questions', err)\n }\n }, [enabled, callExtId, linkVersion, callKey])\n\n useEffect(() => {\n void refresh()\n void refreshQuestions()\n }, [refresh, refreshQuestions])\n\n // Live / ended / chat setting, over WS (the room's own packet says the same).\n useEffect(() => {\n if (!enabled) return\n return onCallEvent('call.webinar', (m) => {\n if (m.call_ext_id !== callExtId) return\n setState((s) => (s ? { ...s, live: m.live, chat: m.chat } : s))\n })\n }, [enabled, callExtId])\n\n // The server's `arbi.webinar` messages.\n const fallback = useRef<ReturnType<typeof setTimeout> | null>(null)\n useEffect(() => {\n if (!enabled) return\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_WEBINAR_TOPIC) return\n const packet = parseWebinarPacket(payload, !!(participant || participantIdentity))\n if (!packet) return\n switch (packet.type) {\n case 'state':\n setState((s) =>\n s ? { ...s, live: packet.live, live_at: packet.live_at, chat: packet.chat } : s\n )\n // Roles may have changed too: read them again.\n void refresh()\n return\n case 'hands':\n setState((s) => (s ? { ...s, hands: packet.hands } : s))\n return\n case 'questions':\n void refreshQuestions()\n return\n case 'promoted':\n setStageCheck(true)\n void refresh()\n return\n case 'demoted':\n setStageCheck(false)\n // The server removes me from the room now; the dock then joins me again as the audience.\n markRejoining(callExtId)\n if (fallback.current) clearTimeout(fallback.current)\n fallback.current = setTimeout(() => void room.disconnect(), DEMOTE_REJOIN_FALLBACK_MS)\n return\n }\n }\n room.on(RoomEvent.DataReceived, onData)\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n }\n }, [enabled, room, callExtId, refresh, refreshQuestions])\n useEffect(\n () => () => {\n if (fallback.current) clearTimeout(fallback.current)\n },\n []\n )\n\n const role = enabled ? (state?.my_role ?? null) : null\n // The room's word once connected, else the server's, else my role: the team starts on stage, so\n // its UI (and the dock's placement) never flickers through the audience viewer while joining.\n const onStage =\n !enabled ||\n (permissions ? permissions.canPublish : state ? state.on_stage : roleHint !== 'attendee')\n\n const patch = useCallback(\n async (body: { live?: boolean; chat?: calls.WebinarChat }, what: string) => {\n const next = await webinarApi().update(callExtId, body, linkVersion).catch(failed(what))\n setState(next)\n },\n [callExtId, linkVersion]\n )\n\n const stepDown = useCallback(async () => {\n // The server removes me during the request: that disconnect is a rejoin, not a leave.\n markRejoining(callExtId)\n setStageCheck(false)\n try {\n await webinarApi().demote(callExtId, myIdentity, linkVersion)\n } catch (err) {\n markRejoining(callExtId, false)\n failed('leave the stage')(err)\n }\n }, [callExtId, myIdentity, linkVersion])\n\n const joinStage = useCallback(\n async (choices: JoinChoices) => {\n const lp = room.localParticipant\n try {\n await lp.setMicrophoneEnabled(\n choices.audioEnabled,\n choices.audioDeviceId ? { deviceId: choices.audioDeviceId } : undefined\n )\n await lp.setCameraEnabled(\n choices.videoEnabled,\n choices.videoDeviceId ? { deviceId: choices.videoDeviceId } : undefined\n )\n } catch (err) {\n failed('turn on your microphone or camera')(err)\n }\n setStageCheck(false)\n },\n [room]\n )\n\n const questionAction = useCallback(\n async (run: () => Promise<unknown>, what: string) => {\n await run().catch(failed(what))\n // Everyone (me too) also gets `questions` from the server; this makes my own change instant.\n void refreshQuestions()\n },\n [refreshQuestions]\n )\n\n return useMemo<WebinarControl>(\n () => ({\n enabled,\n role,\n moderator: !!role && calls.WEBINAR_MODERATORS.has(role),\n team: !!role && calls.WEBINAR_TEAM.has(role),\n live: !!state?.live,\n chat: state?.chat ?? 'panelists',\n onStage,\n handRaised: !!state?.hand_raised,\n hands: state?.hands ?? [],\n attendees: state?.attendees ?? [],\n questions,\n stageCheck: enabled && stageCheck,\n refresh,\n goLive: () => patch({ live: true }, 'go live'),\n end: () => patch({ live: false }, 'end the webinar'),\n setChat: (chat) => patch({ chat }, 'change who can chat'),\n setHand: async (raised) => {\n const next = await webinarApi()\n .setHand(callExtId, raised, linkVersion)\n .catch(failed(raised ? 'raise your hand' : 'lower your hand'))\n setState(next)\n },\n promote: (identity) =>\n webinarApi()\n .promote(callExtId, identity, linkVersion)\n .catch(failed('bring them on stage'))\n .then(refresh),\n demote: (identity) =>\n webinarApi()\n .demote(callExtId, identity, linkVersion)\n .catch(failed('move them to the audience'))\n .then(refresh),\n stepDown,\n joinStage,\n ask: (text) =>\n questionAction(async () => {\n if (!callKey) throw new Error('This call has no key.')\n await webinarApi().questions.ask(\n callExtId,\n await sealQuestionText(text, callKey),\n linkVersion\n )\n }, 'ask the question'),\n vote: (id, up) =>\n questionAction(() => webinarApi().questions.vote(callExtId, id, up, linkVersion), 'vote'),\n setQuestionStatus: (id, status) =>\n questionAction(\n () => webinarApi().questions.update(callExtId, id, { status }, linkVersion),\n 'update the question'\n ),\n answer: (id, text) =>\n questionAction(async () => {\n if (!callKey) throw new Error('This call has no key.')\n await webinarApi().questions.update(\n callExtId,\n id,\n { answer: await sealQuestionText(text, callKey) },\n linkVersion\n )\n }, 'answer the question'),\n removeQuestion: (id) =>\n questionAction(\n () => webinarApi().questions.delete(callExtId, id, linkVersion),\n 'delete the question'\n ),\n }),\n [\n enabled,\n role,\n state,\n onStage,\n questions,\n stageCheck,\n refresh,\n patch,\n callExtId,\n linkVersion,\n callKey,\n stepDown,\n joinStage,\n questionAction,\n ]\n )\n}\n","/**\n * Inside <LiveKitRoom>: tell me when the host muted my mic or turned off my camera. Listens to the\n * server's `arbi.moderation` data messages (a packet sent by a participant is ignored — only the\n * server may moderate) and to WS `call.muted` for this call; one toast per mute.\n */\n\nimport { useEffect } from 'react'\nimport { RoomEvent, type RemoteParticipant } from 'livekit-client'\nimport { useRoomContext } from '@livekit/components-react'\nimport { notify } from '../../notifications/notify-store'\nimport { CALL_MODERATION_TOPIC, createMutedNotifier, mutedNoticeFromPacket, onCallEvent } from '..'\n\nexport function useHostMuteNotice(callExtId: string): void {\n const room = useRoomContext()\n useEffect(() => {\n const notifyMuted = createMutedNotifier((text) => notify.info(text))\n const onData = (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n _encryption?: unknown,\n participantIdentity?: string\n ) => {\n if (topic !== CALL_MODERATION_TOPIC) return\n // Only the server moderates: a packet from a participant is ignored.\n if (participant || participantIdentity) return\n const notice = mutedNoticeFromPacket(payload)\n if (notice) notifyMuted(notice)\n }\n room.on(RoomEvent.DataReceived, onData)\n const offWs = onCallEvent('call.muted', (message) => {\n if (message.callExtId === callExtId) notifyMuted(message)\n })\n return () => {\n room.off(RoomEvent.DataReceived, onData)\n offWs()\n }\n }, [room, callExtId])\n}\n"]}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/host/context.ts
|
|
6
|
+
var ArbiHostContext = react.createContext({});
|
|
7
|
+
function useHostConfigRecord() {
|
|
8
|
+
return react.useContext(ArbiHostContext);
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
// src/ai/normalize-citations.ts
|
|
4
12
|
var SOURCE_RESIDUE = /\(\*+\s*(Sources?\s*:[^\n]*?)\s*\*+\)/g;
|
|
5
13
|
var CITE_CLOSE = /^\]\((#cite-[\w-]+)\)/;
|
|
@@ -170,8 +178,10 @@ function closeOpenEmphasis(markdown) {
|
|
|
170
178
|
return head + line + "**";
|
|
171
179
|
}
|
|
172
180
|
|
|
181
|
+
exports.ArbiHostContext = ArbiHostContext;
|
|
173
182
|
exports.closeOpenEmphasis = closeOpenEmphasis;
|
|
174
183
|
exports.normalizeCitationMarkup = normalizeCitationMarkup;
|
|
175
184
|
exports.trimOpenCitation = trimOpenCitation;
|
|
176
|
-
|
|
177
|
-
//# sourceMappingURL=chunk-
|
|
185
|
+
exports.useHostConfigRecord = useHostConfigRecord;
|
|
186
|
+
//# sourceMappingURL=chunk-5NOZDH3F.cjs.map
|
|
187
|
+
//# sourceMappingURL=chunk-5NOZDH3F.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/host/context.ts","../src/ai/normalize-citations.ts"],"names":["createContext","useContext"],"mappings":"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","file":"chunk-5NOZDH3F.cjs","sourcesContent":["/**\n * The host configuration's React context: one value for the whole tree, set by `<ArbiHost>`\n * (./ArbiHost.tsx). It is untyped here so the SDK-free slices (`/ui`, `/shell`, the blocks root)\n * can read their part (`dictate`, `environment`) without reaching the SDK's types; the typed read\n * is `useArbiHost()` (react) and `useHost()` (blocks).\n */\n\nimport { createContext, useContext } from 'react'\n\n/** The host configuration as stored: see `ArbiHostConfig`. */\nexport type HostConfigRecord = Readonly<Record<string, unknown>>\n\nexport const ArbiHostContext = createContext<HostConfigRecord>({})\n\n/** The host configuration in scope, untyped (`{}` outside an `<ArbiHost>`). */\nexport function useHostConfigRecord(): HostConfigRecord {\n return useContext(ArbiHostContext)\n}\n","/**\n * Citation markup normaliser.\n *\n * The backend marks a cited statement as a markdown link, `[statement](#cite-N)`, and the\n * statement can include the markdown that surrounds it: a list marker, a heading marker or the\n * opener of a bold/italic span whose closer sits after the link. Inside link text those tokens\n * are not parsed as block or inline syntax, so they show literally and break lists and bold:\n *\n * [- **Claimed quantum (by Claimant)](#cite-1):** **USD 47 million**\n *\n * `normalizeCitationMarkup` hoists the leading tokens out of the link text (and a trailing\n * emphasis closer after it), so the link only wraps the words:\n *\n * - **[Claimed quantum (by Claimant)](#cite-1):** **USD 47 million**\n *\n * It is conservative: emphasis that opens and closes inside the link text is valid markdown and\n * is left alone, an opener is only hoisted when its closer follows on the same line, and fenced\n * code blocks are never touched. The result is idempotent.\n *\n * It also tidies the residue the model leaves when it cites in prose as well: a literal\n * `(*Source: Award.pdf, p. 12*)` shows its asterisks, because `(*` does not open emphasis. It\n * becomes the italic note `*(Source: Award.pdf, p. 12)*`.\n */\n\nconst SOURCE_RESIDUE = /\\(\\*+\\s*(Sources?\\s*:[^\\n]*?)\\s*\\*+\\)/g\n\nconst CITE_CLOSE = /^\\]\\((#cite-[\\w-]+)\\)/\nconst BLOCK_MARKER = /^(?:[-*+]|\\d{1,9}[.)]|#{1,6})[ \\t]+/\nconst LEADING_EMPHASIS = /^(?:\\*\\*|__|\\*|_)+/\nconst TRAILING_EMPHASIS = /(\\*\\*|__|\\*|_)(:?)$/\n\n/** Occurrences of `token` in `text`; a single `*` is counted outside any `**` pair. */\nfunction countToken(text: string, token: string): number {\n const double = token + token\n if (token.length === 2) return text.split(token).length - 1\n const withoutDouble = text.split(double).join('')\n return withoutDouble.split(token).length - 1\n}\n\n/** Split a run of emphasis characters (`***`, `**`, `*`...) into its parser-level tokens. */\nfunction emphasisTokens(run: string): string[] {\n const char = run[0]\n const tokens: string[] = []\n let rest = run\n while (rest.length > 0) {\n const size = rest.length >= 2 ? 2 : 1\n tokens.push(char.repeat(size))\n rest = rest.slice(size)\n }\n return tokens\n}\n\nfunction hoistFromLink(text: string, before: string, after: string): [string, string, string] {\n let body = text\n let prefix = ''\n let suffix = ''\n\n if (before.trim() === '') {\n const marker = BLOCK_MARKER.exec(body)\n if (marker) {\n prefix += marker[0]\n body = body.slice(marker[0].length)\n }\n }\n\n // The link opened inside an emphasis span: `*Sources:[* Letter](#cite-2)`. A leading token that\n // the text before the link left open, and that is followed by a space, is the span's CLOSER (an\n // opener cannot precede a space), so it moves out in front of the link with its space.\n const closer = /^(\\*\\*|__|\\*|_)(\\s+)(?=\\S)/.exec(body)\n if (closer && countToken(before + prefix, closer[1]) % 2 === 1) {\n prefix += closer[1] + closer[2]\n body = body.slice(closer[0].length)\n }\n\n const leading = LEADING_EMPHASIS.exec(body)\n if (leading) {\n let kept = ''\n let rest = body.slice(leading[0].length)\n for (const token of emphasisTokens(leading[0]).reverse()) {\n // Balanced inside the link text: valid as written.\n if (countToken(rest, token) % 2 === 1) {\n kept = token + kept\n continue\n }\n // Unmatched here: hoist only if the line closes it after the link.\n if (countToken(after, token) % 2 === 1) prefix += token\n else kept = token + kept\n }\n body = kept + rest\n rest = ''\n }\n\n // A span opened before the link and closed inside it (`**Spence v. [Costa Rica** arbitration.]`)\n // cannot close across the link boundary: move the words up to the closer out of the link.\n for (const token of ['**', '__']) {\n const at = body.indexOf(token)\n if (at === -1 || countToken(body, token) % 2 === 0) continue\n if (countToken(before + prefix, token) % 2 === 0) continue\n const rest = body.slice(at + token.length)\n if (!/[\\p{L}\\p{N}]/u.test(rest)) continue\n prefix +=\n body.slice(0, at + token.length) + rest.slice(0, rest.length - rest.trimStart().length)\n body = rest.trimStart()\n break\n }\n\n const trailing = TRAILING_EMPHASIS.exec(body)\n if (trailing) {\n const token = trailing[1]\n const inner = body.slice(0, body.length - trailing[0].length)\n const openedBefore = countToken(before + prefix, token) % 2 === 1\n if (countToken(inner, token) % 2 === 0 && openedBefore) {\n body = inner\n suffix = trailing[0]\n }\n }\n\n // The link ends inside an emphasis span that closes after it: `*(Source](#cite-1): a.md)*`. The\n // unmatched opener and the words after it leave the link, so the span opens and closes in the\n // same text again: `[words](#cite-1) *(Source: a.md)*`.\n if (!suffix) {\n for (const token of ['**', '*']) {\n const at = lastUnmatchedOpener(body, token)\n if (at > 0 && countToken(after, token) % 2 === 1) {\n suffix = ' ' + body.slice(at)\n body = body.slice(0, at).trimEnd()\n break\n }\n }\n }\n\n return [prefix, body, suffix]\n}\n\n/** Index of the last `token` in `text` that opens emphasis (followed by a non-space) and has no closer. */\nfunction lastUnmatchedOpener(text: string, token: string): number {\n if (countToken(text, token) % 2 === 0) return -1\n const pattern = token === '**' ? /\\*\\*(?=\\S)/g : /(?<!\\*)\\*(?![*\\s])/g\n let at = -1\n for (const m of text.matchAll(pattern)) at = m.index ?? -1\n return at\n}\n\ninterface CiteLink {\n start: number\n end: number\n text: string\n href: string\n}\n\n/**\n * The `[text](#cite-N)` links of a line. The text may hold brackets of its own\n * (`[2. **[PLACEHOLDER]** names the claimant.](#cite-3)`), so a regex cannot find the opener: a\n * stack of `[` is scanned, and a `](#cite-N)` takes the nearest open one.\n */\nfunction findCiteLinks(line: string): CiteLink[] {\n const links: CiteLink[] = []\n const open: number[] = []\n for (let i = 0; i < line.length; i++) {\n const c = line[i]\n if (c === '[') open.push(i)\n else if (c === ']') {\n const opener = open.pop()\n const close = CITE_CLOSE.exec(line.slice(i, i + 40))\n if (opener !== undefined && close) {\n links.push({\n start: opener,\n end: i + close[0].length,\n text: line.slice(opener + 1, i),\n href: close[1],\n })\n i += close[0].length - 1\n }\n }\n }\n return links.sort((x, y) => x.start - y.start)\n}\n\nfunction normalizeLine(line: string): string {\n if (!line.includes('](#cite-')) return line\n let out = ''\n let last = 0\n for (const link of findCiteLinks(line)) {\n // A link inside another link's text is part of that text.\n if (link.start < last) continue\n // Markdown links do not nest: a citation that wraps another citation (`[a [9](#cite-9)](#cite-10)`)\n // keeps the words and the inner mark, and the outer wrapper is dropped.\n if (link.text.includes('](#cite-')) {\n out += line.slice(last, link.start) + link.text\n last = link.end\n continue\n }\n const before = line.slice(0, link.start)\n const after = line.slice(link.end)\n const [prefix, body, suffix] = hoistFromLink(link.text, before, after)\n out += line.slice(last, link.start)\n out += `${prefix}[${body}](${link.href})${suffix}`\n last = link.end\n }\n return out + line.slice(last)\n}\n\nfunction normalizeSourceResidue(line: string): string {\n return line.includes('(*') ? line.replace(SOURCE_RESIDUE, '*($1)*') : line\n}\n\nexport function normalizeCitationMarkup(markdown: string): string {\n if (!markdown.includes('](#cite-') && !markdown.includes('(*')) return markdown\n let inFence = false\n return markdown\n .split('\\n')\n .map((line) => {\n if (/^\\s*(```|~~~)/.test(line)) {\n inFence = !inFence\n return line\n }\n return inFence ? line : normalizeSourceResidue(normalizeLine(line))\n })\n .join('\\n')\n}\n\n/** A trailing, still-open `[words](#cite-N` marker (or an unclosed `[words`) on the last line. */\nconst OPEN_CITATION_TAIL = /\\[[^\\]\\n]*(?:\\](?:\\((?:#(?:c(?:i(?:t(?:e(?:-[\\w-]*)?)?)?)?)?)?)?)?$/\n\n/**\n * Drops an unfinished citation marker from the end of text that is still streaming (or was\n * stopped mid-marker), so `[Change of control](#cite-` never shows as raw markup: the words appear\n * once the marker is complete. Complete markers and everything else are left alone.\n */\nexport function trimOpenCitation(markdown: string): string {\n return markdown.replace(OPEN_CITATION_TAIL, '')\n}\n\n/** `**` pairs outside inline code in a line. */\nfunction boldMarks(line: string): number {\n return (line.replace(/`[^`]*`/g, '').match(/\\*\\*/g) ?? []).length\n}\n\n/**\n * Makes the tail of text that is still streaming (or was stopped) render cleanly: a `**` opened\n * in the last line and not yet closed (`| Valuation | **[USD 6.2 million](#cite-2)`) would show as\n * literal asterisks until its closer arrives, because an unclosed emphasis is not emphasis. The\n * open bold is closed at the end of the line, or removed when it has no text yet (`| **`, or a\n * half-typed closer `**USD 6*`). Text with balanced emphasis, and every line but the last, is\n * left alone. Apply after `trimOpenCitation`.\n */\nexport function closeOpenEmphasis(markdown: string): string {\n const cut = markdown.lastIndexOf('\\n') + 1\n const head = markdown.slice(0, cut)\n const fences = head.split('\\n').filter((l) => /^\\s*(```|~~~)/.test(l)).length\n let line = markdown.slice(cut)\n if (fences % 2 === 1 || /^\\s*(```|~~~)/.test(line)) return markdown\n // A half-typed opener: the first `*` of `**` after a space or a cell border.\n line = line.replace(/(^|[\\s|])\\*$/, '$1')\n if (boldMarks(line) % 2 === 0) return head + line\n // A half-typed closer: `**USD 6*` -> the second asterisk has not arrived.\n line = line.replace(/([^*\\s])\\*$/, '$1')\n if (boldMarks(line) % 2 === 0) return head + line\n if (/\\*\\*\\s*$/.test(line)) return head + line.replace(/\\s*\\*\\*\\s*$/, ' ')\n return head + line + '**'\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { clearSealedDrafts, useWorkspaces } from './chunk-
|
|
2
|
-
import { arbiQueryKeys, callQueryKeys } from './chunk-
|
|
3
|
-
import {
|
|
4
|
-
import { notify, clearChatArtifacts } from './chunk-G4Z3IP4J.js';
|
|
1
|
+
import { clearSealedDrafts, useWorkspaces } from './chunk-KTXZ222T.js';
|
|
2
|
+
import { useArbi, arbiQueryKeys, useArbiHost, callQueryKeys } from './chunk-BFNY3RZG.js';
|
|
3
|
+
import { notify, clearChatArtifacts } from './chunk-BF5KW5ZI.js';
|
|
5
4
|
import { getUserDisplayName, DEFAULT_SEGMENTER_CONFIG, INITIAL_SEGMENTER_STATE, flushSegmenter, stepSegmenter, levelFromRms } from './chunk-APZZQZ6P.js';
|
|
6
5
|
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
7
6
|
import { useSyncExternalStore, useEffect, useState, useCallback, useMemo } from 'react';
|
|
@@ -2475,5 +2474,5 @@ function useOpenCallMeetingChat() {
|
|
|
2475
2474
|
}
|
|
2476
2475
|
|
|
2477
2476
|
export { AUDIENCE_CHOICES, CALL_CAPTION_TOPIC, CALL_CHAT_MAX_CHARS, CALL_CHAT_TOPIC, CALL_MODERATION_TOPIC, CALL_RECORDING_TOPIC, CALL_TRANSCRIPTION_TOPIC, CALL_WEBINAR_TOPIC, CAPTION_MAX_CHARS, COMPOSITE_AUDIO_BITS_PER_SECOND, COMPOSITE_VIDEO_BITS_PER_SECOND, DEFAULT_JOIN_CHOICES, EMPTY_CALL_SESSION, EXPORT_SAMPLE_RATE, HISTORY_LIMIT, LIVE_SEGMENTER, MAX_AVATAR_FILE_BYTES, MUTED_DEDUPE_MS, PLAYBACK_LOOKAHEAD_MS, READ_ONLY_MEETING_TEXT, RECORDING_CHUNK_MS, RECORDING_SEGMENTER, SEGMENT_FRAME_MS, SEGMENT_ID_PATTERN, SEGMENT_PRE_ROLL_MS, SHORT_PIECE_MERGE_GAP_MS, SPEAKER_AUDIO_BITS_PER_SECOND, TrackUploader, UPLOAD_ATTEMPTS, UPLOAD_BACKOFF_MS, acceptRing, addConversationToList, appendToThread, applyAgentDmStatus, applyCallEvent, applyChatEvent, applyChatMessage, applyChatRead, applyChatUpdated, arbiAccountClient, buildMeetingChatBody, cachedChat, cachedChats, callLink, callMemberKeys, callSession, chatByExtId, chatHasLiveCall, chatLiveCallId, chatTranscriptRef, clearMeetingChatCache, clearTrackUploaders, clockTime, compositeFiles, compositeTrack, conversationKeyForCall, createLocalFeatureStore, createMutedNotifier, createTrackCutter, cutAtPauses, declineRing, decodeCallChatPacket, decodeCaptionPacket, decodeMono16k, decryptPart, deleteChatMessage, dropFromThread, encodeCallChatPacket, encodeCaptionPacket, encodeWav, encryptPart, ensureMeetingChat, entitlementRefusal, extensionFor, fetchPart, fileSafe, findConversation, floatToWav, formatTranscriptMarkdown, getOpenChat, hasRecordingTranscript, invalidateCall, invalidateConversationDetails, invalidateConversationLists, isConversationListKey, isConversationShared, isRecordingOver, isRecordingSegmentId, isRetryable, isWorkspaceGuestOf, joinFromPreJoin, knownMeetingChat, loadMeetingHistory, markRejoining, meetingChatRefFrom, meetingRefForCall, mergeChatLines, mutedNoticeFromEvent, mutedNoticeFromPacket, mutedNoticeText, myChatId, newPacketId, newSegmentId, newTrackKey, nextSeqAfter, onCallEvent, openCall, openQuestion, openRecording, parseWebinarPacket, partKey, partOffsetMs, partsDue, patchConversation, patchConversationList, persistMeetingMessage, persistTranscriptSegment, playheadAt, postRecordingDocsToThread, postTranscriptToThread, readLocalFeature, recordingFiles, recordingWindowsOf, rejoinAsAudience, removeChat, removeConversationFromLists, resetCallSession, resolveMeetingChat, saveRecordingFilesToThread, schedulePart, sealQuestionText, serverCallsExperimental, setOpenChat, sortTranscriptMessages, sortedParts, speakerTracks, speakerWav, splitIntoFiles, standalone, startChatCall, startContactsCall, startDmCall, startThreadCall, startsMediaFile, storeTranscriptSegment, stripSpeakerPrefix, supersedeLiveTranscript, supersededTranscriptLines, threadHasLiveCall, threadLiveCallId, threadTranscriptLines, threadTranscriptRef, threadTranscriptText, timelineDurationMs, timelineOf, toProfileView, trackUploaderFor, transcribeRecording, transcriptPersistRole, transcriptSegmentOf, unwrapTrackKey, upsertChat, useAccountClient, useAvatarCrop, useCall, useCallInviteLinks, useCallRecording, useCallRecordings, useCallSession, useCallTranscriptionAvailable, useCallsConfig, useCallsEnabled, useCanHostCalls, useEntitlements, useFeature, useFeatureSwitch, useInvalidateEntitlements, useIsEntitled, useMeetingReadOnly, useNameEditor, useOpenCallMeetingChat, useProfile, useRecordingActions, useRecordingWindows, useRevokeCallInviteLink, useSaveToThread, useServerCallsEnabled, useServerCallsExperimental, useUpdateProfile, useUpdateUserSettings, useUserSettings, wrapTrackKey, writeSamples };
|
|
2478
|
-
//# sourceMappingURL=chunk-
|
|
2479
|
-
//# sourceMappingURL=chunk-
|
|
2477
|
+
//# sourceMappingURL=chunk-73ENECAT.js.map
|
|
2478
|
+
//# sourceMappingURL=chunk-73ENECAT.js.map
|