@arbidocs/blocks 0.5.2 → 0.5.4
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/dist/{ConnectedCallDock-NNX5PEPK.cjs → ConnectedCallDock-Q7GSQICC.cjs} +6 -6
- package/dist/{ConnectedCallDock-NNX5PEPK.cjs.map → ConnectedCallDock-Q7GSQICC.cjs.map} +1 -1
- package/dist/{ConnectedCallDock-UGGY6YUK.js → ConnectedCallDock-XCTBUJOT.js} +5 -5
- package/dist/{ConnectedCallDock-UGGY6YUK.js.map → ConnectedCallDock-XCTBUJOT.js.map} +1 -1
- package/dist/{ConnectedCallRoom-B7SZHQNV.cjs → ConnectedCallRoom-T6PGW6VC.cjs} +6 -6
- package/dist/{ConnectedCallRoom-B7SZHQNV.cjs.map → ConnectedCallRoom-T6PGW6VC.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-I4HPWMK2.js → ConnectedCallRoom-W2AHTPYR.js} +5 -5
- package/dist/{ConnectedCallRoom-I4HPWMK2.js.map → ConnectedCallRoom-W2AHTPYR.js.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-CWEW7GV3.js → ConnectedNativeDocxComparison-4MI22H2R.js} +10 -10
- package/dist/{ConnectedNativeDocxComparison-CWEW7GV3.js.map → ConnectedNativeDocxComparison-4MI22H2R.js.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-A7PMTYD7.cjs → ConnectedNativeDocxComparison-VZLB7WWW.cjs} +11 -11
- package/dist/{ConnectedNativeDocxComparison-A7PMTYD7.cjs.map → ConnectedNativeDocxComparison-VZLB7WWW.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-IWXEOAIF.cjs → ConnectedNativeDocxEditor-74PFGTMR.cjs} +11 -11
- package/dist/{ConnectedNativeDocxEditor-IWXEOAIF.cjs.map → ConnectedNativeDocxEditor-74PFGTMR.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-6EBF7U4E.js → ConnectedNativeDocxEditor-YBHAQQSY.js} +9 -9
- package/dist/{ConnectedNativeDocxEditor-6EBF7U4E.js.map → ConnectedNativeDocxEditor-YBHAQQSY.js.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-WRGCCU5H.cjs → ConnectedStreamedWordArtifact-63ME4QD5.cjs} +11 -11
- package/dist/ConnectedStreamedWordArtifact-63ME4QD5.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-27ISQYHI.js → ConnectedStreamedWordArtifact-ELHQ2VYL.js} +10 -10
- package/dist/ConnectedStreamedWordArtifact-ELHQ2VYL.js.map +1 -0
- package/dist/agents/index.cjs +328 -328
- package/dist/agents/index.js +6 -6
- package/dist/calls/index.cjs +39 -39
- package/dist/calls/index.js +7 -7
- package/dist/chat/DraftingDocChip.d.ts +23 -7
- package/dist/chat/index.cjs +63 -63
- package/dist/chat/index.js +1 -1
- package/dist/{chunk-QK2HR3LC.js → chunk-2A2QX3MS.js} +3 -3
- package/dist/{chunk-QK2HR3LC.js.map → chunk-2A2QX3MS.js.map} +1 -1
- package/dist/{chunk-JBG5MFVX.cjs → chunk-2CTG4DHL.cjs} +5 -5
- package/dist/{chunk-JBG5MFVX.cjs.map → chunk-2CTG4DHL.cjs.map} +1 -1
- package/dist/{chunk-PSBZ65VU.cjs → chunk-2ETLLFQV.cjs} +4 -4
- package/dist/{chunk-PSBZ65VU.cjs.map → chunk-2ETLLFQV.cjs.map} +1 -1
- package/dist/{chunk-ULQV2NJT.js → chunk-3FKM4G2T.js} +46 -9
- package/dist/chunk-3FKM4G2T.js.map +1 -0
- package/dist/{chunk-VMXLNBHF.js → chunk-3IQUMSJI.js} +3 -3
- package/dist/{chunk-VMXLNBHF.js.map → chunk-3IQUMSJI.js.map} +1 -1
- package/dist/{chunk-LMXMUWPA.cjs → chunk-3LDVSHRD.cjs} +4 -4
- package/dist/{chunk-LMXMUWPA.cjs.map → chunk-3LDVSHRD.cjs.map} +1 -1
- package/dist/{chunk-5D32XL3E.cjs → chunk-54RSCDE6.cjs} +7 -7
- package/dist/{chunk-5D32XL3E.cjs.map → chunk-54RSCDE6.cjs.map} +1 -1
- package/dist/{chunk-ID2EVM5M.cjs → chunk-67L2XS3P.cjs} +4 -4
- package/dist/{chunk-ID2EVM5M.cjs.map → chunk-67L2XS3P.cjs.map} +1 -1
- package/dist/{chunk-2BNWISLH.cjs → chunk-6HPBSKXG.cjs} +4 -4
- package/dist/{chunk-2BNWISLH.cjs.map → chunk-6HPBSKXG.cjs.map} +1 -1
- package/dist/{chunk-25YFJLFP.cjs → chunk-6TJQTDQI.cjs} +2 -2
- package/dist/{chunk-25YFJLFP.cjs.map → chunk-6TJQTDQI.cjs.map} +1 -1
- package/dist/{chunk-ZC5MJIRC.js → chunk-7KAJKYA7.js} +3 -3
- package/dist/{chunk-ZC5MJIRC.js.map → chunk-7KAJKYA7.js.map} +1 -1
- package/dist/{chunk-2RSUVU5V.js → chunk-AQ2XKOQ7.js} +3 -3
- package/dist/{chunk-2RSUVU5V.js.map → chunk-AQ2XKOQ7.js.map} +1 -1
- package/dist/{chunk-QEE4DOEU.cjs → chunk-AY66THUZ.cjs} +18 -18
- package/dist/{chunk-QEE4DOEU.cjs.map → chunk-AY66THUZ.cjs.map} +1 -1
- package/dist/{chunk-UIZZFZ5Z.cjs → chunk-BYCGAAV5.cjs} +5 -5
- package/dist/{chunk-UIZZFZ5Z.cjs.map → chunk-BYCGAAV5.cjs.map} +1 -1
- package/dist/{chunk-YBB3KRTU.cjs → chunk-CIJUKCZI.cjs} +7 -7
- package/dist/{chunk-YBB3KRTU.cjs.map → chunk-CIJUKCZI.cjs.map} +1 -1
- package/dist/{chunk-P2ZB2WTE.js → chunk-D7YJY3JW.js} +3 -3
- package/dist/{chunk-P2ZB2WTE.js.map → chunk-D7YJY3JW.js.map} +1 -1
- package/dist/{chunk-DRLRR44Q.js → chunk-FEYRHZYB.js} +6 -6
- package/dist/{chunk-DRLRR44Q.js.map → chunk-FEYRHZYB.js.map} +1 -1
- package/dist/{chunk-CNHLPFFK.cjs → chunk-HSAEIBRA.cjs} +4 -4
- package/dist/{chunk-CNHLPFFK.cjs.map → chunk-HSAEIBRA.cjs.map} +1 -1
- package/dist/{chunk-MQIUL32N.cjs → chunk-IFEQSARV.cjs} +5 -5
- package/dist/{chunk-MQIUL32N.cjs.map → chunk-IFEQSARV.cjs.map} +1 -1
- package/dist/{chunk-OD3UJ7XR.js → chunk-IK4AWPDW.js} +3 -3
- package/dist/{chunk-OD3UJ7XR.js.map → chunk-IK4AWPDW.js.map} +1 -1
- package/dist/{chunk-JANBEB7P.js → chunk-K35QAFR7.js} +3 -3
- package/dist/{chunk-JANBEB7P.js.map → chunk-K35QAFR7.js.map} +1 -1
- package/dist/{chunk-PAW2PC2M.cjs → chunk-L22BJYHL.cjs} +11 -11
- package/dist/{chunk-PAW2PC2M.cjs.map → chunk-L22BJYHL.cjs.map} +1 -1
- package/dist/{chunk-PY5D6HBD.js → chunk-LSKTOCKN.js} +5 -5
- package/dist/{chunk-PY5D6HBD.js.map → chunk-LSKTOCKN.js.map} +1 -1
- package/dist/{chunk-ZSW6FZG5.cjs → chunk-M6Z7HTJ2.cjs} +8 -8
- package/dist/{chunk-ZSW6FZG5.cjs.map → chunk-M6Z7HTJ2.cjs.map} +1 -1
- package/dist/{chunk-LDD7NXIQ.js → chunk-M7EI5V6H.js} +3 -3
- package/dist/{chunk-LDD7NXIQ.js.map → chunk-M7EI5V6H.js.map} +1 -1
- package/dist/{chunk-J6JED6TA.cjs → chunk-M7LMEVXY.cjs} +52 -52
- package/dist/{chunk-J6JED6TA.cjs.map → chunk-M7LMEVXY.cjs.map} +1 -1
- package/dist/{chunk-BMFXDDJG.cjs → chunk-NJ72FUE2.cjs} +9 -9
- package/dist/{chunk-BMFXDDJG.cjs.map → chunk-NJ72FUE2.cjs.map} +1 -1
- package/dist/{chunk-KRNX2PVC.js → chunk-PG5A6DJY.js} +3 -3
- package/dist/{chunk-KRNX2PVC.js.map → chunk-PG5A6DJY.js.map} +1 -1
- package/dist/{chunk-YSNQWUQQ.js → chunk-PISYMKGS.js} +5 -5
- package/dist/{chunk-YSNQWUQQ.js.map → chunk-PISYMKGS.js.map} +1 -1
- package/dist/{chunk-GKM4EOH7.js → chunk-PKB4LBPC.js} +2 -2
- package/dist/{chunk-GKM4EOH7.js.map → chunk-PKB4LBPC.js.map} +1 -1
- package/dist/{chunk-MDFXGRLY.cjs → chunk-PSTA227J.cjs} +26 -26
- package/dist/{chunk-MDFXGRLY.cjs.map → chunk-PSTA227J.cjs.map} +1 -1
- package/dist/{chunk-F66OH26L.cjs → chunk-PU7CEHTL.cjs} +45 -8
- package/dist/chunk-PU7CEHTL.cjs.map +1 -0
- package/dist/{chunk-5DXTO7CE.cjs → chunk-QGSVHWXR.cjs} +6 -6
- package/dist/{chunk-5DXTO7CE.cjs.map → chunk-QGSVHWXR.cjs.map} +1 -1
- package/dist/{chunk-QE7MS7NA.js → chunk-QH4OY5GP.js} +3 -3
- package/dist/{chunk-QE7MS7NA.js.map → chunk-QH4OY5GP.js.map} +1 -1
- package/dist/{chunk-IFAIUKQQ.cjs → chunk-QIY3ZHD2.cjs} +4 -4
- package/dist/{chunk-IFAIUKQQ.cjs.map → chunk-QIY3ZHD2.cjs.map} +1 -1
- package/dist/{chunk-7GAS4N7L.js → chunk-RC2REIM4.js} +3 -3
- package/dist/{chunk-7GAS4N7L.js.map → chunk-RC2REIM4.js.map} +1 -1
- package/dist/{chunk-BWKBLCWC.js → chunk-S4KPVLHO.js} +3 -3
- package/dist/{chunk-BWKBLCWC.js.map → chunk-S4KPVLHO.js.map} +1 -1
- package/dist/{chunk-RMLU363Q.cjs → chunk-TUODUKDK.cjs} +4 -4
- package/dist/{chunk-RMLU363Q.cjs.map → chunk-TUODUKDK.cjs.map} +1 -1
- package/dist/{chunk-CSUKLEQH.js → chunk-TYOZWK4G.js} +4 -4
- package/dist/{chunk-CSUKLEQH.js.map → chunk-TYOZWK4G.js.map} +1 -1
- package/dist/{chunk-WYQKDE6S.js → chunk-TZHPRK4H.js} +3 -3
- package/dist/{chunk-WYQKDE6S.js.map → chunk-TZHPRK4H.js.map} +1 -1
- package/dist/{chunk-IMTJFBDC.cjs → chunk-VBMNPJDD.cjs} +4 -4
- package/dist/{chunk-IMTJFBDC.cjs.map → chunk-VBMNPJDD.cjs.map} +1 -1
- package/dist/{chunk-6YI6BC6L.js → chunk-VDWZL5WT.js} +3 -3
- package/dist/{chunk-6YI6BC6L.js.map → chunk-VDWZL5WT.js.map} +1 -1
- package/dist/{chunk-AU6ZSYW6.js → chunk-VX5I35HZ.js} +3 -3
- package/dist/{chunk-AU6ZSYW6.js.map → chunk-VX5I35HZ.js.map} +1 -1
- package/dist/{chunk-EBRYYVNH.cjs → chunk-WB4B6TSW.cjs} +14 -14
- package/dist/{chunk-EBRYYVNH.cjs.map → chunk-WB4B6TSW.cjs.map} +1 -1
- package/dist/{chunk-34LBKTII.js → chunk-X5FS27BM.js} +6 -6
- package/dist/{chunk-34LBKTII.js.map → chunk-X5FS27BM.js.map} +1 -1
- package/dist/{chunk-HTOYFP3D.js → chunk-Z7KGBVKI.js} +5 -5
- package/dist/{chunk-HTOYFP3D.js.map → chunk-Z7KGBVKI.js.map} +1 -1
- package/dist/{chunk-TXPOODAY.js → chunk-Z7PVDIUN.js} +3 -3
- package/dist/{chunk-TXPOODAY.js.map → chunk-Z7PVDIUN.js.map} +1 -1
- package/dist/{chunk-3XA7EDPS.cjs → chunk-ZOUVLJLV.cjs} +12 -12
- package/dist/{chunk-3XA7EDPS.cjs.map → chunk-ZOUVLJLV.cjs.map} +1 -1
- package/dist/citations/index.cjs +10 -10
- package/dist/citations/index.js +2 -2
- package/dist/connect/docx.cjs +13 -13
- package/dist/connect/docx.js +9 -9
- package/dist/connect/index.cjs +740 -719
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +50 -29
- package/dist/connect/index.js.map +1 -1
- package/dist/connect/viewer.cjs +107 -78
- package/dist/connect/viewer.cjs.map +1 -1
- package/dist/connect/viewer.js +45 -16
- package/dist/connect/viewer.js.map +1 -1
- package/dist/facts/index.cjs +3 -3
- package/dist/facts/index.js +2 -2
- package/dist/files/index.cjs +223 -223
- package/dist/files/index.js +3 -3
- package/dist/home/index.cjs +30 -30
- package/dist/home/index.js +5 -5
- package/dist/index.cjs +512 -512
- package/dist/index.js +12 -12
- package/dist/provider/environment.d.ts +10 -3
- package/dist/retrieval/index.cjs +4 -4
- package/dist/retrieval/index.js +2 -2
- package/dist/shell/index.cjs +46 -46
- package/dist/shell/index.js +3 -3
- package/dist/studio/index.cjs +13 -13
- package/dist/studio/index.js +5 -5
- package/dist/workflow-canvas/index.cjs +26 -26
- package/dist/workflow-canvas/index.js +8 -8
- package/dist/workspaces/index.cjs +20 -20
- package/dist/workspaces/index.js +4 -4
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/src/docx/README.md +10 -6
- package/dist/ConnectedStreamedWordArtifact-27ISQYHI.js.map +0 -1
- package/dist/ConnectedStreamedWordArtifact-WRGCCU5H.cjs.map +0 -1
- package/dist/chunk-F66OH26L.cjs.map +0 -1
- package/dist/chunk-ULQV2NJT.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { HeaderAction, usePendingRecording, setPendingRecording, MODE_LABEL, formatCallDuration, CallUserPill, EXPIRY_DAYS, expiryFor, expiryChoiceOf, useMyCallStatus, useSpeakingIds, recordingLink } from './chunk-NNPFFPBF.js';
|
|
3
|
-
import { useConnectedConversations } from './chunk-
|
|
4
|
-
import { useConnectedWorkspace } from './chunk-
|
|
3
|
+
import { useConnectedConversations } from './chunk-7KAJKYA7.js';
|
|
4
|
+
import { useConnectedWorkspace } from './chunk-Z7PVDIUN.js';
|
|
5
5
|
import { EmptyState } from './chunk-P6GHJSLR.js';
|
|
6
|
-
import { useBlocksEnvironment } from './chunk-
|
|
6
|
+
import { useBlocksEnvironment } from './chunk-PKB4LBPC.js';
|
|
7
7
|
import { TranscriptLine, transcriptRuns, ProvisionalTranscriptLine } from './chunk-FXTNUJHP.js';
|
|
8
8
|
import { create } from 'zustand';
|
|
9
9
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
@@ -1010,5 +1010,5 @@ function threadTranscriptRuns(messages) {
|
|
|
1010
1010
|
}
|
|
1011
1011
|
|
|
1012
1012
|
export { CallConversationEmpty, PickThreadDialog, ProvisionalSpeakers, RecordingCard, RecordingsList, SaveTranscriptToThread, ThreadCallLogCard, TranscriptEntry, TranscriptRunsContext, requestCalendarComposer, requestCalendarEvent, threadTranscriptRuns, useCalendarViewStore, useCallPersonName, useMeetingThreadMessages, useProvisionalSpeakers, useTranscriptRuns };
|
|
1013
|
-
//# sourceMappingURL=chunk-
|
|
1014
|
-
//# sourceMappingURL=chunk-
|
|
1013
|
+
//# sourceMappingURL=chunk-PISYMKGS.js.map
|
|
1014
|
+
//# sourceMappingURL=chunk-PISYMKGS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection/calendar/store.ts","../src/connection/conversation/useMeetingThreadMessages.ts","../src/calls/connected/SaveTranscriptToThread.tsx","../src/calls/connected/RecordingCard.tsx","../src/calls/connected/ThreadCallLogCard.tsx","../src/calls/connected/TranscriptEntry.tsx","../src/calls/connected/call-person-name.ts","../src/calls/connected/CallConversationParts.tsx","../src/calls/connected/provisional-speakers.ts","../src/calls/connected/transcript-runs-context.ts"],"names":["useMemo","jsx","Fragment","jsxs","cn","useState","Button","useSaveToThread","useArbi","useCall","useCallSession","Captions","useRef","useEffect"],"mappings":"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","file":"chunk-YSNQWUQQ.js","sourcesContent":["/**\n * The connected calendar's view state: the chosen view is remembered across reloads (localStorage),\n * the anchor date lives for the session, and two requests carry intents from elsewhere into the\n * calendar once it mounts: an event to open (a deep link, a reminder) and a prefilled new event\n * (\"Schedule a call\" from a thread). The host navigates to its calendar page after making one.\n */\nimport { create } from 'zustand'\nimport { createJSONStorage, persist } from 'zustand/middleware'\nimport type { CalendarViewKind } from '../../calendar/types'\n\n/** \"Schedule a call\" from elsewhere (a thread, a DM, a dashboard): the editor opens prefilled. */\nexport interface CalendarComposerPrefill {\n title?: string\n attendees?: { email?: string | null; user_id?: string | null; name?: string | null }[]\n conversationId?: string | null\n /** Add an ARBI call when the event is saved (\"Add ARBI call\" ticked). */\n addCall?: boolean\n}\n\nexport interface PendingCalendarEvent {\n id: string\n recurrenceId?: string | null\n}\n\ninterface CalendarViewState {\n /** `null` until the user picks one: the settings' default view applies. */\n view: CalendarViewKind | null\n /** YYYY-MM-DD anchor; `null` = today. */\n date: string | null\n pendingEvent: PendingCalendarEvent | null\n pendingComposer: CalendarComposerPrefill | null\n setPendingComposer: (prefill: CalendarComposerPrefill | null) => void\n setView: (view: CalendarViewKind) => void\n setDate: (date: string | null) => void\n setPendingEvent: (pending: PendingCalendarEvent | null) => void\n}\n\nexport const useCalendarViewStore = create<CalendarViewState>()(\n persist(\n (set) => ({\n view: null,\n date: null,\n pendingEvent: null,\n pendingComposer: null,\n setPendingComposer: (pendingComposer) => set({ pendingComposer }),\n setView: (view) => set({ view }),\n setDate: (date) => set({ date }),\n setPendingEvent: (pendingEvent) => set({ pendingEvent }),\n }),\n {\n name: 'arbi-calendar-view',\n storage: createJSONStorage(() => localStorage),\n partialize: (s) => ({ view: s.view }),\n }\n )\n)\n\nconst EVT_RE = /^evt-[A-Za-z0-9]{8}$/\n\n/** Ask the calendar to open on an event (ignored unless it is an `evt-` id). */\nexport function requestCalendarEvent(event: PendingCalendarEvent): void {\n if (EVT_RE.test(event.id)) useCalendarViewStore.getState().setPendingEvent(event)\n}\n\n/** Ask the calendar to open the event editor prefilled. */\nexport function requestCalendarComposer(prefill: CalendarComposerPrefill): void {\n useCalendarViewStore.getState().setPendingComposer(prefill)\n}\n","/**\n * A conversation's messages as its thread shows them: in a call's meeting thread, a recording's\n * transcript supersedes the live lines spoken while it recorded (else both would show).\n */\nimport { useMemo } from 'react'\nimport {\n hasRecordingTranscript,\n supersedeLiveTranscript,\n threadTranscriptRef,\n useRecordingWindows,\n} from '@arbidocs/react'\nimport type { ChatMessage } from '@arbidocs/sdk/browser'\n\nexport function useMeetingThreadMessages(\n meetingCallExtId: string | null,\n messageHistory: ChatMessage[]\n): ChatMessage[] {\n const hasRecTranscript = useMemo(\n () => !!meetingCallExtId && hasRecordingTranscript(messageHistory, threadTranscriptRef),\n [meetingCallExtId, messageHistory]\n )\n const recordingWindows = useRecordingWindows(meetingCallExtId, hasRecTranscript)\n return useMemo(\n () =>\n hasRecTranscript\n ? supersedeLiveTranscript(messageHistory, threadTranscriptRef, recordingWindows)\n : messageHistory,\n [hasRecTranscript, messageHistory, recordingWindows]\n )\n}\n","/**\n * Host action \"Save transcript to thread\": the meeting chat's transcript is decrypted here, in the\n * host's browser, and posted as ONE attributed transcript comment (title, date, then\n * `Speaker [hh:mm:ss]: text` lines) into a workspace thread the host picks — a shared thread of the\n * current workspace they can post in, or a new one. The thread is encrypted with the workspace key\n * like any comment; the meeting chat itself is unchanged and nobody outside it gains access to it.\n */\n\nimport { useSaveToThread, useWorkspaces, type TranscriptExportLine } from '@arbidocs/react'\nimport { useMemo, useState, type ReactElement, type ReactNode } from 'react'\nimport { FileText } from 'lucide-react'\nimport {\n Button,\n cn,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@arbidocs/react/ui'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { useConnectedConversations } from '../../connection/workspaceData'\nimport { HeaderAction } from '../HeaderAction'\n\nconst NEW_THREAD = '__new__'\n\n/** The open workspace and my role in it (the threads I can post in are its shared ones). */\nfunction useCurrentWorkspace() {\n const { workspaceId, userId } = useConnectedWorkspace()\n const { data: workspaces } = useWorkspaces()\n const workspace = workspaces?.find((w) => w.external_id === workspaceId)\n const role = workspace?.users?.find((wu) => wu.user.external_id === userId)?.role ?? null\n return { workspace, role }\n}\n\nexport function SaveTranscriptToThread({\n title,\n lines,\n excludeConversationExtId,\n iconOnly = false,\n className,\n}: {\n /** The meeting's title (decrypted). */\n title: string | null | undefined\n lines: TranscriptExportLine[]\n /** Not offered as a target (the meeting thread itself). */\n excludeConversationExtId?: string | null\n /** Icon only, the label in a tooltip (a crowded header). */\n iconOnly?: boolean\n className?: string\n}): ReactElement | null {\n const [open, setOpen] = useState(false)\n if (!lines.length) return null\n return (\n <>\n <HeaderAction\n label=\"Save transcript to thread\"\n icon={<FileText className=\"size-3.5\" aria-hidden />}\n iconOnly={iconOnly}\n className={className}\n onClick={() => setOpen(true)}\n testId=\"save-transcript-to-thread\"\n />\n {open && (\n <SaveTranscriptDialog\n title={title}\n lines={lines}\n excludeConversationExtId={excludeConversationExtId ?? null}\n onClose={() => setOpen(false)}\n />\n )}\n </>\n )\n}\n\nfunction SaveTranscriptDialog({\n title,\n lines,\n excludeConversationExtId,\n onClose,\n}: {\n title: string | null | undefined\n lines: TranscriptExportLine[]\n excludeConversationExtId: string | null\n onClose(): void\n}): ReactElement {\n const { notify } = useBlocksEnvironment()\n const save = useSaveToThread()\n const { workspace } = useCurrentWorkspace()\n return (\n <PickThreadDialog\n heading=\"Save transcript to thread\"\n description={\n <>\n The transcript ({lines.length} {lines.length === 1 ? 'line' : 'lines'}) is posted as one\n comment in a thread of {workspace?.name ?? 'the current workspace'}. Only that thread’s\n members can read it there.\n </>\n }\n testIdPrefix=\"save-transcript\"\n excludeConversationExtId={excludeConversationExtId}\n onClose={onClose}\n onConfirm={async (target) => {\n await save.transcript({ conversationExtId: target, title, lines })\n notify('Transcript saved to the thread', 'success')\n }}\n />\n )\n}\n\n/**\n * Pick a shared thread of the current workspace I can post in (or a new one) and act on it: the\n * dialog behind \"Save transcript to thread\" and the recording's \"Save to thread\".\n */\nexport function PickThreadDialog({\n heading,\n description,\n testIdPrefix,\n excludeConversationExtId,\n confirmLabel = 'Save',\n busyLabel = 'Saving…',\n onConfirm,\n onClose,\n}: {\n heading: string\n description: ReactNode\n /** `<prefix>-dialog`, `<prefix>-target-<id>`, `<prefix>-confirm`. */\n testIdPrefix: string\n excludeConversationExtId?: string | null\n confirmLabel?: string\n busyLabel?: string\n /** `target` null: a new thread. Throwing keeps the dialog open and shows the error. */\n onConfirm(target: string | null): Promise<unknown>\n onClose(): void\n}): ReactElement {\n const { notify } = useBlocksEnvironment()\n const { role } = useCurrentWorkspace()\n const { data: conversations } = useConnectedConversations()\n const canPost = role === 'owner' || role === 'collaborator'\n const threads = useMemo(\n () =>\n canPost\n ? conversations\n .filter((c) => c.is_shared && c.external_id !== excludeConversationExtId)\n .sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at))\n : [],\n [conversations, canPost, excludeConversationExtId]\n )\n const [target, setTarget] = useState<string>(NEW_THREAD)\n const [busy, setBusy] = useState(false)\n\n const save = async () => {\n setBusy(true)\n try {\n await onConfirm(target === NEW_THREAD ? null : target)\n onClose()\n } catch (err) {\n notify((err as Error).message, 'error')\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Dialog open onOpenChange={(o) => !o && !busy && onClose()}>\n <DialogContent className=\"sm:max-w-md\" data-testid={`${testIdPrefix}-dialog`}>\n <DialogHeader>\n <DialogTitle>{heading}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n {!canPost ? (\n <p className=\"text-sm text-muted-foreground\">\n Open a workspace you can post in to save here.\n </p>\n ) : (\n <ul className=\"flex max-h-72 flex-col gap-1 overflow-y-auto\" role=\"radiogroup\">\n {[{ external_id: NEW_THREAD, title: 'New thread' }, ...threads].map((t) => (\n <li key={t.external_id}>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={target === t.external_id}\n className={cn(\n 'w-full truncate rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted',\n target === t.external_id && 'bg-muted font-medium'\n )}\n onClick={() => setTarget(t.external_id)}\n data-testid={`${testIdPrefix}-target-${t.external_id}`}\n >\n {t.title || 'Untitled thread'}\n </button>\n </li>\n ))}\n </ul>\n )}\n <DialogFooter>\n <Button variant=\"ghost\" onClick={onClose} disabled={busy}>\n Cancel\n </Button>\n <Button\n onClick={() => void save()}\n disabled={busy || !canPost}\n data-testid={`${testIdPrefix}-confirm`}\n >\n {busy ? busyLabel : confirmLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","/**\n * The Recording card of a call (ARBI `docs/meeting-chats-plan.md` §6): a `kind = recording` chat\n * message in an E2E meeting chat, a `recording` activity event in a workspace meeting thread, and\n * each entry of a meeting chat's \"Recordings\" list.\n *\n * Everything that touches media happens in this browser: parts are downloaded as ciphertext and\n * decrypted with the track keys (unwrapped under the meeting chat's / workspace's key). Members of\n * the meeting chat can play, download and copy an in-app link; the host can also transcribe, delete\n * the media (keeping the transcript), set an expiry, save the files to a thread, or delete it.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactElement } from 'react'\nimport {\n Captions,\n Download,\n FileUp,\n Link2,\n Loader2,\n Mic,\n Pause,\n Play,\n Trash2,\n Video,\n} from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { downloadBlob } from '@arbidocs/react/document-tools'\nimport {\n useArbi,\n useCallRecording,\n useCallRecordings,\n useCall,\n useRecordingActions,\n useSaveToThread,\n meetingChatRefFrom,\n compositeFiles,\n compositeTrack,\n fetchPart,\n recordingFiles,\n speakerTracks,\n type OpenedRecording,\n PLAYBACK_LOOKAHEAD_MS,\n partKey,\n partsDue,\n playheadAt,\n schedulePart,\n standalone,\n timelineDurationMs,\n timelineOf,\n type TimelinePart,\n} from '@arbidocs/react'\nimport type { calls } from '@arbidocs/sdk/browser'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { recordingLink, setPendingRecording, usePendingRecording } from '../recording-link'\nimport { formatCallDuration } from '../call-cards'\nimport { EXPIRY_DAYS, MODE_LABEL, expiryChoiceOf, expiryFor } from '../recording-labels'\nimport { PickThreadDialog } from './SaveTranscriptToThread'\nimport { CallUserPill } from './CallUserPill'\n\n/** A card for one recording (by id), or for each of the call's recordings when no id is known. */\nexport function RecordingCard({\n callExtId,\n recordingExtId,\n title,\n time,\n}: {\n callExtId: string\n recordingExtId?: string | null\n /** The meeting's title (decrypted), for file names. */\n title?: string | null\n time?: string\n}): ReactElement | null {\n const { data: call } = useCall(callExtId)\n const one = useCallRecording(callExtId, recordingExtId)\n const all = useCallRecordings(callExtId, !recordingExtId)\n if (!call) return null\n if (recordingExtId) {\n if (one.isError) return <RecordingUnavailable />\n return one.data ? (\n <RecordingCardBody call={call} recording={one.data} title={title} time={time} />\n ) : null\n }\n return (\n <>\n {(all.data ?? []).map((r) => (\n <RecordingCardBody\n key={r.external_id}\n call={call}\n recording={r}\n title={title}\n time={time}\n />\n ))}\n </>\n )\n}\n\n/** All of a call's recordings (the meeting chat's \"Recordings\" view), newest first. */\nexport function RecordingsList({\n callExtId,\n title,\n className,\n}: {\n callExtId: string\n title?: string | null\n className?: string\n}): ReactElement {\n const { data: call } = useCall(callExtId)\n const { data, isLoading, isError } = useCallRecordings(callExtId)\n const sorted = useMemo(\n () => [...(data ?? [])].sort((a, b) => Date.parse(b.started_at) - Date.parse(a.started_at)),\n [data]\n )\n return (\n <div className={cn('flex flex-col gap-2', className)} data-testid=\"recordings-list\">\n {isLoading && <Loader2 className=\"mx-auto size-4 animate-spin text-muted-foreground\" />}\n {isError && (\n <p className=\"text-center text-xs text-muted-foreground\">Could not load the recordings.</p>\n )}\n {!isLoading && !isError && !sorted.length && (\n <p className=\"text-center text-xs text-muted-foreground\">No recordings yet.</p>\n )}\n {call &&\n sorted.map((r) => (\n <RecordingCardBody key={r.external_id} call={call} recording={r} title={title} />\n ))}\n </div>\n )\n}\n\nfunction RecordingUnavailable(): ReactElement {\n return (\n <div\n className=\"mx-auto my-1 w-fit rounded-md border border-border bg-card px-3 py-2 text-xs text-muted-foreground\"\n data-testid=\"recording-card\"\n >\n Recording unavailable\n </div>\n )\n}\n\n/** A two-step destructive button: the first click asks, the second does. */\nfunction ConfirmButton({\n label,\n confirmLabel,\n testId,\n disabled,\n onConfirm,\n icon,\n}: {\n label: string\n confirmLabel: string\n testId: string\n disabled?: boolean\n onConfirm(): Promise<void>\n icon: ReactElement\n}): ReactElement {\n const [asking, setAsking] = useState(false)\n const [busy, setBusy] = useState(false)\n useEffect(() => {\n if (!asking) return\n const t = setTimeout(() => setAsking(false), 5000)\n return () => clearTimeout(t)\n }, [asking])\n return (\n <Button\n type=\"button\"\n size=\"sm\"\n variant={asking ? 'destructive' : 'outline'}\n className=\"h-7\"\n disabled={disabled || busy}\n onClick={() => {\n if (!asking) {\n setAsking(true)\n return\n }\n setAsking(false)\n setBusy(true)\n void onConfirm().finally(() => setBusy(false))\n }}\n data-testid={asking ? `${testId}-confirm` : testId}\n >\n {busy ? <Loader2 className=\"mr-1 size-3.5 animate-spin\" aria-hidden /> : icon}\n {asking ? confirmLabel : label}\n </Button>\n )\n}\n\nfunction RecordingCardBody({\n call,\n recording,\n title,\n time,\n}: {\n call: calls.CallResponse\n recording: calls.CallRecording\n title?: string | null\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const actions = useRecordingActions(call)\n const save = useSaveToThread()\n const { notify, runtimeConfig } = useBlocksEnvironment()\n const isHost = call.is_creator\n const mediaDeleted = !!recording.media_deleted_at\n const live = recording.state === 'recording' || (!recording.stopped_at && !mediaDeleted)\n const speakers = speakerTracks(recording)\n const timeline = useMemo(() => timelineOf(recording.tracks ?? []), [recording.tracks])\n const durationMs = timelineDurationMs(timeline)\n const hasMedia = !mediaDeleted && timeline.length > 0\n const [opened, setOpened] = useState<OpenedRecording | null>(null)\n const [playing, setPlaying] = useState(false)\n const [progress, setProgress] = useState<string | null>(null)\n const [saveOpen, setSaveOpen] = useState(false)\n const { workspaceId: selectedWorkspaceId } = useConnectedWorkspace()\n\n // A link asked to show this recording: bring it into view.\n const pending = usePendingRecording()\n const highlighted = pending === recording.external_id\n const cardRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n if (!highlighted) return\n cardRef.current?.scrollIntoView({ block: 'center', behavior: 'smooth' })\n const t = setTimeout(() => setPendingRecording(null), 4000)\n return () => clearTimeout(t)\n }, [highlighted])\n\n const { refresh } = actions\n\n const open = useCallback(async (): Promise<OpenedRecording> => {\n if (opened && opened.recording === recording) return opened\n const next = await actions.open(recording)\n setOpened(next)\n return next\n }, [actions, opened, recording])\n\n const run = async (label: string, task: () => Promise<void>) => {\n setProgress(label)\n try {\n await task()\n } catch (err) {\n console.warn('[calls] recording action failed', err)\n notify((err as Error).message, 'error')\n } finally {\n setProgress(null)\n }\n }\n\n const download = () =>\n run('Decrypting…', async () => {\n const files = await recordingFiles(arbi, await open(), title, (done, total) =>\n setProgress(`Decrypting ${done}/${total}…`)\n )\n if (!files.length) throw new Error('Nothing to download')\n for (const f of files) downloadBlob(f, f.name)\n })\n\n const transcribe = () =>\n run('Transcribing…', async () => {\n const { stored, failed } = await actions.transcribe(await open(), (done, total) =>\n setProgress(`Transcribing ${done}/${total}…`)\n )\n notify(\n failed\n ? `Transcribed ${stored} lines; ${failed} parts failed`\n : `Transcribed ${stored} lines into the meeting chat`,\n failed ? 'warning' : 'success'\n )\n })\n\n const copyLink = async () => {\n const ref = meetingChatRefFrom(call)\n if (!ref) {\n notify('This recording has no meeting chat to link to', 'error')\n return\n }\n try {\n await navigator.clipboard.writeText(\n recordingLink(ref, recording.external_id, runtimeConfig.deploymentDomain)\n )\n notify('Link copied: it opens for members of the meeting chat', 'success')\n } catch {\n notify('Could not copy the link', 'error')\n }\n }\n\n const saveToThread = async (target: string | null) => {\n if (!selectedWorkspaceId) throw new Error('Open a workspace first')\n const files = await recordingFiles(arbi, await open(), title, (done, total) =>\n setProgress(`Decrypting ${done}/${total}…`)\n )\n if (!files.length) throw new Error('Nothing to save')\n // Re-encrypted under the workspace key, as a direct document upload.\n try {\n await save.recording({\n workspaceExtId: selectedWorkspaceId,\n files,\n conversationExtId: target,\n title,\n onUploading: () => setProgress('Uploading…'),\n })\n } finally {\n setProgress(null)\n }\n notify('Recording saved to the thread', 'success')\n }\n\n const summary = [\n 'Recording',\n MODE_LABEL[recording.mode],\n formatCallDuration(durationMs / 1000),\n speakers.length ? `${speakers.length} ${speakers.length === 1 ? 'speaker' : 'speakers'}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n\n return (\n <div\n ref={cardRef}\n className={cn(\n 'mx-auto my-1 flex w-full max-w-xl flex-col gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs',\n highlighted && 'ring-2 ring-primary'\n )}\n data-testid=\"recording-card\"\n data-recording={recording.external_id}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n {recording.mode === 'audio_video' ? (\n <Video className=\"size-4 text-red-500\" aria-hidden />\n ) : (\n <Mic className=\"size-4 text-red-500\" aria-hidden />\n )}\n <span className=\"font-medium\" data-testid=\"recording-summary\">\n {summary}\n </span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live && <span className=\"text-red-500\">recording…</span>}\n {mediaDeleted && (\n <span className=\"text-muted-foreground\">Audio and video deleted — transcript kept</span>\n )}\n {!mediaDeleted && recording.expires_at && (\n <span className=\"text-muted-foreground\">\n Deleted after {new Date(recording.expires_at).toLocaleDateString()}\n </span>\n )}\n </div>\n {speakers.length > 0 && (\n <p className=\"flex flex-wrap items-center gap-1 text-muted-foreground\">\n {speakers.map((t, i) =>\n t.speaker_ext_id ? (\n <CallUserPill\n key={t.speaker_ext_id}\n identity={t.speaker_ext_id}\n name={t.speaker_name}\n />\n ) : (\n <span key={i}>{t.speaker_name || 'Someone'}</span>\n )\n )}\n </p>\n )}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n aria-pressed={playing}\n onClick={() => setPlaying((p) => !p)}\n data-testid=\"recording-play\"\n >\n {playing ? (\n <Pause className=\"mr-1 size-3.5\" aria-hidden />\n ) : (\n <Play className=\"mr-1 size-3.5\" aria-hidden />\n )}\n {playing ? 'Close player' : 'Play'}\n </Button>\n )}\n {hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress}\n onClick={() => void download()}\n data-testid=\"recording-download\"\n >\n <Download className=\"mr-1 size-3.5\" aria-hidden />\n Download\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n onClick={() => void copyLink()}\n title=\"Copy an in-app link (only members of the meeting chat can open it)\"\n data-testid=\"recording-copy-link\"\n >\n <Link2 className=\"mr-1 size-3.5\" aria-hidden />\n Copy link\n </Button>\n {isHost && hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress || live}\n onClick={() => void transcribe()}\n data-testid=\"recording-transcribe\"\n >\n <Captions className=\"mr-1 size-3.5\" aria-hidden />\n Transcribe\n </Button>\n )}\n {isHost && hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress || live}\n onClick={() => setSaveOpen(true)}\n data-testid=\"recording-save-to-thread\"\n >\n <FileUp className=\"mr-1 size-3.5\" aria-hidden />\n Save to thread\n </Button>\n )}\n {isHost && !mediaDeleted && (\n <ConfirmButton\n label=\"Keep transcript, delete audio/video\"\n confirmLabel=\"Delete audio/video now\"\n testId=\"recording-delete-media\"\n disabled={!!progress || live}\n icon={<Trash2 className=\"mr-1 size-3.5\" aria-hidden />}\n onConfirm={async () => {\n try {\n await arbi.calls.recording.deleteMedia(call.external_id, recording.external_id)\n setPlaying(false)\n setOpened(null)\n refresh()\n } catch (err) {\n notify((err as Error).message, 'error')\n }\n }}\n />\n )}\n {isHost && (\n <ConfirmButton\n label=\"Delete\"\n confirmLabel=\"Delete recording\"\n testId=\"recording-delete\"\n disabled={!!progress || live}\n icon={<Trash2 className=\"mr-1 size-3.5\" aria-hidden />}\n onConfirm={async () => {\n try {\n await arbi.calls.recording.delete(call.external_id, recording.external_id)\n refresh()\n } catch (err) {\n notify((err as Error).message, 'error')\n }\n }}\n />\n )}\n {isHost && !mediaDeleted && (\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Keep\n <select\n className=\"h-7 rounded-sm border border-border bg-background px-1 text-xs text-foreground\"\n value={expiryChoiceOf(recording.expires_at ?? null)}\n onChange={(e) => {\n const days = e.target.value === 'none' ? null : Number(e.target.value)\n void arbi.calls.recording\n .setExpiry(call.external_id, recording.external_id, expiryFor(days))\n .then(refresh)\n .catch((err: unknown) => notify((err as Error).message, 'error'))\n }}\n data-testid=\"recording-expiry\"\n aria-label=\"Keep the audio and video for\"\n >\n {EXPIRY_DAYS.map((d) => (\n <option key={d ?? 'none'} value={d ?? 'none'}>\n {d ? `${d} days` : 'until deleted'}\n </option>\n ))}\n </select>\n </label>\n )}\n {progress && (\n <span className=\"inline-flex items-center gap-1 text-muted-foreground\">\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n {progress}\n </span>\n )}\n </div>\n {playing && hasMedia && (\n <RecordingPlayer recording={recording} open={open} durationMs={durationMs} />\n )}\n {saveOpen && (\n <PickThreadDialog\n heading=\"Save recording to thread\"\n description=\"The recording is decrypted here and uploaded as documents (one audio file per speaker, and the video) into a thread of the current workspace, encrypted under its key. Only that workspace’s members can read them there.\"\n testIdPrefix=\"save-recording\"\n confirmLabel=\"Save\"\n busyLabel=\"Saving…\"\n onClose={() => setSaveOpen(false)}\n onConfirm={saveToThread}\n />\n )}\n </div>\n )\n}\n\n/**\n * Plays a recording: the composite video when there is one (it carries the mixed audio the host\n * heard), otherwise the speaker tracks mixed in sync on one WebAudio timeline.\n */\nfunction RecordingPlayer({\n recording,\n open,\n durationMs,\n}: {\n recording: calls.CallRecording\n open(): Promise<OpenedRecording>\n durationMs: number\n}): ReactElement {\n const composite = compositeTrack(recording)\n const [view, setView] = useState<'video' | 'audio'>(composite?.parts?.length ? 'video' : 'audio')\n return (\n <div className=\"flex flex-col gap-2\" data-testid=\"recording-player\">\n {composite?.parts?.length ? (\n <div className=\"flex gap-1\" role=\"group\" aria-label=\"Play\">\n {(['video', 'audio'] as const).map((v) => (\n <button\n key={v}\n type=\"button\"\n className={cn(\n 'rounded-full px-2 py-0.5',\n view === v ? 'bg-muted font-medium' : 'text-muted-foreground hover:bg-muted'\n )}\n aria-pressed={view === v}\n onClick={() => setView(v)}\n >\n {v === 'video' ? 'Video' : 'Speakers'}\n </button>\n ))}\n </div>\n ) : null}\n {view === 'video' && composite ? (\n <CompositeVideo open={open} trackExtId={composite.external_id} />\n ) : (\n <MixPlayer recording={recording} open={open} durationMs={durationMs} />\n )}\n </div>\n )\n}\n\nfunction CompositeVideo({\n open,\n trackExtId,\n}: {\n open(): Promise<OpenedRecording>\n trackExtId: string\n}): ReactElement {\n const arbi = useArbi()\n const [urls, setUrls] = useState<string[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n let made: string[] = []\n void (async () => {\n try {\n const opened = await open()\n const track = (opened.recording.tracks ?? []).find((t) => t.external_id === trackExtId)\n const key = opened.keys.get(trackExtId)\n if (!track || !key) throw new Error('The video does not open with your key')\n const blobs = await compositeFiles(arbi, track, key)\n made = blobs.map((b) => URL.createObjectURL(b))\n if (cancelled) made.forEach((u) => URL.revokeObjectURL(u))\n else setUrls(made)\n } catch (err) {\n if (!cancelled) setError((err as Error).message)\n }\n })()\n return () => {\n cancelled = true\n made.forEach((u) => URL.revokeObjectURL(u))\n }\n }, [arbi, open, trackExtId])\n if (error) return <p className=\"text-destructive\">{error}</p>\n if (!urls) {\n return (\n <span className=\"inline-flex items-center gap-1 text-muted-foreground\">\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n Decrypting the video…\n </span>\n )\n }\n return (\n <>\n {urls.map((u, i) => (\n <video\n key={u}\n src={u}\n controls\n className=\"w-full rounded-sm bg-black\"\n aria-label={`Video ${i + 1}`}\n />\n ))}\n </>\n )\n}\n\nconst fmt = (ms: number) => {\n const s = Math.max(0, Math.floor(ms / 1000))\n const h = Math.floor(s / 3600)\n const m = Math.floor((s % 3600) / 60)\n const sec = String(s % 60).padStart(2, '0')\n return h ? `${h}:${String(m).padStart(2, '0')}:${sec}` : `${m}:${sec}`\n}\n\n/**\n * The speaker tracks mixed in sync: parts are fetched, decrypted and decoded a little ahead of the\n * playhead and started on one AudioContext clock at their offsets (see `recording-playback.ts`).\n */\nfunction MixPlayer({\n recording,\n open,\n durationMs,\n}: {\n recording: calls.CallRecording\n open(): Promise<OpenedRecording>\n durationMs: number\n}): ReactElement {\n const arbi = useArbi()\n const { notify } = useBlocksEnvironment()\n const parts = useMemo(() => timelineOf(speakerTracks(recording)), [recording])\n const [position, setPosition] = useState(0)\n const [playing, setPlaying] = useState(false)\n const session = useRef<{\n ctx: AudioContext\n ctxStart: number\n seekMs: number\n scheduled: Set<string>\n timer: ReturnType<typeof setInterval>\n } | null>(null)\n\n const halt = useCallback(() => {\n const s = session.current\n session.current = null\n if (!s) return\n clearInterval(s.timer)\n void s.ctx.close().catch(() => undefined)\n }, [])\n\n useEffect(() => halt, [halt])\n\n const play = useCallback(\n async (fromMs: number) => {\n halt()\n const opened = await open()\n const ctx = new AudioContext()\n const s = {\n ctx,\n ctxStart: ctx.currentTime + 0.25,\n seekMs: fromMs,\n scheduled: new Set<string>(),\n timer: 0 as unknown as ReturnType<typeof setInterval>,\n }\n const schedule = async (part: TimelinePart) => {\n const track = (opened.recording.tracks ?? []).find((t) => t.external_id === part.trackExtId)\n const key = opened.keys.get(part.trackExtId)\n const raw = track?.parts?.find((p) => p.seq === part.seq)\n if (!track || !key || !raw) return\n try {\n const bytes = await fetchPart(arbi, raw, key)\n const buffer = await ctx.decodeAudioData(standalone(bytes).buffer)\n if (session.current !== s) return\n const at = schedulePart({\n partOffsetMs: part.offsetMs,\n bufferDurationS: buffer.duration,\n ctxStart: s.ctxStart,\n seekMs: s.seekMs,\n ctxNow: ctx.currentTime,\n })\n if (!at) return\n const source = ctx.createBufferSource()\n source.buffer = buffer\n source.connect(ctx.destination)\n source.start(at.when, at.offset)\n } catch (err) {\n console.warn('[calls] a recording part does not play', err)\n }\n }\n const tick = () => {\n if (session.current !== s) return\n const head = playheadAt(ctx.currentTime, s.ctxStart, s.seekMs)\n setPosition(Math.min(head, durationMs))\n if (head >= durationMs) {\n halt()\n setPlaying(false)\n return\n }\n for (const part of partsDue(parts, head, PLAYBACK_LOOKAHEAD_MS, s.scheduled)) {\n s.scheduled.add(partKey(part))\n void schedule(part)\n }\n }\n s.timer = setInterval(tick, 500)\n session.current = s\n setPlaying(true)\n tick()\n },\n [arbi, open, parts, durationMs, halt]\n )\n\n const toggle = () => {\n if (playing) {\n halt()\n setPlaying(false)\n } else {\n void play(position >= durationMs ? 0 : position).catch((err: unknown) => {\n setPlaying(false)\n notify((err as Error).message, 'error')\n })\n }\n }\n\n return (\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"outline\"\n className=\"size-7\"\n aria-label={playing ? 'Pause' : 'Play'}\n onClick={toggle}\n data-testid=\"recording-mix-toggle\"\n >\n {playing ? <Pause className=\"size-3.5\" /> : <Play className=\"size-3.5\" />}\n </Button>\n <input\n type=\"range\"\n min={0}\n max={Math.max(1, durationMs)}\n step={1000}\n value={position}\n className=\"flex-1\"\n aria-label=\"Position\"\n onChange={(e) => {\n const ms = Number(e.target.value)\n setPosition(ms)\n if (playing) {\n void play(ms).catch((err: unknown) => notify((err as Error).message, 'error'))\n }\n }}\n />\n <span className=\"tabular-nums text-muted-foreground\">\n {fmt(position)} / {fmt(durationMs)}\n </span>\n </div>\n )\n}\n","/**\n * A thread call's log card in the thread transcript: the `convo_events` row of kind `call` the\n * server writes when the call starts and updates when it ends (plaintext ids and times only).\n *\n * live: \"Call started by Ada · invited Bob, Cy\" · Join\n * ended: \"Call · 12 min · joined Ada, Bob\" · Open meeting chat\n *\n * It re-reads on `call.started` / `call.ended` (see `refreshCallCards`).\n */\n\nimport { useArbi, useCallSession, useCall, useOpenCallMeetingChat, openCall } from '@arbidocs/react'\nimport { useState, type ReactElement } from 'react'\nimport { MessageSquare, Phone, PhoneOff } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { formatCallDuration, type CallLogDetail } from '../call-cards'\n\nfunction joinNames(people: string[], name: (id: string) => string): string {\n const names = people.map(name)\n return names.length > 4\n ? `${names.slice(0, 4).join(', ')} +${names.length - 4}`\n : names.join(', ')\n}\n\nexport function ThreadCallLogCard({\n detail,\n name,\n workspaceExtId,\n time,\n}: {\n detail: CallLogDetail\n /** A person's display name by user ext id. */\n name: (userExtId: string) => string\n /** The thread's workspace (the meeting thread lives there too). */\n workspaceExtId: string | null\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const openCallMeetingChat = useOpenCallMeetingChat()\n const live = !detail.ended_at\n const inThisCall = useCallSession((s) => s.active?.callExtId === detail.call_ext_id)\n const inAnotherCall = useCallSession(\n (s) => !!s.active && s.active.callExtId !== detail.call_ext_id\n )\n // Only people holding K (the creator and those rung) can join from the card.\n const { data: call } = useCall(live ? detail.call_ext_id : null)\n const invitedOnly = live && !!call && !call.my_sealed_key\n const [busy, setBusy] = useState(false)\n\n const summary = live\n ? [\n detail.started_by ? `Call started by ${name(detail.started_by)}` : 'Call started',\n detail.invited.length ? `invited ${joinNames(detail.invited, name)}` : null,\n ]\n : [\n 'Call',\n formatCallDuration(detail.duration_s),\n detail.joined.length ? `joined ${joinNames(detail.joined, name)}` : null,\n ]\n\n return (\n <div\n className=\"mx-auto my-1 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs\"\n data-testid=\"thread-call-log-card\"\n data-live={live || undefined}\n >\n {live ? (\n <Phone className=\"size-4 animate-pulse text-green-text\" aria-hidden />\n ) : (\n <PhoneOff className=\"size-4 text-muted-foreground\" aria-hidden />\n )}\n <span data-testid=\"thread-call-log-summary\">{summary.filter(Boolean).join(' · ')}</span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live ? (\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 bg-green-600 text-white hover:bg-green-700\"\n disabled={busy || inThisCall || inAnotherCall || invitedOnly}\n title={\n invitedOnly\n ? 'Only the people rung into this call can join'\n : inAnotherCall\n ? 'You are already in a call'\n : undefined\n }\n onClick={() => {\n setBusy(true)\n void openCall(arbi, { callExtId: detail.call_ext_id }).finally(() => setBusy(false))\n }}\n data-testid=\"thread-call-log-join\"\n >\n {inThisCall ? 'In call' : 'Join'}\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n onClick={() =>\n void openCallMeetingChat({\n callExtId: detail.call_ext_id,\n meetingConversationExtId: detail.meeting_conversation_ext_id,\n workspaceExtId,\n })\n }\n data-testid=\"thread-call-log-open-chat\"\n >\n <MessageSquare className=\"mr-1 size-3.5\" aria-hidden />\n Open meeting chat\n </Button>\n )}\n </div>\n )\n}\n","/**\n * One stored line of a call transcript in its conversation (meeting chat or workspace meeting\n * thread): `TranscriptLine` from `@arbidocs/blocks`, centred for everyone. What someone is saying\n * right now shows as a provisional \"is speaking…\" row below, not as a highlight on a past line.\n */\n\nimport type { ReactElement } from 'react'\nimport { TranscriptLine } from '../../chat/TranscriptLine'\nimport { CallUserPill } from './CallUserPill'\n\nfunction formatTime(iso: string | null | undefined): string {\n if (!iso) return ''\n const at = Date.parse(iso)\n if (Number.isNaN(at)) return ''\n return new Date(at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\nexport function TranscriptEntry({\n speakerId,\n speakerName,\n text,\n at,\n continued = false,\n className,\n}: {\n /** The speaker's identity (user ext id), for `data-speaker`. */\n speakerId: string\n /** The name to show (\"Me\" for my own lines). */\n speakerName: string\n text: string\n /** ISO time the segment started (or the message was stored). */\n at: string | null | undefined\n /** A further line of the same speaker's run (no name repeated). */\n continued?: boolean\n className?: string\n}): ReactElement {\n return (\n <TranscriptLine\n speakerId={speakerId}\n speakerName={speakerName}\n speaker={<CallUserPill identity={speakerId} name={speakerName} />}\n time={formatTime(at)}\n text={text}\n continued={continued}\n className={className}\n />\n )\n}\n","/** A call participant's name, as the people directory knows them. */\n\nimport { useMemo } from 'react'\nimport { useArbi, usePeople } from '@arbidocs/react'\nimport { getUserDisplayName } from '@arbidocs/react/ui'\n\n/** The name for an identity (user ext id): mine, a known person's, else the call's name for them. */\nexport function useCallPersonName(identity: string, fallbackName?: string | null): string {\n const arbi = useArbi()\n const { byId } = usePeople()\n const me = arbi.isLoggedIn && arbi.user.identity()?.externalId === identity\n const profile = me ? arbi.user.profile() : null\n return useMemo(() => {\n if (profile)\n return getUserDisplayName({ given_name: profile.givenName, family_name: profile.familyName })\n const user = byId(identity)\n if (user) return getUserDisplayName(user)\n return (fallbackName || identity).trim().split(/\\s+/).join(' ')\n }, [profile, byId, identity, fallbackName])\n}\n","/**\n * A call's conversation (meeting chat or meeting thread), call-aware: its empty state (\"Call in\n * progress — the transcript will appear here\", or \"No transcript\" afterwards) instead of the\n * generic one, and provisional \"<speaker> is speaking…\" rows while a line is on its way.\n */\n\nimport { useCallSession } from '@arbidocs/react'\nimport type { ReactElement } from 'react'\nimport { AudioLines, Captions, CaptionsOff } from 'lucide-react'\nimport { EmptyState } from '../../components/EmptyState'\nimport { ProvisionalTranscriptLine } from '../../chat/TranscriptLine'\nimport { useMyCallStatus } from '../call-status'\nimport { CallUserPill } from './CallUserPill'\nimport { useCallPersonName } from './call-person-name'\n\n/** The empty conversation of a call: live while the call runs, \"No transcript\" after. */\nexport function CallConversationEmpty({ callExtId }: { callExtId: string }): ReactElement {\n const { inCall, transcribing } = useMyCallStatus(callExtId)\n const live = useCallSession((s) => !!s.liveCalls[callExtId]) || inCall\n if (!live) {\n return (\n <EmptyState\n icon={AudioLines}\n title=\"No transcript\"\n description=\"This call was not transcribed. When a call here is transcribed, what people say appears in this conversation.\"\n className=\"mx-auto my-8 max-w-xl\"\n testId=\"call-conversation-empty\"\n />\n )\n }\n return (\n <EmptyState\n icon={transcribing ? Captions : CaptionsOff}\n title=\"Call in progress — the transcript will appear here\"\n description={\n transcribing\n ? 'Transcription is on: what people say shows up here as they speak.'\n : 'Transcription is off. The host can turn it on with CC in the call.'\n }\n className=\"mx-auto my-8 max-w-xl\"\n testId=\"call-conversation-empty\"\n />\n )\n}\n\nfunction ProvisionalRow({ identity }: { identity: string }): ReactElement {\n const name = useCallPersonName(identity)\n return (\n <ProvisionalTranscriptLine\n speakerId={identity}\n speakerName={name}\n speaker={<CallUserPill identity={identity} />}\n />\n )\n}\n\n/** The provisional rows at the bottom of a call's conversation (never stored). */\nexport function ProvisionalSpeakers({ ids }: { ids: string[] }): ReactElement | null {\n if (!ids.length) return null\n return (\n <div className=\"pb-2\" data-testid=\"transcript-provisional-rows\">\n {ids.map((id) => (\n <ProvisionalRow key={id} identity={id} />\n ))}\n </div>\n )\n}\n","/** Who gets a provisional \"is speaking…\" row in a call's conversation. */\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { useMyCallStatus } from '../call-status'\nimport { useSpeakingIds } from '../voice-levels'\n\n/** A spoken stretch whose line has not arrived yet. */\ninterface Pending {\n startedAt: number\n lastHeardAt: number\n}\n\n/** How long after someone stops a provisional row waits for their line before it gives up. */\nconst LINE_WAIT_MS = 10_000\n/** A burst shorter than this (a cough, a word) gets no row. */\nconst MIN_SPEECH_MS = 800\n\n/**\n * Who should show a provisional row: people talking now, and people who stopped but whose line\n * has not arrived yet (a line started at or after their stretch began replaces the row).\n */\nexport function useProvisionalSpeakers(\n callExtId: string | null | undefined,\n lines: { speakerId: string; at: number }[]\n): string[] {\n const { inCall, transcribing } = useMyCallStatus(callExtId)\n const speaking = useSpeakingIds()\n const pending = useRef(new Map<string, Pending>())\n const [, tick] = useState(0)\n const active = inCall && transcribing\n const now = Date.now()\n if (active) {\n for (const id of speaking) {\n const p = pending.current.get(id)\n if (p) p.lastHeardAt = now\n else pending.current.set(id, { startedAt: now, lastHeardAt: now })\n }\n } else if (pending.current.size) {\n pending.current.clear()\n }\n // A line that began within the stretch (a little slack for clock skew) replaces the row.\n const latest = useMemo(() => {\n const m = new Map<string, number>()\n for (const l of lines) m.set(l.speakerId, Math.max(m.get(l.speakerId) ?? 0, l.at))\n return m\n }, [lines])\n for (const [id, p] of [...pending.current]) {\n const arrived = (latest.get(id) ?? 0) >= p.startedAt - 3000\n const stale = !speaking.includes(id) && now - p.lastHeardAt > LINE_WAIT_MS\n if ((arrived && !speaking.includes(id)) || stale) pending.current.delete(id)\n else if (arrived) p.startedAt = now\n }\n // Re-check while rows wait for their lines.\n const waiting = pending.current.size > 0\n useEffect(() => {\n if (!waiting) return\n const id = setInterval(() => tick((n) => n + 1), 1000)\n return () => clearInterval(id)\n }, [waiting])\n return [...pending.current]\n .filter(([, p]) => p.lastHeardAt - p.startedAt >= MIN_SPEECH_MS)\n .map(([id]) => id)\n}\n","/**\n * How a meeting thread's transcript lines group: which messages continue their speaker's run (the\n * name is not repeated) and which are each speaker's newest line (highlighted while they talk).\n * Provided by the conversation page, read by each transcript message.\n */\n\nimport { createContext, useContext } from 'react'\nimport { transcriptRuns } from '../../chat/transcript-runs'\nimport { transcriptSegmentOf } from '@arbidocs/react'\n\nexport interface TranscriptRunInfo {\n continued: ReadonlySet<string>\n latest: ReadonlySet<string>\n}\n\nconst EMPTY: TranscriptRunInfo = { continued: new Set(), latest: new Set() }\n\nexport const TranscriptRunsContext = createContext<TranscriptRunInfo>(EMPTY)\n\nexport function useTranscriptRuns(): TranscriptRunInfo {\n return useContext(TranscriptRunsContext)\n}\n\ninterface ThreadMessageLike {\n external_id?: string | null\n created_at?: string | null\n tools?: unknown\n meta?: { tools?: unknown } | null\n}\n\n/** Runs and newest lines of a thread's messages (in display order). */\nexport function threadTranscriptRuns(messages: ThreadMessageLike[]): TranscriptRunInfo {\n const segmentOf = (m: ThreadMessageLike) => transcriptSegmentOf(m.tools ?? m.meta?.tools)\n const continuedItems = transcriptRuns(\n messages,\n (m) => segmentOf(m)?.speaker_ext_id ?? null,\n (m) => Date.parse(segmentOf(m)?.started_at ?? m.created_at ?? '') || 0\n )\n const latest = new Map<string, string>()\n for (const m of messages) {\n const seg = segmentOf(m)\n if (seg && m.external_id) latest.set(seg.speaker_ext_id, m.external_id)\n }\n return {\n continued: new Set(\n [...continuedItems].map((m) => m.external_id).filter((id): id is string => !!id)\n ),\n latest: new Set(latest.values()),\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/connection/calendar/store.ts","../src/connection/conversation/useMeetingThreadMessages.ts","../src/calls/connected/SaveTranscriptToThread.tsx","../src/calls/connected/RecordingCard.tsx","../src/calls/connected/ThreadCallLogCard.tsx","../src/calls/connected/TranscriptEntry.tsx","../src/calls/connected/call-person-name.ts","../src/calls/connected/CallConversationParts.tsx","../src/calls/connected/provisional-speakers.ts","../src/calls/connected/transcript-runs-context.ts"],"names":["useMemo","jsx","Fragment","jsxs","cn","useState","Button","useSaveToThread","useArbi","useCall","useCallSession","Captions","useRef","useEffect"],"mappings":"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","file":"chunk-PISYMKGS.js","sourcesContent":["/**\n * The connected calendar's view state: the chosen view is remembered across reloads (localStorage),\n * the anchor date lives for the session, and two requests carry intents from elsewhere into the\n * calendar once it mounts: an event to open (a deep link, a reminder) and a prefilled new event\n * (\"Schedule a call\" from a thread). The host navigates to its calendar page after making one.\n */\nimport { create } from 'zustand'\nimport { createJSONStorage, persist } from 'zustand/middleware'\nimport type { CalendarViewKind } from '../../calendar/types'\n\n/** \"Schedule a call\" from elsewhere (a thread, a DM, a dashboard): the editor opens prefilled. */\nexport interface CalendarComposerPrefill {\n title?: string\n attendees?: { email?: string | null; user_id?: string | null; name?: string | null }[]\n conversationId?: string | null\n /** Add an ARBI call when the event is saved (\"Add ARBI call\" ticked). */\n addCall?: boolean\n}\n\nexport interface PendingCalendarEvent {\n id: string\n recurrenceId?: string | null\n}\n\ninterface CalendarViewState {\n /** `null` until the user picks one: the settings' default view applies. */\n view: CalendarViewKind | null\n /** YYYY-MM-DD anchor; `null` = today. */\n date: string | null\n pendingEvent: PendingCalendarEvent | null\n pendingComposer: CalendarComposerPrefill | null\n setPendingComposer: (prefill: CalendarComposerPrefill | null) => void\n setView: (view: CalendarViewKind) => void\n setDate: (date: string | null) => void\n setPendingEvent: (pending: PendingCalendarEvent | null) => void\n}\n\nexport const useCalendarViewStore = create<CalendarViewState>()(\n persist(\n (set) => ({\n view: null,\n date: null,\n pendingEvent: null,\n pendingComposer: null,\n setPendingComposer: (pendingComposer) => set({ pendingComposer }),\n setView: (view) => set({ view }),\n setDate: (date) => set({ date }),\n setPendingEvent: (pendingEvent) => set({ pendingEvent }),\n }),\n {\n name: 'arbi-calendar-view',\n storage: createJSONStorage(() => localStorage),\n partialize: (s) => ({ view: s.view }),\n }\n )\n)\n\nconst EVT_RE = /^evt-[A-Za-z0-9]{8}$/\n\n/** Ask the calendar to open on an event (ignored unless it is an `evt-` id). */\nexport function requestCalendarEvent(event: PendingCalendarEvent): void {\n if (EVT_RE.test(event.id)) useCalendarViewStore.getState().setPendingEvent(event)\n}\n\n/** Ask the calendar to open the event editor prefilled. */\nexport function requestCalendarComposer(prefill: CalendarComposerPrefill): void {\n useCalendarViewStore.getState().setPendingComposer(prefill)\n}\n","/**\n * A conversation's messages as its thread shows them: in a call's meeting thread, a recording's\n * transcript supersedes the live lines spoken while it recorded (else both would show).\n */\nimport { useMemo } from 'react'\nimport {\n hasRecordingTranscript,\n supersedeLiveTranscript,\n threadTranscriptRef,\n useRecordingWindows,\n} from '@arbidocs/react'\nimport type { ChatMessage } from '@arbidocs/sdk/browser'\n\nexport function useMeetingThreadMessages(\n meetingCallExtId: string | null,\n messageHistory: ChatMessage[]\n): ChatMessage[] {\n const hasRecTranscript = useMemo(\n () => !!meetingCallExtId && hasRecordingTranscript(messageHistory, threadTranscriptRef),\n [meetingCallExtId, messageHistory]\n )\n const recordingWindows = useRecordingWindows(meetingCallExtId, hasRecTranscript)\n return useMemo(\n () =>\n hasRecTranscript\n ? supersedeLiveTranscript(messageHistory, threadTranscriptRef, recordingWindows)\n : messageHistory,\n [hasRecTranscript, messageHistory, recordingWindows]\n )\n}\n","/**\n * Host action \"Save transcript to thread\": the meeting chat's transcript is decrypted here, in the\n * host's browser, and posted as ONE attributed transcript comment (title, date, then\n * `Speaker [hh:mm:ss]: text` lines) into a workspace thread the host picks — a shared thread of the\n * current workspace they can post in, or a new one. The thread is encrypted with the workspace key\n * like any comment; the meeting chat itself is unchanged and nobody outside it gains access to it.\n */\n\nimport { useSaveToThread, useWorkspaces, type TranscriptExportLine } from '@arbidocs/react'\nimport { useMemo, useState, type ReactElement, type ReactNode } from 'react'\nimport { FileText } from 'lucide-react'\nimport {\n Button,\n cn,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@arbidocs/react/ui'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { useConnectedConversations } from '../../connection/workspaceData'\nimport { HeaderAction } from '../HeaderAction'\n\nconst NEW_THREAD = '__new__'\n\n/** The open workspace and my role in it (the threads I can post in are its shared ones). */\nfunction useCurrentWorkspace() {\n const { workspaceId, userId } = useConnectedWorkspace()\n const { data: workspaces } = useWorkspaces()\n const workspace = workspaces?.find((w) => w.external_id === workspaceId)\n const role = workspace?.users?.find((wu) => wu.user.external_id === userId)?.role ?? null\n return { workspace, role }\n}\n\nexport function SaveTranscriptToThread({\n title,\n lines,\n excludeConversationExtId,\n iconOnly = false,\n className,\n}: {\n /** The meeting's title (decrypted). */\n title: string | null | undefined\n lines: TranscriptExportLine[]\n /** Not offered as a target (the meeting thread itself). */\n excludeConversationExtId?: string | null\n /** Icon only, the label in a tooltip (a crowded header). */\n iconOnly?: boolean\n className?: string\n}): ReactElement | null {\n const [open, setOpen] = useState(false)\n if (!lines.length) return null\n return (\n <>\n <HeaderAction\n label=\"Save transcript to thread\"\n icon={<FileText className=\"size-3.5\" aria-hidden />}\n iconOnly={iconOnly}\n className={className}\n onClick={() => setOpen(true)}\n testId=\"save-transcript-to-thread\"\n />\n {open && (\n <SaveTranscriptDialog\n title={title}\n lines={lines}\n excludeConversationExtId={excludeConversationExtId ?? null}\n onClose={() => setOpen(false)}\n />\n )}\n </>\n )\n}\n\nfunction SaveTranscriptDialog({\n title,\n lines,\n excludeConversationExtId,\n onClose,\n}: {\n title: string | null | undefined\n lines: TranscriptExportLine[]\n excludeConversationExtId: string | null\n onClose(): void\n}): ReactElement {\n const { notify } = useBlocksEnvironment()\n const save = useSaveToThread()\n const { workspace } = useCurrentWorkspace()\n return (\n <PickThreadDialog\n heading=\"Save transcript to thread\"\n description={\n <>\n The transcript ({lines.length} {lines.length === 1 ? 'line' : 'lines'}) is posted as one\n comment in a thread of {workspace?.name ?? 'the current workspace'}. Only that thread’s\n members can read it there.\n </>\n }\n testIdPrefix=\"save-transcript\"\n excludeConversationExtId={excludeConversationExtId}\n onClose={onClose}\n onConfirm={async (target) => {\n await save.transcript({ conversationExtId: target, title, lines })\n notify('Transcript saved to the thread', 'success')\n }}\n />\n )\n}\n\n/**\n * Pick a shared thread of the current workspace I can post in (or a new one) and act on it: the\n * dialog behind \"Save transcript to thread\" and the recording's \"Save to thread\".\n */\nexport function PickThreadDialog({\n heading,\n description,\n testIdPrefix,\n excludeConversationExtId,\n confirmLabel = 'Save',\n busyLabel = 'Saving…',\n onConfirm,\n onClose,\n}: {\n heading: string\n description: ReactNode\n /** `<prefix>-dialog`, `<prefix>-target-<id>`, `<prefix>-confirm`. */\n testIdPrefix: string\n excludeConversationExtId?: string | null\n confirmLabel?: string\n busyLabel?: string\n /** `target` null: a new thread. Throwing keeps the dialog open and shows the error. */\n onConfirm(target: string | null): Promise<unknown>\n onClose(): void\n}): ReactElement {\n const { notify } = useBlocksEnvironment()\n const { role } = useCurrentWorkspace()\n const { data: conversations } = useConnectedConversations()\n const canPost = role === 'owner' || role === 'collaborator'\n const threads = useMemo(\n () =>\n canPost\n ? conversations\n .filter((c) => c.is_shared && c.external_id !== excludeConversationExtId)\n .sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at))\n : [],\n [conversations, canPost, excludeConversationExtId]\n )\n const [target, setTarget] = useState<string>(NEW_THREAD)\n const [busy, setBusy] = useState(false)\n\n const save = async () => {\n setBusy(true)\n try {\n await onConfirm(target === NEW_THREAD ? null : target)\n onClose()\n } catch (err) {\n notify((err as Error).message, 'error')\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Dialog open onOpenChange={(o) => !o && !busy && onClose()}>\n <DialogContent className=\"sm:max-w-md\" data-testid={`${testIdPrefix}-dialog`}>\n <DialogHeader>\n <DialogTitle>{heading}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n {!canPost ? (\n <p className=\"text-sm text-muted-foreground\">\n Open a workspace you can post in to save here.\n </p>\n ) : (\n <ul className=\"flex max-h-72 flex-col gap-1 overflow-y-auto\" role=\"radiogroup\">\n {[{ external_id: NEW_THREAD, title: 'New thread' }, ...threads].map((t) => (\n <li key={t.external_id}>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={target === t.external_id}\n className={cn(\n 'w-full truncate rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted',\n target === t.external_id && 'bg-muted font-medium'\n )}\n onClick={() => setTarget(t.external_id)}\n data-testid={`${testIdPrefix}-target-${t.external_id}`}\n >\n {t.title || 'Untitled thread'}\n </button>\n </li>\n ))}\n </ul>\n )}\n <DialogFooter>\n <Button variant=\"ghost\" onClick={onClose} disabled={busy}>\n Cancel\n </Button>\n <Button\n onClick={() => void save()}\n disabled={busy || !canPost}\n data-testid={`${testIdPrefix}-confirm`}\n >\n {busy ? busyLabel : confirmLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","/**\n * The Recording card of a call (ARBI `docs/meeting-chats-plan.md` §6): a `kind = recording` chat\n * message in an E2E meeting chat, a `recording` activity event in a workspace meeting thread, and\n * each entry of a meeting chat's \"Recordings\" list.\n *\n * Everything that touches media happens in this browser: parts are downloaded as ciphertext and\n * decrypted with the track keys (unwrapped under the meeting chat's / workspace's key). Members of\n * the meeting chat can play, download and copy an in-app link; the host can also transcribe, delete\n * the media (keeping the transcript), set an expiry, save the files to a thread, or delete it.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactElement } from 'react'\nimport {\n Captions,\n Download,\n FileUp,\n Link2,\n Loader2,\n Mic,\n Pause,\n Play,\n Trash2,\n Video,\n} from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { downloadBlob } from '@arbidocs/react/document-tools'\nimport {\n useArbi,\n useCallRecording,\n useCallRecordings,\n useCall,\n useRecordingActions,\n useSaveToThread,\n meetingChatRefFrom,\n compositeFiles,\n compositeTrack,\n fetchPart,\n recordingFiles,\n speakerTracks,\n type OpenedRecording,\n PLAYBACK_LOOKAHEAD_MS,\n partKey,\n partsDue,\n playheadAt,\n schedulePart,\n standalone,\n timelineDurationMs,\n timelineOf,\n type TimelinePart,\n} from '@arbidocs/react'\nimport type { calls } from '@arbidocs/sdk/browser'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { recordingLink, setPendingRecording, usePendingRecording } from '../recording-link'\nimport { formatCallDuration } from '../call-cards'\nimport { EXPIRY_DAYS, MODE_LABEL, expiryChoiceOf, expiryFor } from '../recording-labels'\nimport { PickThreadDialog } from './SaveTranscriptToThread'\nimport { CallUserPill } from './CallUserPill'\n\n/** A card for one recording (by id), or for each of the call's recordings when no id is known. */\nexport function RecordingCard({\n callExtId,\n recordingExtId,\n title,\n time,\n}: {\n callExtId: string\n recordingExtId?: string | null\n /** The meeting's title (decrypted), for file names. */\n title?: string | null\n time?: string\n}): ReactElement | null {\n const { data: call } = useCall(callExtId)\n const one = useCallRecording(callExtId, recordingExtId)\n const all = useCallRecordings(callExtId, !recordingExtId)\n if (!call) return null\n if (recordingExtId) {\n if (one.isError) return <RecordingUnavailable />\n return one.data ? (\n <RecordingCardBody call={call} recording={one.data} title={title} time={time} />\n ) : null\n }\n return (\n <>\n {(all.data ?? []).map((r) => (\n <RecordingCardBody\n key={r.external_id}\n call={call}\n recording={r}\n title={title}\n time={time}\n />\n ))}\n </>\n )\n}\n\n/** All of a call's recordings (the meeting chat's \"Recordings\" view), newest first. */\nexport function RecordingsList({\n callExtId,\n title,\n className,\n}: {\n callExtId: string\n title?: string | null\n className?: string\n}): ReactElement {\n const { data: call } = useCall(callExtId)\n const { data, isLoading, isError } = useCallRecordings(callExtId)\n const sorted = useMemo(\n () => [...(data ?? [])].sort((a, b) => Date.parse(b.started_at) - Date.parse(a.started_at)),\n [data]\n )\n return (\n <div className={cn('flex flex-col gap-2', className)} data-testid=\"recordings-list\">\n {isLoading && <Loader2 className=\"mx-auto size-4 animate-spin text-muted-foreground\" />}\n {isError && (\n <p className=\"text-center text-xs text-muted-foreground\">Could not load the recordings.</p>\n )}\n {!isLoading && !isError && !sorted.length && (\n <p className=\"text-center text-xs text-muted-foreground\">No recordings yet.</p>\n )}\n {call &&\n sorted.map((r) => (\n <RecordingCardBody key={r.external_id} call={call} recording={r} title={title} />\n ))}\n </div>\n )\n}\n\nfunction RecordingUnavailable(): ReactElement {\n return (\n <div\n className=\"mx-auto my-1 w-fit rounded-md border border-border bg-card px-3 py-2 text-xs text-muted-foreground\"\n data-testid=\"recording-card\"\n >\n Recording unavailable\n </div>\n )\n}\n\n/** A two-step destructive button: the first click asks, the second does. */\nfunction ConfirmButton({\n label,\n confirmLabel,\n testId,\n disabled,\n onConfirm,\n icon,\n}: {\n label: string\n confirmLabel: string\n testId: string\n disabled?: boolean\n onConfirm(): Promise<void>\n icon: ReactElement\n}): ReactElement {\n const [asking, setAsking] = useState(false)\n const [busy, setBusy] = useState(false)\n useEffect(() => {\n if (!asking) return\n const t = setTimeout(() => setAsking(false), 5000)\n return () => clearTimeout(t)\n }, [asking])\n return (\n <Button\n type=\"button\"\n size=\"sm\"\n variant={asking ? 'destructive' : 'outline'}\n className=\"h-7\"\n disabled={disabled || busy}\n onClick={() => {\n if (!asking) {\n setAsking(true)\n return\n }\n setAsking(false)\n setBusy(true)\n void onConfirm().finally(() => setBusy(false))\n }}\n data-testid={asking ? `${testId}-confirm` : testId}\n >\n {busy ? <Loader2 className=\"mr-1 size-3.5 animate-spin\" aria-hidden /> : icon}\n {asking ? confirmLabel : label}\n </Button>\n )\n}\n\nfunction RecordingCardBody({\n call,\n recording,\n title,\n time,\n}: {\n call: calls.CallResponse\n recording: calls.CallRecording\n title?: string | null\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const actions = useRecordingActions(call)\n const save = useSaveToThread()\n const { notify, runtimeConfig } = useBlocksEnvironment()\n const isHost = call.is_creator\n const mediaDeleted = !!recording.media_deleted_at\n const live = recording.state === 'recording' || (!recording.stopped_at && !mediaDeleted)\n const speakers = speakerTracks(recording)\n const timeline = useMemo(() => timelineOf(recording.tracks ?? []), [recording.tracks])\n const durationMs = timelineDurationMs(timeline)\n const hasMedia = !mediaDeleted && timeline.length > 0\n const [opened, setOpened] = useState<OpenedRecording | null>(null)\n const [playing, setPlaying] = useState(false)\n const [progress, setProgress] = useState<string | null>(null)\n const [saveOpen, setSaveOpen] = useState(false)\n const { workspaceId: selectedWorkspaceId } = useConnectedWorkspace()\n\n // A link asked to show this recording: bring it into view.\n const pending = usePendingRecording()\n const highlighted = pending === recording.external_id\n const cardRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n if (!highlighted) return\n cardRef.current?.scrollIntoView({ block: 'center', behavior: 'smooth' })\n const t = setTimeout(() => setPendingRecording(null), 4000)\n return () => clearTimeout(t)\n }, [highlighted])\n\n const { refresh } = actions\n\n const open = useCallback(async (): Promise<OpenedRecording> => {\n if (opened && opened.recording === recording) return opened\n const next = await actions.open(recording)\n setOpened(next)\n return next\n }, [actions, opened, recording])\n\n const run = async (label: string, task: () => Promise<void>) => {\n setProgress(label)\n try {\n await task()\n } catch (err) {\n console.warn('[calls] recording action failed', err)\n notify((err as Error).message, 'error')\n } finally {\n setProgress(null)\n }\n }\n\n const download = () =>\n run('Decrypting…', async () => {\n const files = await recordingFiles(arbi, await open(), title, (done, total) =>\n setProgress(`Decrypting ${done}/${total}…`)\n )\n if (!files.length) throw new Error('Nothing to download')\n for (const f of files) downloadBlob(f, f.name)\n })\n\n const transcribe = () =>\n run('Transcribing…', async () => {\n const { stored, failed } = await actions.transcribe(await open(), (done, total) =>\n setProgress(`Transcribing ${done}/${total}…`)\n )\n notify(\n failed\n ? `Transcribed ${stored} lines; ${failed} parts failed`\n : `Transcribed ${stored} lines into the meeting chat`,\n failed ? 'warning' : 'success'\n )\n })\n\n const copyLink = async () => {\n const ref = meetingChatRefFrom(call)\n if (!ref) {\n notify('This recording has no meeting chat to link to', 'error')\n return\n }\n try {\n await navigator.clipboard.writeText(\n recordingLink(ref, recording.external_id, runtimeConfig.deploymentDomain)\n )\n notify('Link copied: it opens for members of the meeting chat', 'success')\n } catch {\n notify('Could not copy the link', 'error')\n }\n }\n\n const saveToThread = async (target: string | null) => {\n if (!selectedWorkspaceId) throw new Error('Open a workspace first')\n const files = await recordingFiles(arbi, await open(), title, (done, total) =>\n setProgress(`Decrypting ${done}/${total}…`)\n )\n if (!files.length) throw new Error('Nothing to save')\n // Re-encrypted under the workspace key, as a direct document upload.\n try {\n await save.recording({\n workspaceExtId: selectedWorkspaceId,\n files,\n conversationExtId: target,\n title,\n onUploading: () => setProgress('Uploading…'),\n })\n } finally {\n setProgress(null)\n }\n notify('Recording saved to the thread', 'success')\n }\n\n const summary = [\n 'Recording',\n MODE_LABEL[recording.mode],\n formatCallDuration(durationMs / 1000),\n speakers.length ? `${speakers.length} ${speakers.length === 1 ? 'speaker' : 'speakers'}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n\n return (\n <div\n ref={cardRef}\n className={cn(\n 'mx-auto my-1 flex w-full max-w-xl flex-col gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs',\n highlighted && 'ring-2 ring-primary'\n )}\n data-testid=\"recording-card\"\n data-recording={recording.external_id}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n {recording.mode === 'audio_video' ? (\n <Video className=\"size-4 text-red-500\" aria-hidden />\n ) : (\n <Mic className=\"size-4 text-red-500\" aria-hidden />\n )}\n <span className=\"font-medium\" data-testid=\"recording-summary\">\n {summary}\n </span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live && <span className=\"text-red-500\">recording…</span>}\n {mediaDeleted && (\n <span className=\"text-muted-foreground\">Audio and video deleted — transcript kept</span>\n )}\n {!mediaDeleted && recording.expires_at && (\n <span className=\"text-muted-foreground\">\n Deleted after {new Date(recording.expires_at).toLocaleDateString()}\n </span>\n )}\n </div>\n {speakers.length > 0 && (\n <p className=\"flex flex-wrap items-center gap-1 text-muted-foreground\">\n {speakers.map((t, i) =>\n t.speaker_ext_id ? (\n <CallUserPill\n key={t.speaker_ext_id}\n identity={t.speaker_ext_id}\n name={t.speaker_name}\n />\n ) : (\n <span key={i}>{t.speaker_name || 'Someone'}</span>\n )\n )}\n </p>\n )}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n aria-pressed={playing}\n onClick={() => setPlaying((p) => !p)}\n data-testid=\"recording-play\"\n >\n {playing ? (\n <Pause className=\"mr-1 size-3.5\" aria-hidden />\n ) : (\n <Play className=\"mr-1 size-3.5\" aria-hidden />\n )}\n {playing ? 'Close player' : 'Play'}\n </Button>\n )}\n {hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress}\n onClick={() => void download()}\n data-testid=\"recording-download\"\n >\n <Download className=\"mr-1 size-3.5\" aria-hidden />\n Download\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n onClick={() => void copyLink()}\n title=\"Copy an in-app link (only members of the meeting chat can open it)\"\n data-testid=\"recording-copy-link\"\n >\n <Link2 className=\"mr-1 size-3.5\" aria-hidden />\n Copy link\n </Button>\n {isHost && hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress || live}\n onClick={() => void transcribe()}\n data-testid=\"recording-transcribe\"\n >\n <Captions className=\"mr-1 size-3.5\" aria-hidden />\n Transcribe\n </Button>\n )}\n {isHost && hasMedia && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n disabled={!!progress || live}\n onClick={() => setSaveOpen(true)}\n data-testid=\"recording-save-to-thread\"\n >\n <FileUp className=\"mr-1 size-3.5\" aria-hidden />\n Save to thread\n </Button>\n )}\n {isHost && !mediaDeleted && (\n <ConfirmButton\n label=\"Keep transcript, delete audio/video\"\n confirmLabel=\"Delete audio/video now\"\n testId=\"recording-delete-media\"\n disabled={!!progress || live}\n icon={<Trash2 className=\"mr-1 size-3.5\" aria-hidden />}\n onConfirm={async () => {\n try {\n await arbi.calls.recording.deleteMedia(call.external_id, recording.external_id)\n setPlaying(false)\n setOpened(null)\n refresh()\n } catch (err) {\n notify((err as Error).message, 'error')\n }\n }}\n />\n )}\n {isHost && (\n <ConfirmButton\n label=\"Delete\"\n confirmLabel=\"Delete recording\"\n testId=\"recording-delete\"\n disabled={!!progress || live}\n icon={<Trash2 className=\"mr-1 size-3.5\" aria-hidden />}\n onConfirm={async () => {\n try {\n await arbi.calls.recording.delete(call.external_id, recording.external_id)\n refresh()\n } catch (err) {\n notify((err as Error).message, 'error')\n }\n }}\n />\n )}\n {isHost && !mediaDeleted && (\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Keep\n <select\n className=\"h-7 rounded-sm border border-border bg-background px-1 text-xs text-foreground\"\n value={expiryChoiceOf(recording.expires_at ?? null)}\n onChange={(e) => {\n const days = e.target.value === 'none' ? null : Number(e.target.value)\n void arbi.calls.recording\n .setExpiry(call.external_id, recording.external_id, expiryFor(days))\n .then(refresh)\n .catch((err: unknown) => notify((err as Error).message, 'error'))\n }}\n data-testid=\"recording-expiry\"\n aria-label=\"Keep the audio and video for\"\n >\n {EXPIRY_DAYS.map((d) => (\n <option key={d ?? 'none'} value={d ?? 'none'}>\n {d ? `${d} days` : 'until deleted'}\n </option>\n ))}\n </select>\n </label>\n )}\n {progress && (\n <span className=\"inline-flex items-center gap-1 text-muted-foreground\">\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n {progress}\n </span>\n )}\n </div>\n {playing && hasMedia && (\n <RecordingPlayer recording={recording} open={open} durationMs={durationMs} />\n )}\n {saveOpen && (\n <PickThreadDialog\n heading=\"Save recording to thread\"\n description=\"The recording is decrypted here and uploaded as documents (one audio file per speaker, and the video) into a thread of the current workspace, encrypted under its key. Only that workspace’s members can read them there.\"\n testIdPrefix=\"save-recording\"\n confirmLabel=\"Save\"\n busyLabel=\"Saving…\"\n onClose={() => setSaveOpen(false)}\n onConfirm={saveToThread}\n />\n )}\n </div>\n )\n}\n\n/**\n * Plays a recording: the composite video when there is one (it carries the mixed audio the host\n * heard), otherwise the speaker tracks mixed in sync on one WebAudio timeline.\n */\nfunction RecordingPlayer({\n recording,\n open,\n durationMs,\n}: {\n recording: calls.CallRecording\n open(): Promise<OpenedRecording>\n durationMs: number\n}): ReactElement {\n const composite = compositeTrack(recording)\n const [view, setView] = useState<'video' | 'audio'>(composite?.parts?.length ? 'video' : 'audio')\n return (\n <div className=\"flex flex-col gap-2\" data-testid=\"recording-player\">\n {composite?.parts?.length ? (\n <div className=\"flex gap-1\" role=\"group\" aria-label=\"Play\">\n {(['video', 'audio'] as const).map((v) => (\n <button\n key={v}\n type=\"button\"\n className={cn(\n 'rounded-full px-2 py-0.5',\n view === v ? 'bg-muted font-medium' : 'text-muted-foreground hover:bg-muted'\n )}\n aria-pressed={view === v}\n onClick={() => setView(v)}\n >\n {v === 'video' ? 'Video' : 'Speakers'}\n </button>\n ))}\n </div>\n ) : null}\n {view === 'video' && composite ? (\n <CompositeVideo open={open} trackExtId={composite.external_id} />\n ) : (\n <MixPlayer recording={recording} open={open} durationMs={durationMs} />\n )}\n </div>\n )\n}\n\nfunction CompositeVideo({\n open,\n trackExtId,\n}: {\n open(): Promise<OpenedRecording>\n trackExtId: string\n}): ReactElement {\n const arbi = useArbi()\n const [urls, setUrls] = useState<string[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n let made: string[] = []\n void (async () => {\n try {\n const opened = await open()\n const track = (opened.recording.tracks ?? []).find((t) => t.external_id === trackExtId)\n const key = opened.keys.get(trackExtId)\n if (!track || !key) throw new Error('The video does not open with your key')\n const blobs = await compositeFiles(arbi, track, key)\n made = blobs.map((b) => URL.createObjectURL(b))\n if (cancelled) made.forEach((u) => URL.revokeObjectURL(u))\n else setUrls(made)\n } catch (err) {\n if (!cancelled) setError((err as Error).message)\n }\n })()\n return () => {\n cancelled = true\n made.forEach((u) => URL.revokeObjectURL(u))\n }\n }, [arbi, open, trackExtId])\n if (error) return <p className=\"text-destructive\">{error}</p>\n if (!urls) {\n return (\n <span className=\"inline-flex items-center gap-1 text-muted-foreground\">\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n Decrypting the video…\n </span>\n )\n }\n return (\n <>\n {urls.map((u, i) => (\n <video\n key={u}\n src={u}\n controls\n className=\"w-full rounded-sm bg-black\"\n aria-label={`Video ${i + 1}`}\n />\n ))}\n </>\n )\n}\n\nconst fmt = (ms: number) => {\n const s = Math.max(0, Math.floor(ms / 1000))\n const h = Math.floor(s / 3600)\n const m = Math.floor((s % 3600) / 60)\n const sec = String(s % 60).padStart(2, '0')\n return h ? `${h}:${String(m).padStart(2, '0')}:${sec}` : `${m}:${sec}`\n}\n\n/**\n * The speaker tracks mixed in sync: parts are fetched, decrypted and decoded a little ahead of the\n * playhead and started on one AudioContext clock at their offsets (see `recording-playback.ts`).\n */\nfunction MixPlayer({\n recording,\n open,\n durationMs,\n}: {\n recording: calls.CallRecording\n open(): Promise<OpenedRecording>\n durationMs: number\n}): ReactElement {\n const arbi = useArbi()\n const { notify } = useBlocksEnvironment()\n const parts = useMemo(() => timelineOf(speakerTracks(recording)), [recording])\n const [position, setPosition] = useState(0)\n const [playing, setPlaying] = useState(false)\n const session = useRef<{\n ctx: AudioContext\n ctxStart: number\n seekMs: number\n scheduled: Set<string>\n timer: ReturnType<typeof setInterval>\n } | null>(null)\n\n const halt = useCallback(() => {\n const s = session.current\n session.current = null\n if (!s) return\n clearInterval(s.timer)\n void s.ctx.close().catch(() => undefined)\n }, [])\n\n useEffect(() => halt, [halt])\n\n const play = useCallback(\n async (fromMs: number) => {\n halt()\n const opened = await open()\n const ctx = new AudioContext()\n const s = {\n ctx,\n ctxStart: ctx.currentTime + 0.25,\n seekMs: fromMs,\n scheduled: new Set<string>(),\n timer: 0 as unknown as ReturnType<typeof setInterval>,\n }\n const schedule = async (part: TimelinePart) => {\n const track = (opened.recording.tracks ?? []).find((t) => t.external_id === part.trackExtId)\n const key = opened.keys.get(part.trackExtId)\n const raw = track?.parts?.find((p) => p.seq === part.seq)\n if (!track || !key || !raw) return\n try {\n const bytes = await fetchPart(arbi, raw, key)\n const buffer = await ctx.decodeAudioData(standalone(bytes).buffer)\n if (session.current !== s) return\n const at = schedulePart({\n partOffsetMs: part.offsetMs,\n bufferDurationS: buffer.duration,\n ctxStart: s.ctxStart,\n seekMs: s.seekMs,\n ctxNow: ctx.currentTime,\n })\n if (!at) return\n const source = ctx.createBufferSource()\n source.buffer = buffer\n source.connect(ctx.destination)\n source.start(at.when, at.offset)\n } catch (err) {\n console.warn('[calls] a recording part does not play', err)\n }\n }\n const tick = () => {\n if (session.current !== s) return\n const head = playheadAt(ctx.currentTime, s.ctxStart, s.seekMs)\n setPosition(Math.min(head, durationMs))\n if (head >= durationMs) {\n halt()\n setPlaying(false)\n return\n }\n for (const part of partsDue(parts, head, PLAYBACK_LOOKAHEAD_MS, s.scheduled)) {\n s.scheduled.add(partKey(part))\n void schedule(part)\n }\n }\n s.timer = setInterval(tick, 500)\n session.current = s\n setPlaying(true)\n tick()\n },\n [arbi, open, parts, durationMs, halt]\n )\n\n const toggle = () => {\n if (playing) {\n halt()\n setPlaying(false)\n } else {\n void play(position >= durationMs ? 0 : position).catch((err: unknown) => {\n setPlaying(false)\n notify((err as Error).message, 'error')\n })\n }\n }\n\n return (\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"outline\"\n className=\"size-7\"\n aria-label={playing ? 'Pause' : 'Play'}\n onClick={toggle}\n data-testid=\"recording-mix-toggle\"\n >\n {playing ? <Pause className=\"size-3.5\" /> : <Play className=\"size-3.5\" />}\n </Button>\n <input\n type=\"range\"\n min={0}\n max={Math.max(1, durationMs)}\n step={1000}\n value={position}\n className=\"flex-1\"\n aria-label=\"Position\"\n onChange={(e) => {\n const ms = Number(e.target.value)\n setPosition(ms)\n if (playing) {\n void play(ms).catch((err: unknown) => notify((err as Error).message, 'error'))\n }\n }}\n />\n <span className=\"tabular-nums text-muted-foreground\">\n {fmt(position)} / {fmt(durationMs)}\n </span>\n </div>\n )\n}\n","/**\n * A thread call's log card in the thread transcript: the `convo_events` row of kind `call` the\n * server writes when the call starts and updates when it ends (plaintext ids and times only).\n *\n * live: \"Call started by Ada · invited Bob, Cy\" · Join\n * ended: \"Call · 12 min · joined Ada, Bob\" · Open meeting chat\n *\n * It re-reads on `call.started` / `call.ended` (see `refreshCallCards`).\n */\n\nimport { useArbi, useCallSession, useCall, useOpenCallMeetingChat, openCall } from '@arbidocs/react'\nimport { useState, type ReactElement } from 'react'\nimport { MessageSquare, Phone, PhoneOff } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { formatCallDuration, type CallLogDetail } from '../call-cards'\n\nfunction joinNames(people: string[], name: (id: string) => string): string {\n const names = people.map(name)\n return names.length > 4\n ? `${names.slice(0, 4).join(', ')} +${names.length - 4}`\n : names.join(', ')\n}\n\nexport function ThreadCallLogCard({\n detail,\n name,\n workspaceExtId,\n time,\n}: {\n detail: CallLogDetail\n /** A person's display name by user ext id. */\n name: (userExtId: string) => string\n /** The thread's workspace (the meeting thread lives there too). */\n workspaceExtId: string | null\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const openCallMeetingChat = useOpenCallMeetingChat()\n const live = !detail.ended_at\n const inThisCall = useCallSession((s) => s.active?.callExtId === detail.call_ext_id)\n const inAnotherCall = useCallSession(\n (s) => !!s.active && s.active.callExtId !== detail.call_ext_id\n )\n // Only people holding K (the creator and those rung) can join from the card.\n const { data: call } = useCall(live ? detail.call_ext_id : null)\n const invitedOnly = live && !!call && !call.my_sealed_key\n const [busy, setBusy] = useState(false)\n\n const summary = live\n ? [\n detail.started_by ? `Call started by ${name(detail.started_by)}` : 'Call started',\n detail.invited.length ? `invited ${joinNames(detail.invited, name)}` : null,\n ]\n : [\n 'Call',\n formatCallDuration(detail.duration_s),\n detail.joined.length ? `joined ${joinNames(detail.joined, name)}` : null,\n ]\n\n return (\n <div\n className=\"mx-auto my-1 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs\"\n data-testid=\"thread-call-log-card\"\n data-live={live || undefined}\n >\n {live ? (\n <Phone className=\"size-4 animate-pulse text-green-text\" aria-hidden />\n ) : (\n <PhoneOff className=\"size-4 text-muted-foreground\" aria-hidden />\n )}\n <span data-testid=\"thread-call-log-summary\">{summary.filter(Boolean).join(' · ')}</span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live ? (\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 bg-green-600 text-white hover:bg-green-700\"\n disabled={busy || inThisCall || inAnotherCall || invitedOnly}\n title={\n invitedOnly\n ? 'Only the people rung into this call can join'\n : inAnotherCall\n ? 'You are already in a call'\n : undefined\n }\n onClick={() => {\n setBusy(true)\n void openCall(arbi, { callExtId: detail.call_ext_id }).finally(() => setBusy(false))\n }}\n data-testid=\"thread-call-log-join\"\n >\n {inThisCall ? 'In call' : 'Join'}\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7\"\n onClick={() =>\n void openCallMeetingChat({\n callExtId: detail.call_ext_id,\n meetingConversationExtId: detail.meeting_conversation_ext_id,\n workspaceExtId,\n })\n }\n data-testid=\"thread-call-log-open-chat\"\n >\n <MessageSquare className=\"mr-1 size-3.5\" aria-hidden />\n Open meeting chat\n </Button>\n )}\n </div>\n )\n}\n","/**\n * One stored line of a call transcript in its conversation (meeting chat or workspace meeting\n * thread): `TranscriptLine` from `@arbidocs/blocks`, centred for everyone. What someone is saying\n * right now shows as a provisional \"is speaking…\" row below, not as a highlight on a past line.\n */\n\nimport type { ReactElement } from 'react'\nimport { TranscriptLine } from '../../chat/TranscriptLine'\nimport { CallUserPill } from './CallUserPill'\n\nfunction formatTime(iso: string | null | undefined): string {\n if (!iso) return ''\n const at = Date.parse(iso)\n if (Number.isNaN(at)) return ''\n return new Date(at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\nexport function TranscriptEntry({\n speakerId,\n speakerName,\n text,\n at,\n continued = false,\n className,\n}: {\n /** The speaker's identity (user ext id), for `data-speaker`. */\n speakerId: string\n /** The name to show (\"Me\" for my own lines). */\n speakerName: string\n text: string\n /** ISO time the segment started (or the message was stored). */\n at: string | null | undefined\n /** A further line of the same speaker's run (no name repeated). */\n continued?: boolean\n className?: string\n}): ReactElement {\n return (\n <TranscriptLine\n speakerId={speakerId}\n speakerName={speakerName}\n speaker={<CallUserPill identity={speakerId} name={speakerName} />}\n time={formatTime(at)}\n text={text}\n continued={continued}\n className={className}\n />\n )\n}\n","/** A call participant's name, as the people directory knows them. */\n\nimport { useMemo } from 'react'\nimport { useArbi, usePeople } from '@arbidocs/react'\nimport { getUserDisplayName } from '@arbidocs/react/ui'\n\n/** The name for an identity (user ext id): mine, a known person's, else the call's name for them. */\nexport function useCallPersonName(identity: string, fallbackName?: string | null): string {\n const arbi = useArbi()\n const { byId } = usePeople()\n const me = arbi.isLoggedIn && arbi.user.identity()?.externalId === identity\n const profile = me ? arbi.user.profile() : null\n return useMemo(() => {\n if (profile)\n return getUserDisplayName({ given_name: profile.givenName, family_name: profile.familyName })\n const user = byId(identity)\n if (user) return getUserDisplayName(user)\n return (fallbackName || identity).trim().split(/\\s+/).join(' ')\n }, [profile, byId, identity, fallbackName])\n}\n","/**\n * A call's conversation (meeting chat or meeting thread), call-aware: its empty state (\"Call in\n * progress — the transcript will appear here\", or \"No transcript\" afterwards) instead of the\n * generic one, and provisional \"<speaker> is speaking…\" rows while a line is on its way.\n */\n\nimport { useCallSession } from '@arbidocs/react'\nimport type { ReactElement } from 'react'\nimport { AudioLines, Captions, CaptionsOff } from 'lucide-react'\nimport { EmptyState } from '../../components/EmptyState'\nimport { ProvisionalTranscriptLine } from '../../chat/TranscriptLine'\nimport { useMyCallStatus } from '../call-status'\nimport { CallUserPill } from './CallUserPill'\nimport { useCallPersonName } from './call-person-name'\n\n/** The empty conversation of a call: live while the call runs, \"No transcript\" after. */\nexport function CallConversationEmpty({ callExtId }: { callExtId: string }): ReactElement {\n const { inCall, transcribing } = useMyCallStatus(callExtId)\n const live = useCallSession((s) => !!s.liveCalls[callExtId]) || inCall\n if (!live) {\n return (\n <EmptyState\n icon={AudioLines}\n title=\"No transcript\"\n description=\"This call was not transcribed. When a call here is transcribed, what people say appears in this conversation.\"\n className=\"mx-auto my-8 max-w-xl\"\n testId=\"call-conversation-empty\"\n />\n )\n }\n return (\n <EmptyState\n icon={transcribing ? Captions : CaptionsOff}\n title=\"Call in progress — the transcript will appear here\"\n description={\n transcribing\n ? 'Transcription is on: what people say shows up here as they speak.'\n : 'Transcription is off. The host can turn it on with CC in the call.'\n }\n className=\"mx-auto my-8 max-w-xl\"\n testId=\"call-conversation-empty\"\n />\n )\n}\n\nfunction ProvisionalRow({ identity }: { identity: string }): ReactElement {\n const name = useCallPersonName(identity)\n return (\n <ProvisionalTranscriptLine\n speakerId={identity}\n speakerName={name}\n speaker={<CallUserPill identity={identity} />}\n />\n )\n}\n\n/** The provisional rows at the bottom of a call's conversation (never stored). */\nexport function ProvisionalSpeakers({ ids }: { ids: string[] }): ReactElement | null {\n if (!ids.length) return null\n return (\n <div className=\"pb-2\" data-testid=\"transcript-provisional-rows\">\n {ids.map((id) => (\n <ProvisionalRow key={id} identity={id} />\n ))}\n </div>\n )\n}\n","/** Who gets a provisional \"is speaking…\" row in a call's conversation. */\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { useMyCallStatus } from '../call-status'\nimport { useSpeakingIds } from '../voice-levels'\n\n/** A spoken stretch whose line has not arrived yet. */\ninterface Pending {\n startedAt: number\n lastHeardAt: number\n}\n\n/** How long after someone stops a provisional row waits for their line before it gives up. */\nconst LINE_WAIT_MS = 10_000\n/** A burst shorter than this (a cough, a word) gets no row. */\nconst MIN_SPEECH_MS = 800\n\n/**\n * Who should show a provisional row: people talking now, and people who stopped but whose line\n * has not arrived yet (a line started at or after their stretch began replaces the row).\n */\nexport function useProvisionalSpeakers(\n callExtId: string | null | undefined,\n lines: { speakerId: string; at: number }[]\n): string[] {\n const { inCall, transcribing } = useMyCallStatus(callExtId)\n const speaking = useSpeakingIds()\n const pending = useRef(new Map<string, Pending>())\n const [, tick] = useState(0)\n const active = inCall && transcribing\n const now = Date.now()\n if (active) {\n for (const id of speaking) {\n const p = pending.current.get(id)\n if (p) p.lastHeardAt = now\n else pending.current.set(id, { startedAt: now, lastHeardAt: now })\n }\n } else if (pending.current.size) {\n pending.current.clear()\n }\n // A line that began within the stretch (a little slack for clock skew) replaces the row.\n const latest = useMemo(() => {\n const m = new Map<string, number>()\n for (const l of lines) m.set(l.speakerId, Math.max(m.get(l.speakerId) ?? 0, l.at))\n return m\n }, [lines])\n for (const [id, p] of [...pending.current]) {\n const arrived = (latest.get(id) ?? 0) >= p.startedAt - 3000\n const stale = !speaking.includes(id) && now - p.lastHeardAt > LINE_WAIT_MS\n if ((arrived && !speaking.includes(id)) || stale) pending.current.delete(id)\n else if (arrived) p.startedAt = now\n }\n // Re-check while rows wait for their lines.\n const waiting = pending.current.size > 0\n useEffect(() => {\n if (!waiting) return\n const id = setInterval(() => tick((n) => n + 1), 1000)\n return () => clearInterval(id)\n }, [waiting])\n return [...pending.current]\n .filter(([, p]) => p.lastHeardAt - p.startedAt >= MIN_SPEECH_MS)\n .map(([id]) => id)\n}\n","/**\n * How a meeting thread's transcript lines group: which messages continue their speaker's run (the\n * name is not repeated) and which are each speaker's newest line (highlighted while they talk).\n * Provided by the conversation page, read by each transcript message.\n */\n\nimport { createContext, useContext } from 'react'\nimport { transcriptRuns } from '../../chat/transcript-runs'\nimport { transcriptSegmentOf } from '@arbidocs/react'\n\nexport interface TranscriptRunInfo {\n continued: ReadonlySet<string>\n latest: ReadonlySet<string>\n}\n\nconst EMPTY: TranscriptRunInfo = { continued: new Set(), latest: new Set() }\n\nexport const TranscriptRunsContext = createContext<TranscriptRunInfo>(EMPTY)\n\nexport function useTranscriptRuns(): TranscriptRunInfo {\n return useContext(TranscriptRunsContext)\n}\n\ninterface ThreadMessageLike {\n external_id?: string | null\n created_at?: string | null\n tools?: unknown\n meta?: { tools?: unknown } | null\n}\n\n/** Runs and newest lines of a thread's messages (in display order). */\nexport function threadTranscriptRuns(messages: ThreadMessageLike[]): TranscriptRunInfo {\n const segmentOf = (m: ThreadMessageLike) => transcriptSegmentOf(m.tools ?? m.meta?.tools)\n const continuedItems = transcriptRuns(\n messages,\n (m) => segmentOf(m)?.speaker_ext_id ?? null,\n (m) => Date.parse(segmentOf(m)?.started_at ?? m.created_at ?? '') || 0\n )\n const latest = new Map<string, string>()\n for (const m of messages) {\n const seg = segmentOf(m)\n if (seg && m.external_id) latest.set(seg.speaker_ext_id, m.external_id)\n }\n return {\n continued: new Set(\n [...continuedItems].map((m) => m.external_id).filter((id): id is string => !!id)\n ),\n latest: new Set(latest.values()),\n }\n}\n"]}
|
|
@@ -152,5 +152,5 @@ function useBlocksEnvironment() {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
export { requestSettingsSection, useBlocksEnvironment, useRequestedSettingsSection };
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
156
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-PKB4LBPC.js.map
|
|
156
|
+
//# sourceMappingURL=chunk-PKB4LBPC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider/dialogs.tsx","../src/provider/settings-section.ts","../src/provider/environment.ts"],"names":["request","resolve","notifyStore"],"mappings":"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","file":"chunk-GKM4EOH7.js","sourcesContent":["/**\n * Promise-based prompt dialogs — the blocks replacement for `window.confirm` / `window.alert`.\n * Each call mounts its own short-lived React root, so it works from any event handler with no\n * dialog host in the tree. Hosts reach these through `useBlocksEnvironment().confirm` / `.choose`\n * (the defaults), which lets an app swap in its own dialogs without touching callers.\n *\n * For a confirmation with a loading state, render the declarative {@link ConfirmDialog} instead.\n */\nimport { useState, type ReactElement } from 'react'\nimport { AlertCircle, Info } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { ModalScaffold } from '../settings/ModalScaffold'\n\ntype ChoiceVariant = 'default' | 'destructive' | 'outline'\n\nexport interface PromptChoice<T extends string> {\n label: string\n value: T\n variant?: ChoiceVariant\n}\n\n/** A dialog offering arbitrary choices (e.g. Overwrite / Skip / Cancel). */\nexport interface ChoiceRequest<T extends string> {\n message: string\n title?: string\n choices: PromptChoice<T>[]\n icon?: 'alert' | 'info'\n /** Dialog test id; each button is `${testId}-${value}-button`. Default `choice-modal`. */\n testId?: string\n}\n\n/**\n * `confirm` — Cancel / Confirm (destructive); `yesno` — No / Yes; `alert` — a single OK\n * (resolves true once acknowledged).\n */\nexport type ConfirmKind = 'confirm' | 'yesno' | 'alert'\n\nexport interface ConfirmRequest {\n message: string\n /** Default: \"Alert\" for `alert`, else \"Confirm\". */\n title?: string\n kind?: ConfirmKind\n}\n\n/** Close animation length before the root is unmounted. */\nconst UNMOUNT_DELAY_MS = 300\n\nfunction PromptDialog<T extends string>({\n request,\n onSettle,\n}: {\n request: ChoiceRequest<T>\n onSettle: (value: T | null) => void\n}): ReactElement {\n const [open, setOpen] = useState(true)\n const { message, title = 'Confirm', choices, icon = 'alert', testId = 'choice-modal' } = request\n const settle = (value: T | null) => {\n setOpen(false)\n onSettle(value)\n }\n return (\n <ModalScaffold\n open={open}\n onOpenChange={(next) => {\n if (!next) settle(null)\n }}\n title={title}\n icon={\n icon === 'info' ? (\n <Info className=\"h-5 w-5 text-blue-text\" aria-hidden=\"true\" />\n ) : (\n <AlertCircle className=\"h-5 w-5\" aria-hidden=\"true\" />\n )\n }\n description={<span className=\"whitespace-pre-line\">{message}</span>}\n showDescription\n testId={testId}\n >\n <ModalScaffold.Footer>\n {choices.map((choice) => (\n <Button\n key={choice.value}\n variant={choice.variant ?? 'default'}\n onClick={() => settle(choice.value)}\n data-testid={`${testId}-${choice.value.toLowerCase()}-button`}\n >\n {choice.label}\n </Button>\n ))}\n </ModalScaffold.Footer>\n </ModalScaffold>\n )\n}\n\n/** Show a choice dialog; resolves with the chosen `value`, or `null` when dismissed. */\nexport function choiceDialog<T extends string>(request: ChoiceRequest<T>): Promise<T | null> {\n if (typeof document === 'undefined') return Promise.resolve(null)\n return new Promise((resolve) => {\n const container = document.createElement('div')\n document.body.appendChild(container)\n let settled = false\n void import('react-dom/client').then(({ createRoot }) => {\n const root = createRoot(container)\n const onSettle = (value: T | null) => {\n if (settled) return\n settled = true\n resolve(value)\n setTimeout(() => {\n root.unmount()\n container.remove()\n }, UNMOUNT_DELAY_MS)\n }\n root.render(<PromptDialog request={request} onSettle={onSettle} />)\n })\n })\n}\n\nconst CONFIRM_CHOICES: Record<\n ConfirmKind,\n PromptChoice<'confirm' | 'cancel' | 'yes' | 'no' | 'ok'>[]\n> = {\n confirm: [\n { label: 'Cancel', value: 'cancel', variant: 'outline' },\n { label: 'Confirm', value: 'confirm', variant: 'destructive' },\n ],\n yesno: [\n { label: 'No', value: 'no', variant: 'outline' },\n { label: 'Yes', value: 'yes' },\n ],\n alert: [{ label: 'OK', value: 'ok' }],\n}\n\nconst CONFIRM_TEST_ID: Record<ConfirmKind, string> = {\n confirm: 'confirmation-modal',\n yesno: 'yes-no-modal',\n alert: 'alert-modal',\n}\n\n/** Show a confirmation; resolves true on Confirm / Yes / OK, false on cancel or dismissal. */\nexport async function confirmDialog(request: ConfirmRequest): Promise<boolean> {\n const kind = request.kind ?? 'confirm'\n const choice = await choiceDialog({\n message: request.message,\n title: request.title ?? (kind === 'alert' ? 'Alert' : 'Confirm'),\n choices: CONFIRM_CHOICES[kind],\n icon: kind === 'alert' ? 'info' : 'alert',\n testId: CONFIRM_TEST_ID[kind],\n })\n return choice === 'confirm' || choice === 'yes' || choice === 'ok'\n}\n","/**\n * The settings section asked for last, so `openSettings(section)` opens that section in every host.\n *\n * `BlocksEnvironment.openSettings` records the section here before the host shows its settings\n * (a panel, a route); a `ConnectedSettingsPage` without its own `section` prop opens at it and\n * follows every later request, even one for the section asked for before. A host that keeps the\n * open section itself (`section` + `onSectionChange`) routes `openSettings` to its own state.\n */\nimport { useSyncExternalStore } from 'react'\n\nexport interface SettingsSectionRequest {\n section: string\n /** Increases with every request, so asking again for the same section is a new request. */\n seq: number\n}\n\nlet request: SettingsSectionRequest | undefined\nconst listeners = new Set<() => void>()\n\n/** Ask for a settings section; no section asks for none (the page stays where it is). */\nexport function requestSettingsSection(section?: string): void {\n if (!section) return\n request = { section, seq: (request?.seq ?? 0) + 1 }\n listeners.forEach((listener) => listener())\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nconst snapshot = () => request\n\n/** The last settings-section request (`undefined` until there is one). */\nexport function useRequestedSettingsSection(): SettingsSectionRequest | undefined {\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n","import type { ReactNode } from 'react'\nimport {\n notify as notifyStore,\n useHostConfigRecord,\n type NotifyOptions,\n type NotifyVariant,\n} from '@arbidocs/react/shell'\nimport type { BlockLinkComponent } from '../components/blockLink'\nimport { choiceDialog, confirmDialog, type ChoiceRequest, type ConfirmRequest } from './dialogs'\nimport { requestSettingsSection } from './settings-section'\n\n/** What blocks need from the host's runtime configuration (the app's `config.json`). */\nexport interface BlocksRuntimeConfig {\n /** Origin of the ARBI API; `''` means the page's own origin. */\n apiBaseUrl: string\n /** The deployment's domain, e.g. `www.arbidocs.com` (deep links, key derivation, labels). */\n deploymentDomain: string\n}\n\nexport interface OpenDocumentOptions {\n /** 1-based page to scroll to. */\n page?: number\n /** Passage (chunk) to highlight. */\n passageId?: string\n /**\n * The workspace the document is in, when it is not the open one (a document an agent wrote in\n * its own workspace): the host opens that workspace first.\n */\n workspaceId?: string\n}\n\n/** Where files are added from: this device, links, or an email account. */\nexport type UploadSource = 'computer' | 'internet' | 'email'\n\n/** What `openShare` shares by email. */\nexport interface ShareRequest {\n resourceType: 'document' | 'conversation'\n resourceExtId: string\n workspaceExtId: string\n resourceName?: string\n /** Whether it is private to its owner now: the dialog offers to share it with the workspace. */\n isPrivate: boolean\n}\n\n/** What `openFiles` shows: some files selected, and the list narrowed. */\nexport interface OpenFilesOptions {\n /** Files to select. */\n select?: string[]\n /** Quick filters by key (a label id, `folder:<path>`, `folder:none`): show or hide those files. */\n filters?: Record<string, 'include' | 'exclude'>\n}\n\n/**\n * Something a kit links to (the target of an `open…` intent), for `hrefFor`. `workspaceId` is the\n * workspace it is in, when the kit knows it.\n */\nexport type LinkTarget =\n | { kind: 'document'; documentId: string; workspaceId?: string | null }\n | {\n kind: 'conversation'\n conversationId: string\n workspaceId?: string | null\n messageId?: string\n }\n | { kind: 'workspace'; workspaceId: string }\n\n/**\n * The only way blocks reach the host app's environment: the host configuration's `environment`\n * (`<ArbiHost config={{ environment: { navigate, notify, … } }}>`). Blocks never import a router, a\n * toast library or an app store; the host gives what it has, and every field has a safe default so\n * a block renders correctly with no host at all. A nested host overrides only the fields it gives\n * and inherits the rest.\n */\nexport interface BlocksEnvironment {\n /** Router-aware link (keeps navigation in-SPA). Default: a plain `<a href>`. */\n linkComponent?: BlockLinkComponent\n /** Imperative navigation for buttons and keyboard shortcuts. Default: `window.location.assign`. */\n navigate: (href: string) => void\n /** Surface a transient message (and record it in the notification centre). Default: the shared\n * `@arbidocs/react` notify store, rendered by its `<Toaster/>`. */\n notify: (message: ReactNode, kind?: NotifyVariant, options?: NotifyOptions) => void\n /** Ask the user to confirm. Default: the blocks prompt dialog. */\n confirm: (request: ConfirmRequest) => Promise<boolean>\n /** Ask the user to pick one of several choices; `null` when dismissed. Default: the blocks\n * prompt dialog. */\n choose: <T extends string>(request: ChoiceRequest<T>) => Promise<T | null>\n /** Deployment configuration. Default: same-origin API on the page's own host. */\n runtimeConfig: BlocksRuntimeConfig\n /**\n * The address of a target in the host's router, for a real link (open in a new tab, middle-click,\n * copy link) beside the matching `open…` intent: a kit never builds an app path itself, so its\n * links and its navigation agree on every site. `undefined`: no link (the row still opens on a\n * click). Default: none. ARBI-style paths (`/wrk-…/doc-…`): `deepLinkHref`.\n */\n hrefFor: (target: LinkTarget) => string | undefined\n /** Open a document (optionally at a page / passage) wherever the host shows documents.\n * Default: no-op. */\n openDocument: (documentId: string, options?: OpenDocumentOptions) => void\n /** Open a conversation thread, optionally scrolled to a message. Default: no-op. */\n openConversation: (conversationId: string, options?: { messageId?: string }) => void\n /**\n * Open the user's settings, optionally at a section (a `ConnectedSettingsPage` section id).\n * The section is always recorded for `ConnectedSettingsPage` first (`requestSettingsSection`);\n * the host's handler then shows its settings. Default: only that record.\n */\n openSettings: (section?: string) => void\n /** Open a project. Default: no-op. */\n openProject: (projectId: string) => void\n /**\n * Show the calendar page (`ConnectedCalendar`). A kit records what it opens on first (an event,\n * or the editor prefilled: `requestCalendarEvent` / `requestCalendarComposer`). Default: no-op.\n */\n openCalendar: () => void\n /**\n * Show a new, empty conversation (a launch then composes its first message into the session's\n * draft). Default: no-op.\n */\n openNewConversation: () => void\n /** Show the open workspace's files, optionally with some selected and the list narrowed. Default: no-op. */\n openFiles: (options?: OpenFilesOptions) => void\n /**\n * Add files the host's way (its upload dialog), optionally with some already picked, or from one\n * source. Absent: a kit that adds files uploads them itself.\n */\n openUpload?: (files?: File[], options?: { source?: UploadSource }) => void\n /** Open the host's skills browser, optionally at one skill. Absent: not offered. */\n openSkillsBrowser?: (skillSlug?: string) => void\n /** Share a document or a thread by email (the host's share dialog). Absent: not offered. */\n openShare?: (request: ShareRequest) => void\n /** Open an email draft in the host's mail. Absent: a kit offers no way to open one. */\n openMailDraft?: (draftId: string) => void\n /**\n * A React hook: how to open a workflow in the host's builder (no id: the Workflows page's list),\n * or `undefined` while the host has no Workflows page (a setting turns it off). Absent: never.\n */\n useOpenWorkflow?: () => ((workflowId?: string) => void) | undefined\n /**\n * Show a workspace (its own page). Under `defaultHost`'s sign-in layer the kits select it first\n * (`useConnectedWorkspace().openWorkspace`); a host that keeps its own session switches to it\n * here. `name` is for the host's messages. Default: no-op.\n */\n openWorkspace: (workspaceId: string, options?: { name?: string }) => void\n}\n\nconst noop = () => {}\n\nconst defaultEnvironment: BlocksEnvironment = {\n navigate: (href) => {\n if (typeof window !== 'undefined') window.location.assign(href)\n },\n notify: (message, kind = 'info', options) => {\n notifyStore[kind](message, options)\n },\n confirm: confirmDialog,\n choose: choiceDialog,\n runtimeConfig: {\n apiBaseUrl: '',\n deploymentDomain: typeof window !== 'undefined' ? window.location.host : '',\n },\n hrefFor: () => undefined,\n openDocument: noop,\n openConversation: noop,\n openSettings: requestSettingsSection,\n openProject: noop,\n openCalendar: noop,\n openNewConversation: noop,\n openFiles: noop,\n openWorkspace: noop,\n}\n\nconst resolved = new WeakMap<object, BlocksEnvironment>()\n\nfunction resolve(environment: Partial<BlocksEnvironment>): BlocksEnvironment {\n const { openSettings } = environment\n return {\n ...defaultEnvironment,\n ...environment,\n // The section is recorded for `ConnectedSettingsPage` before the host shows its settings.\n openSettings: openSettings\n ? (section?: string) => {\n requestSettingsSection(section)\n openSettings(section)\n }\n : defaultEnvironment.openSettings,\n }\n}\n\n/** The host's environment, every field filled in (the defaults where the host gives none). */\nexport function useBlocksEnvironment(): BlocksEnvironment {\n const environment = useHostConfigRecord().environment as Partial<BlocksEnvironment> | undefined\n if (!environment) return defaultEnvironment\n let value = resolved.get(environment)\n if (!value) resolved.set(environment, (value = resolve(environment)))\n return value\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider/dialogs.tsx","../src/provider/settings-section.ts","../src/provider/environment.ts"],"names":["request","resolve","notifyStore"],"mappings":"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","file":"chunk-PKB4LBPC.js","sourcesContent":["/**\n * Promise-based prompt dialogs — the blocks replacement for `window.confirm` / `window.alert`.\n * Each call mounts its own short-lived React root, so it works from any event handler with no\n * dialog host in the tree. Hosts reach these through `useBlocksEnvironment().confirm` / `.choose`\n * (the defaults), which lets an app swap in its own dialogs without touching callers.\n *\n * For a confirmation with a loading state, render the declarative {@link ConfirmDialog} instead.\n */\nimport { useState, type ReactElement } from 'react'\nimport { AlertCircle, Info } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { ModalScaffold } from '../settings/ModalScaffold'\n\ntype ChoiceVariant = 'default' | 'destructive' | 'outline'\n\nexport interface PromptChoice<T extends string> {\n label: string\n value: T\n variant?: ChoiceVariant\n}\n\n/** A dialog offering arbitrary choices (e.g. Overwrite / Skip / Cancel). */\nexport interface ChoiceRequest<T extends string> {\n message: string\n title?: string\n choices: PromptChoice<T>[]\n icon?: 'alert' | 'info'\n /** Dialog test id; each button is `${testId}-${value}-button`. Default `choice-modal`. */\n testId?: string\n}\n\n/**\n * `confirm` — Cancel / Confirm (destructive); `yesno` — No / Yes; `alert` — a single OK\n * (resolves true once acknowledged).\n */\nexport type ConfirmKind = 'confirm' | 'yesno' | 'alert'\n\nexport interface ConfirmRequest {\n message: string\n /** Default: \"Alert\" for `alert`, else \"Confirm\". */\n title?: string\n kind?: ConfirmKind\n}\n\n/** Close animation length before the root is unmounted. */\nconst UNMOUNT_DELAY_MS = 300\n\nfunction PromptDialog<T extends string>({\n request,\n onSettle,\n}: {\n request: ChoiceRequest<T>\n onSettle: (value: T | null) => void\n}): ReactElement {\n const [open, setOpen] = useState(true)\n const { message, title = 'Confirm', choices, icon = 'alert', testId = 'choice-modal' } = request\n const settle = (value: T | null) => {\n setOpen(false)\n onSettle(value)\n }\n return (\n <ModalScaffold\n open={open}\n onOpenChange={(next) => {\n if (!next) settle(null)\n }}\n title={title}\n icon={\n icon === 'info' ? (\n <Info className=\"h-5 w-5 text-blue-text\" aria-hidden=\"true\" />\n ) : (\n <AlertCircle className=\"h-5 w-5\" aria-hidden=\"true\" />\n )\n }\n description={<span className=\"whitespace-pre-line\">{message}</span>}\n showDescription\n testId={testId}\n >\n <ModalScaffold.Footer>\n {choices.map((choice) => (\n <Button\n key={choice.value}\n variant={choice.variant ?? 'default'}\n onClick={() => settle(choice.value)}\n data-testid={`${testId}-${choice.value.toLowerCase()}-button`}\n >\n {choice.label}\n </Button>\n ))}\n </ModalScaffold.Footer>\n </ModalScaffold>\n )\n}\n\n/** Show a choice dialog; resolves with the chosen `value`, or `null` when dismissed. */\nexport function choiceDialog<T extends string>(request: ChoiceRequest<T>): Promise<T | null> {\n if (typeof document === 'undefined') return Promise.resolve(null)\n return new Promise((resolve) => {\n const container = document.createElement('div')\n document.body.appendChild(container)\n let settled = false\n void import('react-dom/client').then(({ createRoot }) => {\n const root = createRoot(container)\n const onSettle = (value: T | null) => {\n if (settled) return\n settled = true\n resolve(value)\n setTimeout(() => {\n root.unmount()\n container.remove()\n }, UNMOUNT_DELAY_MS)\n }\n root.render(<PromptDialog request={request} onSettle={onSettle} />)\n })\n })\n}\n\nconst CONFIRM_CHOICES: Record<\n ConfirmKind,\n PromptChoice<'confirm' | 'cancel' | 'yes' | 'no' | 'ok'>[]\n> = {\n confirm: [\n { label: 'Cancel', value: 'cancel', variant: 'outline' },\n { label: 'Confirm', value: 'confirm', variant: 'destructive' },\n ],\n yesno: [\n { label: 'No', value: 'no', variant: 'outline' },\n { label: 'Yes', value: 'yes' },\n ],\n alert: [{ label: 'OK', value: 'ok' }],\n}\n\nconst CONFIRM_TEST_ID: Record<ConfirmKind, string> = {\n confirm: 'confirmation-modal',\n yesno: 'yes-no-modal',\n alert: 'alert-modal',\n}\n\n/** Show a confirmation; resolves true on Confirm / Yes / OK, false on cancel or dismissal. */\nexport async function confirmDialog(request: ConfirmRequest): Promise<boolean> {\n const kind = request.kind ?? 'confirm'\n const choice = await choiceDialog({\n message: request.message,\n title: request.title ?? (kind === 'alert' ? 'Alert' : 'Confirm'),\n choices: CONFIRM_CHOICES[kind],\n icon: kind === 'alert' ? 'info' : 'alert',\n testId: CONFIRM_TEST_ID[kind],\n })\n return choice === 'confirm' || choice === 'yes' || choice === 'ok'\n}\n","/**\n * The settings section asked for last, so `openSettings(section)` opens that section in every host.\n *\n * `BlocksEnvironment.openSettings` records the section here before the host shows its settings\n * (a panel, a route); a `ConnectedSettingsPage` without its own `section` prop opens at it and\n * follows every later request, even one for the section asked for before. A host that keeps the\n * open section itself (`section` + `onSectionChange`) routes `openSettings` to its own state.\n */\nimport { useSyncExternalStore } from 'react'\n\nexport interface SettingsSectionRequest {\n section: string\n /** Increases with every request, so asking again for the same section is a new request. */\n seq: number\n}\n\nlet request: SettingsSectionRequest | undefined\nconst listeners = new Set<() => void>()\n\n/** Ask for a settings section; no section asks for none (the page stays where it is). */\nexport function requestSettingsSection(section?: string): void {\n if (!section) return\n request = { section, seq: (request?.seq ?? 0) + 1 }\n listeners.forEach((listener) => listener())\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nconst snapshot = () => request\n\n/** The last settings-section request (`undefined` until there is one). */\nexport function useRequestedSettingsSection(): SettingsSectionRequest | undefined {\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n","import type { ReactNode } from 'react'\nimport {\n notify as notifyStore,\n useHostConfigRecord,\n type NotifyOptions,\n type NotifyVariant,\n} from '@arbidocs/react/shell'\nimport type { BlockLinkComponent } from '../components/blockLink'\nimport { choiceDialog, confirmDialog, type ChoiceRequest, type ConfirmRequest } from './dialogs'\nimport { requestSettingsSection } from './settings-section'\n\n/** What blocks need from the host's runtime configuration (the app's `config.json`). */\nexport interface BlocksRuntimeConfig {\n /** Origin of the ARBI API; `''` means the page's own origin. */\n apiBaseUrl: string\n /** The deployment's domain, e.g. `www.arbidocs.com` (deep links, key derivation, labels). */\n deploymentDomain: string\n}\n\nexport interface OpenDocumentOptions {\n /** 1-based page to scroll to. */\n page?: number\n /** Passage (chunk) to highlight. */\n passageId?: string\n /**\n * The workspace the document is in, when it is not the open one (a document an agent wrote in\n * its own workspace): the host opens that workspace first.\n */\n workspaceId?: string\n}\n\n/** Where files are added from: this device, links, or an email account. */\nexport type UploadSource = 'computer' | 'internet' | 'email'\n\n/** What `openShare` shares by email. */\nexport interface ShareRequest {\n resourceType: 'document' | 'conversation'\n resourceExtId: string\n workspaceExtId: string\n resourceName?: string\n /** Whether it is private to its owner now: the dialog offers to share it with the workspace. */\n isPrivate: boolean\n}\n\n/** What `openFiles` shows: some files selected, and the list narrowed. */\nexport interface OpenFilesOptions {\n /** Files to select. */\n select?: string[]\n /** Quick filters by key (a label id, `folder:<path>`, `folder:none`): show or hide those files. */\n filters?: Record<string, 'include' | 'exclude'>\n}\n\n/**\n * Something a kit links to (the target of an `open…` intent), for `hrefFor`. `workspaceId` is the\n * workspace it is in, when the kit knows it.\n */\nexport type LinkTarget =\n | { kind: 'document'; documentId: string; workspaceId?: string | null }\n | {\n kind: 'conversation'\n conversationId: string\n workspaceId?: string | null\n messageId?: string\n }\n | { kind: 'workspace'; workspaceId: string }\n\n/**\n * The only way blocks reach the host app's environment: the host configuration's `environment`\n * (`<ArbiHost config={{ environment: { navigate, notify, … } }}>`). Blocks never import a router, a\n * toast library or an app store; the host gives what it has, and every field has a safe default so\n * a block renders correctly with no host at all. A nested host overrides only the fields it gives\n * and inherits the rest.\n */\nexport interface BlocksEnvironment {\n /** Router-aware link (keeps navigation in-SPA). Default: a plain `<a href>`. */\n linkComponent?: BlockLinkComponent\n /** Imperative navigation for buttons and keyboard shortcuts. Default: `window.location.assign`. */\n navigate: (href: string) => void\n /** Surface a transient message (and record it in the notification centre). Default: the shared\n * `@arbidocs/react` notify store, rendered by its `<Toaster/>`. */\n notify: (message: ReactNode, kind?: NotifyVariant, options?: NotifyOptions) => void\n /** Ask the user to confirm. Default: the blocks prompt dialog. */\n confirm: (request: ConfirmRequest) => Promise<boolean>\n /** Ask the user to pick one of several choices; `null` when dismissed. Default: the blocks\n * prompt dialog. */\n choose: <T extends string>(request: ChoiceRequest<T>) => Promise<T | null>\n /** Deployment configuration. Default: same-origin API on the page's own host. */\n runtimeConfig: BlocksRuntimeConfig\n /**\n * The address of a target in the host's router, for a real link (open in a new tab, middle-click,\n * copy link) beside the matching `open…` intent: a kit never builds an app path itself, so its\n * links and its navigation agree on every site. `undefined`: no link (the row still opens on a\n * click). Default: none. ARBI-style paths (`/wrk-…/doc-…`): `deepLinkHref`.\n */\n hrefFor: (target: LinkTarget) => string | undefined\n /** Open a document (optionally at a page / passage) wherever the host shows documents.\n * Default: no-op. */\n openDocument: (documentId: string, options?: OpenDocumentOptions) => void\n /**\n * Open a conversation thread, optionally scrolled to a message. `keepDocumentOpen`: the open\n * document stays on screen beside the thread (a thread about it). Default: no-op.\n */\n openConversation: (\n conversationId: string,\n options?: { messageId?: string; keepDocumentOpen?: boolean }\n ) => void\n /**\n * Open the user's settings, optionally at a section (a `ConnectedSettingsPage` section id).\n * The section is always recorded for `ConnectedSettingsPage` first (`requestSettingsSection`);\n * the host's handler then shows its settings. Default: only that record.\n */\n openSettings: (section?: string) => void\n /** Open a project. Default: no-op. */\n openProject: (projectId: string) => void\n /**\n * Show the calendar page (`ConnectedCalendar`). A kit records what it opens on first (an event,\n * or the editor prefilled: `requestCalendarEvent` / `requestCalendarComposer`). Default: no-op.\n */\n openCalendar: () => void\n /**\n * Show a new, empty conversation (a launch then composes its first message into the session's\n * draft); it starts unbound to any document. `keepDocumentOpen`: the open document stays on\n * screen beside it (a chat started from it). Default: no-op.\n */\n openNewConversation: (options?: { keepDocumentOpen?: boolean }) => void\n /** Show the open workspace's files, optionally with some selected and the list narrowed. Default: no-op. */\n openFiles: (options?: OpenFilesOptions) => void\n /**\n * Add files the host's way (its upload dialog), optionally with some already picked, or from one\n * source. Absent: a kit that adds files uploads them itself.\n */\n openUpload?: (files?: File[], options?: { source?: UploadSource }) => void\n /** Open the host's skills browser, optionally at one skill. Absent: not offered. */\n openSkillsBrowser?: (skillSlug?: string) => void\n /** Share a document or a thread by email (the host's share dialog). Absent: not offered. */\n openShare?: (request: ShareRequest) => void\n /** Open an email draft in the host's mail. Absent: a kit offers no way to open one. */\n openMailDraft?: (draftId: string) => void\n /**\n * A React hook: how to open a workflow in the host's builder (no id: the Workflows page's list),\n * or `undefined` while the host has no Workflows page (a setting turns it off). Absent: never.\n */\n useOpenWorkflow?: () => ((workflowId?: string) => void) | undefined\n /**\n * Show a workspace (its own page). Under `defaultHost`'s sign-in layer the kits select it first\n * (`useConnectedWorkspace().openWorkspace`); a host that keeps its own session switches to it\n * here. `name` is for the host's messages. Default: no-op.\n */\n openWorkspace: (workspaceId: string, options?: { name?: string }) => void\n}\n\nconst noop = () => {}\n\nconst defaultEnvironment: BlocksEnvironment = {\n navigate: (href) => {\n if (typeof window !== 'undefined') window.location.assign(href)\n },\n notify: (message, kind = 'info', options) => {\n notifyStore[kind](message, options)\n },\n confirm: confirmDialog,\n choose: choiceDialog,\n runtimeConfig: {\n apiBaseUrl: '',\n deploymentDomain: typeof window !== 'undefined' ? window.location.host : '',\n },\n hrefFor: () => undefined,\n openDocument: noop,\n openConversation: noop,\n openSettings: requestSettingsSection,\n openProject: noop,\n openCalendar: noop,\n openNewConversation: noop,\n openFiles: noop,\n openWorkspace: noop,\n}\n\nconst resolved = new WeakMap<object, BlocksEnvironment>()\n\nfunction resolve(environment: Partial<BlocksEnvironment>): BlocksEnvironment {\n const { openSettings } = environment\n return {\n ...defaultEnvironment,\n ...environment,\n // The section is recorded for `ConnectedSettingsPage` before the host shows its settings.\n openSettings: openSettings\n ? (section?: string) => {\n requestSettingsSection(section)\n openSettings(section)\n }\n : defaultEnvironment.openSettings,\n }\n}\n\n/** The host's environment, every field filled in (the defaults where the host gives none). */\nexport function useBlocksEnvironment(): BlocksEnvironment {\n const environment = useHostConfigRecord().environment as Partial<BlocksEnvironment> | undefined\n if (!environment) return defaultEnvironment\n let value = resolved.get(environment)\n if (!value) resolved.set(environment, (value = resolve(environment)))\n return value\n}\n"]}
|